C ++, OpenGL Z-buffer prefas

I'm making a simple voxel engine (think Minecraft), and I'm currently in the process of getting rid of occluded faces to get some precious fps. I have not really experimented with OpenGL and don’t quite understand how glColorMask magic works.

This is what I have:

// new and shiny glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // this one goes without saying glEnable(GL_DEPTH_TEST); // I want to see my code working, so fill the mask glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // fill the z-buffer, or whatever glDepthFunc(GL_LESS); glColorMask(0,0,0,0); glDepthMask(GL_TRUE); // do a first draw pass world_display(); // now only show lines, so I can see the occluded lines do not display glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // I guess the error is somewhere here glDepthFunc(GL_LEQUAL); glColorMask(1,1,1,1); glDepthMask(GL_FALSE); // do a second draw pass for the real rendering world_display(); 

This works somewhat, but as soon as I change the position of the camera, the world begins to disappear, I see fewer and fewer lines until nothing works.

+6
c ++ opengl
source share
3 answers

It looks like you are not clearing the depth buffer.

You need to enable depth recording (via glDepthMask(GL_TRUE); ) when you try to clear the depth buffer using glClear . You probably still disconnected it from the previous frame, as a result of which all your cleanups will be absent in the frames of the subframes. Just move your glDepthMask call to glClear .

+9
source share

glColorMask and glDepthMask determine which parts of the frame buffer are actually written to.

The idea of ​​an early Z-clipping is to first display only part of the depth buffer - the actual savings come from sorting the geometry near far so that the GPU can quickly discard occluded fragments. However, when drawing a Z-buffer, you do not want to draw a color component: this allows you to switch shaders, texturing, i.e. In short, everything is computationally intensive.

A word of warning: Early Z only works with opaque geometry . In fact, the entire depth buffer algorithm only works for opaque material. Once you mix, you will have to sort far close and not use depth buffering (search for “order-independent transparency” for algorithms to fix related problems).

S, if you have something that has been mixed, remove it from the “early Z” stage.

In the first pass you set

 glDepthMask(1); // enable depth buffer writes glColorMask(0,0,0); // disable color buffer writes glDepthFunc(GL_LESS); // use normal depth oder testing glEnable(GL_DEPTH_TEST); // and we want to perform depth tests 

After completing the Z-transition, you will change the settings

 glDepthMask(0); // don't write to the depth buffer glColorMask(1,1,1); // now set the color component glDepthFunc(GL_EQUAL); // only draw if the depth of the incoming fragment // matches the depth already in the depth buffer 

GL_LEQUAL does the job, but also allows fragments even closer than in the depth buffer. But since updating the depth buffer does not happen, everything that happens between the source and the stored depth will overwrite it every time something is drawn there.

A small theme change is to use the “early Z” depth buffer as a geometry buffer in several deferred dimming then.

To save additional geometry, check out Occlusive Queries . With occlusal requests, you ask the GPU how much if any fragments pass all the tests. It's like a voxel engine, you probably use octree or Kd tree. Drawing spatial separation faces (with glDepthMask (0), glColorMask (0,0,0)) of the tree branches before the branch intersects tells you if any geometry in this branch is visible at all. This, combined with near and far sorted bypass and (coarse) truncation on the tree, will give you huge performance benefits.

+7
source share

z-pre pass can work with translucent objects. if they are translucent, do not expose them in prepass, then zsort and render.

+5
source share

All Articles