[GLSL 130] Why I don't have the excepted final color in my shader?

Hi everyone!

My plateform (Ubuntu 14.4 LTS 64 bits) only support opengl 3.0 and GLSL 130, I can’t use pixel linked list from opengl 450.

I’m trying to find an alternative so :

Here is the technique which I use :

I clear an FBO with a clear color, at each time I draw something, I get the texture. I also use an FBO with transparent color, and I get a second texture. (for the depthbuffer)

In the first texture I save the color of each fragment and in the second texture I save the depth and the alpha of each fragment. (You’ll see why further)

The first object is drawn with the classical blending equation so :

Blending : clear color (0, 0, 0, 1)

FB color : (0, 0, 0, 1)
DB z : 0
a : 0
Current Color : (1, 0, 0, 0.5)
Current z : 0
a = 0.5

Final color = (1, 0, 0, 0.5) * 0.5 + (0, 0, 0, 1) * (1 - 0.5) = (0.5, 0, 0, 0.75)

FB color is the color written in the first texture, DB z and a are the depth and the alpha written in the second texture, Current Color and Current z and a are the color, the z and the alpha of what I’m curretly drawing.

So the equation is SRCCOLOR * SRCALPHA + DSTCOLOR * (1 - SRCALPHA)

I need to change the blending equation, if the object I draw is behind the object which is already drawn, so in this case the bleding equation is

DSTCOLOR * DSTALPHA + SRCCOLOR * (1 - DSTALPHA)

So dstalpha is the alpha of the fragment which has been drawn previously, I give the same color in the two cases so it doesn’t matter is an object is behind or before another one, in other worlds, the order in which I draw my objects doesn’t matter.

Case 1 : (The object which is drawn is behind the object to draw.)

FB color : (1, 0, 0, 0.75)
DB z : 0
DB a : 0.5
Current Color : (1, 1, 0, 0.5)
Current z : 1
a : 0.5

Final color : (1, 1, 0, 0.5) * 0.5 + (1, 0, 0, 0.75) * (1 - 0.5) = (1, 0.5, 0, 0.652)


Cas 2 : (The object which is drawn is before the object I draw.)

FB color : (1, 0, 0, 0.75)
DB z : 1
DB a : 0.5
Current Color : (1, 1, 0, 0.5)
Current z : 0
a : 0.5

Final color : (1, 1, 0, 0.5) * 0.5 + (1, 0, 0, 0.75) * (1 - 0.5) = (1,0.5, 0, 0, 625)

So I desactivated the opengl blending and I’ve written this two shader (he one to generate the first texture, and the second to generate the second and the final texture that I draw on the window)

The vertex shader is very simple and is the same for both textures.


#version 130
out mat4 projMat;
void main () {
       gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
       gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
       gl_FrontColor = gl_Color;
       projMat = gl_ProjectionMatrix;
};

The fragment shader for the first texture is :


#version 130 

uniform sampler2D depthBuffer;
uniform sampler2D texture;
uniform vec3 resolution;"
uniform float haveTexture;
in mat4 projMat;
void main () {
       vec2 position = ( gl_FragCoord.xy / resolution.xy );
       vec4 color = texture2D(depthBuffer, position);
       vec4 pixel = (haveTexture==1) ? gl_Color * texture2D(texture, gl_TexCoord[0].xy) : gl_Color;
       float z = (gl_FragCoord.w != 1.f) ? (inverse(projMat) * vec4(0, 0, 0, gl_FragCoord.w)).w : gl_FragCoord.z;
       vec4 colors[2];
       colors[1] = vec4(z, pixel.a, z, pixel.a);
       colors[0] = vec4(z, pixel.a, color.b, color.a);
       bool b = (z >= color.z && pixel.a >= color.a);
       gl_FragColor = colors[int(b)];
}

And the one for the second texture is :


#version 130 

uniform sampler2D depthBuffer;
uniform sampler2D frameBuffer;
uniform sampler2D texture;
uniform vec3 resolution;
uniform float haveTexture;
in mat4 projMat;
void main () {
       vec2 position = ( gl_FragCoord.xy / resolution.xy );
       vec4 depth = texture2D(depthBuffer, position);
       vec4 color = texture2D(frameBuffer, position);
       vec4 pixel = (haveTexture==1) ? gl_Color * texture2D(texture, gl_TexCoord[0].xy) : gl_Color;
       float z = (gl_FragCoord.w != 1.f) ? (inverse(projMat) * vec4(0, 0, 0, gl_FragCoord.w)).w : gl_FragCoord.z;
       vec4 colors[2];
       colors[1] = pixel * pixel.a + color * (1 - pixel.a);       
       colors[0] = color * depth.g + pixel * (1 - depth.g);      
       bool b = (z >= depth.r);
       gl_FragColor = colors[int(b)];                           

I avoid to use an if structure for optimization purposes.

My code simply draw two rectangles (a semi-transparent red one and a semi-transparent yellow one) on the textures with the shaders.


currentStates.shader = frameBufferGenerator;
frameBuffer->draw(m_instances[i]->getVertexArray(), currentStates);
frameBuffer->display();
currentStates.shader = depthBufferGenerator;
depthBuffer->draw(m_instances[i]->getVertexArray(), currentStates);
depthBuffer->display();

But the result I get is not the result that I expected.

The alpha blending is not performed. :confused:

Here is what I have :

[ATTACH=CONFIG]934[/ATTACH]

Why the blending isn’t applied in my fragment shader ?

Thanks for help.

Erf I’ve found why, this is because, I draw every vertices of each quads at once for optimization purpose, so I need to find another solution, if anyone have an idea.

Now I draw the rectangles one by one and it works, but the number of draw call increase so the FPS decrease and I’ve a FPS between 15-20 instead of an FPS between 25-30.

The only solution that I’ve is to read/write fragments at the same time, so, I don’t have to wait that the rectangle is drawn to get fragments colors and depth in the buffer but I don’t thing this is possible. :confused:

Not with OpenGL 3.x. You can do it with image load/store, but that requires OpenGL 4.2.

Arf…, ok, so I haven’t any choise, I have to draw the faces of my object one by one.

It’s slower but at least it works with order independant transparency.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.