GLSL MRT 将相同的数据写入所有颜色附件

Posted

技术标签:

【中文标题】GLSL MRT 将相同的数据写入所有颜色附件【英文标题】:GLSL MRT writes same data to all color attachments 【发布时间】:2014-09-23 12:12:57 【问题描述】:

我正在编写延迟着色代码。 我有一个带有 4 个颜色附件(纹理)和一个深度附件(渲染缓冲区)的 FBO。 我使用着色器渲染我的场景,该着色器会写入这 4 个颜色附件。 问题是,第 0 个颜色附件的数据也被写入其他附件。

下面是我的代码:

    Renderer_Deferred.java
    public class Renderer_Deferred 
    
        private final int FBO;
        private final int depthbuffer;
        public final int positiontexture, diffusetexture, normaltexture, bumpmap;

    Renderer_Deferred()
    
        System.out.println("Setting up the deferrer..");
        positiontexture = GL11.glGenTextures();
        diffusetexture = GL11.glGenTextures();
        normaltexture = GL11.glGenTextures();
        bumpmap = GL11.glGenTextures();
        FBO = glGenFramebuffers();
        glBindFramebuffer(GL_FRAMEBUFFER, FBO);

        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, positiontexture);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glTexImage2D(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0, GL30.GL_RGB32F, Configuration.displayWidth, Configuration.displayheight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);

        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, diffusetexture);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glTexImage2D(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0, GL11.GL_RGBA, Configuration.displayWidth, Configuration.displayheight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);

        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, normaltexture);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glTexImage2D(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0, GL30.GL_RGB16F, Configuration.displayWidth, Configuration.displayheight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);

        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, bumpmap);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL11.glTexParameterf(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
        GL11.glTexImage2D(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0, GL11.GL_RGBA, Configuration.displayWidth, Configuration.displayheight, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);

        GL11.glViewport(0, 0, Configuration.displayWidth, Configuration.displayheight); 

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, positiontexture, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, diffusetexture, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, normaltexture, 0);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, bumpmap, 0);

        depthbuffer = glGenRenderbuffers(); 
        glBindRenderbuffer(GL_RENDERBUFFER, depthbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, Configuration.displayWidth, Configuration.displayheight);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, 0);

        if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        
            System.err.println("Generating the deferred FBO failed!");
            System.exit(5321);
        

        glBindFramebuffer(GL_FRAMEBUFFER, 0); ////////////////////////////////////////////////////////
       

    public void startRendering()
    
        // CLEAR AND HOOK UP TEXTURES
        glBindFramebuffer(GL_FRAMEBUFFER, FBO); 

        IntBuffer buf = BufferUtils.createIntBuffer(4);
        buf.put(GL_COLOR_ATTACHMENT0);
        buf.put(GL_COLOR_ATTACHMENT1);
        buf.put(GL_COLOR_ATTACHMENT2);
        buf.put(GL_COLOR_ATTACHMENT3);
        buf.flip();

        GL20.glDrawBuffers(buf);

        if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        
            System.err.println("Deferred renderer failed to setup correctly!");
        

        GL11.glEnable(GL11.GL_DEPTH_TEST); 
        GL11.glDepthFunc(GL11.GL_LEQUAL);
        GL11.glViewport(0, 0, Configuration.displayWidth, Configuration.displayheight);
        GL11.glClearColor(SimpleCraft.world.skycolor.x, SimpleCraft.world.skycolor.y, SimpleCraft.world.skycolor.z, 0f);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    

    public void stopRendering()
    
        glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    

上面是我的代码,用于激活和停用延迟渲染器。 完成后,后处理器激活:

public class Renderer_Postprocessor 

    PostprocessingObject postprocessor;

    public static int loc_pos, loc_diffuse, loc_normal, loc_bump, loc_ambient;
    public static int loc_viewingdistance, loc_modelviewmatrix;

    Renderer_Postprocessor()
    
        postprocessor = new PostprocessingObject();
    

    public void postprocess(int pos, int diffuse, int normal, int bump)
    
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        GL11.glDisable(GL11.GL_DEPTH_TEST); 
        GL20.glUseProgram(Shaders.PROGRAM_POSTPROCESSOR);
        GL20.glDrawBuffers(GL11.GL_BACK);

        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, pos);
        GL13.glActiveTexture(GL13.GL_TEXTURE1);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, diffuse);
        GL13.glActiveTexture(GL13.GL_TEXTURE2);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, normal);
        GL13.glActiveTexture(GL13.GL_TEXTURE3);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, bump);

        GLUtility.uploadToShader(Configuration.viewDistanceInBlocks, loc_viewingdistance);
        GLUtility.uploadToShader(Camera.getModelViewMatrix(new Matrix4f(), Camera.getViewMatrix()), loc_modelviewmatrix);

        GL30.glBindVertexArray(postprocessor.getVAO());
        GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 6);
        GL30.glBindVertexArray(0);
        GL20.glUseProgram(0);

        GL13.glActiveTexture(GL13.GL_TEXTURE0);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);
        GL13.glActiveTexture(GL13.GL_TEXTURE1);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);
        GL13.glActiveTexture(GL13.GL_TEXTURE2);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);
        GL13.glActiveTexture(GL13.GL_TEXTURE3);
        GL11.glBindTexture(ARBTextureRectangle.GL_TEXTURE_RECTANGLE_ARB, 0);
        GL11.glEnable(GL11.GL_DEPTH_TEST); 
    

