4

我看到一个多通道、多 RT 乒乓渲染的奇怪问题

我正在使用 3 个着色器和一个 FBO,在任何阶段都没有错误。我使用的是opengl 4,所以我没有使用glBegin/glEnd,我使用我自己的矩阵进行转换,我使用顶点缓冲区进行渲染

该测试的总体思路是为三个单独的 fbo 附件渲染 3 种不同的颜色(我意识到在第一遍中两次渲染 vbo 效率不高,但这只是为了帮助我理解其他来源中的问题)然后将一组单独的纹理绑定到 fbo 并使用第一组作为采样器。最后一步是将结果混合到后台缓冲区中

奇怪的是,当第一个应该是红色而第二个应该是绿色(因为这些值来自第二个着色器)时,两个四边形的输出都显示为红色。

如果我将第二个着色器中的 SamplePix 函数更改为始终从第二个采样器中获取,则两者都显示为绿色,如果从第三个采样器中查找,则全部显示为黄色,但它似乎只能从一个采样器中读取。

现在我似乎无法解释为什么我可以从每个采样器中读取,但循环似乎没有正确查找(在着色器 2 中)

此外,如果我切换到渲染在着色器 2 中采样的纹理,我会在第二遍中看到黑色四边形(图 2)

希望有人可以对这个问题有所了解。(我也尝试在第一次通过后添加一个同步围栏对象,但这并没有什么不同)

红色的

纹理样本:

特克斯

// initial setup of shaders and vertex buffers ommitted for now (in separate source files)

// fbo setup like so
const int DepthLayers = 3;

bool InitFBO()
{
// width and height 768pixels
    for (int j=0; j<DepthLayers; j++)
    {
        const int idx = j + (DepthLayers*i);

        glGenTextures(1, &g_FBOManager.m_fboTex[ idx ]);
        glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[ idx ]);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        //no mipmaps
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);


        //depth
        glGenTextures(1, &g_FBOManager.m_fboDepthTex[ idx ]);
        glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[ idx ]);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //no mipmaps
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE/* GL_COMPARE_R_TO_TEXTURE*/);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

        glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, g_XMLSettings->WWidth(), g_XMLSettings->WHeight(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);


        glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx]);
        pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, g_FBOManager.m_fboDepthTex[idx], 0);

        glBindTexture(GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx]);
        // attach a texture to FBO color attachment point
        pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_FBOManager.m_fboTex[idx], 0);


        // check FBO status
        pglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, g_FBOManager.FboId(i) );
        if(!CheckFramebufferStatus())
        {
            return false;
        }
    }

    BindFrameBuffer(-1);    // unbind fbo

    if (GLGETERROR("1", fileBuf, lineBuf)) ;    // check for glErrors

    return true;    // all ok
}


// code to init second set of textures before the render loop

    const int w = g_XMLSettings->WWidth();  //res: 768 square
    const int h = g_XMLSettings->WHeight();
    glGenTextures(bufCount, &ttex[0]);  
    for (int i=0; i<bufCount; ++i)
    {
        glBindTexture(GL_TEXTURE_2D, ttex[i]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    }

const int bufCount = 3;

void EnableTexture1()
{
    glActiveTextureARB(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, g_BackTexture);
    glUniform1iARB(g_pPassAShader->m_clr_idx, 0);
}

void RenderLoop()
{

    GLenum buffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT };

    glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);       
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    glUseProgramObjectARB(g_pPassAShader->m_glContext);

    EnableTexture1();

    //... code omitted to set transform matrix and supply to shader


    if (!BindFrameBuffer(0))
        assert(0);

    const GLuint DTex = g_FBOManager.GetDepthTexture(0);

    glBindTexture(GL_TEXTURE_2D, DTex);
    pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,GL_TEXTURE_2D, DTex, 0);
    for (UINT i=0; i<bufCount; ++i)
    {
        glBindTexture(GL_TEXTURE_2D, g_FBOManager.GetTexture(i));
        pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, g_FBOManager.GetTexture(i), 0);
        if (!CheckFramebufferStatus())
            assert(0);
    }
    glDrawBuffers(bufCount,buffers); 
    // this is very important! if we don't clear it won't get written to
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glDisable(GL_BLEND);

    EnableTexture1();

    RenderVertexCache(0);

    //... code omitted to set transform matrix and supply to shader

    // render the second quad to other FBO tex
    RenderVertexCache(0);

    DisableShader(0);
    BindFrameBuffer(-1);    // unbinds fbo

