gl_InvocationID似乎没有更新

时间:2020-05-08 21:53:59

标签: c# opengl glsl opentk

我正在尝试使用计算着色器渲染图像。为了进行测试,我尝试将 gl_GlobalInvocationID 渲染到图像,但这只会给我黑屏。但是,当我为imageStore提供预定义的颜色时,它确实起作用。例如vec4(1, 0, 0, 1);。经过一些测试,看来 gl_GlobalInvocationID.xy 除了[0,0]之外别无其他。我在做什么错了?

如果x或y坐标高于0,我渲染了另一种颜色,则测试了 gl_GlobalInvocationID 的值。

计算着色器:

#version 440
layout (local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D frameBuffer;

void main()
{
    ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
    ivec2 size = ivec2(imageSize(frameBuffer));
    vec4 pixel;
    pixel = vec4(vec2(pixel_coords) / vec2(size.x, size.y),0, 1);

    imageStore(frameBuffer, pixel_coords, pixel);
}

创建帧缓冲区:

frameBuffer = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, frameBuffer);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, Width, Height, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Nearest);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32f, Width, Height, 0, PixelFormat.Rgba, PixelType.Float, IntPtr.Zero);
GL.BindImageTexture(0, frameBuffer, 0, false, 0, TextureAccess.WriteOnly, SizedInternalFormat.Rgba32f);

计算着色器初始化

//Initialise compute shader in Onload()
cShader = new ComputeShader("../../RayTracer.glsl");
cShader.Use();
cShader.Dispatch(Width, Height, 1);

计算着色器类

class ComputeShader {
    int handle;

    //Initialize the compute shader given by the path
    public ComputeShader(string path) {
        handle = GL.CreateProgram();
        int shader = GL.CreateShader(ShaderType.ComputeShader);
        string source;
        using (StreamReader sr = new StreamReader(path)) {
             source = sr.ReadToEnd();
        }

        GL.ShaderSource(shader, source);
        GL.CompileShader(shader);
        string shaderError = GL.GetShaderInfoLog(shader);
        if (shaderError.Length > 0) {
             Console.WriteLine(shaderError);
        }
        GL.AttachShader(handle, shader);
        GL.LinkProgram(handle);

        GL.DetachShader(handle, shader);
        GL.DeleteShader(shader);
    }

    //Sets a uniform 4x4 matrix in the compute shader
    public void SetMatrix4x4(string name, Matrix4 matrix) {
        int location = GL.GetUniformLocation(handle, name);
        GL.UniformMatrix4(location, false, ref matrix);
    }
    //Sets a uniform float in the compute shader
    public void SetUniformFloat(string name, float val) {
        int location = GL.GetUniformLocation(handle, name);
        GL.Uniform1(location, val);
    }
    //Use the compute shader
    public void Use() {
        GL.UseProgram(handle);            
    }
    //Dispatch the compute shader
    public void Dispatch(int xGroups, int yGroups, int zGroups) {
        GL.DispatchCompute(xGroups, yGroups, zGroups);
    }
}

OnRenderFrameMethod:

protected override void OnRenderFrame(FrameEventArgs e) {
    //Launch computer shaders
    cShader.Use();
    cShader.Dispatch(Width, Height, 1);

    //Make sure frame is finsihed before proceeding
    GL.MemoryBarrier(MemoryBarrierFlags.ShaderImageAccessBarrierBit);

    //Clear previous frame
    GL.Clear(ClearBufferMask.ColorBufferBit);

    //Bind VAO
    GL.BindVertexArray(VertexArrayObject);

    //Bind texture
    GL.BindTexture(TextureTarget.Texture2D, frameBuffer);   //Renders GPU

    //Draw primitives
    GL.DrawElements(PrimitiveType.Triangles, canvasIndices.Length, DrawElementsType.UnsignedInt, 0);

    //Swap buffers
    Context.SwapBuffers();
    base.OnRenderFrame(e);
}

0 个答案:

没有答案