gl_InvocationID, похоже, не обновляется - PullRequest
0 голосов
/ 09 мая 2020

Я пытаюсь визуализировать изображение с помощью вычислительного шейдера. В целях тестирования я пытаюсь отобразить gl_GlobalInvocationID на изображении, но это дает мне только черный экран. Однако это работает, когда я задаю imageStore предопределенный цвет. Например vec4(1, 0, 0, 1);. После некоторого тестирования выяснилось, что gl_GlobalInvocationID.xy не продвигается дальше [0,0]. Что я делаю не так?

Я проверил значения gl_GlobalInvocationID , отрисовав другой цвет, если координаты x или y стали больше 0, чего не произошло.

Вычислить шейдер:

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