transparency in opengl (using FLTK) - opengl

I'm drawing some 3D structures in a Fl_Gl_Window in FLTK's implementation of opengl. This images are drawn and rotated so the code looks something like
glTranslatef(-xshift,-yshift,-zshift);
glRotatef(ang1,ang2,ang3);
glTranslatef(xshift,yshift,zshift);
glColor4f((120.0/256.0),(120.0/256.0),(120.0/256.0),0.2);
for (int side=0;side<num_sides;side++){
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
glBegin(GL_TRIANGLES);
//draw shape
glEnd();
glDisable(GL_BLEND);
}
and it almost works apart from at different angles the transparency doesn't work properly. For example, if I draw a cube from one side it will look transparent all the way through without being able to discern the two sides but from the other one side will appear darker as it is supposed to. It's as if it calculates the transparency too 'early' as in before the rotation. Am I doing something wrong? Should I move the rotation to below the transparency effects (i.e. before them in execution) or does the order of the triangles matter?

The order of the triangles matters. To get the desired effect for transparency you need to render the triangles in back to front order because the hardware blending works by reading the color for the fragment in the depth buffer and blending it with the fragment currently being shaded. That's why you are getting different results when you rotate your cube since you are not changing the order of the triangles in the cube. You may also want to look into Order Independent Transparency techniques.
Depending on how many triangles you have sorting them every frame can get really expensive. One approximation technique is to presort the triangles along the x, y, and z axes and then choose the sorted ordered that most closely matches your viewing direction. This only works to a certain extent. One popular type of order independent transparency technique is depth peeling. Here's a tutorial with some code for implementing it: http://mmmovania.blogspot.com/2010/11/order-independent-transparency.html?m=1. You might also want to read the original paper to get a better understanding of the technique: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.18.9286&rep=rep1&type=pdf.

Related

opengl 3.3 z-fighting ortho 2d view

I'm having some issues with z fighting while drawing simple 2d textured quads using opengl. The symptoms are both objects moving at the same speed and one on top of another but periodically one can see through the other and vice versa - sort of like a "flickering". I assume this is indeed z fighting.
I have turned off Depth Testing and have the following as well:
gl.Disable(gl.DEPTH_TEST)
gl.DepthFunc(gl.LESS)
gl.Enable(gl.BLEND)
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
My view and ortho matrices are as follows:
I have tried to set the near and far distances much greater ( like range of 50000 but still no help)
Projection := mathgl.Ortho(0.0, float32(width), float32(height), 0.0, -5.0, 5.0)
View := mathgl.LookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
The only difference with my opengl process is that instead of a drawelements call for each individual object, I package all vertices, uvs(sprite atlas), translation, rotation, etc in one big package sent to vertex shader.
Does anyone have remedies for 2d z fighting?
edit:
i'm adding some pictures to further describe the scenario:
These images are taken a few seconds apart from each other. They are simply texture moving from left to right. As they move; you see from the image, that one sprite over-lapse the other and vice versa back and forth etc very fast.
Also note that my images (sprites) are pngs that have a transparent background to them..
It definitely isn't depth fighting if you have depth testing disabled as shown in the code snippet.
"I package all vertices, uvs(sprite atlas), translation, rotation, etc in one big package sent to vertex shader." - You need to look into the order that you add your sprites. Perhaps it's inconsistent for some reason.
This could be Z fighting
the usual causes are:
fragments are at the same Z-coordinate or closer then accuracy of Z-coordinate
fragments are too far from perspective camera with perspective projection the more far you are from Z near the less accuracy
some ways to fix this:
change size/position of overlapped surfaces slightly
use more bits for Z-Buffer (Depth)
use linear or logarithmic Z-buffer
increase Z-near or decrease Z-far or both for perspective projection you can combine more frustrums to get high definition Z range
sometimes helps to use glDepthFunc(GL_LEQUAL)
This could be an issue with Blending.
as you use Blending you need to render a bit differently. To render transparency correctly you must Z-sort the scene otherwise artifacts can occur. If you got too much dense geometry of transparent objects or objects near them (many polygon edges near). In addition Z-fighting creates a magnitude higher artifacts with blending.
some ways to fix this:
Z sorting can be partially done by multi pass rendering + Depth test + switching front face
so first render all solids and then render Z-sorted transparent objects with front face set to the side not facing camera. Then render the same objects with front face set for side facing camera. You need to use depth test for this!!!. This way you do not need to sort all polygons of scene just the transparent objects. Results are not 100% correct for complex transparent geometries but the results are usually good enough (especially for dynamic scenes). This is how the output from this looks like
it is a glass cup a bit messed up visually by selected blending function for this case because darker pixels means 2 layers of glass on purpose it is not a bug. Therefore the opening looks like the front/back faces are swapped
use less dense geometry for transparent objects
get rid of Z-fighting issues

OpenGL Perspective Texture Flickering

