How using SDL_CreateTexture create transparent texture? By default I'm creating texure with such code:
SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET, x, y);
And then I'm paining on this texture with redirecting output to this texture. However at the end what I want to render this on screen any (nonupdated) pixel is black.
I have tried different ways with using of:
SDL_RenderClear(_Renderer);
or even with drawing and on created texture with painting transparent Rect with different blending modes but all I had as a result was still nontransparent texture :/
SDL_Rect rect={0,0,Width,Height}; SDL_SetRenderDrawBlendMode(_Renderer,SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(_Renderer,255,255,255,0); SDL_RenderFillRect(_Renderer,&rect);
To be more specific:
//this->texDefault.get()->get() = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,SDL_TEXTUREACCESS_TARGET, x, y); SDL_SetRenderTarget(_Renderer.get()->get(), this->texDefault.get()->get()); SDL_SetRenderDrawBlendMode(this->_Renderer.get()->get(),SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(this->_Renderer.get()->get(),255,0,255,0); SDL_RenderClear(this->_Renderer.get()->get()); //SDL_Rect rect={0,0,Width,Height}; //SDL_SetRenderDrawColor(this->_Renderer.get()->get(),255,255,255,255); //SDL_RenderFillRect(this->_Renderer.get()->get(),&rect); //SDL_RenderClear(this->_Renderer.get()->get()); //SDL_SetRenderDrawBlendMode(this->_Renderer.get()->get(),SDL_BLENDMODE_NONE); SDL_SetRenderTarget(_Renderer.get()->get(), NULL); SDL_Rect rect= {relTop+Top,relLeft+Left,Height,Width}; SDL_SetRenderDrawBlendMode(this->_Renderer.get()->get(),SDL_BLENDMODE_BLEND); SDL_RenderCopy(this->_Renderer.get()->get(), this->texDefault->get(), NULL, &rect);
This code is always producing nontransparent Texture independenty what i will set for blending and alpha
The result is :
Maybe there is some other simple method to create transparent empty texture in SDL2 something like x/y-sized fully transparent png but loading having such image in file is little bit pointless :/
- First, you need to set renderer blend mode:
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
. - Second, you need to set texture blend mode:
SDL_SetTextureBlendMode(textures[i], SDL_BLENDMODE_BLEND);
.
Here is working example I created. You can use keys A and S to change alpha channel of third texture, which is invisible at start of the application.
#include <iostream> #include <vector> #include <SDL.h> void fillTexture(SDL_Renderer *renderer, SDL_Texture *texture, int r, int g, int b, int a) { SDL_SetRenderTarget(renderer, texture); SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, r, g, b, a); SDL_RenderFillRect(renderer, NULL); } void prepareForRendering(SDL_Renderer *renderer) { SDL_SetRenderTarget(renderer, NULL); SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); } void checkSdlError() { const char *sdlError = SDL_GetError(); if(sdlError && *sdlError) { ::std::cout << "SDL ERROR: " << sdlError << ::std::endl; } } int main(int argc, char *argv[]) { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_HAPTIC); SDL_Window *window = SDL_CreateWindow("SDL test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, SDL_WINDOW_OPENGL); SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); const int width = 50; const int height = 50; ::std::vector<SDL_Texture*> textures; SDL_Texture *redTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); textures.push_back(redTexture); SDL_Texture *greenTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); textures.push_back(greenTexture); SDL_Texture *purpleTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height); textures.push_back(purpleTexture); // Here is setting the blend mode for each and every used texture: for(int i = 0; i < textures.size(); ++i) { SDL_SetTextureBlendMode(textures[i], SDL_BLENDMODE_BLEND); } int purpleAlpha = 0; fillTexture(renderer, redTexture, 255, 0, 0, 255); fillTexture(renderer, greenTexture, 0, 255, 0, 128); fillTexture(renderer, purpleTexture, 255, 0, 255, purpleAlpha); prepareForRendering(renderer); bool running = true; while(running) { SDL_Rect rect; rect.w = width; rect.h = height; SDL_RenderClear(renderer); rect.x = 50; rect.y = 50; SDL_RenderCopy(renderer, redTexture, NULL, &rect); rect.x = 75; rect.y = 70; SDL_RenderCopy(renderer, greenTexture, NULL, &rect); rect.x = 75; rect.y = 30; SDL_RenderCopy(renderer, purpleTexture, NULL, &rect); SDL_RenderPresent(renderer); // Process events { SDL_Event event; while(SDL_PollEvent(&event) == 1) { if(event.type == SDL_QUIT) { running = false; } else if(event.type == SDL_KEYDOWN) { switch(event.key.keysym.sym) { case SDLK_ESCAPE: running = false; break; case SDLK_a: purpleAlpha = ::std::max(purpleAlpha - 32, 0); fillTexture(renderer, purpleTexture, 255, 0, 255, purpleAlpha); prepareForRendering(renderer); ::std::cout << "Alpha: " << purpleAlpha << ::std::endl; break; case SDLK_s: purpleAlpha = ::std::min(purpleAlpha + 32, 255); fillTexture(renderer, purpleTexture, 255, 0, 255, purpleAlpha); prepareForRendering(renderer); ::std::cout << "Alpha: " << purpleAlpha << ::std::endl; break; } } } checkSdlError(); } } for(int i = 0; i < textures.size(); ++i) { SDL_DestroyTexture(textures[i]); } textures.clear(); SDL_DestroyRenderer(renderer); renderer = NULL; SDL_DestroyWindow(window); window = NULL; SDL_Quit(); checkSdlError(); return 0; }
EDIT: Completely rewritten the answer, original one basically contained blend mode of renderer.