Updated blend semantics so blending uses the following formula:
dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA)) dstA = srcA + (dstA * (1-srcA)) This allows proper compositing semantics without requiring premultiplied alpha. Needs full unit test coverage and bug fixes!
This commit is contained in:
parent
a99edf3519
commit
32188834b5
17 changed files with 362 additions and 1001 deletions
|
@ -87,6 +87,88 @@ LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
|
|||
return texture;
|
||||
}
|
||||
|
||||
void
|
||||
DrawComposite(DrawState *s)
|
||||
{
|
||||
SDL_Rect viewport, R;
|
||||
SDL_Texture *target, *A, *B;
|
||||
|
||||
static SDL_bool blend_tested = SDL_FALSE;
|
||||
if (!blend_tested) {
|
||||
SDL_Texture *A, *B;
|
||||
Uint32 P;
|
||||
|
||||
A = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 1, 1);
|
||||
SDL_SetTextureBlendMode(A, SDL_BLENDMODE_BLEND);
|
||||
|
||||
B = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, 1, 1);
|
||||
SDL_SetTextureBlendMode(B, SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_SetRenderTarget(s->renderer, A);
|
||||
SDL_SetRenderDrawColor(s->renderer, 0x00, 0x00, 0x00, 0x80);
|
||||
SDL_RenderFillRect(s->renderer, NULL);
|
||||
|
||||
SDL_SetRenderTarget(s->renderer, B);
|
||||
SDL_SetRenderDrawColor(s->renderer, 0x00, 0x00, 0x00, 0x00);
|
||||
SDL_RenderFillRect(s->renderer, NULL);
|
||||
SDL_RenderCopy(s->renderer, A, NULL, NULL);
|
||||
SDL_RenderReadPixels(s->renderer, NULL, SDL_PIXELFORMAT_ARGB8888, &P, sizeof(P));
|
||||
|
||||
printf("Blended pixel: 0x%8.8X\n", P);
|
||||
|
||||
SDL_DestroyTexture(A);
|
||||
SDL_DestroyTexture(B);
|
||||
blend_tested = SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_RenderGetViewport(s->renderer, &viewport);
|
||||
|
||||
target = SDL_CreateTexture(s->renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, viewport.w, viewport.h);
|
||||
SDL_SetTextureBlendMode(target, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderTarget(s->renderer, target);
|
||||
|
||||
/* Draw the background.
|
||||
This is solid black so when the sprite is copied to it, any per-pixel alpha will be blended through.
|
||||
*/
|
||||
SDL_SetRenderDrawColor(s->renderer, 0x00, 0x00, 0x00, 0x00);
|
||||
SDL_RenderFillRect(s->renderer, NULL);
|
||||
|
||||
/* Scale and draw the sprite */
|
||||
s->sprite_rect.w += s->scale_direction;
|
||||
s->sprite_rect.h += s->scale_direction;
|
||||
if (s->scale_direction > 0) {
|
||||
if (s->sprite_rect.w >= viewport.w || s->sprite_rect.h >= viewport.h) {
|
||||
s->scale_direction = -1;
|
||||
}
|
||||
} else {
|
||||
if (s->sprite_rect.w <= 1 || s->sprite_rect.h <= 1) {
|
||||
s->scale_direction = 1;
|
||||
}
|
||||
}
|
||||
s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
|
||||
s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
|
||||
|
||||
SDL_RenderCopy(s->renderer, s->sprite, NULL, &s->sprite_rect);
|
||||
|
||||
SDL_SetRenderTarget(s->renderer, NULL);
|
||||
SDL_RenderCopy(s->renderer, s->background, NULL, NULL);
|
||||
|
||||
SDL_SetRenderDrawBlendMode(s->renderer, SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(s->renderer, 0xff, 0x00, 0x00, 0x80);
|
||||
R.x = 0;
|
||||
R.y = 0;
|
||||
R.w = 100;
|
||||
R.h = 100;
|
||||
SDL_RenderFillRect(s->renderer, &R);
|
||||
SDL_SetRenderDrawBlendMode(s->renderer, SDL_BLENDMODE_NONE);
|
||||
|
||||
SDL_RenderCopy(s->renderer, target, NULL, NULL);
|
||||
SDL_DestroyTexture(target);
|
||||
|
||||
/* Update the screen! */
|
||||
SDL_RenderPresent(s->renderer);
|
||||
}
|
||||
|
||||
void
|
||||
Draw(DrawState *s)
|
||||
{
|
||||
|
@ -134,6 +216,7 @@ main(int argc, char *argv[])
|
|||
SDL_Event event;
|
||||
int frames;
|
||||
Uint32 then, now;
|
||||
SDL_bool test_composite = SDL_FALSE;
|
||||
|
||||
/* Initialize test framework */
|
||||
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
||||
|
@ -145,8 +228,17 @@ main(int argc, char *argv[])
|
|||
|
||||
consumed = SDLTest_CommonArg(state, i);
|
||||
if (consumed == 0) {
|
||||
fprintf(stderr, "Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state));
|
||||
return 1;
|
||||
consumed = -1;
|
||||
if (SDL_strcasecmp(argv[i], "--composite") == 0) {
|
||||
test_composite = SDL_TRUE;
|
||||
consumed = 1;
|
||||
}
|
||||
}
|
||||
if (consumed < 0) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s %s [--composite]\n",
|
||||
argv[0], SDLTest_CommonUsage(state));
|
||||
quit(1);
|
||||
}
|
||||
i += consumed;
|
||||
}
|
||||
|
@ -160,7 +252,11 @@ main(int argc, char *argv[])
|
|||
|
||||
drawstate->window = state->windows[i];
|
||||
drawstate->renderer = state->renderers[i];
|
||||
drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
|
||||
if (test_composite) {
|
||||
drawstate->sprite = LoadTexture(drawstate->renderer, "icon-alpha.bmp", SDL_TRUE);
|
||||
} else {
|
||||
drawstate->sprite = LoadTexture(drawstate->renderer, "icon.bmp", SDL_TRUE);
|
||||
}
|
||||
drawstate->background = LoadTexture(drawstate->renderer, "sample.bmp", SDL_FALSE);
|
||||
if (!drawstate->sprite || !drawstate->background) {
|
||||
quit(2);
|
||||
|
@ -181,7 +277,11 @@ main(int argc, char *argv[])
|
|||
SDLTest_CommonEvent(state, &event, &done);
|
||||
}
|
||||
for (i = 0; i < state->num_windows; ++i) {
|
||||
Draw(&drawstates[i]);
|
||||
if (test_composite) {
|
||||
DrawComposite(&drawstates[i]);
|
||||
} else {
|
||||
Draw(&drawstates[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue