Rendering linearized depth buffer by rendering it to another RGB texture

simple_math_single_header
Martin Felis 2018-02-17 23:49:56 +01:00
parent ea2b5d1e13
commit 9c56d3f061
5 changed files with 101 additions and 76 deletions

View File

@ -10,27 +10,7 @@ uniform float uFar;
void main() { void main() {
float z = texture(uTexture, ioUV).r; float z = texture(uTexture, ioUV).r;
float c = (2.0 * uNear) / (uFar + uNear - z * (uFar - uNear)); float c = (z - uNear) / (uFar - uNear);
// c = 2.0 * uNear * uFar / (uFar + uNear - z * (uFar - uNear));
// c = (uNear + (z - uNear) / (uFar - uNear);
c = (z - uNear) / (uFar - uNear);
outColor = vec3(c); outColor = vec3(c);
if (abs(c + 1) < 0.2)
outColor = vec3(1, 0, 0);
// if (abs(c - 0.1) < 0.1)
// outColor = vec3(0, 0, 1);
// if (abs(c - 0.8) < 0.1)
// outColor = vec3(1, 0, 0);
// n ---- z ------- f
// 0 1
//
// (n + (z - n)) (f - n)
//
// (f - n)
// outColor = vec3(z);
} }

View File

@ -2,6 +2,7 @@
#include "Globals.h" #include "Globals.h"
#include "RenderModule.h" #include "RenderModule.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "Serializer.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "imgui_dock.h" #include "imgui_dock.h"
@ -10,10 +11,16 @@ using namespace SimpleMath::GL;
struct Renderer; struct Renderer;
struct RendererSettings {
bool DrawDepth = false;
};
static RendererSettings sRendererSettings;
static const GLfloat g_vertex_buffer_data[] = { static const GLfloat g_vertex_buffer_data[] = {
-0.9f, -0.9f, 0.0f, -0.9f, -0.9f, 0.0f,
0.9f, -0.9f, 0.0f, 0.9f, -0.9f, 0.0f,
0.0f, 0.9f, 1.0f 0.0f, 0.9f, 4.0f
}; };
static const GLfloat g_quad_vertex_buffer_data[] = { static const GLfloat g_quad_vertex_buffer_data[] = {
@ -47,6 +54,7 @@ template <typename Serializer>
static void module_serialize ( static void module_serialize (
struct module_state *state, struct module_state *state,
Serializer* serializer) { Serializer* serializer) {
SerializeBool(*serializer, "protot.RenderModule.DrawDepth", sRendererSettings.DrawDepth);
// // get the state from the serializer // // get the state from the serializer
// Camera* camera = &gRenderer->cameras[gRenderer->activeCameraIndex]; // Camera* camera = &gRenderer->cameras[gRenderer->activeCameraIndex];
// assert (camera != nullptr); // assert (camera != nullptr);
@ -74,6 +82,7 @@ static void module_reload(struct module_state *state, void *read_serializer) {
gLog ("Renderer initialize"); gLog ("Renderer initialize");
assert (state != nullptr); assert (state != nullptr);
state->renderer->Initialize(100, 100); state->renderer->Initialize(100, 100);
state->renderer->mSettings = &sRendererSettings;
gRenderer = state->renderer; gRenderer = state->renderer;
@ -147,7 +156,10 @@ glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data
muDefaultColor = mDefaultProgram.GetUniformLocation("uColor"); muDefaultColor = mDefaultProgram.GetUniformLocation("uColor");
// Render Target // Render Target
mRenderTarget = RenderTarget (width, height, RenderTarget::EnableColor | RenderTarget::EnableDepthTexture); mRenderTarget = RenderTarget (width, height,
RenderTarget::EnableColor
| RenderTarget::EnableDepthTexture
| RenderTarget::EnableLinearizedDepthTexture);
// Render Target Quad // Render Target Quad
glGenVertexArrays(1, &mRenderQuadVertexArrayId); glGenVertexArrays(1, &mRenderQuadVertexArrayId);
@ -186,11 +198,11 @@ void Renderer::RenderGl() {
if (width != mWidth || height != mHeight) if (width != mWidth || height != mHeight)
Resize(width, height); Resize(width, height);
mCamera.eye = Vector3f (0.0f, 0.0f, 1.0f); mCamera.eye = Vector3f (0.0f, 0.0f, 4.0f);
mCamera.poi = Vector3f (0.0f, 0.0f, 0.0f); mCamera.poi = Vector3f (0.0f, 0.0f, 0.0f);
mCamera.up = Vector3f (0.0f, 1.0f, 0.0f); mCamera.up = Vector3f (0.0f, 1.0f, 0.0f);
mCamera.near = 0.0f; mCamera.near = 0.0f;
mCamera.far = 1.0f; mCamera.far = 4.0f;
mCamera.orthographic = true; mCamera.orthographic = true;
mCamera.UpdateMatrices(); mCamera.UpdateMatrices();
@ -230,23 +242,63 @@ void Renderer::RenderGl() {
); );
glDrawArrays(GL_TRIANGLES, 0, 3); // starting from vertex 0; 3 vertices total glDrawArrays(GL_TRIANGLES, 0, 3); // starting from vertex 0; 3 vertices total
if (mSettings->DrawDepth) {
mRenderTarget.RenderToLinearizedDepth(true);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
Matrix44f model_view_projection = Matrix44f::Identity();
// render depth texture
glUseProgram(mRenderQuadProgramDepth.mProgramId);
glUniformMatrix4fv(muRenderQuadModelViewProj, 1, GL_FALSE, model_view_projection.data());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mRenderTarget.mDepthTexture);
glUniform1i(muRenderQuadTexture, 0);
// TODO: adjust for perspective
glUniform1f(muRenderQuadDepthNear, mCamera.near);
// TODO: why do I have to divide by depth range?
glUniform1f(muRenderQuadDepthFar, mCamera.far / (mCamera.far - mCamera.near));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId);
glVertexAttribPointer(
0, // attribute 0
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // offset
);
glDrawArrays(GL_TRIANGLES, 0, 6); // starting from vertex 0; 3 vertices total
mRenderTarget.RenderToLinearizedDepth(false);
}
glDisableVertexAttribArray(0); glDisableVertexAttribArray(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
void Renderer::RenderGui() { void Renderer::RenderGui() {
bool render_color = true;
GLuint texture;
if (render_color) {
texture = mRenderTarget.mColorTexture;
} else {
texture = mRenderTarget.mDepthTexture;
}
if (ImGui::BeginDock("Scene")) { if (ImGui::BeginDock("Scene")) {
ImGui::Checkbox("Draw Depth", &mSettings->DrawDepth);
GLuint texture;
if (mSettings->DrawDepth) {
texture = mRenderTarget.mLinearizedDepthTexture;
} else {
texture = mRenderTarget.mColorTexture;
}
ImGui::Text("Scene"); ImGui::Text("Scene");
const ImVec2 content_avail = ImGui::GetContentRegionAvail(); const ImVec2 content_avail = ImGui::GetContentRegionAvail();
// mRenderTarget.Resize(content_avail.x, content_avail.y);
ImGui::Image((void*) texture, ImGui::Image((void*) texture,
content_avail, content_avail,
ImVec2(0.0f, 1.0f), ImVec2(0.0f, 1.0f),
@ -254,46 +306,6 @@ void Renderer::RenderGui() {
); );
} }
ImGui::EndDock(); ImGui::EndDock();
return;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
Matrix44f model_view_projection = Matrix44f::Identity();
if (render_color) {
// Render the full screen quad
glUseProgram(mRenderQuadProgramColor.mProgramId);
glBindTexture(GL_TEXTURE_2D, mRenderTarget.mColorTexture);
glUniformMatrix4fv(muRenderQuadModelViewProj, 1, GL_FALSE, model_view_projection.data());
glUniform1i(muRenderQuadTexture, 0);
glUniform1f(muRenderQuadTime, (float)(glfwGetTime() * 10.0f));
} else {
// render depth texture
glUseProgram(mRenderQuadProgramDepth.mProgramId);
glBindTexture(GL_TEXTURE_2D, mRenderTarget.mDepthTexture);
glUniformMatrix4fv(muRenderQuadModelViewProj, 1, GL_FALSE, model_view_projection.data());
glUniform1i(muRenderQuadTexture, 0);
glUniform1f(muRenderQuadDepthNear, mCamera.near);
glUniform1f(muRenderQuadDepthFar, mCamera.far);
}
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId);
glVertexAttribPointer(
0, // attribute 0
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // offset
);
glDrawArrays(GL_TRIANGLES, 0, 6); // starting from vertex 0; 3 vertices total
glDisableVertexAttribArray(0);
} }
void Renderer::Resize (int width, int height) { void Renderer::Resize (int width, int height) {

View File

@ -106,7 +106,11 @@ struct Mesh {
GLuint mVertexBuffer = -1; GLuint mVertexBuffer = -1;
}; };
struct RendererSettings;
struct Renderer { struct Renderer {
RendererSettings* mSettings = nullptr;
bool mInitialized = false; bool mInitialized = false;
uint32_t mWidth = 1; uint32_t mWidth = 1;
uint32_t mHeight = 1; uint32_t mHeight = 1;

View File

@ -170,6 +170,11 @@ void RenderTarget::Cleanup() {
glDeleteRenderbuffers(1, &mDepthBuffer); glDeleteRenderbuffers(1, &mDepthBuffer);
mDepthBuffer = -1; mDepthBuffer = -1;
} }
if (mLinearizedDepthTexture != -1) {
glDeleteTextures(1, &mLinearizedDepthTexture);
mLinearizedDepthTexture = -1;
}
} }
void RenderTarget::Resize(int width, int height) { void RenderTarget::Resize(int width, int height) {
@ -210,6 +215,17 @@ void RenderTarget::Resize(int width, int height) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture, 0);
if (mFlags & EnableLinearizedDepthTexture) {
glGenTextures(1, &mLinearizedDepthTexture);
glBindTexture(GL_TEXTURE_2D, mLinearizedDepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
} else if (mFlags & EnableDepth) { } else if (mFlags & EnableDepth) {
assert((mFlags & EnableDepthTexture) == false); assert((mFlags & EnableDepthTexture) == false);
glGenRenderbuffers(1, &mDepthBuffer); glGenRenderbuffers(1, &mDepthBuffer);
@ -219,4 +235,11 @@ void RenderTarget::Resize(int width, int height) {
} }
} }
void RenderTarget::RenderToLinearizedDepth(bool render_to_depth) {
if (render_to_depth) {
assert(mFlags & EnableLinearizedDepthTexture);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mLinearizedDepthTexture, 0);
} else {
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0);
}
}

View File

@ -146,6 +146,9 @@ struct RenderProgram {
bool Load(); bool Load();
}; };
struct RenderSettings;
struct RenderTarget { struct RenderTarget {
int mWidth = 0; int mWidth = 0;
int mHeight = 0; int mHeight = 0;
@ -153,11 +156,13 @@ struct RenderTarget {
GLuint mColorTexture = -1; GLuint mColorTexture = -1;
GLuint mDepthBuffer = -1; GLuint mDepthBuffer = -1;
GLuint mDepthTexture = -1; GLuint mDepthTexture = -1;
GLuint mLinearizedDepthTexture = -1;
typedef enum { typedef enum {
EnableColor = 1, EnableColor = 1,
EnableDepth = 2, EnableDepth = 2,
EnableDepthTexture = 4 EnableDepthTexture = 4,
EnableLinearizedDepthTexture = 8
} Flags; } Flags;
int mFlags = 0; int mFlags = 0;
@ -168,6 +173,7 @@ struct RenderTarget {
void Cleanup(); void Cleanup();
void Resize(int width, int height); void Resize(int width, int height);
void RenderToLinearizedDepth(bool render_to_depth);
}; };
#endif #endif