计算着色器 OpenGL 写入纹理

Posted

技术标签:

【中文标题】计算着色器 OpenGL 写入纹理【英文标题】:Compute Shader OpenGL Write to Texture 【发布时间】:2018-06-29 02:10:20 【问题描述】:

我想用计算着色器写入纹理。出于测试目的,我只想将蓝色像素写入给定的空纹理。 我只是得到一个黑屏。 我将展示我的代码的相关部分

顶点着色器

#version 330 core
layout (location = 0) in vec2 aPos; 
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;

void main()

   TexCoords = aTexCoords;
   gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);

片段着色器

#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D screenTexture;

void main()

    vec3 col = texture(screenTexture, TexCoords).rgb;
    FragColor = vec4(col, 1.0);

编译计算着色器(所有使用的变量都是我班级的成员) //按照Rabbid76的建议更新,还是不行

cshader = glCreateShader(GL_COMPUTE_SHADER);
const char *csSrc[] = 
    "#version 440\n",
    "layout (binding = 0, rgba32f) uniform image2D destTex;\
     layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;\
     void main() \
           ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);\
           imageStore(destTex, storePos, vec4(0.0,0.0,1.0,1.0));\
    "
;
glShaderSource(cshader, 2, csSrc, NULL);
glCompileShader(cshader);
cshaderprogram = glCreateProgram();
glAttachShader(cshaderprogram, cshader);
glLinkProgram(cshaderprogram);

创建输出纹理

glGenTextures(1, &this->outputTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, this->outputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width(), height(), 0, GL_RGBA32F, 
GL_FLOAT, NULL);
glBindImageTexture(0, this->outputTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, 
GL_RGBA32F);

绘制四边形

glUseProgram(cshaderprogram);
glUniform1i(0, 0);
glActiveTexture(GL_TEXTURE0);
glBindImageTexture(0, outputTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, 
GL_RGBA32F);
glDispatchCompute(width() / 16, height() / 16, 1);

glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

screenProgram.bind();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindVertexArray(screenVao);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glDrawArrays(GL_TRIANGLES, 0, 6);

我希望你们能帮助我。如果有问题就问他们

【问题讨论】:

【参考方案1】:

您的计算着色器甚至无法编译,因为它由 2 个字符串组成:

const char *csSrc[] = 

    "#version 440\n",

    "layout (binding = 0, rgba32f) uniform image2D destTex;\
    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;\
    void main() \
        ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);\
        imageStore(destTex, storePos, vec4(0.0,0.0,1.0,1.0));\
    "
;

您必须将两个字符串都附加到着色器对象才能解决问题:

glShaderSource(cshader, 2, csSrc, NULL); // <--- 2 instead of 1

我推荐使用Raw string literals:

const char *csSrc[] = 

    "#version 440",

    R"(
    layout (binding = 0, rgba32f) uniform image2D destTex;
    layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;

    void main() 

        ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);
        imageStore(destTex, storePos, vec4(0.0,0.0,1.0,1.0));
    )"
;

使用glGetShaderiv检查编译错误:

GLuint cshader = glCreateShader( GL_COMPUTE_SHADER );
glShaderSource(cshader, 2, csSrc, NULL);
glCompileShader(cshader);
GLint compile_status;
glGetShaderiv( cshader, GL_COMPILE_STATUS, &compile_status );
if ( compile_status == GL_FALSE )

    GLint maxLen;
    glGetShaderiv( cshader, GL_INFO_LOG_LENGTH, &maxLen );
    std::vector< char >log( maxLen );
    GLsizei len;
    glGetShaderInfoLog( cshader, maxLen, &len, log.data() );
    std::cout << "compile error:" << std::endl << log.data() << std::endl;
  

并使用glGetProgramiv 来检查链接错误:

GLuint cshaderprogram = glCreateProgram();
glAttachShader(cshaderprogram, cshader);
glLinkProgram(cshaderprogram);
GLint link_status;
glGetProgramiv( cshaderprogram, GL_LINK_STATUS, &link_status );
if ( link_status == GL_FALSE )

    GLint maxLen;
    glGetProgramiv( cshaderprogram, GL_INFO_LOG_LENGTH, &maxLen );
    std::vector< char >log( maxLen );
    GLsizei len;
    glGetProgramInfoLog( cshaderprogram, maxLen, &len, log.data() );
    std::cout  << "link error:" << std::endl << log.data() << std::endl;


进一步注意,GL_RGBA32F 不是glTexImage2D 的正确格式 参数。 internalFormat 参数指定 GPU 上目标纹理的格式,formattype(一起)指定源纹理的格式。使用GL_RGBA 而不是GL_RGBA32F

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, cx, cy, 0, GL_RGBA, GL_FLOAT, NULL);

【讨论】:

感谢您的回答!你是对的,这是一个错误。并感谢调试帮助。但是解决了这个问题后我的屏幕仍然是黑色的。有什么想法吗? 太棒了!现在是 Wirkung!

以上是关于计算着色器 OpenGL 写入纹理的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL着色器 - 重叠多个纹理

OpenGL 计算着色器中的样本深度缓冲区

OpenGL几何着色器传递纹理坐标

具有多个着色器程序的 OpenGL 多纹理

OpenGL着色器没有传递正确的纹理坐标

OpenGL4.0教程 计算着色器简介