User Clip planes on Nvidia

I am using clip planes to do reflections and on my Nvidia card and if I specify 0, -1, 0, 0 for a reflection on Y axis my Nvidia card will not chop off whats above the plane? On my ATI card it works fine and I can get the ATI card to render the same image as the Nvidia card, but I can also get the ATI card to clip the image so it chops off the image at the plane??? So who’s right? I am thinking user defined clip planes aren’t working on Nvidias cards? Unless there is some special way I need to setup the clip plane for Nvidia vs. ATI? Thanks

You may use oblique frustum clipping, which modifies near projection plane to be an extra cliplane. It works on nVidia and ATi both, cause it works everywhere ))
Try googling on “oblique frustum clipping”, there is a code sample from Eric Lengyel somewhere, I don’t remember exactly. Do not forget to transfom clipplane in currently set modelview transformation space!

Originally posted by Jackis:
You may use oblique frustum clipping, which modifies near projection plane to be an extra cliplane. It works on nVidia and ATi both, cause it works everywhere ))
Try googling on “oblique frustum clipping”, there is a code sample from Eric Lengyel somewhere, I don’t remember exactly. Do not forget to transfom clipplane in currently set modelview transformation space!

I would rather use the OpenGL ones… Unless this is a known problem I will look into the ones Eric has come up with.

I highly recommend the Eric Lengyel clipplanes as metioned above:
http://www.terathon.com/code/oblique.html

for reflection plane mirrors as they are free. (OpenGL clipplanes can involve a speed expense)

On Nvidia hardware, unless you’re using the conventional transform path or a position-invariant vertex program, you need to explicitly calculate clip plane distances in yourself. You can use the NV_vertex_program2 option to output to result.clip[i]. The hardware interpolates these distances during rasterization and kills any fragments for which any one of them goes negative.

ATI hardware works differently, and I believe they actually do a geometric clip. (Someone correct me if that’s not true.)

Either way, you do pay a small performance price by using OpenGL clip planes, and as you’ve noticed, there isn’t one way that works well on hardware from both companies. The oblique view frustum only modifies the projection matrix, however, and is guaranteed to work on all hardware at absolutely no performance cost.

Originally posted by Eric Lengyel:
[b]On Nvidia hardware, unless you’re using the conventional transform path or a position-invariant vertex program, you need to explicitly calculate clip plane distances in yourself. You can use the NV_vertex_program2 option to output to result.clip[i]. The hardware interpolates these distances during rasterization and kills any fragments for which any one of them goes negative.

ATI hardware works differently, and I believe they actually do a geometric clip. (Someone correct me if that’s not true.)

Either way, you do pay a small performance price by using OpenGL clip planes, and as you’ve noticed, there isn’t one way that works well on hardware from both companies. The oblique view frustum only modifies the projection matrix, however, and is guaranteed to work on all hardware at absolutely no performance cost.[/b]
Hi Eric. I am thinking about giving your code a try. I do have the GEM 5 book. My question is logical order to use your function…

1.save current projection matrix?
2.call your function with parameters I would have sent to glClipplane()
3.do rendering
4.reset projection matrix to saved one?
5.repeat for my refraction code ect…

Would this be correct? If I don’t save the current projection I should lose my setup of gluPerspective right? Thanks for all the help and ideas…

That sounds fine except for step 2. The glClipPlane() function transforms the plane by the inverse transpose of the model-view matrix to move it into eye space. My function assumes that this transformation has already been applied to the plane.

Originally posted by Eric Lengyel:
That sounds fine except for step 2. The glClipPlane() function transforms the plane by the inverse transpose of the model-view matrix to move it into eye space. My function assumes that this transformation has already been applied to the plane.
So I would need another function to take my 0.0, -1.0, 0.0, 0.0 values and transform them by inverse of the model view matrix and then send those new 4 values into your function. If I am understanding you .

Yes, just do whatever is necessary to put the plane in eye space, and then call my function.

Originally posted by Eric Lengyel:
Yes, just do whatever is necessary to put the plane in eye space, and then call my function.
Ugh, I knew I was going to hit a wall with the math behind moving my plane into eye space. If I was doing it in GLSL I would call

