Rendering texture->texture with alpha

Yay! Just been approved, now I can post :slight_smile:

So, here’s my problem - I’m trying to get a fog-of-war effect by doing:

  • render the background
  • render the fog to a texture, calculating on a tile-basis every frame
  • render the fog on top of the background
  • render …

The fog is supposed to be black by default (RGBA=0,0,0,255) and I’m tiling the fog texture with “grey fog” (i.e.: RGBA=0,0,0,0->255) then copying the fog texture over the background in the main renderer… The code below is slightly simplified to get rid of non-relevant logic, but still exhibits the same problem

Code:

  • (void) renderAt:(SDL_Rect)screen withPCs:(NSArray *)pcs
    {
    _box.x = 32 * (screen.x / 32);
    _box.y = 32 * (screen.y / 32);

    SDL_SetRenderTarget(_renderer, _fogMap);
    SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);

    SDL_SetRenderDrawColor(_renderer, 0x00, 0x00, 0x00, 0x00);
    SDL_RenderClear(_renderer);

    SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
    for (int y=0; y<_box.h; y += 32)
    for (int x=0; x<_box.w; x += 32)
    {
    SDL_Rect src = (SDL_Rect){0,0,32,32};
    SDL_Rect dst = (SDL_Rect){x, y, 32, 32};
    SDL_RenderCopy(_renderer, _tiles, &src, &dst);
    }
    SDL_SetRenderTarget(_renderer, NULL);

    SDL_Rect src = (SDL_Rect){screen.x%32, screen.y%32, _screenSize.w, _screenSize.h};
    SDL_Rect dst = (SDL_Rect){0, 0, _screenSize.w, _screenSize.h};
    SDL_RenderCopy(_renderer, _fogMap, &src, &dst);
    }

So with the above, all I see on the screen is black, over which subsequent renders to the main target (the screen) render fine. Basically I don’t see any background at all.

If I change the initial call to SDL_SetRenderDrawColor() to be

Code:

SDL_SetRenderTarget(_renderer, _fogMap);
SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_NONE);

SDL_SetRenderDrawColor(_renderer,[color=red]0xff, 0xff, 0xff[/color], 0x00);
SDL_RenderClear(_renderer);

… then I see the tile that I’m rendering in the loop appear, as expected, but I’m still not seeing anything behind the stamped 32-by-32 tile when I render this texture on top of the background at the last line in the code snippet.

To clarify - I can see the render (“SDL_RenderCopy(_renderer, _fogMap, &src, &dst);”) happening but instead of whatever is behind the texture (my carefully prepared background texture) showing through where the alpha is non-unity, all I see is the ‘_fogMap’ texture, no background. In other words the fog seems to be replacing the background, not blending with it.

I’m reasonably sure the textures that make up the tiles I’m blitting in the inner loop have alpha because if I put a white background behind them, the areas with lower alpha in the tile show brighter (I basically rendered a gaussian spot in the center of the tile, with the center alpha “darkest” in the tile, meaning it should show through the background more than the surrounds, and I see a whole bunch of circular spots on the screen when the background is white).

So I’m presumably doing something wrong. Alpha blitting is working when I blit the tiles into the fog texture (which is also texture-to-texture) so I don’t see why it ought not work when I blit from the fog-texture to the main renderer. The only difference I can see between the fog texture and any other is that it has been created with SDL_TEXTUREACCESS_TARGET on it…

Code:

  • (BOOL) createScreenWithRenderer:(SDL_Renderer *)renderer
    inWindow:(SDL_Window *)window
    {
    uint32_t format;
    BOOL ok = NO;
    _renderer = renderer;
    _window = window;

    SDL_GetWindowSize(window, &_screenSize.w, &_screenSize.h);
    _box.w = _screenSize.w + 64;
    _box.h = _screenSize.h + 64;

    format = SDL_GetWindowPixelFormat(window);

    _fogMap = SDL_CreateTexture(_renderer, format, SDL_TEXTUREACCESS_TARGET, _box.w, _box.h);
    if (_fogMap)
    ok = YES;
    else
    NSLog(@“Cannot create fog-of-war screen texture\n”);

    _surface = SDL_ConvertSurfaceFormat([_alpha surface], format, 0); // ‘_alpha’ contains the fog texture tiles set at 32x32 each
    _tiles = SDL_CreateTextureFromSurface(renderer, _surface);

    return ok;
    }

