1

I want to write to a texture with a compute shader. for testing purposes i only want to write blue pixels to a given empty texture.
I am only getting a black screen. I will show the relevant part of my code

Vertex Shader

#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);
}

Fragement Shader

#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);
}

Compilation Compute Shader (all used variables are members of my class) //Update as Rabbid76 suggested, still not working

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);

Creating Output Texture

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);

Drawing on Quad

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);

I hope you guys can help me. if there are questions just ask them

1 Answer 1

5

Your compute shader does not even compile, because it consists of 2 strings:

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));\
    }"
};

You have to attach both string to the shader object to solve the issue:

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

I recommend to use 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));
    })"
};

Use glGetShaderiv to check for compile errors:

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;
}  

And use glGetProgramiv to check for link errors:

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;
}

Further note, that GL_RGBA32F is not a proper format parameter for glTexImage2D. While the internalFormat parameter specify the format of the target texture on the GPU, format and type (together) specify the format of the source texture. Use GL_RGBA instead of GL_RGBA32F:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, cx, cy, 0, GL_RGBA, GL_FLOAT, NULL);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.