fog question

Hello,

is anyone of you able and willing to explain how to do simple OpenGL fog when using ARB_vertex_program and NV_fragment_program? I read the specs and tried several things but nothing produced anything fog-like .

Standard OpenGL fog parameters like FOG_START, FOG_END and FOG_MODE are set to appropriate values and the fog looks perfectly fine when disabling vertex and fragment programs, and now it should look similar when using vertex and fragment programs.

Thanks…
Jan

Vertex program:

TEMP eye;
DP4 eye.z, state.matrix.modelview[0].row[2], v0;
ABS result.fogcoord.x, eye.z;

Fragment Program:

TEMP fogFactor;
ADD fogFactor.x, state.fog.params.z, -fragment.fogcoord;
MUL_SAT fogFactor.x, fogFactor.x, state.fog.params.w;
LRP result.color, fogFactor.x, fragment.color, state.fog.color;

[This message has been edited by jra101 (edited 03-01-2004).]

thanks but what is v0 in the vertex program? simply the vertex position?

and something like state.fog.params doesn’t seem to exist in NV_fragment_program, so use a program local parameter for this instead?

[This message has been edited by JanHH (edited 03-01-2004).]

Oops, ya, that should be vertex.position.

Originally posted by JanHH:
something like state.fog.params doesn’t seem to exist in NV_fragment_program, so use a program local parameter for this instead?

Yes, you’ll need to use a parameter for this.

jra101’s example was for linear fog (ie, GL_LINEAR fog mode).

As it’s name implies, linear fog is linear. Other types of fog such as exponential fog (GL_EXP) or exponential squared fog (GL_EXP2) are non-linear.

As an optimization, linear fragment math can be “lifted” to the vertex program.

In this case, you can move the ADD and MUL (but not the _SAT) operations into the vertex program. You’ll also want to combine the ADD and MUL into a MAD. Better yet, you can fold the MAD into the DP4 (because these are all linear operations).

This takes more work; you can’t just use the state.matrix.modelview[0].row[2] as shown above because you’d have to combine the fog start and end parameters into this float4.

You also do NOT want to perform the ABS at the per-vertex level. You want it done at the per-fragment level! Absolute value is NOT a linear operation. Think about what happens for a triangle where two vertices have a negative fog coordinate but the other one has a positive fog coordinate. The fog coordiante should interpolate nicely between the values over the triangle.

Then your per-fragment ADD and MUL_SAT can just be done as MOV_SAT like this:

MOV_SAT R0.x, |fragment.fogcoord|;

Then do the LRP:

LRP result.color, R0.x, fragment.color, state.fog.color;

Do you need to “lift” the linear math into the vertex program? No, you don’t have to, but assuming you have fewer fragments than vertices, it can improve your performance. Does it may your program more complex. Sure, but you’ll have to decide if that performance is worth it for the extra effort.

I hope this helps.

  • Mark

I guess in the last paragraph what you mean is that I have more fragments than vertices!?

Sure this helps, thanks, but it seems to be more complex than I thougt.

Also I use NV_fragment_program and not ARB… this makes it even more complicated.

Jan

Also I use NV_fragment_program and not ARB… this makes it even more complicated.

It’s a little more annoying, but not all that compilcated.

fragment.fogcoord is f[FOGC] and fragment.color is f[COL0]. state.fog.color can be a program parameter, such as “DECLARE fog_color;” in your FP, and then call glProgramNamedParameter4fNV() to set its value to whatever the fog color is set to.

I tried to include the code from jra101 into my program and it doesn’t work (translated to NV_fragment_program with state.fog.params and state.fog.color as parameters).

I have to admit that I do not know certain things, most of all what a “fog coordinate” is. I guess it is something which depends on FOG_START, FOG_END and the position of the vertex compared to that. But if that would be the case, I could just use the fog coordinate (vertex.fogcoord as input paramter in the vertex program) and would not have to compute it on my own (like in jra101’s vertex program code)!?

And in which range ist the fog coord value? 0…1 or FOG_START…FOG_END? I guess, rather the latter?

thx in advance…

Jan

now it works… I just forgot to compile the program before runnig it sorry jra101…

I have to admit that I do not know certain things, most of all what a “fog coordinate” is. I guess it is something which depends on FOG_START, FOG_END and the position of the vertex compared to that.

There are two important terms when discussing OpenGL fog, the fog coordinate and the fog factor.

The fog coordinate is the “eye-coordinate distance from the eye, (0, 0, 0, 1) in eye coordinates, to the fragment center” (text taken from the OpenGl 1.5 spec). This is generally computed per-vertex and the interpolated value is available in the fragment pipeline.

You can approximate the fog coordinate by using the absolute value of the z component of the eye-coordinate position, which is what my snippet of ARB_vertex_program code does.

The fog factor is a value in the range [0…1] which is used to lerp between the fog color and the final fragment color. This value gets computed per-fragment (although for GL_LINEAR it can be computed in the vertex program as Mark described above).

How the fog factor gets computed from the fog coordinate is controlled by the fog mode (GL_LINEAR, GL_EXP, or GL_EXP2). The ARB_fragment_program code I posted computes a GL_LINEAR fog factor from the fog coordinate.

I could just use the fog coordinate (vertex.fogcoord as input paramter in the vertex program) and would not have to compute it on my own

You can only use vertex.fogcoord if you explicitely set it using the glFogCoord function.

[This message has been edited by jra101 (edited 03-03-2004).]