PDA

View Full Version : ARB_vertex_program and the fog coordinate



Ysaneya
02-07-2004, 09:41 AM
I've got a vertex program doing geomorphing for my terrain. I just wanted to enable the FFP fog, but it obviously doesn't work as i'm using a vertex program. So i'm trying to replicate the FFP fog by the vertex program.

The spec. is unclear about how the fog coordinate is to be interpreted. On my Radeon 9700, it seems to expect a world space distance. For ex. if i set my fog mode to linear with a start distance of 1000 and an end distance of 2000, a vertex at a distance of 1500 will result in 50% fog. In consequence in my program i just feed in fogcoord.x the distance between the vertex and the camera, and fogging appears correctly.

Unfortunately the meaning seems to be different on NVidia cards. I haven't tested a lot, just saw that no fog appeared on a GF4 Ti 4600 with latest drivers. I'm suspecting they need the foog coord to be in the [0-1] range as a percentage directly.

Do i need to implement two seperate shaders just to fix that ?

Y.


[This message has been edited by Ysaneya (edited 02-07-2004).]

Zeno
02-07-2004, 01:30 PM
I can confirm the difference in VP fog behaviour between NV and ATI cards. I'm also interested to know why and what should be done about it.

idr
02-09-2004, 11:44 AM
I believe the Nvidia driver is wrong. The ARB_vertex_program spec is pretty clear in saying the fog output of the vertex program is treated the same as the fog coordinate specificed if EXT_fog_coord (http://oss.sgi.com/projects/ogl-sample/registry/EXT/fog_coord.txt) is used. That spec is very clear about the interpretation of the coordinate. The third issue says "Since we're now specifying a number which behaves like an eye-space distance, rather than a [0,1] quantity..."

I'd suggest reporting it as a bug to Nvidia. If they respond with a reasonable justification of why their driver does what it does, could you post it here? That should shed some light on the issue. http://www.opengl.org/discussion_boards/ubb/smile.gif

zeckensack
02-09-2004, 01:38 PM
Originally posted by Ysaneya:
Do i need to implement two seperate shaders just to fix that ?As a workaround you can set linear fog with a [0...1] range, for all cards.

I don't see anything about fog coord clamping in the ARB_vp spec, so maybe that plays a role, too. Clamping doesn't make much sense for EXP and EXP2 fog, but I can see how it could be needed for linear fog ... http://www.opengl.org/discussion_boards/ubb/confused.gif

zeckensack
02-17-2004, 06:42 AM
*bump*

I suspect I have found a bug in Catalyst 4.2, but as I'm not too experienced with vertex programs, I thought I'd ask before bothering ATI.

Question: Shouldn't the following two ways of rendering be equivalent?
It appears I can't use vertex.fogcoord as an input in ARB_vertex_program. I get a constant zero on R300 and outright "undefined" values on RV280. I can however use result.fogcoord as an output without any issues. This isn't shown here.

Is there some enable or other required state I've missed?

Common init

struct Vertex
{
float x,y;
float fogcoord;
};

Vertex vert[3];

static const char vertex_program_code_f[]=
"!!ARBvp1.0\n"
"OPTION ARB_position_invariant;"
"MOV result.color,vertex.color;"
"MOV result.fogcoord,vertex.fogcoord;"
"END";

GLuint vertex_program_fogcoord=0;

void
init()
{
//initialize fog parameters
glFogf(GL_FOG_START,0.0f);
glFogf(GL_FOG_END,1.0f);
glFogi(GL_FOG_MODE,GL_LINEAR);
glFogi(GL_FOG_COORDINATE_SOURCE_EXT,GL_FOG_COORDIN ATE_EXT);
glEnable(GL_FOG);

//initialize vertex array
vert[0].x=-0.5f; vert[0].y=-0.5f; vert[0].fogcoord=0.0f;
vert[1].x= 0.5f; vert[1].y= 0.0f; vert[1].fogcoord=0.5f;
vert[2].x= 0.0f; vert[2].y= 0.5f; vert[2].fogcoord=1.0f;

glVertexPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].x);
glEnableClientState(GL_VERTEX_ARRAY);

glFogCoordPointerEXT(GL_FLOAT,sizeof(Vertex),&vert[0].fogcoord);

//initialize colors
glClearColor(0.0f,0.0f,0.0f,0.0f);
glFogfv(GL_FOG_COLOR,blue);
glColor4fv(red);

int gl_error=glGetError();
printf("Last GL error is %d\n",gl_error);
glGenProgramsARB(1,&vertex_program_fogcoord);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB,vertex_prog ram_fogcoord);
glProgramStringARB(GL_VERTEX_PROGRAM_ARB,GL_PROGRA M_FORMAT_ASCII_ARB,
strlen(vertex_program_code_f),
vertex_program_code_f);

int error_position=0;
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&error _position);
printf("Vertex program error position=%d\n",error_position);
printf("Error string: %s\n",(const char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB));
}

Fixed function version

glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
glDisable(GL_VERTEX_PROGRAM_ARB);
glLoadIdentity();
glDrawArrays(GL_TRIANGLES,0,3);

Vertex program version


glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB,vertex_prog ram_fogcoord);
glEnable(GL_VERTEX_PROGRAM_ARB);
glLoadIdentity();
glDrawArrays(GL_TRIANGLES,0,3);

There are no errors reported by the GL. The triangle rendered with ARB_vp is flat red. The triangle rendered with fixed function vertex processing shows the expected red->blue color gradient.

