OpenGL - Один дает проход cubemap не выход
Я написал реализацию отображения сырой тень, которая делает эту сцену 6 раз с 6 различными матрицами зрения для создания cubemap.
Как оптимизация, я пытаюсь перейти на однопроходный подход, используя геометрический шейдер, но изо всех сил пытаюсь получить какой-либо вывод из моих шейдеров.
Проблема возникает при связывании текстуры куба. С multi-pass я просто связываю 1 из 6 FBOs за один раз, однако с одним проходом мне нужно связать все 6 кубических граней сразу, и у меня нет дескриптора для этого. В этих случаях документация предлагает создать один FBO с FrameBufferTexture
, который содержит все 6 лиц. Правильно ли я это сделал?
В качестве альтернативы, проблема может быть маршрутизирована в геометрическом шейдере, но, видя, что я не получаю никакого вывода, его очень сложно отладить.
ПОЛИСТНОЙ (без вывода)
создание FBO
// Create the FBO
GL.GenFramebuffers(1, out FBO_handle);
// Create and bind the cubemap Texture
GL.GenTextures(1, out cubeMapTexture);
GL.BindTexture(TextureTarget.TextureCubeMap, cubeMapTexture);
// Generate each of the single cubemap faces as 2D texture
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
// Set the suitable texture parameters
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureBaseLevel, 0);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMaxLevel, 0);
// Attach cubemap texture as the FBO's color buffer
GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO_handle);
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, cubeMapTexture, 0);
Геометрия шейдер
#version 330
layout(triangles) in;
layout (triangle_strip, max_vertices=18) out;
uniform mat4 projectionMatrix;
uniform mat4 shadowTransforms[6];
out vec4 frag_position;
void main()
{
for(int face = 0; face < 6; face++)
{
gl_Layer = face;
for(int i=0; i<3; i++)
{
frag_position = shadowTransforms[face] * gl_in[i].gl_Position;
gl_Position = projectionMatrix * shadowTransforms[shadowTransforms] * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
}
Rendering
for (int j = 0; j < lights.Count; j++)
{
// GL setup
GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowBuffers[j].FBO_handle);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Matrix4 viewMatrix = Matrix4.Identity;
// Create the light's view matrices
List<Matrix4> shadowTransforms = new List<Matrix4>();
shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(1, 0, 0), new Vector3(0, -1, 0)));
shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(-1, 0, 0), new Vector3(0, -1, 0)));
shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 1, 0), new Vector3(0, 0, -1)));
shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, -1, 0), new Vector3(0, 0, -1)));
shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, 1), new Vector3(0, -1, 0)));
shadowTransforms.Add(Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, -1), new Vector3(0, -1, 0)));
// Send them to the shader
for (int i = 0; i < 6; ++i)
{
Matrix4 shadowTransform = shadowTransforms[i];
GL.UniformMatrix4(shader.getUniformID("shadowTransforms[" + i + "]"), false, ref shadowTransform);
}
// Draw Scene
for (int r = 0; r < renderables.Count; r++)
renderables[r].draw(shader);
}
Я прошу прощения за массивный свалку кода, FBOs довольно длинны, я уверен, вы знаете. Для тех, кто не знаком с оболочкой OpenTK C#, я полагаю, что это было бы полезно, если бы я также предоставил рабочий код многопроходного кода.
многопроходной (работает нормально)
создание FBO
// Create cubemap texture
GL.GenTextures(1, out cubeTex);
GL.BindTexture(TextureTarget.TextureCubeMap, cubeTex);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureBaseLevel, 0);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMaxLevel, 0);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeX, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeY, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
GL.TexImage2D(TextureTarget.TextureCubeMapNegativeZ, 0, PixelInternalFormat.R16f, size, size, 0, PixelFormat.Red, PixelType.Float, IntPtr.Zero);
// Create cubemap FBOs
GL.GenFramebuffers(6, cubeFBOs);
for (int i = 0; i < 6; i++)
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, cubeFBOs[i]);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.TextureCubeMapPositiveX + i, cubeTex, 0);
}
Геометрия шейдер
#version 330
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
out vec4 frag_position;
void main()
{
for(int i=0; i<3; i++)
{
frag_position = viewMatrix * gl_in[i].gl_Position;
gl_Position = projectionMatrix * viewMatrix * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}
Rendering
for (int j = 0; j < lights.Count; j++)
{
for (int i = 0; i < 6; ++i)
{
GL.BindFramebuffer(FramebufferTarget.Framebuffer, shadowBuffers[j].cubeFBOs[i]);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Matrix4 viewMatrix = Matrix4.Identity;
if (i == 0) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(1, 0, 0), new Vector3(0, -1, 0));
if (i == 1) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(-1, 0, 0), new Vector3(0, -1, 0));
if (i == 2) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 1, 0), new Vector3(0, 0, -1));
if (i == 3) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, -1, 0), new Vector3(0, 0, -1));
if (i == 4) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, 1), new Vector3(0, -1, 0));
if (i == 5) viewMatrix = Matrix4.LookAt(lights[j].position, lights[j].position + new Vector3(0, 0, -1), new Vector3(0, -1, 0));
GL.UniformMatrix4(shader.getUniformID("viewMatrix"), false, ref viewMatrix);
// Draw Scene
for (int r = 0; r < renderables.Count; r++)
renderables[r].draw(shader);
}
}
Фрагмент Shader
#version 330
precision lowp float;
in vec4 frag_position;
layout (location = 0) out vec4 outColor;
void main() {
float depth = length(vec3(frag_position))/20;
float moment1 = depth;
float moment2 = depth * depth;
float dx = dFdx(depth);
float dy = dFdy(depth);
moment2 += 0.25*(dx*dx+dy*dy);
outColor = vec4(moment1, moment2, 0.0, 0.0);
}
Любое понимание было бы весьма признателен, спасибо!
Итак ... как насчет вашего буфера глубины? Вы проверяли, завершено ли ваше FBO? Или если вы получили ошибки OpenGL? –
Я пока храню глубину в текстуре. Я добавлю шейдер фрагмента выше, это будет иметь смысл, как только вы это увидите. –
FBO завершен в обоих случаях. Я не уверен, как проверить ошибки OpenGL, но я получу на нем. –