[OpenTK] Depth Buffer as texture problems.

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.

Things I’ve tried so far.
PixelType.UnsignedInt , float, uint, etc.
PixelInternalFormat.DepthComponent, DepthComponenet16, 24, 32

Tried using perspective instead of ortho, different clipping planes.

Images don’t show. Here they are in order.
http://postimg.org/image/u0ezoqarf/
http://postimg.org/image/jd03ll3zv/
http://postimg.org/image/tbzrg1fgb/

i think the projection matrix is responsible for the transformation …
from 0.1 <–> 100 (your scene’s view frustum)
to 0 <–> 1 (normalized device coords, a cube of length 1)
by multiplying a vertex with that matrix, you calculate the position in that “cube of length 1”:

you can change the values directly using this function:
https://www.opengl.org/sdk/docs/man/html/glDepthRange.xhtml

Thats not gonna change anything, changing the depthRange is gonna change what is maps to. So glDepthRange(0, 10) will map 0 to 0 and 100 to 10. That’s not the problem. The problem is that the depth buffer only gets written when the vertex is in the range of 0 to 1, even though my near and far planes are set to 1 and 100.

Solved.

Changed some code.


---------vertex shader------
#version 330

in vec3 vertIn;

uniform mat4 view;
uniform mat4 proj;
uniform mat4 model;

void main()
{
	mat4 lightSpace = proj * view;
	gl_Position = lightSpace * model * vec4(vertIn, 1);
}

------Program------
            var proj = Matrix4.CreateOrthographicOffCenter(-10, 10, -10, 10, 1.0f, 100.5f);
            var light = Matrix4.LookAt(new Vector3(.1f, 10, 5.1f), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
            Matrix4 lightSpace = Matrix4.Mult(proj, light);
            depthShader.Use();
            depthShader.setUniform("proj", proj);
            depthShader.setUniform("view", light);

CLEARLY doing proj * view = lightSpace; then lightSpace * model * vec4; works.

But when I do

Matrix4 lightSpace = Matrix4.Mult(proj, light);
depthShader.setUniform(“lightSpace”, lightSpace);

and in shader do lightSpace * model * vec4; IT DOESN’T F****** work. I just found out that I have to multiply them backwards for it to work. Matrix4 lightSpace = Matrix4.Mult(light, proj); <===== all this s*** cause of this. WHY is it backwards?