OpenGL - How to create Order Independent transparency? - c++

I've been working on a game engine for educational purposes and I came across this issue I cannot seem to find an answer for:
Alpha channel only works for objects that have already been drawn before the object that has the alpha channel (For example: in a scene with 3 objects, let's say a cat, a dog and a bottle(transparent). both the cat and the dog are behind the bottle; the dog is drawn first, the bottle second, the cat third. only the dog will be seen through the bottle).
Here's a picture of this issue:
I used C++ for the engine, Win32 API for the editor and GLSL for shading:
// some code here
vec4 alpha = texture2D(diffuse, texCoord0).aaaa;
vec4 negalpha = alpha * vec4(-1,-1,-1,1) + vec4(1,1,1,0);
vec4 textureComponentAlpha = alpha*textureComponent+negalpha*vec4(1,1,1,0);//(texture2D ( diffuse, texCoord0 ) ).aaaa;
gl_FragColor = (textureComponentAlpha + vec4(additiveComponent.xyz, 0)) * vec4(lightingComponent.xyz, 1);
In C++:
glEnable(GL_ALPHA_TEST);
glDepthFunc(GL_EQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
I assume it has something to do with the way the alpha test is made, or something like that.
Could anyone help me fix this, please?

I am using something similar to that answer linked by #RetoKoradi comment but I got double layered transparent models with textures (glass with both inner and outer surface) with fully solid machinery and stuff around.
For such scenes I am using also multi pass approach and the Z-sorting is done by sequence of setting front face.
render all solid objects
render all transparent objects
This is the tricky part first I set
glGetIntegerv(GL_DEPTH_FUNC,&depth_funct);
glDepthFunc(GL_ALWAYS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_CULL_FACE);
I got the geometry layers stored separately (inner outer) so The Z-sorting is done like this:
Render outer layer back faces with glFrontFace(GL_CW);
Render inner layer back faces with glFrontFace(GL_CW);
Render inner layer front faces with glFrontFace(GL_CCW);
Render outer layer front faces with glFrontFace(GL_CCW);
And lastly restore
glDisable(GL_BLEND);
glDepthFunc(depth_funct);
render all solid objects again
It is far from perfect but enough for my purposes it looks like this:

I cannot encourage you enough to have a look at this NVidia paper and the related blog post by Morgan McGuire.
This is pretty easy to implement and has great results overall.

Im not entirely sure this will help your situation, but do you have blending and alpha enabled? As in :
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

The method to get correct transparency of rendered objects independently from the order in which they are drawn is named Order Independent Transparency (OIT).
There is a great presentation from Nvidia summarizing the latest solutions in this area: Order Independent Transparency In OpenGL 4.x
"OpenGL 4.x" in the title is not accidental, because only in OpenGL 4.2 core appears Atomic Counters, which are important for OIT implementation.
One of the algorithms of OIT is as follows:
During the first pass of rendering, store each fragment in a buffer, and collect all fragments for a single screen pixel in a linked list. Atomic Counters are used both to store new fragments in a buffer and to maintain linked list in each screen pixel.
During the second pass of rendering, each linked list is sorted according to z-depth and fragments are alpha-blended in correct order.
A simple alternative to OIT is to discard every second (odd) fragment in a fragment shader:
if (onlyOddFragments && ((int(gl_FragCoord.x) + int(gl_FragCoord.y)) % 2) == 1)
discard;
So you will see the objects farther from the camera in the discarded fragments. If multisample antialiasing (MSAA) is activated, then no checkboard pattern is visible even in lowest resolution.
Here is a video comparing the standard transparency approach where all triangles are output simply in order, as well as two above approaches. The implementation can be found in some open-source GitHub projects, e.g. here.

Related

OpenGL 3.0 (and higher) alpha test based on accumulated alpha value

I have a scene in which there are many parallel squares with different semi-transparent textures.
To render them properly, I disable Z-buffer test, enable blending in the following way and render squares from the most distant one to the closest one (i.e. from back to front).
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
So each square contribute to the resulting value in the color buffer. Is it possible to render them from front to back and discard a fragment if this fragment does not contribute much to the resulting color (i.e. alpha value in color buffer > some threshold)?
I know there is discard command in the fragment shader, but I see no way how I can control blending from the shader.
P.S. I do not know OpenGL terminology much. To be clear, I'll provide an example. Imagine you have a dark optical filter and put it against a wall. The wall will be barely visible (it gives a small contribution to the "rendering"). Put another optical filter in the front of the first one. The wall will not be visible behind those filters. Is there a way in OpenGL to not render that part of the wall which is not visible?

Draw multiple shapes in one vbo

I want to render multiple 3D cubes from one vbo. Each cube has a uniform color.
At this time, I create a vbo where each vertex has a color information.
Is it posible to upload only one color for a one shape (list of verticies)?
I'm also want to mix GL_TRIANGLES and GL_LINES in the glDrawElements-method of the same shader. Is it posible?
//Edit : I only have OpenGL 2.1. Later I want to build this project on Android.
//Edit 2:
I want to render a large count of cubes (up to 150.000). One cube has 24 verticies of geometry and color and 34 indices. Now my idea is to create some vbo's (maybe 50) and share out the cubes to the vbo's. I hope that this minimizes the overhead.
Drawing lots of cubes
Yes, if you want to draw a bunch of cubes, you can specify the color for each cube once.
Create a VBO containing the vertexes for one cube.
// cube = 36 vertexes with glDrawArrays(GL_TRIANGLES)
vbo1 = [v1] [v2] [v3] ... [v36]
Create another VBO with the view matrix and color for each cube, and use an attribute divisor of 1. (You can use the same vbo, but I would use a separate one.)
vbo2 = [cube 1 mat, color] [cube 2 mat, color] ... [cube N mat, color]
Call glDrawElementsInstanced() or glDrawArraysInstanced(). This will draw the cube over and over again.
Alternatively, you can use glUniform() for each cube, but this will limit the number of cubes you can draw. The above method will let you draw thousands, easily.
Mixing GL_TRIANGLES and GL_LINES
You will have to call glDraw????() once for each type of primitive. You can use the same shader for both times, if you like.
Regarding your questions :
Is it possible to upload only one color for one shape ?
Yes , you can use a uniform instead of a vertex attribute(ofc this means changes in more places). However, you will need to set the uniform for each shape, and have a different drawcall for each differently colored shape .
Is it possible to mix GL_TRIANGLES and GL_LINES in the glDrawElements ?
Yes and no. Yes , but you will need a new drawcall (which is obvious). You cannot do on the same drawcall some shapes with GL_TRIANGLES and some shapes with GL_LINES.
In pseudocode this will look like this :
draw shapes 1,2,10 from the vbo using color red and GL_TRIANGLES
draw shapes 3,4,6 from the vbo using color blue and GL_LINES
draw shapes 7,8,9 from the vb using color blue and GL_TRIANGLES
With OpenGL 2.1, I don't think there's a reasonable way of specifying the color only once per cube, and still draw everything in a single draw call.
The most direct approach is that, instead of having the color attribute in a VBO, you specify it directly before the draw call. Assuming that you're using generic vertex attributes, where you would currently have:
glEnableVertexAttribArray(colorLoc);
glVertexAttripPointer(colorLoc, ...);
you do this:
glDisableVertexAttribArray(colorLoc);
glVertexAttrib3f(colorLoc, r, g, b);
where glDisableVertexAttribArray() is only needed if the array was previously enabled for the location.
The big disadvantage is that you can only draw cubes with the same color in one draw call. In the extreme case, that's one draw call per cube. Of course if you have multiple cubes with the same color, you could still batch those into a single draw call.
You wonder whether this is more efficient than having a color for each vertex in the VBO? Impossible to say in general. You'll always get the same answer in cases like this: Try both, and benchmark. I'm skeptical that you will find it beneficial. In my experience, it's fairly rare for fetching vertex data to be a major performance bottleneck. So cutting out one attribute will likely no give you much of a gain. On the other hand, making many small draw calls absolutely can (and often will) hurt performance.
There is one option you can use that is sort of a hybrid. I'm not necessarily recommending it, but just in the interest of brainstorming. If you use a fairly limited number of colors, you can use a single scalar attribute in the VBO that encodes a "color index". Then in the vertex shader, you can use a texture lookup to translate the "color index" to the actual color.
The really good options are beyond OpenGL 2.1. #DietrichEpp nicely explained instanced rendering, which is an elegant solution for cases like this.
And no, you can not have lines and triangles in the same draw call. Even the most flexible draw calls in OpenGL 4.x, like glDrawElementsIndirect(), still take only one primitive type.

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.

GLSL Shader for geometric primitives in the Blender Game Engine

I want to draw geometric primitives in Blenders Game Engine by using a GLSL Shader.
For example:
glBegin(GL_LINE_STRIP);
glVertex2f(-0.6,0.3);
glVertex2f(-0.3,0.2);
glVertex2f(-.65, 0.2);
glVertex2f(-0.4, 0.05);
glEnd();
How to wrap this into VertexShader = """
...code...
""" or does it even belong there at all since this shape has nothing to do with a scene-objects vertecies? And do I enable it in the Logic Editor to an object by using an always sensor that links to the script in order for it to work?
All I want to do is to draw a line, along some x and y coordinates (z is 0 in this case). Also it should be scalable enough to draw an entire array of values, but after hours of research i'd be happy to just get three points to work! A simple example would be appreciated a lot.
So its all about how to geht basic stuff like this displayed in BGE by using gpu based GLSL:
http://www.informit.com/articles/article.aspx?p=328646&seqNum=6
or here on stackoverflow
Is it possible to draw line thickness in a fragment shader?
PS.
I could not find anything fitting for my Problem on http://en.wikibooks.org/wiki/GLSL_Programming
And Rasterizer.drawLine() from bge doesn't work for my purposes, since it behaves odd, disappears immediately and the points cant be accessed/edited/moved afterwards.

Outline effects in OpenGL

In OpenGL, I can outline objects by drawing the object normally, then drawing it again as a wireframe, using the stencil buffer so the original object is not drawn over. However, this results in outlines with one solid color.
In this image, the pixels of the creature's outline seem to get more transparent the further they are from the creature they outline. How can I achieve a similar effect with OpenGL?
They did not use wireframe for this. I guess it is heavily shader related and requires this:
Rendering object to a stencil buffer
Rendering stencil buffer with color of choice while applying blur
Rendering model on top of it
I'm late for an answer but I was trying to achieve the same thing and thought I'd share the solution I'm using.
A similar effect can be achieved in a single draw operation with a not so complex shader.
In the fragment shader, you will calculate the color of the fragment based on lightning and texture giving you the un-highlighted color 'colorA'.
Your second color is the outline color, 'colorB'.
You should obtain the fragment to camera vector, normalize it, then get the dot product of this vector with the fragment's normal.
The fragment to camera vector is simply the inverse of the fragment's position in eye-space.
The colour of the fragment is then:
float CameraFacingPercentage = dot(v_fragmentToCamera, v_Normal);
gl_FragColor = ColorA * CameraFacingPercentage + ColorB * (1 - FacingCameraPercentage);
This is the basic idea but you'll have to play around to have more or less of the outline color. Also, the concave parts of your model will also be highlighted but that is also the case in the image posted in the question.
Detect edges in GLSL shader using dotprod(view,normal)
http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Toon_Shading#Outlines
As far as I see it the effect on the screen short and many "edge" effects are not pure edges, as in comic outline. What mostly is done, you have one pass were you render the object normally then a pass with only the geometry (no textures) and a GLSL shader. In the fragment shader the normal is taken and that normal is perpendicular to the camera vector you color the object. The effect is then smoothed by including area close to perfect perpendicular.
I would have to look up the exact math but I think if you take the dot product of the camera vector and the normal you get the amount of "perpendicularness". That you can then run through a function like exp to get a bias towards 1.
So (without guarantee that it is correct):
exp(dot(vec3(0, 0, 1), normal));
(Note: everything is in screenspace.)