gl_ModelViewProjectionMatrixInverseTranspose 

and multiply it by the plane values… But I don’t have that available to me under FFP AFAKI?

Here’s some functions for you:-

void plane_transform(float* dst, float* src, float* matrix)
{
	#define M(ROW,COL) matrix[((COL)*4)+(ROW)]

	dst[0] = src[0] * M(0,0) + src[1] * M(1,0) + src[2] * M(2,0) + src[3] * M(3,0);
	dst[1] = src[0] * M(0,1) + src[1] * M(1,1) + src[2] * M(2,1) + src[3] * M(3,1);
	dst[2] = src[0] * M(0,2) + src[1] * M(1,2) + src[2] * M(2,2) + src[3] * M(3,2);
	dst[3] = src[0] * M(0,3) + src[1] * M(1,3) + src[2] * M(2,3) + src[3] * M(3,3);

	#undef M
}

void mat4_transpose(float* dst, float* src)
{
	dst[0]=src[0];
	dst[1]=src[4];
	dst[2]=src[8];
	dst[3]=src[12];
	dst[4]=src[1];
	dst[5]=src[5];
	dst[6]=src[9];
	dst[7]=src[13];
	dst[8]=src[2];
	dst[9]=src[6];
	dst[10]=src[10];
	dst[11]=src[14];
	dst[12]=src[3];
	dst[13]=src[7];
	dst[14]=src[11];
	dst[15]=src[15];
}

void mat4_inverseOrth(float* dst, float* src)
{
	dst[0]=src[0];
	dst[1]=src[4];
	dst[2]=src[8];
	dst[3]=0.0f;
	dst[4]=src[1];
	dst[5]=src[5];
	dst[6]=src[9];
	dst[7]=0.0f;
	dst[8]=src[2];
	dst[9]=src[6];
	dst[10]=src[10];
	dst[11]=0.0f;
	dst[12]=-src[12]*src[0]-src[13]*src[1]-src[14]*src[2];
	dst[13]=-src[12]*src[4]-src[13]*src[5]-src[14]*src[6];
	dst[14]=-src[12]*src[8]-src[13]*src[9]-src[14]*src[10];
	dst[15]=1.0f;
}

void applyPlane(float* plane)
{
	float mat1[16];
	float mat2[16];

	glGetFloatv(GL_MODELVIEW_MATRIX, mat1);

	mat4_inverseOrth(mat2, mat1);
	mat4_transpose(mat1, mat2);

	float xplane[4];

	plane_transform(xplane, plane, mat1);

	ModifyProjectionMatrix(Vector4D(xplane[0], xplane[1], xplane[2], xplane[3]));
}

BTW, as you can see, the projection matrix is not involved in transforming the plane into eye space, so your GLSL code snippet is incorrect.

Thanks all for the help and ideas, but I can’t get it to work so I will just have to stick with the way I am doing it now which renders correct, but the data I see when I texture the depthmap, colortextures says otherwise on my nvidia card but the image looks correct for rendering…

hello, sorry for bringing this up again but I tried to implement it and failed… Using the technique by Mr. Lengyel

It looks like the backplane is transformed as well depending on where I look…

hope this illustrates things a bit.

do I have to modify the clipping plane anymore then just the transforms already mentioned ?

should add that my plane is (1,0,0,0) and I do transform it like the codesamples above.

Well I am not sure if this will help but are you calling glPushMatrix glPopMatrix before and after the clipping? Some code would be helpful. I am no expert but I don’t think the clipplane should move due to you want that plane to clip correct?

Your clip plane of (1,0,0,0) is probably the cause of your problems. This plane contains the camera, and my technique only works if the camera is on the negative side of the clipping plane.

The far plane is moved when you adjust the projection matrix for an oblique near plane, and it’s no longer parallel to the near plane. The code that I’ve posted, though, calculates the projection matrix that gives the best far plane possible.

thanks, I digged thru some forums and found your original post on the maths forum here, which did mention the camera side thing, but I hoped there was a workaround

thanks for your help. and your code snippets on the website =)

mars, I use my own matrix operations, because the rest of the engine needs those, too.