Question

So Im trying to figure out the best way to render a 3D model in OpenGL when some of the textures applied to it have alpha channels.

When I have the depth buffer enabled, and start drawing all the triangles in a 3D model, if it draws a triangle that is in front of another triangle in the model, it will simply not render the back triangle when it gets to it. The problem is when the front triangle has alpha transparency, and should be able to be seen through to the triangle behind it, but the triangle behind is still not rendered.

Disabling the depth buffer eliminates that problem, but creates the obvious issue that if the triangle IS opaque, then it will still render triangles behind it on top if rendered after.

For example, I am trying to render a pine tree that is basically some cones stacked on top of each other that have a transparent base. The following picture shows the problem that arises when the depth buffer is enabled:

Depth Buffer Enabled

You can see how you can still see the outline of the transparent triangles.

The next picture shows what it looks like when the depth buffer is disabled.

Depth Buffer Disabled

Here you can see how some of the triangles on the back of the tree are being rendered in front of the rest of the tree.

Any ideas how to address this issue, and render the pine tree properly?

P.S. I am using shaders to render everything.

Was it helpful?

Solution

If you're not using any partial transparency (everything is either 0 or 255), you can glEnable(GL_ALPHA_TEST) and that should help you. The problem is that if you render the top cone first, it deposits the whole quad into the z-buffer (even the transparent parts), so the lower branches underneath get z-rejected when its their time to be drawn. Enabling alpha testing doesn't write pixels to the z buffer if they fail the alpha test (set with glAlphaFunc).

If you want to use partial transparency, you'll need to sort the order of rendering objects from back to front, or bottom to top in your case.

You'll need to leave z-buffer enabled as well.

[edit] Whoops I realized that those functions I don't believe work when you're using shaders. In the shader case you want to use the discard function in the fragment shader if the alpha value is close to zero.

if(color.a < 0.01) {
   discard;
} else {
   outcolor = color;
}

OTHER TIPS

You needs to implement a two-pass algorithm.

The first pass render only the back faces, while the second pass render only the front faces.

In this way you don't need to order the triangles, but some artifacts may occour depending whether your geometry is convex or not.

I may be wrong, but this is because when you render in 3d you do no render the backside of triangles using Directx's default settings, when the Z is removed - it draws them in order, with the Z on it doesnt draw the back side of the triangles anymore. It is possible to show both sides of the triangle, even with Z enabled, however I'm thinking there might be a reason its normally enabled.. such as speed..

Device->SetRenderState(D3DRS_CULLMODE, Value);

value can equal

D3DCULL_NONE - Shows both sides of triangle
D3DCULL_CW - Culls Front side of triangle
D3DCULL_CCW - Default state
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top