从GL_DEPTH_ATTACHMENT获得纯黑色纹理

时间:2013-12-03 17:51:25

标签: opengl textures lwjgl framebuffer texture-mapping

我正在尝试使用LWJGL实现一组着色器来渲染SPH流体模拟,如this presentation from NVidia所示。为此,我需要首先将我的粒子渲染为纹理,并在生成的纹理上应用不同的着色器。

算法的第一部分渲染效果很好,将预期的流体厚度图像保存在GL_COLOR_ATTACHMENT0纹理处:

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE);
    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferID.get(0));
    GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, renderBufferID.get(0));
    glDisable(GL_DEPTH_TEST);
    glDepthMask(false);
    glDrawBuffer(GL30.GL_COLOR_ATTACHMENT0);
    glClearColor(0.f, 0.f, 0.f, 0.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    drawSpheres();
    glEnable(GL_DEPTH_TEST);
    glDepthMask(true);
    glDisable(GL_BLEND);

第二部分也渲染得很好,将流体颜色图像保存在GL_COLOR_ATTACHMENT4纹理:

    glDrawBuffer(GL30.GL_COLOR_ATTACHMENT4);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    drawSpheres();

但是,我在尝试生成流体法线图像时遇到问题。它应该从渲染缓冲区中获取GL_DEPTH_ATTACHMENT(写入代码的第一部分)和GL_COLOR_ATTACHMENT4来自第二部分。

    glDrawBuffer(GL30.GL_COLOR_ATTACHMENT5);
    GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
    depth2.get(0), 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, depth.get(0));
    glEnable(GL_TEXTURE_2D);
    smooth();
    glDisable(GL_TEXTURE_2D);
    GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth.get(0), 0);
    glDisable(GL_DEPTH_TEST);
    glDepthMask(false);
    glEnable(GL_BLEND);

我的normal()方法如下:

private void normal() {
    ARBShaderObjects.glUseProgramObjectARB(programNormal);
    GL20.glUniform1i(GL20.glGetUniformLocation(programSmooth, "depthTex"), 0);
    GL20.glUniform1i(GL20.glGetUniformLocation(programSmooth, "colorTex"), 1);
    GL20.glUniform1f(GL20.glGetUniformLocation(programSmooth, "del_x"), 1.0f/620.0f);
    GL20.glUniform1f(GL20.glGetUniformLocation(programSmooth, "del_y"), 1.0f/620.0f);
    fullscreenQuad();
}

public void fullscreenQuad(){
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    GLU.gluOrtho2D(0, 620, 0, 620);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    glBegin(GL_QUADS);
        glTexCoord2f(0.f, 0.f);
        glVertex2f(0.f, 0.f);
        glTexCoord2f(1f, 0.f);
        glVertex2f(620.f, 0.f);
        glTexCoord2f(1.f, 1.f);
        glVertex2f(620.f, 620.f);
        glTexCoord2f(0.f, 1.f);
        glVertex2f(0.f, 620.f);
    glEnd();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}

GL_COLOR_ATTACHMENT5纹理上生成的渲染只是一个纯黑色图像。因此,最终渲染最终也是纯黑色。

programNormal方法中使用的normal()由以下顶点着色器构成:

uniform float pointRadius;
uniform float near;
uniform float far;
varying vec3 posEye;

void main()
{
    vec3 n;
    n.xy = gl_PointCoord.st*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
    float mag = dot(n.xy, n.xy);
    if (mag > 1.0) discard;
    n.z = sqrt(1.0-mag);

    vec4 spherePosEye =vec4(posEye+n*pointRadius,1.0);

    vec4 clipSpacePos = gl_ProjectionMatrix*spherePosEye;
    float normDepth = clipSpacePos.z/clipSpacePos.w;

    gl_FragDepth = (((far-near)/2.)*normDepth)+((far+near)/2.);

    gl_FragData[0] = gl_Color;
}

片段着色器:

uniform sampler2D depthTex;
uniform sampler2D colorTex;
uniform float del_x;
uniform float del_y;

vec3 uvToEye(vec2 texCoord,float z)
{
    vec2 xyPos = (texCoord*2. -1.);
    vec4 clipPos = vec4( xyPos, z, 1.0 );
    vec4 viewPos =  (gl_ProjectionMatrixInverse * clipPos);
    return(viewPos.xyz/viewPos.w);
}

void main(){
    float maxDepth = 0.999;
    float depth = texture2D(depthTex,gl_TexCoord[0].xy).x;
    if(depth>maxDepth)
    {
        discard;
    }

    vec3 posEye = uvToEye(gl_TexCoord[0].xy,depth);
    vec2 texCoord1 = vec2(gl_TexCoord[0].x+del_x,gl_TexCoord[0].y);
    vec2 texCoord2 = vec2(gl_TexCoord[0].x-del_x,gl_TexCoord[0].y);

    vec3 ddx = uvToEye(texCoord1, texture2D(depthTex,texCoord1.xy).x)-posEye;
    vec3 ddx2 = posEye-uvToEye(texCoord2, texture2D(depthTex,texCoord2.xy).x);
    if(abs(ddx.z)>abs(ddx2.z))
    {
        ddx = ddx2;
    }

    texCoord1 = vec2(gl_TexCoord[0].x,gl_TexCoord[0].y+del_y);
    texCoord2 = vec2(gl_TexCoord[0].x,gl_TexCoord[0].y-del_y);

    vec3 ddy = uvToEye(texCoord1, texture2D(depthTex,texCoord1.xy).x)-posEye;
    vec3 ddy2 = posEye-uvToEye(texCoord2, texture2D(depthTex,texCoord2.xy).x);
    if(abs(ddy.z)>abs(ddy2.z))
    {
        ddy = ddy2;
    }

    vec3 n = cross(ddx,ddy);
    n = normalize(n);
    const vec3 lightDir = vec3(-0.5, 1.5, 5.);
    const float shininess = 100.0;
    float diffuse = max(0.0,dot(lightDir,n));

    vec3 v = normalize(-posEye);
    vec3 h = normalize(lightDir + v);
    float specular = pow(max(0.0, dot(n, h)), shininess);
    gl_FragData[0] = texture2D(colorTex,gl_TexCoord[0].xy)*diffuse+specular;
}

1 个答案:

答案 0 :(得分:0)

我知道这是一个老问题,但对于任何想知道你应该在深度纹理中使用GL_DEPTH_ATTACHMENT24的人来说。