Rendering highlights on 2d map based on grayscale texture

Started by
2 comments, last by Kripke 11 years, 5 months ago
Hello,
Long time lurker, first time poster.

Using Java and LWJGL (2d), I am trying to render highlights on specific parts (areas) of a screen sized textured quad:

3VZfX.png?1




The areas are as you can see irregular and further defined by another image, grayscale, where each area has a unique color value:

TvKkv.png?1

The purpose is to through the gray scale image and a variably sized collection of grayscale color values (e.g byte[] barr = {56, 59, 61, 46, 51}), specify what areas that should be highlighted.

I have something that works somewhat, using shaders, but is horribly slow.

It involves sending an array with the areas (gray scale color values) I want highlighted to the shader, setting the color of those areas to for instance green in the shader, and the rest to alpha 0, iterating over the array with a for-loop.

When the shader is done, a screen sized quad is rendered, alpha blended with the original color map. This gives the result I want but suffers greatly from increasing the size variable. Highlighting 50 areas gives a framerate of ~5-10.

The fragment shader looks something like this:

[source lang="cpp"]
uniform sampler2d texture;
uniform int size;
uniform float cols[100];

void main()
{
vec4 pixel = texture2d(texture,vec2(pos));

for(int i = 0; i < size; i++)
{
if(pixel.r == (1.0/255.0) * cols)
{
// set color to transparent green
break;
}
else
{
// set color to invisible
}
}
}
[/source]


It seems as the for-loop is the culprit, looping over 1 element for instance is ok, but still slow.
Another way would be to create a 1d texture instead of an array to send to the shader, but I guess I still would need to loop over the texels of that texture and do the comparison. Or is it possible to check if the pixel's color "exists" in the 1d texture/array? Is there another way of going about this effect with or without shaders? Some fancy blending technique?

Any ideas would be very welcome, and let me know if you need any more information.
Advertisement
Didn't really put much thought into it, but are you sure the culprit is the loop and not the if/else? I know there's a function that lets you choose between two values based on a condition (avoiding the if/else structure), though I can't remember its name right now.

Also I'm wondering, what do you need the loop for? Can't you just check if the relevant color for that texel in the array is set, or am I missing something? That'd be just one check per pixel and you avoid iterations completely.
Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.
Either use a 1d texture or a binary-float array, but don't use it as list of indicies (list = 1,3,5...) instead use it as binary array (value = 1, if area of index is highlighted, else 0):
float area_highlighted[MAX_AREAS] = {1,0,0,1,0,0...} ;


uniform sampler2d texture;
uniform int size;
uniform float area_highlighted[100];

void main()
{
vec4 pixel = texture2d(texture,vec2(pos));

// scale to index
float index = floor(pixel.r*128.0);
float highlighted = area_highlighted[index];
}


Thanks for the input!

I don't see why that wouldn't work and why I didn't think of it :) I will tinker a bit and get back!

This topic is closed to new replies.

Advertisement