我正在进行双深度剥离。我想问你,如何正确。我有这样的算法。
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBindFramebuffer(GL_FRAMEBUFFER, dualDepthFBOID);
// Render targets 1 and 2 store the front and back colors
// Clear to 0.0 and use MAX blending to filter written color
// At most one front color and one back color can be written every pass
glDrawBuffers(2, &drawBuffers[1]);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
GL_CHECK_ERRORS
// Render target 0 stores (-minDepth, maxDepth, alphaMultiplier)
glDrawBuffer(drawBuffers[0]);
glClearColor(-MAX_DEPTH, -MAX_DEPTH, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glBlendEquation(GL_MAX);
DrawScene(MVP, initShader);
// 2. Depth peeling + blending pass
glDrawBuffer(drawBuffers[6]);
glClearColor(bg.x, bg.y, bg.z, bg.w);
glClear(GL_COLOR_BUFFER_BIT);
int numLayers = (NUM_PASSES - 1) * 2;
int currId = 0;
for (int layer = 1; bUseOQ || layer < numLayers; layer++) {
currId = layer % 2;
int prevId = 1 - currId;
int bufId = currId * 3;
glDrawBuffers(2, &drawBuffers[bufId+1]);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(drawBuffers[bufId+0]);
glClearColor(-MAX_DEPTH, -MAX_DEPTH, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
// Render target 0: RG32F MAX blending
// Render target 1: RGBA MAX blending
// Render target 2: RGBA MAX blending
glDrawBuffers(3, &drawBuffers[bufId+0]);
glBlendEquation(GL_MAX);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE, depthTexID[prevId]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_RECTANGLE, texID[prevId]);
DrawScene(MVP, dualPeelShader, true,true);
// Full screen pass to alpha-blend the back color
glDrawBuffer(drawBuffers[6]);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (bUseOQ) {
glBeginQuery(GL_SAMPLES_PASSED_ARB, queryId);
}
GL_CHECK_ERRORS
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE, backTexID[currId]);
blendShader.Use();
DrawFullScreenQuad();
blendShader.UnUse();
if (bUseOQ) {
glEndQuery(GL_SAMPLES_PASSED);
GLuint sample_count;
glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, &sample_count);
if (sample_count == 0) {
break;
}
}
GL_CHECK_ERRORS
}
GL_CHECK_ERRORS
glDisable(GL_BLEND);
// 3. Final render pass
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK_LEFT);
glBindTexture(GL_TEXTURE_RECTANGLE, colorBlenderTexID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE, depthTexID[currId]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_RECTANGLE, texID[currId]);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_RECTANGLE, colorBlenderTexID);
finalShader.Use();
DrawFullScreenQuad();
finalShader.UnUse();
我正在使用dualPeelShader进行照明,每次通过都会点亮。这导致了极其明亮的物体。我应该在finalShader做照明吗?
--- ---- EDIT
剥离片段着色器
#version 330 core
layout(location = 0) out vec4 vFragColor0;
layout(location = 1) out vec4 vFragColor1;
layout(location = 2) out vec4 vFragColor2;
uniform vec4 vColor;
uniform float isObject;
uniform vec3 LightPosition;
uniform sampler2DRect depthBlenderTex;
uniform sampler2DRect frontBlenderTex;
in vec4 vOutColor;
in vec3 position;
in vec3 normal;
in vec3 eyeDirection;
in vec3 lightDirection;
#define MAX_DEPTH 1.0
vec4 Lighted()
{
vec3 LightColor = vec3(1.0,1.0,1.0);
float LightPower = 50;
// Material properties
vec3 MaterialDiffuseColor = vOutColor.rgb;
vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
vec3 MaterialSpecularColor = vec3(0.3,0.3,0.3);
// Distance to the light
float distance = length( LightPosition - position );
// Normal of the computed fragment, in camera space
vec3 n = normalize( normal );
// Direction of the light (from the fragment to the light)
vec3 l = normalize( lightDirection);
// Cosvaryinge of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendicular to the triangle -> 0
// - light is behvaryingd the triangle -> 0
float cosTheta = clamp( dot( n,l ), 0,1 );
// Eye vector (towards the camera)
vec3 E = normalize(eyeDirection);
// Direction in which the triangle reflects the light
vec3 R = reflect(-l,n);
// Cosvaryinge of the angle between the Eye vector and the Reflect vector,
// clamped to 0
// - Lookvaryingg varyingto the reflection -> 1
// - Lookvaryingg elsewhere -> < 1
float cosAlpha = clamp( dot( E,R ), 0,1 );
return vec4(MaterialAmbientColor + MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) +
MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance),vOutColor.a);
}
void main(void)
{
float fragDepth = gl_FragCoord.z;
vec2 depthBlender = texture(depthBlenderTex, gl_FragCoord.xy).xy;
vec4 forwardTemp = texture(frontBlenderTex, gl_FragCoord.xy);
// Depths and 1.0-alphaMult always increase
// so we can use pass-through by default with MAX blending
vFragColor0.xy = depthBlender;
// Front colors always increase (DST += SRC*ALPHA_MULT)
// so we can use pass-through by default with MAX blending
vFragColor1 = forwardTemp;
// Because over blending makes color increase or decrease,
// we cannot pass-through by default.
// Each pass, only one fragment writes a color greater than 0
vFragColor2 = vec4(0.0);
float nearestDepth = -depthBlender.x;
float farthestDepth = depthBlender.y;
float alphaMultiplier = 1.0 - forwardTemp.w;
if (fragDepth < nearestDepth || fragDepth > farthestDepth) {
// Skip this depth in the peeling algorithm
vFragColor0.xy = vec2(-MAX_DEPTH);
return;
}
if (fragDepth > nearestDepth && fragDepth < farthestDepth) {
// This fragment needs to be peeled again
vFragColor0.xy = vec2(-fragDepth, fragDepth);
return;
}
// If we made it here, this fragment is on the peeled layer from last pass
// therefore, we need to shade it, and make sure it is not peeled any farther
vFragColor0.xy = vec2(-MAX_DEPTH);
vec4 Color;
if(isObject == 0.0)
Color = vColor;
else
Color = Lighted();
if (fragDepth == nearestDepth) {
vFragColor1.xyz += Color.rgb * Color.a * alphaMultiplier;
vFragColor1.w = 1.0 - alphaMultiplier * (1.0 - Color.a);
} else {
vFragColor2 += Color;
}
}
Blend Fragment Shader
#version 330 core
uniform sampler2DRect tempTexture;
layout(location = 0) out vec4 vFragColor;
void main(void)
{
vFragColor = texture(tempTexture, gl_FragCoord.xy);
if(vFragColor.a == 0)
discard;
}