Techniques for drawing coplanar polygons in OpenGL - 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

Related

In OpenGL, is it possible to draw the edges of the unoccluded triangles only?

I have a mesh to render with OpenGL. What I want is to render its edges, but only the ones of the un-occluded faces. However, I realize that this is not possible with only:
glEnable(GL_DEPTH_TEST); // Enable depth test
glDepthFunc(GL_LEQUAL); // Accept fragment if it closer to the camera than the former one
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
since there is no depth information in-between the edges, so the edges of the occluded triangles are still rendered.
A work around is to draw the triangles with GL_FILL first in background color (in my case, white), and then draw the edges separately. But doing so results in artifacts similar to the z-fighting phenomenon, i.e., some edges seem thinner than others or even vanish, as shown below
On the left is what I have, and on the right is what I desire (viewed in MeshLab). Since depth test of triangles seems to be unavoidable in this case, I guess I am also asking:
How can I draw edges over triangles without the z-fighting artifacts?
Note that face culling is not useful, as it only eliminates faces facing backward, but cannot deal with occlusion.
Set a polygon offset for the first pass with glPolygonOffset:
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1, 1);
Disable the polygon offset for the 2nd pass:
glDisable(GL_POLYGON_OFFSET_FILL);
Polygon fill offset manipulates the depth of a fragment by a minimum amount. This results in the depth of the fragments in the first pass being a small amount greater than the depth of the same fragments in the second pass. This is how you get rid of the deep conflict.

What other ways can I draw the outline of an object?

I have a very simple case. I want to draw the outline of an object, in this case I think they'll only be spheres, but I'd like to not rely on this.
I've found methods such as:
Draw the object to the stencil buffer
Turn on wireframe mode
Draw the object with thick lines
Draw the real object on the top
The problem I have with this method is that my models have a lot of vertices, and this requires me to draw it three times. I'm getting some significant frame rate drops.
Are there other ways to do this? My next guess would be to draw circles on the final render as a post-process effect, seeing as I'm only looking at spheres. But I'd much much rather do this for more than just spheres.
Is there something I can do in an existing shader to outline?
I'd also like the outline to appear when the object is behind others.
I'm using OpenGL 4.3.
I know 3 ways of doing contour rendering:
Using the stencil buffer
The first one is a slightly modified version of the one you described: you first render your object as normal with stencil buffer on, then you slightly scale it and render it plain color where the stencil buffer is not filled. You can find an explanation of this technique here.
Using image processing techniques
The second one is a post-process step, where you look for edges using image processing filters (like the sobel operator) and you compose your rendering with your contour detection result. The good thing with the sobel operator is that it is separable; this means you can do the detection in two 1D passes, which is more efficient that doing one 2D pass.
Using the geometry shader
Last but not least, you can use the geometry shader to extract the silhouette of your mesh. The idea is to use adjacent vertices of a triangle to detect if one edge of this triangle (let call it t0) is a contour.
To do this, for each edge ei of t0:
build a new triangle ti using the vertices of ei and its associated vertex,
compute the normal ni of ti, and the normal n0 of t0, transform them both in view space (the silhouette depends on the point of view),
compute the dot product between n0 and ni. If its value is negative, this means that the normals are in opposite directions and the edge ei is a silhouette edge.
You then build a quad around ei, emit each of its vertices and color them the way you want in the fragment shader.
This is the basic idea of this algorithm. Using only this will result in aliased edges, with holes between them, but this can be improved. You can read this paper, and this blog post for further informations.
In my experience you get good results if you render the outlined object in white (unlit) to a texture as big as the final framebuffer, then draw a framebuffer-sized quad with that texture and have the fragment shader blur or otherwise process it and apply the desired color.
I have an example here

transparency in opengl (using FLTK)

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.

How to clip texture with arbitrary shape?

I am rendering complex 3d objects. Here is a simple example with a sphere-like object:
Next I am applying a clipping plane to these objects and rendering a texture on this plane, giving the impression you are looking at the inside of the object, as if it was sliced. For example:
The problem is the jagged edge of the texture. It will stick out passed the boundary of the surface. Here's another angle where you can see it sticking out. The surface and the texture both derive from the same source data, but the surface is smoothed and has a higher resolution than the texture.
What I want is to be able to somehow clip the texture, so that it never sticks out past the boundary of the surface. Also, I don't want to simply scale down the texture, since although this might prevent it from sticking outside, it would create interior gaps between the texture edge and the surface edge. I would rather the texture be a little too big and have it clipped so that it sits flush against the edge of the surface.
Here's where I am:
I figured the first step would be to define the intersection of the plane and the surface. So now I have that, as an ordered list of line segments. However, I'm not sure how to proceed with this info (or if this is even the best approach).
I've been reading up on stencil buffers. One approach might be to turn the intersection line into a 2d shape and draw this into a stencil buffer. Then apply this when drawing the texture. (Although I think it's a lot of work since the shapes can be complicated.)
I am wondering if I can somehow use the already drawn surface (in conjunction with a stencil buffer or some other technique) to somehow clip the texture -- without having to go through the extra trouble of deriving the intersection line, etc.
What's the best approach here? (Any online examples you can point me to would also be really helpful.)
If you're clipping convex objects and know coordinates of clipped points, you can create polygonal "cap" yourself - just draw clipped points in proper order using GL_TRIANGLE_FAN, and that's it. Won't work with non-convex object - that would require triangulation algorithm. You could use glu tesselators to triangulate polygons, but that can be tricky/difficult.
If clipped area can be defined by formula, you can write a shader that'll precisely clip pixels over certain distance (i.e. if x^2+x^2+z^2 > r^2 do not draw pixel).
You could also draw back-facing faces with a shader that would draw every back facing pixel as if it were on on clip-plane using simple raytracing. That's complicated, and might be overkill in your case. Dead Rising used similar technique in their game engine.
Also you can use stencil buffer.
Draw back-facing faces first with GL_INCR (glStencilOp(GL_KEEP, GL_INCR, GL_INCR)), then draw front-facing surfaces with GL_DECR (glStencilOp(GL_KEEP, GL_DECR, GL_DECR)). Then draw texture only where stencil is non-zero. (glStencilFunc(GL_GREATER, 0, 0xff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);). If you have many overlapping shapes, however, you'll need to take special care of them.
--edit--
However, I'm not sure how to proceed with this info (or if this is even the best approach).
Draw it as a triangle fan. For convex objects, that's all you need. For non-convex objects that won't work.
ve been reading up on stencil buffers. One approach might be to turn the intersection line into a 2d shape
No, it won't work like that. Region you want to fill with texture should hold certain stencil value. That's how stencil clipping works.
to somehow clip the texture
In OpenGL you have 6(?) clip planes. If you need more than that, you'll need advanced techniques - stencil, deriving intersection line, shaders, or triangulation.
Any online examples you can point me to would also be really helpful
Drawing Filled, Concave Polygons Using the Stencil Buffer

Can you render two quads with transparency at the same point?

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.