PDA

View Full Version : Issues Rendering to Cubemapped FBO



sgsrules
07-09-2010, 10:40 AM
I've been using cubemaps as environment maps successfully but i'm having trouble setting up a dynamic one. I've been able to setup the fbo correctly along with it's multiple attachments and i can see the reflections on the surface of the object but it looks like I've got the faces in the wrong order. I'm pretty sure that the culprit is in my viewmatrix setup for each face. If i'm not mistaken the order should be: +x,-x,+y-,y,+z,-z from 0-5. I don't want to use the geometry shader approach because some of my objects use geometry shaders and incorporating the two would be a pain. Been staring at this for hours any help would be much appreciated. coded in c#, all the fbo stuff seems to work.
<code>
using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace ML3D
{
public class CubeFBO
{
public int[] FBO;
public int[] ColorTexture;
public int[] DepthTexture;
public int DepthMap;
private string fboMsg;
private Camera camera;
public CubeFBO()
{
FBO = new int[1];
ColorTexture = new int[1];
GL.GenTextures(1, ColorTexture);
GL.BindTexture(TextureTarget.TextureCubeMap, ColorTexture[0]);
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.TextureMinFilter,
(int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter,
(int)TextureMinFilter.Nearest);
for (int i = 0; i < 6; i++)
{
GL.TexImage2D(TextureTarget.TextureCubeMapPositive X + i, 0, PixelInternalFormat.Rgba16f, 512, 512, 0, PixelFormat.Bgra, PixelType.HalfFloat, IntPtr.Zero);
}
GL.BindTexture(TextureTarget.TextureCubeMap, 0);

DepthTexture = new int[1];

GL.GenTextures(1, DepthTexture);
GL.BindTexture(TextureTarget.TextureCubeMap, DepthTexture[0]);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS,
(int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT,
(int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter,
(int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter,
(int)TextureMinFilter.Nearest);
GL.TexImage2D(TextureTarget.TextureCubeMap, 0, PixelInternalFormat.DepthComponent24, 512, 512, 0,
PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero);
GL.BindTexture(TextureTarget.TextureCubeMap, 0);

GL.GenFramebuffers(1, FBO);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO[0]);
for (int i = 0; i < 6; i++)
{
GL.FramebufferTexture2D(FramebufferTarget.Framebuf fer, FramebufferAttachment.ColorAttachment0 + i, TextureTarget.TextureCubeMapPositiveX + i, ColorTexture[0], 0);

}
GL.FramebufferTexture2D(FramebufferTarget.Framebuf fer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2D, DepthTexture[0], 0);

GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
fboMsg = GL.CheckFramebufferStatus(FramebufferTarget.Frameb uffer).ToString();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
camera = new Camera();
camera.Fov = 90;
}

public Vector3 pos;
private Matrix4 tempMatrix;
public void Render()
{
GL.Enable(EnableCap.TextureCubeMapSeamless);
Camera.SetFov(90); // changes perspective matrix and is later sent to the shader during RenderScene();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO[0]);
for (int i = 0; i < 6; i++)
{
GL.DrawBuffer(DrawBufferMode.ColorAttachment0 + i);
Background.Render(); // this clears the buffers
GL.FramebufferTexture2D(FramebufferTarget.Framebuf fer, FramebufferAttachment.ColorAttachment0 + i, TextureTarget.TextureCubeMapPositiveX + i, ColorTexture[0], 0);

switch (i)
{
case 0: Camera.ViewMatrix = Matrix4.LookAt(pos, pos + Vector3.UnitX, Vector3.UnitY); //pos is the center of the cubemap in world coordinates
break;
case 1: Camera.ViewMatrix = Matrix4.LookAt(pos, pos - Vector3.UnitX, Vector3.UnitY); // camera view matrix is later sent to the shader during RenderScene();
break;
case 2: Camera.ViewMatrix = Matrix4.LookAt(pos, pos + Vector3.UnitY, Vector3.UnitZ);
break;
case 3: Camera.ViewMatrix = Matrix4.LookAt(pos, pos - Vector3.UnitY, -Vector3.UnitZ);
break;
case 4: Camera.ViewMatrix = Matrix4.LookAt(pos, pos + Vector3.UnitZ, Vector3.UnitY);
break;
case 5: Camera.ViewMatrix = Matrix4.LookAt(pos, pos - Vector3.UnitZ, Vector3.UnitY);
break;
}
RenderScene();
}
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}

public void Destroy()
{
GL.DeleteTextures(1, ColorTexture);
GL.DeleteTextures(1, DepthTexture);
GL.DeleteBuffers(1, FBO);
}

public void BindTexture(int texUnit)
{
Renderer.ActiveTexture(texUnit);
GL.BindTexture(TextureTarget.TextureCubeMap, ColorTexture[0]);
}

}
}
</code>

and the relevant part of the shader that applies the cubemap:
<code>
vec3 R = reflect(In,normal); //In is incident vector
fragColor= texture(reflectCubeSampler,R);
</code>

carsten neumann
07-09-2010, 03:03 PM
I think the order is +Z -Z +Y -Y +X -X, at least that is what the comments in some of my code I looked at say... ;)

sgsrules
07-09-2010, 08:44 PM
Thanks for the reply Carsten but the order that i was using was correct.

I figured out what part of my problem was:
1) I was changing the FOV but i wasn't changing the aspect ratio.
2) I forgot to change the viewport size when rendering the cubemap.
3) I had to make the up vector (0,-1,0) for some reason.

Everything almost works now. I'm having an issue with the top borders not lining up properly. I've attached a jpg of a reflective sphere inside a box. If you look at the top edge of the reflection of the box you'll notice that the edges don't line up properly like the bottom ones do. Any ideas as to what might cause this?

http://www.opentk.com/files/cubemaptest.jpg