//pass 2
    if (!BindFrameBuffer(0))
        assert(0);

    // bind other set of textures to the fbo
    for (UINT i=0; i<bufCount; ++i)
    {
        glBindTexture(GL_TEXTURE_2D,ttex[i]);
        pglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, ttex[i], 0);
        if (!CheckFramebufferStatus())
            assert(0);
    }
    glDrawBuffers(bufCount,buffers); 
    // this is very important! if we don't clear it won't get written to
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT  );
    // bind our set from prev pass to the samplers as input
    glUseProgramObjectARB(g_pPassBShader->m_glContext);

    for (UINT i=0; i<bufCount; ++i)
    {
        glActiveTextureARB(GL_TEXTURE0+i);
        glBindTexture(GL_TEXTURE_2D,g_FBOManager.GetTexture(i));
        glUniform1iARB(g_pPassBShader->m_intex_idx[i], i);
    }


    VertexBufferManager2::RenderUsingOrthoEx(g_pPassBShader);   // renders a full screen quad

    DisableShader(0);
    BindFrameBuffer(-1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// pass 3
    glUseProgramObjectARB(g_pPassCShader->m_glContext);
    for (UINT i=0; i<bufCount; ++i)
    {
        glActiveTextureARB(GL_TEXTURE0+i);
        glBindTexture(GL_TEXTURE_2D, ttex[i]);
        glUniform1iARB(g_pPassCShader->m_intex_idx[i], i);
    }

    VertexBufferManager2::RenderUsingOrthoEx(g_pPassCShader);



    if (GLGETERROR("at1", fileBuf, lineBuf)) ;  // reports any glErrors

}

// the three shaders (fragment shaders only)
// vertex shaders transfer uv's and transform vertices (version set to 410 in all)

// shader for pass1
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410

uniform sampler2D   g_ClrMap;
in vec2         g_InterpUV;     // supplied by vshader
out vec4        g_FBOLayers[ 3 ];

void main(void)
{   
    vec4 tex = texture(g_ClrMap, g_InterpUV);   // if we set fbo from texture only first texture renders
    g_FBOLayers[0] = vec4(1,0,0,.5);
    g_FBOLayers[1] = vec4(0,1,0,1);
    g_FBOLayers[2] = vec4(1,1,0,1);
}


// shader pass 2
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410

uniform sampler2D   g_inLayers0;
uniform sampler2D   g_inLayers1;
uniform sampler2D   g_inLayers2;
in vec2         g_InterpUV ;
out vec4        g_FBOLayers[ 3 ];
vec2            fTextureSize;

vec4 SamplePix(in int buf, in vec2 tCoords, in float lod)
{
    if (buf==1)
        return textureLod(g_inLayers1, tCoords, lod);
    else if (buf==2)
        return textureLod(g_inLayers2, tCoords, lod);
    return textureLod(g_inLayers0, tCoords, lod);
}

void main(void)
{   
    ivec2 iCoords = ivec2(int(gl_FragCoord.x),int(gl_FragCoord.y));
    ivec2 iTextureSize = textureSize(g_inLayers0,0);
    fTextureSize = vec2(float(iTextureSize.x), float(iTextureSize.y));
    vec2 coords = vec2(gl_FragCoord.x/iTextureSize.x,gl_FragCoord.y/iTextureSize.y);

    for(int i=0; i<3; ++i)
    {
        g_FBOLayers[i] = vec4(0.,0.,0.,0.); 
    }
    int j = 0;
    for(; j < 2; ++j)
    {
        g_FBOLayers[j] = SamplePix(j,coords,0); 

    }

}

// shader pass 3    
//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
#version 410

uniform sampler2D   g_inLayers0;
uniform sampler2D   g_inLayers1;
uniform sampler2D   g_inLayers2;
in vec2         g_InterpUV ;
out vec4        g_PixColour;

vec4 tFetch(in int buf, in ivec2 tCoords, in int lod)
{
    if (buf==1)
        return texelFetch(g_inLayers1, tCoords, lod);
    if (buf==2)
        return texelFetch(g_inLayers2, tCoords, lod);

    return texelFetch(g_inLayers0, tCoords, lod);
}

void main(void)
{   
    ivec2 iCoords = ivec2(int(gl_FragCoord.x),int(gl_FragCoord.y));
    ivec2 iTextureSize = textureSize(g_inLayers0,0);
    vec2 coords = vec2(gl_FragCoord.x/iTextureSize.x,gl_FragCoord.y/iTextureSize.y);

    vec4 colour =  vec4(0.,0.,0.,0.);
    int i = 0;
    for(; i <2; ++i) // 3rd texture omitted for now
    {
        vec4 texel = tFetch(i,iCoords,0);
        if(texel.a + colour.a <= 1.0)
        {
            colour.rgb += (texel.rgb*texel.a);
            colour.a += texel.a;

        }
        else
        {
            texel.a -= (texel.a + colour.a) - 1.0;
            colour.rgb += (texel.rgb*texel.a);
            colour.a += texel.a;    
            break;      
        }

    }

    g_PixColour = colour;

}
4

0 回答 0