Jared
02-17-2004, 07:56 AM
so fog is the next mystery? on my gf3 when using a vertex program i could just do
MOV result.fogcoord, vertex.fogcoord;

and the fog appeared correctly.
when using a fragment program i did
OPTION ARB_fog_linear;

and again fog appeared correctly.
now when using that vertex program AND fragment program together -> no fog at all. i just noticed its the same on my radeon (though i never tested both programs on their own with this card).

when checking whats wrong btw. it seemed like the fogcoord was always zero
(MOV result.color, fragment.fogcoord.x http://www.opengl.org/discussion_boards/ubb/wink.gif

zeckensack
02-17-2004, 08:32 AM
Originally posted by Jared:
so fog is the next mystery? on my gf3 when using a vertex program i could just do
MOV result.fogcoord, vertex.fogcoord;

and the fog appeared correctly.I've just swapped cards again. My Geforce 3 behaves as I expected, ie there's fog.

when using a fragment program i did
OPTION ARB_fog_linear;
and again fog appeared correctly.ARB_fragment_program has always worked correctly for me on R300. You don't need to use the ARB_fog_* options. "fragment.fogcoord" behaves just like any other interpolated attribute, as it should.

now when using that vertex program AND fragment program together -> no fog at all. i just noticed its the same on my radeon (though i never tested both programs on their own with this card).You have just confirmed my findings. Good http://www.opengl.org/discussion_boards/ubb/smile.gif
Try outputting some constant (or other attribute) to result.fogcoord from the vertex program. It will work fine, as stated. It's the fogcoord input to the vertex program that's broken.

[/B]
when checking whats wrong btw. it seemed like the fogcoord was always zero
(MOV result.color, fragment.fogcoord.x; )[/B]Yes, on R300. I get different results on RV280 though. The fog coord seems to be garbled, the color gradient even starts at the wrong vertex and proceeds in the wrong direction. Going to test R200 in a few minutes.

Thanks. I think I'll send a bug report then.

Brian Paul
02-17-2004, 01:00 PM
I've been working on fragment program / fog support in Mesa these days. It took some experimentation to figure it out myself.

In general, the vertex program should emit a fog coordinate (i.e. an eye-space Z distance), not a fog blend factor (in [0,1]).
The fog coordinate may just be vertex.fogcoord or it may be computed from the incoming vertex position.

Then in your fragment program you can either specify a fog option (i.e. "OPTION ARB_fog_linear;") or use the incoming fragment.fogcoord.x value to compute your own fog blend factor and modify result.color accordingly.

I tested with NVIDIA's 53.36 driver and GeForceFX 5200. Mesa produces identical results now. See Mesa's progs/demos/arbfplight.c for an example.

-Brian

zeckensack
02-17-2004, 01:59 PM
Brian,
Note how I set up my fog mode:

glFogf(GL_FOG_START,0.0f);
glFogf(GL_FOG_END,1.0f);
glFogi(GL_FOG_MODE,GL_LINEAR);
This is essentially an identity transform for the fogcoord, except for clamping - the per-vertex fogcoords in my sample code don't need further clamping though.

Even though I just recently started working with ARB_vertex_program, I don't have any problems with ARB_fragment_program. I've been using it for quite some time now. Fog coords work as expected in the fragment program (if they get there). So the issue is not using the interpolated fogcoord in fragment processing, nor is it computing a fogcoord in a vertex program. This is all working fine on ATI cards AFAICS.

The issue is that per-vertex fogcoords cannot be passed *into* the vertex program.
I've found two workarounds for ATI cards. You can pass the fogcoords in either as 1D texcoords or as generic vertex attribute #5 (which aliases to vertex.fogcoord if it aliases at all - it doesn't alias with ATI drivers, which is perfectly allowed behaviour, of course). In both cases, I just MOV to result.fogcoord and everything starts working again.

PS: the bug report has already been sent.

Ysaneya
02-17-2004, 02:20 PM
I'm not sure this is an "input only" problem. My vertex program doesn't use the fog input, it directly writes into the fog destination register the eye-space distance to the vertex. It works well on ATIs, but is broken (no fog) on a GF4 Ti with latest drivers. Note that i later tested on a GF3 with drivers a month or two older, and that it worked perfectly well. So it doesn't happen on all NVidia cards.

Y.

Jared
02-18-2004, 04:41 AM
holy... either that fog business is more complicated than rocket science or something is just weird.

passing on vertex.fogcoord isnt a good idea, for some reason its always 0. not touching it will produce a fogcoord in the fragment program. using that as color looks good at first. until you move and notice "hey, its completely static". also, the fog seems to appear along a diagonal line from left/front to right/back. not to mention all the artefacts along the seems that made me wonder if screwed up the index buffers. then i saw the same artifacts on clipped triangles. if they arent completely visible they end up with no fogcoord.

doesnt matter, lets just use fragment.position.z, which (as far as i understood) shouldnt contain a constant 1 (and w should be 1/w which seems to ALWAYS equal 0??)

so what, then pass the z coord of the transformed vertex as fogcoord. looked well and updated correctly, though it still had artifacts like clipped triangles wouldnt be interpolated correctly. additionally, some other values (either texcoords or colors from a texture lookup) were completely off (probably my fault, lets double check the attributes).

another nice thing when displaying the fogcoord as color is that close to the geometry holes appear and show a flickering checkboard pattern.

in vertex program:
...
MOV result.texcoord.x, res.z;
MOV result.position, res;

in fragment program:
ADD f, fragment.fogcoord.x, -20;
MUL_SAT f, f, .016666;
MOV result.color, f;

result: http://festini.device-zero.de/depth.jpg