SDL2: Generate fully transparent texture

匿名 (未验证) 提交于 2019-12-03 02:56:01

问题:

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 :/

回答1:

  • 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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!