I have a very simple OpenGL (3.2) setup, no lighting, perspective projection and a simple shader program (applies projection transformation and uses texture2D to read the color from the texture).
The camera is looking down the negative z-axis and I draw a few walls and pillars on the x-y-plane with a texture (http://i43.tinypic.com/2ryszlz.png).
Now I'm moving the camera in the x-y-plane and this is what it looks like:
http://i.imgur.com/VCrNcly.gif.
My question is now: How do I handle the flickering of the wall texture?
As the camera centers the walls, the view angle onto the texture compresses the texture for the screen, so one pixel on the screen is actually several pixels on the texture, but only one is chosen for display. From the information I have access to in the shaders, I don't see how to perform an operation which interpolates the required color.
As this looks like a problem nearly every 3D application should have, the solution is probably pretty simple (I hope?).
I can't seem to understand the images, but from what you are describing you seem to be looking for MIPMAPPING. Please google it, it's a very easy and very generally used concept. You will be able to use it by adding one or two lines to your program. Good Luck. I'd be more detailed but I am out of time for today.

Rendering 3D Models With Textures That Have Alpha In OpenGL

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:
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.
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.
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;
}
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

Techniques for drawing coplanar polygons in OpenGL

I'm going to have meshes with several coplanar polygons, all lying in a certain plane, that I'm not going to be able to eliminate.
These polygons have a specific draw order. Some polygons are behind other polygons. If I turn off depth testing I'll have the effect I want, but I want to be able to position this mesh in a 3D scene.
I do not trust glPolygonOffset because I'll potentially have several of these overlapping polygons and am am worried about the cumulative effects of the offset.
If I turn off depth testing I'll have the effect I want, but I want to be able to position this mesh in a 3D scene.
Simply disable writing to z-buffer, without disabling depth test.
glDepthMask(GL_FALSE);
Make sure to render all polygons that doesn't require glDepthMask(GL_FALSE) before rendering any polygons with glDepthMask(GL_FALSE); Otherwise object will be incorrectly positioned.
If you can't do that, then you should change your geometry or use texture instead.
glDepthMask documentation

In openGL, how can you get items to draw back to front?

By default it seems that objects are drawn front to back. I am drawing a 2-D UI object and would like to create it back to front. For example I could create a white square first then create a slightly smaller black square on top of it thus creating a black pane with a white border. This post had some discussion on it and described this order as the "Painter's Algorithm" but ultimately the example they gave simply rendered the objects in reverse order to get the desired effect. I figure back to front (first objects go in back, subsequent objects get draw on top) rendering can be achieved via some transformation (gOrtho?) ?
I will also mention that I am not interested in a solution using a wrapper library such as GLUT.
I have also found that the default behavior on the Mac using the Cocoa NSOpenGLView appears to draw back to front, where as in windows I cannot get this behavior. The setup code in windows I am using is this:
glViewport (0, 0, wd, ht);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho (0.0f, wd, ht, 0.0f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
The following call will turn off depth testing causing objects to be drawn in the order created. This will in effect cause objects to draw back to front.
glDepthFunc(GL_NEVER); // Ignore depth values (Z) to cause drawing bottom to top
Be sure you do not call this:
glEnable (GL_DEPTH_TEST); // Enables Depth Testing
For your specific question, no there is no standardized way to specify depth ordering in OpenGL. Some implementations may do front to back depth ordering by default because it's usually faster, but that is not guaranteed (as you discovered).
But I don't really see how it will help you in your scenario. If you draw a black square in front of a white square the black square should be drawn in front of the white square regardless of what order they're drawn in, as long as you have depth buffering enabled. If they're actually coplanar, then neither one is really in front of the other and any depth sorting algorithm would be unpredictable.
The tutorial that you posted a link to only talked about it because depth sorting IS relevant when you're using transparency. But it doesn't sound to me like that's what you're after.
But if you really have to do it that way, then you have to do it yourself. First send your white square to the rendering pipeline, force the render, and then send your black square. If you do it that way, and disable depth buffering, then the squares can be coplanar and you will still be guaranteed that the black square is drawn over the white square.
Drawing order is hard. There is no easy solution. The painter's alogorithm (sort objects by their distance in relation to your camera's view) is the most straightforward, but as you have discovered, it doesn't solve all cases.
I would suggest a combination of the painter's algroithm and layers. You build layers for specific elements on your program. So you got a background layer, objects layers, special effect layers, and GUI layer.
Use the painter's algorithm on each layer's items. In some special layers (like your GUI layer), don't sort with the painter's algorithm, but by your call order. You call that white square first so it gets drawn first.
Draw items that you want to be in back slightly behind the items that you want to be in the front. That is, actually change the z value (assuming z is perpendicular to the screen plane). You don't have to change it a lot to get the items to draw in front of eachother. And if you only change the z value slightly, you shouldn't notice much of an offset from their desired position. You could even go really fancy, and calculate the correct x,y position based on the changed z position, so that the item appears where it is supposed to be.
Your stuff will be drawn in the exact order you call the glBegin/glEnd functions in. You can get depth-buffering using the z-buffer, and if your 2d objects have different z values, you can get the effect you want that way. The only way you are seeing the behavior you describe on the Mac is if the program is drawing stuff in back-to-front order manually or using the z-buffer to accomplish this. OpenGL otherwise does not have any functionality automatically as you describe.
As AlanKley pointed out, the way to do this is to disable the depth buffer. The painter's algorithm is really a 2D scan-conversion technique used to render polygons in the correct order when you don't have something like a z-buffer. But you wouldn't apply it to 3D polygons. You'd typically transform and project them (handling intersections with other polygons) and then sort the resulting list of 2D projected polygons by their projected z-coordinate, then draw them in reverse z-order.
I've always thought of the painter's algorithm as an alternate technique for hidden surface removal when you can't (or don't want to) use a z-buffer.