Я пытаюсь визуализировать изображение с помощью вычислительного шейдера. В целях тестирования я пытаюсь отобразить 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);
}