environmental mapping

At the moment i use for environmental mapping GL_ADD_SIGNED, which yields to pretty good results.

However i was wondering if there is a possibility to control how much the environment gets reflected. For example an iron object reflects the surrounding quite perfect, but sheet metal (if that´s the word), like a dirty car reflects the surrounding not that good. So from the car you would see mainly its texture and the environment gets only lightly reflected.

Is there a way to do this? Maybe using the primary/secondary color to influence the reflection?
But i have to admit, that i don´t know much about extensions like texture_env_combine. If someone knows of a good tutorial about this extension i would be happy already.

Thanks.
Jan.

Well, if you’re using fragment shaders it would be a simple problem to solve, but it seams you’re not. You could for instance use the interpolation operation in tex_env_combine to interpolate between a base color and environment map.

Hi,

You could, in the first stage, interpolate between the enviroment map and a constant (0.5, 0.5, 0.5) color. The less reflection, the more gray. Then in the second stage ADD_SIGNED it to the base texture. You can store interpolation factor and the gray color in a constant using glTexenvfv.

I’d use ADD instead of ADD_SIGNED, after all, reflections never remove light… And you could just modulate the reflection instead of interpolating, making the combiner setup a little easier. If your material looks too bright, just dim the diffuse texture. But if it works for you, do whatever looks good.

-Ilkka

ADD_SIGNED sounds wrong. A reflection really is just additional light, so ADD would be the appropriate operation.

If you’re using register combiners or some similar function (or ARB_fragment_program) you can scale the environment map output by using a multiply by some constant.

If you’re on classic hardware, you probably have to apply environment map as a second pass, using MODULATE for the environment map, and GL_ONE,GL_ONE for the blend function, and send brightness in as a color value.

Last, you can get the environment to be more fuzzy if you provide MIP maps for your cube map, and use the LOD bias.

At the moment i am trying to find out how texture_env_combine works. I would like to get it work with no additional extensions. However i have 4 texture units free for use.

I would really appreciate it, if one of you could show me how this could be done with the texture_env_combine extension, cause at the moment i still have some trouble understanding how all those sources and operands work together, so i would have a small example, which i can examine.

Jan.

I use the following (but I must admit I can’t remember what level of testing I have done and how successful it will be - perhaps I’ll look into it on the w’end)

glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);

glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_REPLACE);
glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT);

glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_CONSTANT_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT);
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE);
glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT);

glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_COLOR);
glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);

if (utilGlobal.bFullChrome)
{
fCol[0] = fCol[1] = fCol[2] = fCol[3] = 1.0f;
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fCol);
}
else
{
fCol[0] = fCol[1] = fCol[2] = fCol[3] = materials[0].reflectivity;
glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, fCol);
}

PS. Anyone else noticed how just about every question these days has at least one answer stating “You could do it with an fp”?

[This message has been edited by rgpc (edited 04-23-2003).]

rgpc,

The problem is that you’re using INTERPOLATE. What we really want for texture environment application is Out = Prev + Texture * Scale, which isn’t actually available as a texture environment function in unextended OpenGL. Boo-hoo!

It’s too bad that the fixed-function pipe defines a flow which is strictly from interpolation to tex0, to tex1, to tex2, to tex3, with no way of combining them in any other order, and there are a few useful functions missing (Arg0Arg2 + Arg1Arg3 for example, which could be used to emulate this by setting A2 to 1).

Yes, it’s interesting how everything you want to do can be done with a fragment program. That’s what the whole thing about fragment programs is about :wink:

Well THAT yields to exactely the result i wanted to have. Thanks very much.

But now i run into another problem - state changes. My engine draws geometry front to back. It batches all polys together and calls DrawElements when another texture has to be bound. Now it also flushes this cache when env mapping has to be enabled/disabled. And NOW it also has to flush the cache, when the constant color changes, resulting in real small batches, that are sent to the card. Any idea how i could work around that?

Jan.

Originally posted by jwatte:
What we really want for texture environment application is Out = Prev + Texture * Scale, which isn’t actually available as a texture environment function in unextended OpenGL. Boo-hoo!

Where do you draw the line of “unextended”? Unextended OpenGL 1.3 has multitexturing (and texture_env_combine - better than EXT_texture_env_combine, in line with ARB_texture_env_combine, if I remember correctly), which usually gives you the possibility to split an expression onto two different texture units. E.g. OUT = AB+C can be OUT1 = AB, OUT2 = OUT1 + C.

I admit I have not looked too hard at this specific problem, but it does not seem impossible.