'Ghosting' objects using the stencil buffer?

I’m trying to put together a relatively simple isometric-perspective game, and I’d like the ability to ‘ghost out’ various portions of the screen as part of UI feedback. Specifically, when the player is trying to place a specific building, I’d like to have the building-preview (and possibly underlying terrain) turn red or green depending on whether it’s over a legal or illegal location.

As in, for every pixel corresponding to the elements in question, I’d average the RGB components, and then set either R, G or B to that exact value (with 0 in other components.) How would I go about this?

You might want to look into shaders. I just did yesterday and I wrote an Opacity(changes the transparency of textured objects) shader.


If that isn’t what you mean then I don’t quite understand what your asking?

Well, I mean imagine a standard RTS, where you’re placing a new building- the little image of the building will turn different colours depending on where you’re trying to put it. I’m almost certain you wouldn’t need a vertex shader for something like this, since I saw this effect back 10-15 years ago.

I’d imagine you could use different textures for them,
or perhaps blending different textures say(a red texture + original texture)

Shader’s aren’t as ugly as they sound, I just found that out.

I’m sure you don’t NEED a shader, but it is very practical, in my opinion. Just load the shader to change the color balance of the texture, if it is picked/under mouse, or selected, then unload it after.

If there’s another way to achieve this effect in JOGL(OpenGL even) I’d be interested as well. However, I’ve googled for probably 15(collectively) hours to find an alternative to shaders using JOGL for changing the color balance of a textured object, and came up with nothing.

I’m actually about to write a shader for this for practice and possibly for my own personal project, if you’d like I could post the code here?

And just as a little side-note… If you’ve seen that effect 15 years ago, I gaurantee you DO NOT want to structure your code/game in a similar method. The complexity of it would be mind numbing and beyond fruitless for the hours put in versus the product received. Maybe I’m biased but I believe using a shader has to be better then down-stepping technology to below OpenGL 1.3(when I believe GLSL was invented/implemented).

http://www.opengl.org/wiki/Texture_Combiners

I wrote the code for that shader, if you want it just post back sometime tommarrow. Otherwise I’m not going to use my time posting it.

Well, I’m almost certain there’s some way to do this without shaders, but I guess it wouldn’t hurt to take a look. So, sure, please…

If by “practical” you mean “won’t work on the majority of laptop computers” then yes, using a shader is practical.

For a non-shader approach it depends exactly what effect you’re after. If you just need the “can place”/“can’t place” feedback then just changing the vertex colours will multiply the texture by the vertex colour so a light green or red will give the sprite a green or red appearence (but with the side effect of making it darker too, since you’re multiplying).

Alternatively you can use glTexEnv with DOT3 to make your sprite greyscale, or SECONDARY_COLOR to tint a sprite towards a specific colour. Both of which will work on pretty much any hardware still in use today.

Orangy Tang knows what hes talking about. So I guess you might not wanna use a shader. But if you do for whatever reason, here’s the code:(Fragment shader)


uniform sampler2D BaseImage;
uniform float ColorR;
uniform float ColorG;
uniform float ColorB;
uniform float ColorA;
void main (void) {
vec4 base = texture2D(BaseImage, gl_TexCoord[0].xy);
gl_FragColor = vec4(base.r * ColorR, base.g * ColorB, base.b * ColorB, base.a * ColorA);
}

VertexShader


void main (void) {
gl_TexCoord[0] = gl_MultiTexCoord0;
}

