PDA

View Full Version : Transparency problem - Not able to see all faces behind a transparent face



lucask
11-23-2015, 07:04 AM
Hi,

I am new to this forum. I am programming in C# with Tao.FreeGlut
I am trying to display a list of colored faces from which some are transparent.

I initialize openGL with the following code (this is only the code I think matters for the problem I have):



Glut.glutInit();
Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_DEPTH);

Gl.Enable(EnableCap.DepthTest);
Gl.Enable(EnableCap.Blend);
Gl.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
Gl.ClearColor(1, 1, 1, 1);

Shader.program = new ShaderProgram(Shader.VertexShader, Shader.FragmentShader);

Shader.program.Use();
Shader.program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.4 5f, (float)width / height, 0.1f, 1000f));
Shader.program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(100, 100, 100), Vector3.Zero, Vector3.Up));

Shader.program["light_direction"].SetValue(new Vector3(0, 1, 1));
Shader.program["enable_lighting"].SetValue(lighting);

Glut.glutMainLoop();


Shader is simply a class that contains the ShaderProgram, the the VertexShader and the FragmentShader which are as follows:



string VertexShader = "
#version 130

in vec3 vertexPosition;
in vec3 vertexNormal;
in vec3 vertexColor;
in vec2 vertexAlpha;

out vec3 normal;
out vec3 color;
out vec2 alpha;

uniform mat4 projection_matrix;
uniform mat4 view_matrix;
uniform mat4 model_matrix;

void main(void)
{
normal = normalize((model_matrix * vec4(floor(vertexNormal), 0)).xyz);
color = vertexColor;
alpha = vertexAlpha;

gl_Position = projection_matrix * view_matrix * model_matrix * vec4(vertexPosition, 1);
}
";
string FragmentShader = "
#version 130

uniform vec3 light_direction;
uniform bool enable_lighting;

in vec3 normal;
in vec3 color;
in vec2 alpha;

out vec4 fragment;

void main(void)
{
float diffuse = max(dot(normal, light_direction), 0);
float ambient = 0.3;
float lighting = (enable_lighting ? max(diffuse, ambient) : 1);

fragment = vec4(lighting * color, alpha[0]);
}
";


Then I try to render the next frame like this:



Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

Gl.UseProgram(Shader.program);
Shader.program["model_matrix"].SetValue(myCam.ViewMatrix);
Shader.program["enable_lighting"].SetValue(lighting);

foreach (Glut3DModel model in MyGlut.models)
{
foreach (Glut3DObj obj in model.objects)
{
Gl.BindBufferToShaderAttribute(obj.VBOObj, Shader.program, "vertexPosition");
Gl.BindBufferToShaderAttribute(obj.VBONormals, Shader.program, "vertexNormal");
Gl.BindBufferToShaderAttribute(obj.VBOColors, Shader.program, "vertexColor");
Gl.BindBufferToShaderAttribute(obj.VBOAlphas, Shader.program, "vertexAlpha");
Gl.BindBuffer(obj.VBOQuads);

Gl.DrawElements(BeginMode.TriangleFan, obj.VBOQuads.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
}
}

Glut.glutSwapBuffers();


As you can see in the foreach loops I have a list of 3D objects that consist of multiple faces. These are stored with their points (VBOObj), normals, colors and alpha values.

Now I have the problem that I can see the transparent faces, but not all faces that are behind that face are visible through the transparent face (as you can see in the images below).

2189

I hope anyone here can help me with this problem. I couldn't find out whats wrong in my code.
Thank you very much for your help!

Lucas (from Germany)

Cornix
11-23-2015, 09:03 AM
If I had to guess I would say the problem is with depth testing. Even if a face is translucent it may write a value to the depth buffer. A face that is later drawn may then be discarded because it fails the depth test. For translucent faces you have to disable depth tasting and sort your meshes back-to-front before rendering.

lucask
11-24-2015, 02:00 AM
Thanks Cornix,

I also read something about the depth buffer and tried to deactivate it.
But how do I do the sorting of the meshes before the rendering then?
Appreciate your help!
Thanks,

Lucas

GClements
11-24-2015, 06:05 AM
But how do I do the sorting of the meshes before the rendering then?

In the general case, you need to use a topological sort (https://en.wikipedia.org/wiki/Topological_sorting). Note that it's possible for the ordering graph to contain cycles, in which case you need to split polygons to break the cycles. If the relative locations of the polygons are fixed, It's possible to store them in a BSP tree, which reduces the amount of work which needs to be done each frame.

In some cases, simply sorting by the eye-space Z coordinate of some point (centroid, closest point, farthest point) may be sufficient.

Either way, it's only necessary to sort the translucent faces; opaque faces can be rendered normally using depth testing.

Nowadays, use of "depth peeling" is more common, but that's fairly complex. It involves rendering in multiple passes, using a fragment shader to discard fragments which have already been rendered, and compositing the results.