我正在尝试SDL2,遇到一种情况,当我在中间透明纹理上绘制时无法正确处理。
我要融合的图像:
255
,128
或0
因此,如果我将其表示为图层,则如下所示
img_w_A_channel img_w_A_channel img_w_A_channel img_w_A_channel
solid_texture half_transparent transparent_texture
window window window window
solid_texture
表示带有alpha=255
的黑色中间纹理,在其中绘制图像,然后在窗口上绘制纹理。 half_transparent
表示带有alpha=128
的黑色中间纹理,在其中绘制图像,然后在窗口上绘制纹理。 transparent_texture
表示带有alpha=0
的黑色中间纹理,在其中绘制图像,然后在窗口上绘制纹理。 因此,请考虑将中间纹理作为我要绘制的容器。由于窗口可以具有此处的背景纹理,因此SDL_BLENDMODE_NONE
不是中间纹理的选项。
结果是:
如您所见,第一张和第二张图像(在固体中间纹理上绘制的是相同的)。 第三和第四张图像(绘制在半透明和透明的中间纹理上)不同。
问题出在右边的图像上。我希望结果与左侧的图像匹配。即能够在透明容器中绘制并获得与直接在窗口上绘制相同的结果。
我的完整测试代码是:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *background = NULL;
SDL_Texture *image = NULL;
SDL_Surface* surface = NULL;
SDL_Rect dst = {20, 20, 100, 100};
#define SOLID 255
#define HALF_TRANSPARENT 128
#define TRANSPARENT 0
SDL_Texture * renderImageInATexture(SDL_Texture *image, Uint8 transparency) {
// Create an intermediate texture
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 200, 200);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(renderer, texture);
// Paint it
SDL_SetRenderDrawColor(renderer, (Uint8) 0, (Uint8) 0, (Uint8) 0,(Uint8) transparency);
SDL_RenderClear(renderer);
// Render the image in intermediate texture
SDL_SetRenderTarget(renderer, texture);
SDL_RenderCopy( renderer, image, NULL, &dst );
SDL_SetRenderTarget(renderer, NULL);
return texture;
}
int main(char *argc, char **argv) {
SDL_Init( SDL_INIT_VIDEO);
window = SDL_CreateWindow("Win", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
800, 200, SDL_WINDOW_SHOWN);
// So we can save into pngs to check the value
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetRenderTarget(renderer, NULL);
// Fill the window with a texture for fun (doesn't change anything on the problem) can be removed ....
surface = IMG_Load( "./carbone.png" );
background = SDL_CreateTextureFromSurface( renderer, surface );
SDL_FreeSurface( surface );
// draw background in main display
SDL_RenderCopy( renderer, background, NULL, NULL );
// .... until here
surface = IMG_Load( "./image.png" );
image = SDL_CreateTextureFromSurface( renderer, surface );
SDL_FreeSurface( surface );
// draw imagein main display
SDL_RenderCopy( renderer, image, NULL, &dst );
SDL_Texture *texture = renderImageInATexture(image, SOLID);
// render intermediate texture in main display
SDL_Rect dstTexture = {200, 0, 200, 200};
SDL_RenderCopy( renderer, texture, NULL, &dstTexture );
SDL_Texture *texture2 = renderImageInATexture(image, HALF_TRANSPARENT);
// render intermediate texture2 in main display
SDL_Rect dstTexture2 = {400, 0, 200, 200};
SDL_RenderCopy( renderer, texture2, NULL, &dstTexture2 );
SDL_Texture *texture3 = renderImageInATexture(image, TRANSPARENT);
// render intermediate texture3 in main display
SDL_Rect dstTexture3 = {600, 0, 200, 200};
SDL_RenderCopy( renderer, texture3, NULL, &dstTexture3 );
SDL_RenderPresent(renderer);
SDL_Delay(10000);
SDL_DestroyTexture(image);
SDL_DestroyTexture(bakcground); // only if you use a background
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
并进行构建:
cc main.c -lSDL2 -lSDL2_image
内置SDL 2.0.8,但这没关系。
有解决此问题的主意吗?
**编辑**
所以我根据@aram的答案替换来修改了renderImageInATexture()
函数:
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
作者:
SDL_BlendMode mode = SDL_ComposeCustomBlendMode(1, 1,
SDL_BLENDOPERATION_ADD,
1, 1,
SDL_BLENDOPERATION_ADD);
SDL_SetTextureBlendMode(texture, mode);
我还直接在上面的先前代码中更改了初始化,以便能够按照@aram的建议保存屏幕。但是我必须使用SDL_RENDERER_ACCELERATED
来阻止not supported operation
上的SDL_ComposeCustomBlendMode()
通话。
无论如何,我收到一条Surface doesn't have a colorkey
消息。有问题吗?
但是看来SDL_ComposeCustomBlendMode()
仍然不是解决方案。
首先,尽管背景图片并不重要,因为通过我的测试,无论有没有背景图片,我都能得到相同的结果。
不幸的是,如果@aram的答案给我的结果与以实心的中间纹理渲染图像时的结果相同: