Order of translucent object rendering - opengl

When rendering a translucent object (using glBlend), it is advised to sort objects from back to front z order.
From opengl docs:
When using depth buffering in an application, you need to be careful about the order in which you render primitives. Fully opaque primitives need to be rendered first, followed by partially opaque primitives in back-to-front order. If you don't render primitives in this order, the primitives, which would otherwise be visible through a partially opaque primitive, might lose the depth test entirely.
So, whenever I'm rendering translucent objects after rendering opaque triangles, if I render translucent triangles from back to front in relation to the "view direction", is this correct? What exactly does back to front mean here? I'm trying to understand, if I have a scene objects that go through a mvp transformation, do I need to specifically look at the order in world coordinates, and in relation to the camera center?
Also, additionally does this change depending on the blend type?

Whenever you render translucent triangles, you have to draw them back-to-front. Back-to-front here means, that you have to draw triangles first that are further away from the screen (that have a higher depth value).
The reason why this is necessary is that most blending equations yield different results depending on the order. The equations as implemented in OpenGL are usually such that they give "correct" results when rendering back-to-front.

I think the order matters not only because of the blending function you
are using but one important aspect of pipeline you have to keep in mind. The z test happens before blending operation down the line in pipeline.
Consider scenario where we are drawing two triangles t1 and t2 t1 is back of t2.
So If z test rejects all fragments belonging to t1 so no color value for t1 is written to color buffer. Now later on t2 fragments are being drawn which is exactly in front of t1 which z test rejected in last step. So ideally the colors of t1 would have been blended with colors of t2 but because of failed z test of t1 and blending operation being after z test t2 colors wont be blended.
Hence If you are not keeping order then disable z test and then draw your object with proper blending function. This is not so good in performance as lots of z tests will fail.
So you maintain order or polygons but this solution also doesnt scale with number of polygons increasing and when there is mixture of opaque and transparent objects.
Hence new solution is proposed of using order independent trasparency.
Different ways are there to implement this and you dont have to worry about order of objects.
I have implemented solution using per pixel linked list in fragment shader. You can find link below. This is not best solution but should give you fair idea.
Order Independent Transparency

Related

Is there a defined draw order for OpenGL instanced drawing? [duplicate]

Here's what I'm trying to do: I want to render a 2D scene, consisting of a number of objects (quads), using instancing. Objects with a lower y value (towards the bottom of the screen) need to be rendered in front of the ones with higher y values. And alpha blending also needs to work.
So my first idea was to use the Z value for depth, but I soon realized alpha blending will not work unless the objects are drawn in the right order. But I'm not issuing one call for each quad, but use a single instanced call to render the whole scene. Putting the instance data in the correct sorted order seems to work for me, but I doubt this is something I can rely on, since the GPU is supposed to run those computations in parallel as much as possible.
So the question is, is there a way to make this work? The best thing I can think of right now is to issue an instanced call for each separate y value (and issue those in order, back to front). Is there a better way to do this?
Instancing is best used for cases where each instance is medium-sized: hundreds or maybe thousands of triangles. Quads are not a good candidate for instancing.
Just build and render a sequence of triangles. There are even ways to efficiently get around the lack of a GL_QUADS primitive type in modern OpenGL.
Putting the instance data in the correct sorted order seems to work for me, but I doubt this is something I can rely on, since the GPU is supposed to run those computations in parallel as much as possible.
That's not how GPUs work.
When you issue a rendering command, what you (eventually) get is a sequence of primitives. Because the vertices that were given to that command are ordered (first to last), and the instances in that command are ordered, and even the draws within a single draw command are ordered, an order can be assigned to every primitive in the draw call with respect to every other primitive based on the order of vertices, instances, and draws.
This defines the primitive order for a drawing command. GPUs guarantee that blending (and logical operations and other visible post-fragment shader operations) will respect the primitive order of a rendering command and between rendering commands. That is, if you draw 2 triangles in a single call, and the first is behind the second (with depth testing turned off), then blending for the second triangle will respect the data written by the first.
Basically, if you give primitives to the GPU in an order, the GPU will respect that order with regard to blending and such.
So again, just build a ordered stream of triangles to represent your quads and render them.

Using OpenGL instancing for rendering 2D scene with object depths and alpha blending

Here's what I'm trying to do: I want to render a 2D scene, consisting of a number of objects (quads), using instancing. Objects with a lower y value (towards the bottom of the screen) need to be rendered in front of the ones with higher y values. And alpha blending also needs to work.
So my first idea was to use the Z value for depth, but I soon realized alpha blending will not work unless the objects are drawn in the right order. But I'm not issuing one call for each quad, but use a single instanced call to render the whole scene. Putting the instance data in the correct sorted order seems to work for me, but I doubt this is something I can rely on, since the GPU is supposed to run those computations in parallel as much as possible.
So the question is, is there a way to make this work? The best thing I can think of right now is to issue an instanced call for each separate y value (and issue those in order, back to front). Is there a better way to do this?
Instancing is best used for cases where each instance is medium-sized: hundreds or maybe thousands of triangles. Quads are not a good candidate for instancing.
Just build and render a sequence of triangles. There are even ways to efficiently get around the lack of a GL_QUADS primitive type in modern OpenGL.
Putting the instance data in the correct sorted order seems to work for me, but I doubt this is something I can rely on, since the GPU is supposed to run those computations in parallel as much as possible.
That's not how GPUs work.
When you issue a rendering command, what you (eventually) get is a sequence of primitives. Because the vertices that were given to that command are ordered (first to last), and the instances in that command are ordered, and even the draws within a single draw command are ordered, an order can be assigned to every primitive in the draw call with respect to every other primitive based on the order of vertices, instances, and draws.
This defines the primitive order for a drawing command. GPUs guarantee that blending (and logical operations and other visible post-fragment shader operations) will respect the primitive order of a rendering command and between rendering commands. That is, if you draw 2 triangles in a single call, and the first is behind the second (with depth testing turned off), then blending for the second triangle will respect the data written by the first.
Basically, if you give primitives to the GPU in an order, the GPU will respect that order with regard to blending and such.
So again, just build a ordered stream of triangles to represent your quads and render them.

OpenGL Alpha blending and object independent transparency

I am trying to implement object independent transparency (OIT) using the following naive technique:
Sort opaque and transparent objects.
Render opaque with depth write on.
Disable depth write, enable alpha blending, and render the transparent objects.
It work ok if I have fully opaque and transparent objects only.But what about the case where some objects have transparent alpha textures (all my meshes are planar) and need Alpha blending on, and other are transparent.What is the routine in this case?
Currently, if I render the transparent first with depth write on and alpha blend on too, then rendering the object with alpha channel texture (depth write off, blend on) what happens is that the part of the last rendered plane that intersects into the first plane gets culled. Here is a picture to depict what I am after:
Both planes have some amount of transparency and still maintain depth sort.
I know I can use more sophisticated approaches for OIT like this. But is it possible to do it without getting into fragment linked lists etc?
A rasterization-based renderer, by its very nature, cannot handle transparency well. Rasterizers work by rendering an object, then rendering another. It has no idea of what has been rendered before or what will be rendered afterwards. It's job is to take a 3D shape and turn it into a field of colors.
If there was a simple technique for doing order-independent transparency, then you'd have heard about it by now because everyone would be using it. There isn't. Every general OIT technique is complicated and has some performance downsides associated with it.
Is it possible to find a way for the very specific case of two planes intersecting with nothing else on the screen? Yes. Could you generalize that method for arbitrary scenes with arbitrary transparency? No.

Is drawing front-to-back necessary for optimizing renders?

I've seen the occasional article suggest ordering your vertices from nearest to furthest from the camera when sending them to OpenGL (for any of the OpenGL variants). The reason suggested by this is that OpenGL will not fully process/render a vertex if it is behind another vertex already rendered.
Since ordering vertices by depth is a costly component of any project, as typically this ordering frequently changes, how common or necessary is such design?
I had previously thought that OpenGL would "look" at all the vertices submitted and process its own depth buffering on them, regardless of their order, before rendering the entire batch. But if in fact a vertex gets rendered to the screen before another, then I can see how ordering might benefit performance.
Is drawing front-to-back necessary for optimizing renders?
Once a primitive is rasterized, its z value can be used to do an "early z kill", which skips running the fragment shader. That's the main reason to render front-to-back. Tip: When you have transparent (alpha textured) polygons, you must render back-to-front.
The OpenGL spec defines a state machine and does not specify in what order the rendering actually happens, only that the results should be correct (within certain tolerances).
Edit for clarity: What I'm trying to say above is that the hardware can do whatever it wants, as long as the primitives appear to have been processed in order
However, most GPUs are streaming processors and their OpenGL drivers do not "batch up" geometry, except perhaps for performance reasons (minimum DMA size, etc). If you feed in polygon A followed by polygon B, then they are fed into the pipeline one after the other and are processed independently (for the most part) of each other. If there are a sufficient number of polys between A and B, then there's a good chance A completes before B, and if B was behind A, its fragments will be discarded via "early z kill".
Edit for clarity: What I'm trying to say above is that since hw does not "batch up" geometry, it cannot do the front-to-back ordering automatically.
You are confusing a few concepts here. There is no need to re-order vertices (*). But you should draw objects that are opaque front to back. This enables what is called "early z rejection" on the GPU. If the GPU knows that a pixel is not going to be shaded by the z test it does not have to run the shader, do texture fetches etc.. This applies to objects in draw calls though, not to individual objects.
A simple example: You have a player character and a sky background. If you draw the player first, the GPU will never have to do the texture lookups for the pixels where the player is. If you do it the other way around, you first draw all the sky and then cover it up.
Transparent geometry needs to draw back to front of course.
( * )=vertices can be re-ordered for better performance. But doing early z is much more important and done per object.

Disable writing in depth buffer from glsl

All geometry is storing in one VBO (Transparent + Not transparent). I can not sort geometry. How I can disable writing in depth buffer from glsl without loss the data colors?
If I understand right, you want to disable depth writes because you draw both opaque and transparent objects. Apart from the fact that it doesn't work that way from within GLSL, it would not produce what you want, if it did.
If you just disabled depth writes ad hoc, the opaque objects coming after a transparent object would overwrite it, regardless of the z order.
What you really want to do is this:
Enable depth writes and depth test
Draw all opaque geometry. If you can, in a roughly sorted (roughly is good enough!) order, closest objects first.
Disable depth writes, keep depth test enabled
Enable blending
Draw transparent objects, sorted in the opposite direction, that is farthest away first. This occludes transparent objects with opaque geometry and makes blending work correctly.
If, for some reason, you can't sort the opaque geometry (though there is really no reason why you can't do that?), never mind -- it will be slightly slower because it does not cull fragments, but it will produce the same image.
If, for some reason, you can't sort the transparent geometry, you will have to expect incorrect results where several transparent objects overlap. This may or may not be noticeable (especially if the order is "random", i.e. changes frame by frame, it will be very noticeable -- otherwise you might in fact get away with it although it's incorrect).
Note that as datenwolf has pointed out already, the fact that several objects are in one VBO does not mean you can't draw a subset of them, or several subsets in any order you want. After all, a VBO only holds some vertices, it is up to you which groups of them you draw in which order.
You can't.
I can not sort geometry.
Why? You think because it's all in one VBO? Then I've got good news: It's perfectly possible to draw from just a subset of a buffer object.