So, any ideas on what I’m doing wrong ?

Cheers
Simon

No bites, huh ?

Ok,well, if it’s not easy to do with standard SDL2, it’s sort of feels like this is something I ought to be able to do by writing a shader to do it (and in fact I’d be able to get better results because I’d not have to do the tiling effect, I’d be able to do it “properly”.

The shader would need to basically do:

Code:

  • take background image texture as input A

  • take alpha-stamp image texture as input B

  • set a threshold alpha for ‘we’ve seen this pixel before but it’s not in the field of view any more’

  • Convolve the alpha-stamp over the alpha-value for the background texture around the character thusly:

    if (A:alpha < B:alpha)
    else
    {
    if (B:alpha < threshold)
    else
    }

Which (off the top of my head :slight_smile: ) should let me walk the character around, altering the alpha of the background image such that if an area of the map has been fully seen (the character was close to that pixel), it’s alpha is at least (say) 0xa0 and otherwise it’s defined by the alpha of what the character can see in his/her immediate vicinity.

I’ve written stuff like this for open CL, but not written any open GL shaders before, so I’ll have to bone up on how you actually get a program to run over a texture or two. I’ve been digging around, and come across SDL_GPU which looks like it gives me a standard way to write GPU programs, but it looks as though it sort of takes over the rendering completely, so I’d have to re-write the rendering stuff I already have. Maybe not a problem, but worth noting.

Are there any good tutorials of how to get SDL_GPU to interact with textures using shaders ? Or any applications with open code that do the same ?

Cheers
SimonA:alpha = B:alpha
A:alpha = threshold
A:alpha = B:alpha

No bites, huh ?

Ok,well, if it’s not easy to do with standard SDL2, it’s sort of feels like
this is something I ought to be able to do by writing a shader to do it (and
in fact I’d be able to get better results because I’d not have to do the
tiling effect, I’d be able to do it “properly”.

The shader would need to basically do:

Code:

  • take background image texture as input A
  • take alpha-stamp image texture as input B
  • set a threshold alpha for ‘we’ve seen this pixel before but it’s not in
    the field of view any more’
  • Convolve the alpha-stamp over the alpha-value for the background texture
    around the character thusly:

if (A:alpha < B:alpha)
else
{
if (B:alpha < threshold)
else
}

Which (off the top of my head :slight_smile: ) should let me walk the character around,
altering the alpha of the background image such that if an area of the map
has been fully seen (the character was close to that pixel), it’s alpha is
at least (say) 0xa0 and otherwise it’s defined by the alpha of what the
character can see in his/her immediate vicinity.

I’ve written stuff like this for open CL, but not written any open GL
shaders before, so I’ll have to bone up on how you actually get a program to
run over a texture or two. I’ve been digging around, and come across SDL_GPU
which looks like it gives me a standard way to write GPU programs, but it
looks as though it sort of takes over the rendering completely, so I’d have
to re-write the rendering stuff I already have. Maybe not a problem, but
worth noting.

Are there any good tutorials of how to get SDL_GPU to interact with textures
using shaders ? Or any applications with open code that do the same ?

Cheers
Simon

Complete shot in the dark, but have you tried setting the blend mode
on your fog textures too? e.g.
SDL_SetTextureBlendMode(the_texture, SDL_BLENDMODE_BLEND);

FYI, I’m developing a new SDL based SDK called Blurrr. It includes a
lot of pre-built binaries, including SDL_gpu. I’ve been working on a
few examples for SDL_gpu. I have one semi-elaborate one, but it is not
finished. Check out blurrrsdk.com and look for the Quick Introduction
video. You’ll spot the SDL_gpu example pretty easily. The SDK is still
in prelaunch, but I’m looking for early adopters/testers. So if you
(or anybody reading this) is interested, please feel free to contact
me.

Thanks,
EricOn 2/8/16, SpacedCowboy <simon.gornall at mac.com> wrote:

  A:alpha = B:alpha
  	A:alpha = threshold
  	A:alpha = B:alpha

In the end, I wrote it using OpenCL. The function turned out to be more involved than I originally thought - there are two smoothing curves to apply, one to when the “light” should fade to black, and one to when it fades to the “place I’ve been before but is currently out of view”.

There’s more I want to do on the GPU as well (routing for one, A* is slow on large maps using a CPU) so biting the bullet and putting the renderer in OpenCL seemed logical. It provides quite a nice separation between the OpenCL and OpenGL stages as well, so there’s not too many issues with interop or syncing. Here’s a screenshot of what it looks like atm…

[Image: http://i.imgur.com/n1QtLae.png ]

What I’m focussed on right now is writing a tool to help make the large map tiles. The idea is to start off with a basic (say, grass) texture, and allow thresholding of various profiles (eg: Perlin noise) to define how other textures can be overlaid, also adding an alpha/1-alpha blend to the edges of that threshold and defining a region within which it operates. The next stage is to then define bezier paths to “stamp” a texture along, again using blend functions towards the edge, and eroding the “stamp” texture to provide variability along the path. I think I can get pretty far with those two to making a kick-ass background, over which the usual suspects (trees, stones, water etc.) can be alpha-blended.

The map tool will also generate the moveability map, which lets the router know where characters can move, and the icing on the cake is that it will actually write out a lua script to represent the map - which means it’ll be editable and customisable in code. I’m putting quite a bit of effort into this because I think there’ll be a lot of outdoor maps in my game, and I want the graphics to be top-notch :slight_smile:

Cheers though,

Simon.

In the end, I wrote it using OpenCL. The function turned out to be more involved than I originally thought - there are two smoothing curves to apply, one to when the “light” should fade to black, and one to when it fades to the “place I’ve been before but is currently out of view”.

There’s more I want to do on the GPU as well (routing for one, A* is slow on large maps using a CPU) so biting the bullet and putting the renderer in OpenCL seemed logical. It provides quite a nice separation between the OpenCL and OpenGL stages as well, so there’s not too many issues with interop or syncing. Here’s a screenshot of what it looks like atm…

[Image: http://i.imgur.com/n1QtLae.png ]

What I’m focussed on right now is writing a tool to help make the large background maps. The idea is to start off with a basic (say, grass) texture, and allow thresholding of various profiles (eg: Perlin noise) to define how other textures can be overlaid, also adding an {alpha/1-alpha} blend to the edges of that threshold and defining a region within which it operates. The next stage is to then define bezier paths to “stamp” a texture along, again using blend functions towards the edge, and eroding the “stamp” texture to provide variability along the path. I think I can get pretty far with those two to making a kick-ass background, over which the usual suspects (trees, stones, water etc.) can be alpha-blended. I’m no artist, but I can draw paths and blend data :slight_smile:

The map tool will also generate the moveability map, which lets the router know where characters can move, and the icing on the cake is that it will actually write out a lua script to represent the map - which means it’ll be editable and customisable in code. I’m putting quite a bit of effort into this because I think there’ll be a lot of outdoor maps in my game, and I want the graphics to be top-notch :slight_smile:

Cheers though,

Simon.

Whoops - sorry for the double post. I can’t seem to delete the 1st one though…

Welcome to the forums Spaced. You have to be a bit patient with replies on here, as it’s a fairly casual forum. Most of the time you wont get any reply.

Your fog of war looks great! This is something I’d like to solve using the 2D alpha texture routines - it is possible.