void setupclipplane()
{
float modelview[16];
glGetFloatv(GL_MODELVIEW_MATRIX , modelview);
//transforming point{A,B,C,D} to camera space point {pX,pY,pZ,pW}
float A = 1, B = 0, C = 1, D = 0;
float pX = A*modelview[0] + B*modelview[1] + C*modelview[2] + D*modelview[3];
float pY = A*modelview[4] + B*modelview[5] + C*modelview[6] + D*modelview[7];
float pZ = A*modelview[8] + B*modelview[9] + C*modelview[10] + D*modelview[11];
float pW = A*modelview[12] + B*modelview[13] + C*modelview[14] + D*modelview[15];
//transforming waterplane normal {A, B, C, D} to camera space normal {nX, nY, nZ, nW }
A = 0, B = 1, C = 0, D = 0;
float nX = A*modelview[0] + B*modelview[1] + C*modelview[2] + D*modelview[3];
float nY = A*modelview[4] + B*modelview[5] + C*modelview[6] + D*modelview[7];
float nZ = A*modelview[8] + B*modelview[9] + C*modelview[10] + D*modelview[11];
float nW = A*modelview[12] + B*modelview[13] + C*modelview[14] + D*modelview[15];
//computing dotproduct between camera space normal and camera space point
plane.x = nX;
plane.y = nY;
plane.z = nZ;
plane.w = -(pX*nX + pY*nY + pZ*nZ + pW*nW);
}
void ModifyProjectionMatrix(const Vector4D& clipPlane)
{
float matrix[16];
Vector4D q;
// Grab the current projection matrix from OpenGL
glGetFloatv(GL_PROJECTION_MATRIX, matrix);
// Calculate the clip-space corner point opposite the clipping plane
// as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
// transform it into camera space by multiplying it
// by the inverse of the projection matrix
q.x = (sgn(clipPlane.x) + matrix[8]) / matrix[0];
q.y = (sgn(clipPlane.y) + matrix[9]) / matrix[5];
q.z = -1.0F;
q.w = (1.0F + matrix[10]) / matrix[14];
// Calculate the scaled plane vector
Vector4D c = clipPlane * (2.0F / (clipPlane * q));
// Replace the third row of the projection matrix
matrix[2] = c.x;
matrix[6] = c.y;
matrix[10] = c.z + 1.0F;
matrix[14] = c.w;
// Load it back into OpenGL
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(matrix);
}
inline float sgn(float a)
{
if (a > 0.0F) return (1.0F);
if (a < 0.0F) return (-1.0F);
return (0.0F);
}
struct Vector4D
{
float x, y, z, w;
Vector4D() {}
Vector4D(float a, float b, float c, float d)
{
x = a; y = b; z = c; w = d;
}
// Scalar product
Vector4D operator *(float s) const
{
return (Vector4D(x * s, y * s, z * s, w * s));
}
// Dot product
float operator *(const Vector4D& v) const
{
return (x * v.x + y * v.y + z * v.z + w * v.w);
}
} plane;
<font color=purple>/////////////////////
//RENDER TO TEXTURE//
/////////////////////</font><font color=green>
//set clipping at the water plane</font>
double water_plane[] = {0,-1, 0, 0};
glClipPlane(GL_CLIP_PLANE0, water_plane);
glEnable(GL_CLIP_PLANE0);
<font color=green>//clear buffers and flip modelview matrix about water plane
//also setup a viewport equal to the dimensions of the reflection texture</font>
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
gluLookAt( cam_x, cam_y , cam_z, eye_x, eye_y, eye_z, 0, 1 ,0);
glViewport(0, 0, 512, 512);
glPushMatrix();
glScalef(1,-1,1);
<font color=green>//draw the scene as normal minus the water of course
//also return to the original modelview matrix</font>
draw_scene();
glPopMatrix();
<font color=green>//copy color buffer into texture</font>
glBindTexture(GL_TEXTURE_2D, reflection_texture );
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 512, 512, 0);
<font color=purple>//////////////////////////////
//RENDER SCENE THE USUAL WAY//
//////////////////////////////</font><font color=green>
//disable clipping</font>
glDisable(GL_CLIP_PLANE0);
<font color=green>//clear buffers and set the viewport to screen resolution</font>
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glViewport(0, 0, 1024, 768);
<font color=green>//draw the scene</font>
draw_scene();
<font color=green>//draw the water with the reflection texture
// Setup texture coordinate equations</font>
static GLfloat lsPlaneS[] = { 1, 0, 0, 0 };
static GLfloat lsPlaneT[] = { 0, 1, 0, 0 };
static GLfloat lsPlaneR[] = { 0, 0, 1, 0 };
static GLfloat lsPlaneQ[] = { 0, 0, 0, 1 };
glPushMatrix();
glLoadIdentity();
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
glTexGenfv(GL_S, GL_EYE_PLANE, lsPlaneS);
glTexGenfv(GL_T, GL_EYE_PLANE, lsPlaneT);
glTexGenfv(GL_R, GL_EYE_PLANE, lsPlaneR);
glTexGenfv(GL_Q, GL_EYE_PLANE, lsPlaneQ);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glPopMatrix();
<font color=green>//setting up texture matrix</font>
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glTranslatef(.5f, .5f, 0);
glScalef(.5f,.5f, 1);
<font color=orange>setupclipplane();
ModifyProjectionMatrix(plane);</font>
gluPerspective( 60.0, 1024.0f / 768.0f, 1, 8000.0 );
glMatrixMode(GL_MODELVIEW);
<font color=green>//Now you render your water plane here</font>
glBindTexture(GL_TEXTURE_2D, reflection_texture );
draw_water();
<font color=green>//To finish, disable auto texture generation.</font>
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
swap_buffers();
[Edited by - Khaos Dragon on August 9, 2004 12:43:54 AM]