以下是我的延迟器和后处理器的片段着色器:

Deferred_Fragment.frag
#version 330 core
#extension GL_ARB_explicit_uniform_location : require
layout(location=0) uniform sampler2DArray texture_diffuse;
layout(location=1) uniform sampler2DArray texture_normal;

uniform vec3 pass_EyeVector;

in vec4 pass_Position;
in vec3 pass_TextureCoord;
in vec3 pass_Normal;

layout(location = 0) out vec4 pos;
layout(location = 1) out vec4 dif;
layout(location = 2) out vec4 nor;
layout(location = 3) out vec4 bum;

void main(void)

    pos = texture(texture_diffuse, pass_TextureCoord); // Transform from -1 / 1 to 0 / 1
    dif = pass_Position;
    nor = vec4(pass_Normal, 1.0);
    bum = texture(texture_normal, pass_TextureCoord);

还有 postprocessor.frag

#version 330 core
#extension GL_ARB_explicit_uniform_location : require

layout(location=0) uniform sampler2DRect positiontexture;
layout(location=1) uniform sampler2DRect diffusetexture;
layout(location=2) uniform sampler2DRect normaltexture;
layout(location=3) uniform sampler2DRect bumpmap;

in vec2 pass_TextureCoord;
out vec4 out_Color;

void main(void)

    out_Color = texture(diffusetexture, pass_TextureCoord);

【问题讨论】:

出于好奇,为什么在 GL 3.3 中使用矩形纹理?您应该能够使用texelFetch (...) 完成同样的事情。 我从一个星期以来就遇到了这个问题,我感到很沮丧,循环浏览我发现的任何关于延迟着色的教程。一个使用矩形纹理,所以我也尝试过。之前没用过texelFetch(),现在试试,写下结果。 【参考方案1】:

您正在尝试将 location 布局限定符用于统一变量:

layout(location=0) uniform sampler2DArray texture_diffuse;
layout(location=1) uniform sampler2DArray texture_normal;

layout(location=0) uniform sampler2DRect positiontexture;
layout(location=1) uniform sampler2DRect diffusetexture;
layout(location=2) uniform sampler2DRect normaltexture;
layout(location=3) uniform sampler2DRect bumpmap;

我在 GLSL 规范中找不到任何表明支持此功能的内容。至少在 330 中,仅列出了顶点着色器输入和片段着色器输出以支持location。在以后的版本中,似乎也支持in/out其他着色器阶段的变量,但我仍然没有看到任何关于制服的提及。

您可能打算使用此限定符设置采样器的纹理单元。有一个binding 限定符,如下所示:

layout(binding=0) uniform sampler2DArray texture_diffuse;
layout(binding=1) uniform sampler2DArray texture_normal;

不过,这仅在 OpenGL 4.2(GLSL 版本 420)及更高版本中受支持。如果您想坚持使用 GLSL 330,则需要以老式方式设置采样器制服的纹理单元,使用 glGetUniformLocaction()glUniform1i()

【讨论】:

感谢您的回答!制服的布局(位置)由扩展启用。我将尝试再次以老式方式上传纹理并发布结果。我明确地发现,我的错误很可能出现在延迟渲染器中,因为我尝试了带有预加载纹理的后处理器,它工作正常。 啊,好吧,我应该在着色器代码中看到这一点。顾名思义,它定义了统一的 location,对吗?所以这使得glGetUniformLocation() 调用变得不必要了,但您仍然需要调用glUniform1i() 来设置值? 很有可能。我已经删除了所有布局(位置)并回到了老式的方式。现在一切正常,尽管我并没有真正理解我的错误。感谢您的帮助!【参考方案2】:

您应该使用布局绑定而不是布局位置来绑定采样器。 您可能还应该重新检查您的绑定点,因为您有多个采样器绑定到同一位置。如果将纹理绑定到 TEXTURE0,请将其指定为 binding=0。

尝试将其更改为:

layout(binding=0) uniform sampler2DArray texture_diffuse;
layout(binding=1) uniform sampler2DArray texture_normal;

layout(binding=0) uniform sampler2DRect positiontexture;
layout(binding=1) uniform sampler2DRect diffusetexture;
layout(binding=2) uniform sampler2DRect normaltexture;
layout(binding=3) uniform sampler2DRect bumpmap;

【讨论】:

以上是关于GLSL MRT 将相同的数据写入所有颜色附件的主要内容,如果未能解决你的问题,请参考以下文章

在 GLSL 中检索 FBO 数据

GLSL将颜色数据从片段着色器发送到顶点着色器似乎总是等于0

OpenGL 3.30 / GLSL 3.30 - MRT 输出黑色纹理

GLSL 将 uint 转换为 float 以获取颜色

iOS:背景颜色——UITableView 和附件具有相同的背景颜色

openGL之API学习(二零二)glsl的smooth flat