I didn’t know most labtops didn’t support GLSL :(, thats a bummer. I guess I’m lucky mine does!

[quote]Alternatively you can use glTexEnv with DOT3 to make your sprite greyscale, or SECONDARY_COLOR to tint a sprite towards a specific colour. Both of which will work on pretty much any hardware still in use today.
[/quote]
Thanks a lot. That sounds exactly like what I need. :slight_smile:

And thanks for the shader code too.

How, exactly, would I use glTexEnv with DOT3 again? I mean, what’s the precise syntax? Are you talking about generating a secondary texture?

I’m afraid the technique you suggested doesn’t work… after some experimentation, I managed to get the following results:

http://img13.imageshack.us/img13/982/greycompare.png

The problem is that the GL_DOT3_RGB formula goes like this:

4 × (((A0 r - 0.5) × (A1 r - 0.5)) + ((A0 g - 0.5) × (A1 g - 0.5)) + ((A0 b - 0.5) × (A1 b - 0.5)))

It’s the “-0.5f” all over the place that ruins it. Basically, any RGB values less than 50% just disappear. What I need is:

(A0 r x A1 r) + (A0 g x A1 g) + (A0 b x A1 b)

…also, GL_COMBINE seemed to eliminate normal lighting calculations, which is not what I’m looking for…

I might be a bit off mark here, but is this the sort of effect you’re looking for:

http://www.cokeandcode.com/demos/thevillage/village4.png

The green house in the upper left is in a valid location so could be placed by the user. If so, arn’t vertex colours set with the colour and non-1 alpha enough?

Kev

If your object has a blue-ish texture, and you set vertex-colors to green, you end up with black…

You can look into HSL and change the texture (…slowww…) and set the Hue to green for every pixel.

:persecutioncomplex:

[quote]If your object has a blue-ish texture, and you set vertex-colors to green, you end up with black…
[/quote]
Yep, but that doesn’t actually look bad - see the corner dark wood on the house above. It’s down to what they’re trying to achieve in game (rather than in the head).

Kev

Wouldn’t it be easiest to:

  1. render the item to the stencil buffer
  2. render it for real
  3. render a semi-transparant red/green quad using the ‘shape’ in the stencil buffer

No shaders, and it looks perfect, as there is a colored haze over the item, independant of the item’s texture - even a totally black item would end up red-ish or green-ish.

This might sound dumb but what if you multi-textured it and made a screen-texture for the second texture
something like this but instead of black the colors you wanted,

Just trying to think outside of the box.

If you’re just looking to tint a texture then SECONDARY_COLOR is a better option IMHO. Whereas vertex colours multiply the texture colour with an additional colour, secondary colour can be added on top - so you can either brighten a texture or shift it’s hue towards a specific colour (including rendering a sprite as pure white, which can be very useful for masking effects).

IIRC you need something like:


// General state
GL11.glEnable(GL14.GL_COLOR_SUM);

// Vertex array state
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glEnableClientState(EXTSecondaryColor.GL_SECONDARY_COLOR_ARRAY_EXT);

// Vertex data
GL11.glColorPointer(4, stride, data);
EXTSecondaryColor.glSecondaryColorPointerEXT(3, stride, data);

The result is
fragment colour = (texture colour * vertex colour) + secondary colour

Now if you wanted to tint towards purple at 80% then you set that as your secondary colour (1, 0, 1), and set the primary vertex colour as (1 - tintAlpha, 1 - tintAlpha, 1 - tintAlpha, 1), in this case (0.2, 0.2, 0.2, 1).

This only requires a single draw call, and you don’t need a pesky stencil buffer either.

I’d forgotten about the pesky -0.5 in the DOT3 extension, stupid bumpmapping hacks. :stuck_out_tongue: However if you combine that with SECONDARY_COLOR above you could use that to add 0.5 onto your texture colour and hopefully eliminate the clamping.

However I’m not entirely sure what order those operations are done in, so you might find that the colours have already been clamped before the +0.5 gets applied.

[quote]I might be a bit off mark here, but is this the sort of effect you’re looking for:
[/quote]
Very similar, yes. (The screen looks nice, by the way- where’d you get it from?) I’ll use vertex colouring if push comes to shove, but I’m reasonably sure there must be some simple method for getting true greyscale, and then tinting toward a specific colour.

[quote]This might sound dumb but what if you multi-textured it and made a screen-texture for the second texture…
[/quote]
Oh, sure- you can manufacture luminance textures easily enough… I dunno. It just seems sort of like a waste of memory…

[quote]I’d forgotten about the pesky -0.5 in the DOT3 extension, stupid bumpmapping hacks. However if you combine that with SECONDARY_COLOR above you could use that to add 0.5 onto your texture colour and hopefully eliminate the clamping.

However I’m not entirely sure what order those operations are done in, so you might find that the colours have already been clamped before the +0.5 gets applied.
[/quote]
I’ll try and give that a shot and see what the results are, thanks. (Mind you, I’d be quite interested to know how DOT3 is used for bumpmapping. :slight_smile: )

It’s one of my previous projects, The Village, more screenies here http://www.cokeandcode.com/demos/thevillage/

The art mostly came from Reiners

Kev