I am going through the NeHe tutorials for OpenGL... I am at lesson 8 (drawing a cube with blending). http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=08
I wanted to experiment and change half of the faces to be opaque so that there is always a semi-transparent face opposite to an opaque one and be able to rotate the cube...
I changed the code a little bit, the entire source is there : http://pastebin.com/uzfSk2wB
I changed a few things :
enable blending by default and set the blending function to glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
changed the order of drawing the faces and colors for each face.
I set the depth testing
I draw all the opaque faces
I disable depth test
I draw all the transparent faces
Now, it's hard to tell exactly what is going wrong, but it definitely does not look right, I cannot recognize what face is opaque compared to the transparent ones, sometimes some faces do not seem to get drawn when they should...etc...
Seems like calculating what face is in front compared to back would not be trivial (although I am sure possible), I hope there is a way of doing that would not need to do that.
Looking either for what is wrong in my code or whether this is not the right way of doing it in the first place.
If you disable depth testing before drawing the transparent faces, then they will be drawn with no regard for their correct z-ordering. It probably looks like the transparent faces are being drawn atop all the other faces. Leave depth testing on.
Related
I want to draw transparent polygon(a pyramid for example). Some faces appear transparent where as some faces appear opaque.
Im drawing using GL_TRIANGLE_STRIP.
I have enabled blend mode, but no luck.
Please see the attached image,
This happens because of the draw order of the triangles. Some triangles get drawn first, these write their depth values to the depth texture, then the next triangle comes along and checks if there's something in front of it. If there is, then it won't render.
If a triangle that is at the back renders first, then there's no problem, the triangle in front of it looks at the depth texture, sees that it has a greater z value so it gets correctly rendered, these are the places where the color is less transparent.
The problem arises when the triangle at the front renders first. It writes it's depth value to the depth buffer, then the triangle in the back comes along, sees that there's already something in front of it, so it doesn't get rendered.
You have multiple ways to solve this, you can disable depth testing, sort the triangles so they come in order or use an algorithm like depth peeling. Each of these algorithms have side effects or are simply very complex, this is why you don't see too much transparency in games.
I have a model with transparent quads for a beard. I can not tell what triangles belong to the beard because their color comes from the texture passed to the fragment shader. I have tried to presort the triangles back to front during export of the model, but this does not help. So I implemented MSAA and Alpha to Coverage, but this did not help either. My last attempt was to draw the model, with a depth mask off and skipping any transparent data, so the color buffer would have non-clear color values to blend with. Then I would draw the model a second time with depth testing on and drawing the alpha pieces.
Nothing I have tried so far has worked. What other techniques can I try to get the beard of the model to properly draw? I am looking for a way to handle this that doesn't use a bunch of extensions. I'd prefer techniques that can be handled with plain old OpenGL 4.
Here is an image of what I am dealing with.
This is what I got after I applied the selected answer.
What you're trying to do there is a still largely unsolved problem: Order independent transparency. MSAA is something entirely different, as is alpha coverage.
So far the best working solution is to separate the model into an opaque and a hairy part. Draw the opaque parts of your scene first, then draw everything (semi-)translucent, ordered far to near in a second pass.
The way your image looks like it seems like the beard is rendered as the first thing, which is quite the opposite of what you actually want.
Simple way:
Enable depth write (depth mask), disable alpha-blending, draw model without the beard.
Disable depth write, enable alpha-blending, draw the beard. Make sure face culling is enabled.
Hard way:
Because order-independent transparency in renderers that use z-buffer is an unsolved problem (as datenwolf said), you could try depth-peeling. I believe the paper is available within OpenGL SDK. Most likely it'll be slower than "simple way", and there'll be a limit on number of maximum overlapping transparent polygons. Also check wikipedia article on order-independent transparency.
I'm trying to translate an OpenGL renderer into DirectX9. It mostly seems to work, but the two don't seem to agree on the settings for alpha blending. In OpenGL, I'm using:
glDepthFunc(GL_LEQUAL);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
and never actually setting the GL_DEST_ALPHA, so it's whatever the default is. This works fine. Translating to DirectX, I get:
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
which should do about the same thing, but totally doesn't. The closest I can get is:
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
which is almost right, but if the geometry overlaps itself, the alpha in front overrides the alpha in back, and makes the more distant faces invisible. For the record, the other potentially related render states I've got going on are:
device->SetRenderState(D3DRS_LIGHTING, FALSE);
device->SetRenderState(D3DRS_ZENABLE, TRUE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
At this point, I feel like I'm just changing states at random to see which combination gives the best results, but nothing is working as well as it did in OpenGL. Not sure what I'm missing here...
The alpha blending itself is performed correctly. Otherwise, every particle would look strange. The reason why some parts of some particles are not drawn, is that they are behind the transparent parts of some other particles.
To solve this problem you have two options:
Turn off ZWriteEnable for the particles. With that, every object drawn after the particle will be in front of it. This could lead to problems, if you have objects that should actually behind the particles and are drawn afterwards.
Enable alpha testing for the particles. Alpha testing is a technique to remove transparent pixels (given a certain threshold) from the target. This includes the ZBuffer.
Btw. when rendering transparent objects, it is almost always necessary to sort the objects to solve ZBuffer issues. The above solutions work for some special cases.
I am currently using glLogicOp() with a cube, which i render twice: with glFrontFace(GL_CW) and then with glFrontFace(GL_CCW). This allows me to see which area of the other 3d object my cube is overlapping with.
But i want to change the negative color to something else, lets say 0.5f transparent blue color.
How this can be done? Sorry about the title, i dont know the name of this method.
--
Also, i am having problem with being inside the cube with my camera: i need to fill the screen with negative coloring, is there any other way than swithing to 2d mode and drawing a quad with glLogicOp() enabled ? Also the problem is that theres a chance to see bugged rendering if i am at the edge of the cube surface, any ideas for preventing this perfectly?
You should look into the "Carmack's reverse" algorithm and the stencil shadow algorithms in general, as your problem is closely related to them (your cube being a shadow volume object). You will not get away with using glLogicOp() if you want other colors than black and white.
I'm learning about how to use JOGL and OpenGL to render texture-mapped quads. I have a test program and a test quad, and I figured out how to enable GL_BLEND so that I can specify the alpha value of a vertex to make a quad with a sort of gradient... but now I want this to show through to another textured quad at the same position.
Drawing two quads with the same vertex locations didn't work, it only renders the first quad. Is this possible then, or will I need to basically construct a custom texture on-the-fly based on what I want and then draw one quad with this texture? I was really hoping to take advantage of blending in this case...
Have a look at which glDepthFunc you're using, perhaps you're using GL_LESS/GL_GREATER and it could work if you're using GL_LEQUAL/GL_GEQUAL.
Its difficult to make out of the question what exactly you're trying to achieve but here's a try
For transparency to work correctly in OpenGL you need to draw the polygons from the furthest to the nearest to the camera. If you're scene is static this is definitely something you can do. But if it's rotating and moving then this is usually not feasible since you'll have to sort the polygons for each and every frame.
More on this can be found in this FAQ page:
http://www.opengl.org/resources/faq/technical/transparency.htm
For alpha blending, the renderer blends all colors behind the current transparent object (from the camera's point of view) at the time the transparent object is rendered. If the transparent object is rendered first, there is nothing behind it to blend with. If it's rendered second, it will have something to blend it with.
Try rendering your opaque quad first, then rendering your transparent quad second. Plus, make sure your opaque quad is slightly behind your transparent quad (relative to the camera) so you don't get z-buffer striping.