Sign in to follow this  
Myke111

Enable Early Z Test

Recommended Posts

Hey guys, i have the following situation: i need to render some geometry with a fast vertexShader and a slow fragmentShader. Because of the slow pixelshader i want to run them just for the nearest geometry found in the scene. my solution is to render the whole scene twice. 1) i render the scene with a fast fragmentShader and glEnable(GL_DEPTH_TEST) and glDepthFunc(GL_LESS) in order to fill the depth buffer. 2) i want to render the scene with the slow fragmentShader AND i wan't to utilize early z test in order to run the fragmentShader just on the foremost geometry. Therefore i use glDepthFunc(GL_EQUAL) in the second pass. Unfortunatelly this doesn't work and the fragmentShaders aren't skipped. i heard that early z test just works with alpha test disabled so i did: glDisable(GL_ALPHA_TEST) and glDisable(GL_BLEND) on the second pass, but it still doesn't work. any ideas? what else do i have to enable disable to get early z test running?

Share this post


Link to post
Share on other sites
How would you know it doesn't work? Wheter early z is used or not is completly transparent to the API. Also, I would advice not to switch the depth function but use GL_LEQUAL in both render passes. It could be the case that early z does not work well for GL_EQUAL. Generally changing the depth function is a bad idea.

Share this post


Link to post
Share on other sites
I know it doesn't work because rendering (with slow shader) takes the same time no matter if i use early z or not. If early z would work properly, only 25% of the fragmentShader would have started and a noticable speedup would accour (since the fragmentshader takes about 95% of the rendering time). The time overhead for z-test is neglectable compared to the time a fragmentshader takes.

LEQUAL is a good idea, but doesn't change the behaviour mentioned. z-test still not working.

Share this post


Link to post
Share on other sites
Have you tried:

For first pass:
Disabling fragment shader. Only use vertex shader. Render using fixed function pipeline (with possible vertex shader).
Disabling COLOR_BUFFER writes: glColorMask (0,0,0,0) + glDrawBuffers (GL_NONE);
Enable depth test.
(this should allow the H/W to write to depth at twice the normal speed)

Then for the second pass:

Enable fragment shaders, enable vertex shaders
enable color buffers
Depth Func LEQUAL

And (this is the important bit) - in your rendering loop you MUST never change the direction of the DEPTH test function. E.g From GL_LESS to GL_GREATER etc ....

Share this post


Link to post
Share on other sites
Thanks 4 your reply BionicBytes,

I've incorporated your suggestions now but with no success =( my code looks like this now (swap buffer is called after Renderer::Render()):


void Renderer::Render() {
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// if mode cascade for other clears

// prepare projection matrix for camera
this->camera->Render(); // setup gluLookAt(...);

ModelVector::iterator it = this->volumes.begin();
for (; it != volumes.end(); ++it) {
(*it)->Render();
}
}



void Model::Render() {
this->Recompute();

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMultMatrixd(this->transformations.getPointer());

this->SetUpPreStates();
this->PreSubRender();

this->SetUpStates(); // enable all openGL states needed
this->SubRender(); // actual models do their stuff here

this->SetUpPostStates();
this->PostSubRender();

glPopMatrix();
}



void EmptySpaceVolumeModel::SetUpPreStates()
{
this->SetUpGeometry();
VolumeModel::SetUpShader();

glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);

glDisable(GL_BLEND);
glDisable(GL_ALPHA);
glDisable(GL_ALPHA_TEST);

glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);

glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);
glDisable(GL_CULL_FACE);

glShadeModel(GL_FLAT);

glDrawBuffer(GL_NONE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
}

void EmptySpaceVolumeModel::PreSubRender()
{
this->shader->Disable();
this->depthShader->Disable();

this->RenderGeometry();

this->depthShader->Disable();
}


void EmptySpaceVolumeModel::SetUpStates()
{
glEnable(GL_TEXTURE_3D);
glEnable(GL_TEXTURE_1D);

glEnable(GL_DEPTH_TEST);
//*/glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glDepthFunc(GL_LEQUAL);

glDrawBuffer(GL_BACK);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}

void EmptySpaceVolumeModel::SubRender()
{
this->depthShader->Disable();
this->shader->Enable();

this->RenderGeometry();

this->shader->Disable();
}

void EmptySpaceVolumeModel::SetUpPostStates()
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_TRUE);
}

void EmptySpaceVolumeModel::RenderGeometry()
{
glBindBuffer(GL_TEXTURE_COORD_ARRAY, texCoordHandle);
glBindBuffer(GL_ARRAY_BUFFER, vertexHandle);
glVertexPointer(3, GL_FLOAT, 0, (char*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexHandle);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_INDEX_ARRAY);

glDrawRangeElements(GL_QUADS, 0, maxIndex, indizesLength, GL_UNSIGNED_INT, 0);

glDisableClientState(GL_INDEX_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}


sometimes the resulting image is ok, but the renderingperformance is still crap (the noise at the edge of the head is due to the JPGs incapability in treating high frequencies in image data)

sometimes the resulting image looks like this (depending on viewing angle)


Share this post


Link to post
Share on other sites
When you say rendering performance is still crap? What is your FPS rate? What H/W are you running on?

The other thing to do is examine your 'slow' pixel shader and optimize it.
There are a number of tools on the web from both Nvidia and ATI that can examine the code and produce output that might be of interest. For example, I'm assuming you manipulate texture data - For 8-bit textures you should be using the half data type rather than using float.

Share this post


Link to post
Share on other sites
Error #1 glDisable(GL_ALPHA);
Error #2 glEnable(GL_TEXTURE_3D); and glEnable(GL_TEXTURE_1D);
Not really an error but why enable both? Also, you are using shaders so these have no effect.
Error #3 glBindBuffer(GL_TEXTURE_COORD_ARRAY, texCoordHandle);
I suggest you call glGetError()
Error #4 glEnableClientState(GL_INDEX_ARRAY); but glIndexPointer has not been called
Error #5 glEnableClientState(GL_TEXTURE_COORD_ARRAY); called but glTexCoordPointer ?

Error #6 glDrawRangeElements(GL_QUADS, 0, maxIndex, indizesLength, GL_UNSIGNED_INT, 0);
maxIndex might be wrong. It should be maxVertex-1
Error #7 glDisableClientState(GL_VERTEX_ARRAY);, why disabled?


I suggest you call glGetError() once in a while.
Also, to help debug http://glintercept.nutty.org

Perhaps this will help as well
http://www.opengl.org/wiki/index.php/GLSL_:_common_mistakes

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this