PDA

View Full Version : Screen space decal blending



germangb
03-20-2015, 05:21 AM
Hi, I have small system to render decals in my program. The pipeline is as follows:

-bind gbuffer (framebuffer)
-render scene
-bind default framebuffer
-render scene
-render box

the box is used to draw the decal, using depth information from the g-buffer pass. What I'm doing is reconstructing the position with the depth buffer from the g-buffer in a fragment shader and then, if the position falls inside the box of the decal, I put the apropiate fragment from the decal texture. This looks ok with single decals, or when the decals do not overlap eachother. For transparency I am mixing the diffuse color from the g-buffer with the color from the decal texture (interpolated using the alpha channel from the decal texture)

https://i.imgur.com/aPcBmNn.png https://i.imgur.com/OcJonK6.png https://i.imgur.com/9lH1JXJ.png

The first image shows a single decal
The second one I try rendering two overlapping decals
The third one shows the boundary of the decal

I know this is expected if I mix the colors the way I am doing it right now, but how could I avoid this behavior? The fragment shader I am using is this:
#version 130

out vec4 frag_color;

// gbuffer information
uniform sampler2D depth;
uniform sampler2D diffuse;

// decal texture
uniform sampler2D texture;
uniform vec3 size;
uniform vec2 resolution;
uniform mat4 inv_mvp; // inverted modelViewProjection

void main () {
// reconstruct position from depth buffer
vec2 uv = gl_FragCoord.xy / resolution;
float depth = texture2D(depth, uv).r;
vec4 screenPos = vec4(uv*2.0-1.0, depth*2.0-1.0, 1.0); // clip space
vec4 localPos = inv_mvp * screenPos;
localPos = vec4(localPos.xyz/localPos.w, localPos.w);

if (
abs(localPos.x) < size.x/2 &&
abs(localPos.y) < size.y/2 &&
abs(localPos.z) < size.z/2) {
vec2 decUv = localPos.xz/size.xz + 0.5;
vec4 color = texture2D(texture, decUv);
vec4 backColor = texture2D(diffuse, uv);
frag_color = vec4(mix(backColor.rgb, color.rgb, color.a), 1.0);
} else discard;

}

EDIT:Enabling blending mode and tweaking the rendering order of the decals solved the problem. can it be made order-independent without sorting?

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
...
...
...
frag_color = color.rgba;

EDIT2:

I disabled depth mask and it worked just fine for now

https://i.imgur.com/SkOJ1rt.png