hardtop

06-21-2006, 04:23 PM

Hi all, I've gone through Mr Eric Lengyel's tutorial on Oblique near-plane clipping, but I can't get it working. Here's what I'm doing:

void HT_Graphics::ModifyProjectionMatrix(CVector4& clipPlane)

{

float matrix[16];

CVector4 q;

float mat1[16];

float mat2[16];

glGetFloatv(GL_MODELVIEW_MATRIX, mat1);

CMatrix::mat4_inverseOrth(mat2, mat1);

CMatrix::mat4_transpose(mat1, mat2);

float xplane[4];

CMatrix::plane_transform(xplane, clipPlane.v, mat1);

CVector4 resVec(xplane[0], xplane[1], xplane[2], xplane[3]);

// 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(resVec.x) + matrix[8]) / matrix[0];

q.y = (sgn(resVec.y) + matrix[9]) / matrix[5];

q.z = -1.0f;

q.w = (1.0f + matrix[10]) / matrix[14];

// Calculate the scaled plane vector

CVector4 c = resVec * (2.0f / (resVec * 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);

glMatrixMode(GL_MODELVIEW);

}

static inline 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

}

static inline 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];

}

static inline 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;

}

...

isReflection = true;

framesComputeReflection = 0;

// *** calculate reflection ************************************************** *********

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferReflection);

glViewport(0,0, REFLECTION_TEXTURE_SIZE, REFLECTION_TEXTURE_SIZE);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

gluLookAt(pos.x, pos.y, pos.z,

view.x, view.y, view.z,

up.x, up.y, up.z);

glPushMatrix();

if(pos.y > waterHeight)

{

glTranslatef(0.0f, waterHeight * 2.0f, 0.0f);

glScalef(1.0, -1.0, 1.0);

glCullFace(GL_FRONT);

ModifyProjectionMatrix(CVector4(0.0, 1.0, 0.0, -waterHeight));

// render scene to reflection texture

HT_Graphics::SetActiveShaderProgram(HT_Constants:: SH_NONE);

m_skybox->Render(pos.x, pos.y, pos.z, engineconfig->farPlane-10.0f, engineconfig->farPlane-10.0f, engineconfig->farPlane-10.0f);

if(engineconfig->reflectionsFull)

{

m_mapI->Render();

}

ResetProjectionMatrix();

glCullFace(GL_BACK);

}

else

{

ModifyProjectionMatrix(CVector4(0.0, 1.0, 0.0, waterHeight));

if(engineconfig->reflectionsFull)

{

m_mapI->Render();

}

ResetProjectionMatrix();

}

glPopMatrix();

glBindTexture(GL_TEXTURE_2D, reflTex);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

...I don't know what's gone wrong :confused:

What I do is I pass the clipping plane equation as world coordinates (as for the glClipPlane function), and I transform the coordinates to eye coords using inverse transpose modelview matrix. Then I modify the projection matrix accordingly as described in Mr Lengyel's article.

Here's a shot of the problem

http://www.hardtopnet.net/temp/OBLIQUE.JPG

The plane still seems to "follow" the camera, and doesn't clip along the surface of the water (the brick wall is actually a "reflection" of the bottom of the pool, and the black thing is a clipped region)

Anybody got a clue?

Thanks a lot

HardTop

void HT_Graphics::ModifyProjectionMatrix(CVector4& clipPlane)

{

float matrix[16];

CVector4 q;

float mat1[16];

float mat2[16];

glGetFloatv(GL_MODELVIEW_MATRIX, mat1);

CMatrix::mat4_inverseOrth(mat2, mat1);

CMatrix::mat4_transpose(mat1, mat2);

float xplane[4];

CMatrix::plane_transform(xplane, clipPlane.v, mat1);

CVector4 resVec(xplane[0], xplane[1], xplane[2], xplane[3]);

// 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(resVec.x) + matrix[8]) / matrix[0];

q.y = (sgn(resVec.y) + matrix[9]) / matrix[5];

q.z = -1.0f;

q.w = (1.0f + matrix[10]) / matrix[14];

// Calculate the scaled plane vector

CVector4 c = resVec * (2.0f / (resVec * 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);

glMatrixMode(GL_MODELVIEW);

}

static inline 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

}

static inline 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];

}

static inline 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;

}

...

isReflection = true;

framesComputeReflection = 0;

// *** calculate reflection ************************************************** *********

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, frameBufferReflection);

glViewport(0,0, REFLECTION_TEXTURE_SIZE, REFLECTION_TEXTURE_SIZE);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

gluLookAt(pos.x, pos.y, pos.z,

view.x, view.y, view.z,

up.x, up.y, up.z);

glPushMatrix();

if(pos.y > waterHeight)

{

glTranslatef(0.0f, waterHeight * 2.0f, 0.0f);

glScalef(1.0, -1.0, 1.0);

glCullFace(GL_FRONT);

ModifyProjectionMatrix(CVector4(0.0, 1.0, 0.0, -waterHeight));

// render scene to reflection texture

HT_Graphics::SetActiveShaderProgram(HT_Constants:: SH_NONE);

m_skybox->Render(pos.x, pos.y, pos.z, engineconfig->farPlane-10.0f, engineconfig->farPlane-10.0f, engineconfig->farPlane-10.0f);

if(engineconfig->reflectionsFull)

{

m_mapI->Render();

}

ResetProjectionMatrix();

glCullFace(GL_BACK);

}

else

{

ModifyProjectionMatrix(CVector4(0.0, 1.0, 0.0, waterHeight));

if(engineconfig->reflectionsFull)

{

m_mapI->Render();

}

ResetProjectionMatrix();

}

glPopMatrix();

glBindTexture(GL_TEXTURE_2D, reflTex);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

...I don't know what's gone wrong :confused:

What I do is I pass the clipping plane equation as world coordinates (as for the glClipPlane function), and I transform the coordinates to eye coords using inverse transpose modelview matrix. Then I modify the projection matrix accordingly as described in Mr Lengyel's article.

Here's a shot of the problem

http://www.hardtopnet.net/temp/OBLIQUE.JPG

The plane still seems to "follow" the camera, and doesn't clip along the surface of the water (the brick wall is actually a "reflection" of the bottom of the pool, and the black thing is a clipped region)

Anybody got a clue?

Thanks a lot

HardTop