Hello, I am following this tutorial Learn OpenGL, extensive tutorial resource for learning Modern OpenGL, except I’m using OpenTK. My issue is that I’m creating framebuffer with a depth component as a texture. I draw using a shader, then I plan to use the texture(which has all the depth data) for shadows. However the texture is all white! I’ve spend about 5 hours trying to figure this s*** out and cannot.
Here is my DepthBufferCode
/// <summary>
/// A frame buffer that just holds a depth buffer
/// </summary>
public class DepthBuffer
{
/// <summary>
/// OpenGL ID
/// </summary>
public int ID { get; private set; }
/// <summary>
/// ID to texture attached to the frambuffer, it acts as a depth buffer, and is used for sampling (this is public)
/// </summary>
public int TextureID { get; private set; }
/// <summary>
/// Status code FramebufferComplete is what we want
/// </summary>
public FramebufferErrorCode FramebufferStatus { get; private set; }
/// <summary>
/// Size of the buffer, we cannot change this, it would be easier to create a new on instead of changing size
/// </summary>
public Size Size { get; private set; }
/// <summary>
/// Create the frambuffer and attach the color and stencil/depth buffers
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
public DepthBuffer(int width, int height)
{
this.Size = new Size(width, height);
//gen depthbuffer as texture
TextureID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, TextureID);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, width, height, 0, PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (float)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (float)TextureWrapMode.Repeat);
//gen frambuffer
ID = GL.GenFramebuffer();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, ID);
//attach depth
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureID, 0);
//since we dont have a color buffer, we cant draw do it (we dont need to)
GL.DrawBuffer(DrawBufferMode.None);
GL.ReadBuffer(ReadBufferMode.None);
//check status and store it
FramebufferStatus = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
//unbind everything
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
/// <summary>
/// bind the frambuffer and set the viewport to its size
/// </summary>
public void Use()
{
GL.Viewport(new Point(0, 0), Size);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, ID);
}
/// <summary>
/// delete the buffers from memory
/// </summary>
public void Dispose()
{
GL.DeleteTexture(TextureID);
GL.DeleteFramebuffer(ID);
}
}
Here is my main class
using System;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK;
using GLTools;
using System.Collections.Generic;
using ShadowMapping;
using System.Drawing;
namespace Million_Cubes
{
class Program
{
private GameWindow window;
private Camera cam;
private List<Model> models;
private DepthBuffer depthBuffer;
private ShaderProgram depthShader;
private ModelVBOs frame;
private ShaderProgram frameShader;
Texture txt;
VBO<float> verts;
VBO<float> uv;
VBO<uint> element;
public Program()
{
window = new GameWindow(1600, 900, new GraphicsMode(32, 24, 8, 4), "Million Cubes");
//window.VSync = VSyncMode.Off;
window.UpdateFrame += Window_UpdateFrame;
window.RenderFrame += Window_RenderFrame;
window.MouseDown += Window_MouseDown;
window.MouseUp += Window_MouseUp;
window.MouseMove += Window_MouseMove;
window.MouseWheel += Window_MouseWheel;
window.Resize += Window_Resize;
window.KeyDown += Window_KeyDown;
window.Closed += Window_Closed;
cam = new Camera();
depthBuffer = new DepthBuffer(1024, 1024);
var de = depthBuffer.FramebufferStatus;
models = new List<Model>();
ObjLoader loader = new ObjLoader();
var cube = loader.loadVBOS("content/floor.obj", 3);
var dragon = loader.loadVBOS("content/dragon.obj", 3);
var shader = new ShaderProgram("content/default.vert", "content/default.frag", "default");
shader.writeAllInfoLogs();
depthShader = new ShaderProgram("content/depth.vert", "content/depth.frag", "depth");
depthShader.Use();
var proj = Matrix4.CreateOrthographicOffCenter(-10, 10, -10, 10, 1.0f, 100.5f);
var light = Matrix4.LookAt(new Vector3(.1f, 10, .1f), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
Matrix4 lightSpace = Matrix4.Mult(proj, light);
depthShader.setUniform("lightSpaceMatrix", lightSpace);
depthShader.writeAllInfoLogs();
models.Add(new MyModel(dragon, null, shader));
models.Add(new MyModel(cube, null, shader) { Position = new Vector3(0, -5, 0), Scale = 3f });
//frame
verts = new VBO<float>(new float[] { -1, .5f, 0, -.5f, .5f, 0, -.5f, 1, 0, -1, 1, 0 }, BufferTarget.ArrayBuffer, VBO<float>.PointerType.vertex);
uv = new VBO<float>(new float[] { 0, 0, 1, 0, 1, 1, 0, 1 }, BufferTarget.ArrayBuffer, VBO<float>.PointerType.texCoord);
element = new VBO<uint>(new uint[] { 0, 1, 2, 3 }, BufferTarget.ElementArrayBuffer, VBO<uint>.PointerType.element);
frameShader = new ShaderProgram("content/frame.vert", "content/frame.frag", "frame");
frameShader.writeAllInfoLogs();
txt = new Texture("content/derp.jpg");
}
private void Window_RenderFrame(object sender, FrameEventArgs e)
{
//depthBuffer
depthBuffer.Use();
GL.Clear(ClearBufferMask.DepthBufferBit);
foreach (Model m in models)
((MyModel)m).draw(cam, depthShader);
//normal drawwing
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
GL.Viewport(new Rectangle(0, 0, window.Bounds.Width, window.Bounds.Height));
GL.ClearColor(new Color4(46, 49, 54, 255));
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
foreach (Model m in models)
m.draw(cam, true);
//right bottom texture
frameShader.Use();
frameShader.bindBufferToShaderAttrib(verts, "vertIn");
frameShader.bindBufferToShaderAttrib(uv, "uvIn", 2);
GL.BindTexture(TextureTarget.Texture2D, depthBuffer.TextureID);
element.bind();
GL.DrawElements(PrimitiveType.Quads, 4, DrawElementsType.UnsignedInt, 0);
window.SwapBuffers();
}
private void Window_UpdateFrame(object sender, FrameEventArgs e)
{
cam.update();
}
private void run()
{
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.Texture2D);
//GL.EnableClientState(ArrayCap.VertexArray);
//GL.EnableClientState(ArrayCap.TextureCoordArray);
GL.CullFace(CullFaceMode.Back);
GL.Enable(EnableCap.CullFace);
GL.MatrixMode(MatrixMode.Projection);
Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(75), window.Width / (float)window.Height, .1f, 100f);
cam = new Camera();
cam.Projection = perspective;
window.Run();
}
#region Events
private void Window_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs e)
{
cam.keydown(e);
}
private void Window_Resize(object sender, EventArgs e)
{
GL.Viewport(0, 0, window.Width, window.Height);
}
private void Window_MouseMove(object sender, OpenTK.Input.MouseMoveEventArgs e)
{
cam.mouseMove(e.X, e.Y);
}
private void Window_MouseUp(object sender, OpenTK.Input.MouseButtonEventArgs e)
{
cam.mouseUp();
}
private void Window_MouseDown(object sender, OpenTK.Input.MouseButtonEventArgs e)
{
cam.mouseDown(e.X, e.Y);
}
private void Window_MouseWheel(object sender, OpenTK.Input.MouseWheelEventArgs e)
{
cam.mouseWheel(e.Delta);
}
private void Window_Closed(object sender, EventArgs e)
{
window.Close();
}
#endregion
#region Entry
static void Main(string[] args)
{
Program p = new Program();
p.run();
}
#endregion
}
}
Here are the shaders. These are empty cause we just want to draw them from the light’s perspective and write to the depth buffer (done in fragment shader, automatically)
-----------------Vert--------------
#version 330
in vec3 vertIn;
uniform mat4 lightSpaceMatrix;
uniform mat4 model;
void main()
{
gl_Position = lightSpaceMatrix * model * vec4(vertIn, 1);
}
-----------------Frag--------------
#version 330
void main()
{
}
Here is what is looks like. The box in the corner renders the depth buffer. I put the shader to render red if the depth is EXCATLY 1.
After messing around. I tried using the camera as the light source. And if I zoom in. it stars to show something. Note that the far plane for the camera is 100.
I set the camera’s zfar and znear planes to .1f and 1.f and the two images start to line up.
So it looks like the depth buffer only writes from 0 to 1. Yes that’s accurate but it should write from 0 to 1 within the clipping planes (0 = 0, 1 = 100). I have no idea how to fix this. Ive tried messing around with a bunch of s*** and none of it seems to work.