From 0810224356f79e7db8bbcd3b1edbe5851a4793c8 Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Sun, 11 Mar 2018 22:05:42 +0100 Subject: [PATCH] Rendering of perspective linearized depth map kind of works now --- data/shaders/fs_depthbuffer.glsl | 12 ++- data/shaders/fs_shadowmap.frag | 32 ++++++ data/shaders/vs_shadowmap.vert | 25 +++++ src/modules/RenderModule.cc | 177 +++++++++++++++---------------- src/modules/RenderModule.h | 99 ++++------------- src/modules/RenderUtils.cc | 118 ++++++++++++++++++--- src/modules/RenderUtils.h | 64 ++++++++++- 7 files changed, 338 insertions(+), 189 deletions(-) create mode 100644 data/shaders/fs_shadowmap.frag create mode 100644 data/shaders/vs_shadowmap.vert diff --git a/data/shaders/fs_depthbuffer.glsl b/data/shaders/fs_depthbuffer.glsl index e3c7cda..4c8a50d 100644 --- a/data/shaders/fs_depthbuffer.glsl +++ b/data/shaders/fs_depthbuffer.glsl @@ -4,13 +4,19 @@ in vec2 ioUV; out vec3 outColor; -uniform sampler2D uTexture; +uniform sampler2D uDepthTexture; +uniform float uIsOrthographic; uniform float uNear; uniform float uFar; void main() { - float z = texture(uTexture, ioUV).r; - float c = (z - uNear) / (uFar - uNear); + float z = texture(uDepthTexture, ioUV).r; + float c; + if (uIsOrthographic == 1.0) { + c = (z - uNear) / (uFar - uNear); + } else { + c = (2.0 * uNear) / (uFar + uNear - z * (uFar - uNear)); + } outColor = vec3(c); } diff --git a/data/shaders/fs_shadowmap.frag b/data/shaders/fs_shadowmap.frag new file mode 100644 index 0000000..43747df --- /dev/null +++ b/data/shaders/fs_shadowmap.frag @@ -0,0 +1,32 @@ +#version 150 core + +uniform vec4 uColor; +uniform vec3 uLightDirection; +uniform vec3 uViewPosition; + +smooth in vec4 ioFragColor; +in vec3 ioNormal; +in vec3 ioFragPosition; + +out vec4 outColor; + +void main() { + // ambient lighting + float ambient_strength = 0.1; + vec4 ambient = ambient_strength * ioFragColor; + + // diffuse lighting + vec3 normal_dir = normalize(ioNormal); + vec3 light_dir = normalize(uLightDirection); + float diff = max(dot(normal_dir, light_dir), 0.0); + vec4 diffuse = diff * ioFragColor; + + // specular lighting + vec3 view_dir = normalize(uViewPosition - ioFragPosition); + vec3 halfway_dir = normalize(light_dir + view_dir); + + float spec = pow(max(dot(normal_dir, halfway_dir), 0.0), 32); + vec4 specular = spec * vec4(0.5); + + outColor = ambient + diffuse + specular; +} diff --git a/data/shaders/vs_shadowmap.vert b/data/shaders/vs_shadowmap.vert new file mode 100644 index 0000000..549947c --- /dev/null +++ b/data/shaders/vs_shadowmap.vert @@ -0,0 +1,25 @@ +#version 150 core +#extension GL_ARB_explicit_attrib_location : require + +in vec4 inCoord; +in vec3 inNormal; +in vec2 inUV; +in vec4 inColor; + +uniform mat4 uModelMatrix; +uniform mat4 uViewMatrix; +uniform mat4 uProjectionMatrix; +uniform mat3 uNormalMatrix; +uniform vec3 uLightDirection; +uniform vec3 uViewPosition; + +smooth out vec4 ioFragColor; +out vec3 ioNormal; +out vec3 ioFragPosition; + +void main() { + gl_Position = uProjectionMatrix * uViewMatrix * uModelMatrix * inCoord; + ioFragColor = inColor; + ioNormal = uNormalMatrix * inNormal; + ioFragPosition = (uModelMatrix * inCoord).xyz; +} diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index d106bde..9f8fb20 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -154,37 +154,31 @@ const struct module_api MODULE_API = { -// -// Camera -// -void Camera::UpdateMatrices() { - mViewMatrix = LookAt(mEye, mPoi, mUp); +void Light::Initialize() { + gLog("Initializing light"); + mShadowMapProgram = RenderProgram("data/shaders/vs_shadowmap.vert", "data/shaders/fs_shadowmap.frag"); - if (mIsOrthographic) { - mProjectionMatrix = Ortho(-1.0f, 1.0f, -1.0f, 1.0f, mNear, mFar); - } else { - mProjectionMatrix = Perspective(mFov, mWidth / mHeight, mNear, mFar); - } + bool load_result = mShadowMapProgram.Load(); + mShadowMapProgram.RegisterFileModification(); + assert(load_result); + + gLog("Initializing light render target size: %d, %d", mShadowMapSize, mShadowMapSize); + mShadowMapTarget.Initialize(mShadowMapSize, mShadowMapSize, + RenderTarget::EnableColor + | RenderTarget::EnableDepthTexture + | RenderTarget::EnableLinearizedDepthTexture); + + glBindFramebuffer(GL_FRAMEBUFFER, mShadowMapTarget.mFrameBufferId); + gLog("Framebuffer of light has id: %d", mShadowMapTarget.mFrameBufferId); + gLog("Initializing light done"); } -void Camera::DrawGui() { - ImGui::Text("Width %3.4f, Height %3.4f", mWidth, mHeight); - - ImGui::InputFloat3("Eye", mEye.data(), -10.0f, 10.0f); - ImGui::SliderFloat3("EyeS", mEye.data(), -10.0f, 10.0f); - - ImGui::InputFloat3("Poi", mPoi.data(), -10.0f, 10.0f); - ImGui::InputFloat3("Up", mUp.data(), -10.0f, 10.0f); - ImGui::Checkbox("Orthographic", &mIsOrthographic); - ImGui::SliderFloat("Fov", &mFov, 5, 160); - ImGui::SliderFloat("Near", &mNear, -10, 10); - ImGui::SliderFloat("Far", &mFar, -20, 50); - if (ImGui::Button("Reset")) { - *this = Camera(); - } +void Light::UpdateMatrices() { + mLightProjection = Ortho (-mBBoxSize * 0.5f, mBBoxSize * 0.5f, -mBBoxSize * 0.5f, mBBoxSize * 0.5f, mNear, mFar); + mLightView = LookAt(mDirection * mBBoxSize * 0.5f, Vector3f (0.0f, 0.0f, 0.0f), Vector3f (0.0f, 1.0f, 0.0f)); + mLightSpaceMatrix = mLightProjection * mLightView; } - // // Renderer // @@ -300,20 +294,6 @@ void Renderer::Initialize(int width, int height) { mDefaultProgram.RegisterFileModification(); assert(load_result); - // Render Target - mRenderTarget = RenderTarget (width, height, - RenderTarget::EnableColor - | RenderTarget::EnableDepthTexture - | RenderTarget::EnableLinearizedDepthTexture); - - // Render Target Quad - glGenVertexArrays(1, &mRenderQuadVertexArrayId); - glBindVertexArray(mRenderQuadVertexArrayId); - - glGenBuffers(1, &mRenderQuadVertexBufferId); - glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId); - glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW); - // Program for color texture rendering mRenderQuadProgramColor = RenderProgram("data/shaders/vs_passthrough.glsl", "data/shaders/fs_simpletexture.glsl"); load_result = mRenderQuadProgramColor.Load(); @@ -333,6 +313,27 @@ void Renderer::Initialize(int width, int height) { muRenderQuadDepthNear = mRenderQuadProgramDepth.GetUniformLocation("uNear"); muRenderQuadDepthFar = mRenderQuadProgramDepth.GetUniformLocation("uFar"); + // Render Target + gLog("Initializing main render target size: %d,%d", width, height); + mRenderTarget.Initialize(width, height, + RenderTarget::EnableColor + | RenderTarget::EnableDepthTexture + | RenderTarget::EnableLinearizedDepthTexture); + + // Render Target Quad + glGenVertexArrays(1, &mRenderQuadVertexArrayId); + glBindVertexArray(mRenderQuadVertexArrayId); + + glGenBuffers(1, &mRenderQuadVertexBufferId); + glBindBuffer(GL_ARRAY_BUFFER, mRenderQuadVertexBufferId); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW); + + mRenderTarget.mQuadVertexArray = mRenderQuadVertexArrayId; + mRenderTarget.mQuadVertexBuffer = mRenderQuadVertexBufferId; + mRenderTarget.mLinearizeDepthProgram = mRenderQuadProgramDepth; + + // Light + mLight.Initialize(); } void Renderer::Shutdown() { @@ -348,14 +349,25 @@ void Renderer::RenderGl() { mCamera.mHeight = mSceneAreaHeight; } - glViewport(0, 0, mCamera.mWidth, mCamera.mHeight); - mCamera.UpdateMatrices(); + // Shadow Map + glViewport(0, 0, mLight.mShadowMapSize, mLight.mShadowMapSize); + mLight.mShadowMapTarget.Bind(); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glUseProgram(mLight.mShadowMapProgram.mProgramId); + RenderScene(mLight.mShadowMapProgram); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + // TODO: render linearized depth for the light + // mLight.mShadowMapTarget.RenderToLinearizedDepth(mCamera); + // Regular rendering glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_MULTISAMPLE); glEnable(GL_CULL_FACE); + glViewport(0, 0, mCamera.mWidth, mCamera.mHeight); + mCamera.UpdateMatrices(); + Matrix44f model_matrix = TranslateMat44(0.0f, 0.0f, 0.0f); Matrix44f model_view_projection = model_matrix @@ -373,7 +385,7 @@ void Renderer::RenderGl() { // clear color and depth glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); + glDisable(GL_DEPTH_TEST); glUseProgram(mSimpleProgram.mProgramId); mSimpleProgram.SetMat44("uModelViewProj", model_view_projection); @@ -399,65 +411,38 @@ void Renderer::RenderGl() { gVertexArray.Bind(); gXZPlaneMesh.Draw(GL_LINES); - // Unit cube + // Scene glUseProgram(mDefaultProgram.mProgramId); - gVertexArray.Bind(); + glBindTexture(GL_TEXTURE_2D, mLight.mShadowMapTarget.mDepthTexture); + glEnable(GL_DEPTH_TEST); - model_matrix = TranslateMat44(3.0f, 0.0f, 1.0f); - Matrix33f normal_matrix = model_matrix.block<3,3>(0,0).transpose(); - normal_matrix = normal_matrix.inverse(); - - mDefaultProgram.SetMat44("uModelMatrix", model_matrix); - mDefaultProgram.SetMat44("uViewMatrix", mCamera.mViewMatrix); - mDefaultProgram.SetMat44("uProjectionMatrix", mCamera.mProjectionMatrix); - mDefaultProgram.SetMat33("uNormalMatrix", normal_matrix); - - mDefaultProgram.SetVec4("uColor", Vector4f (1.0f, 0.0f, 0.0f, 1.0f)); - mDefaultProgram.SetVec3("uLightDirection", mLight.mDirection); - mDefaultProgram.SetVec3("uViewPosition", mCamera.mEye); - gVertexArray.Bind(); - gUnitCubeMesh.Draw(GL_TRIANGLES); + RenderScene(mDefaultProgram); 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.mNear); - // TODO: why do I have to divide by depth range? - glUniform1f(muRenderQuadDepthFar, mCamera.mFar / (mCamera.mFar - mCamera.mNear)); - - 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); + mRenderTarget.RenderToLinearizedDepth(mCamera); } glDisableVertexAttribArray(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void Renderer::RenderScene(RenderProgram &program) { + Matrix44f model_matrix = TranslateMat44(3.0f, 0.0f, 1.0f); + Matrix33f normal_matrix = model_matrix.block<3,3>(0,0).transpose(); + normal_matrix = normal_matrix.inverse(); + + program.SetMat44("uModelMatrix", model_matrix); + program.SetMat44("uViewMatrix", mCamera.mViewMatrix); + program.SetMat44("uProjectionMatrix", mCamera.mProjectionMatrix); + program.SetMat33("uNormalMatrix", normal_matrix); + + program.SetVec4("uColor", Vector4f (1.0f, 0.0f, 0.0f, 1.0f)); + program.SetVec3("uLightDirection", mLight.mDirection); + program.SetVec3("uViewPosition", mCamera.mEye); + gVertexArray.Bind(); + gUnitCubeMesh.Draw(GL_TRIANGLES); +} + void Renderer::RenderGui() { if (ImGui::BeginDock("Scene")) { ImGui::Checkbox("Draw Depth", &mSettings->DrawDepth); @@ -486,11 +471,17 @@ void Renderer::RenderGui() { if (ImGui::BeginDock("Render Settings")) { ImGui::Text("Light"); ImGui::SliderFloat3("Direction", mLight.mDirection.data(), -10.0f, 10.0f); + ImVec2 content_avail = ImGui::GetContentRegionAvail(); + ImGui::Image((void*) mLight.mShadowMapTarget.mLinearizedDepthTexture, + ImVec2(content_avail.x, content_avail.x), + ImVec2(0.0f, 1.0f), + ImVec2(1.0f, 0.0f) + ); ImGui::Text("Camera"); mCamera.DrawGui(); ImGui::Text("Default Texture"); - const ImVec2 content_avail = ImGui::GetContentRegionAvail(); + content_avail = ImGui::GetContentRegionAvail(); ImGui::Image((void*) mDefaultTexture.mTextureId, ImVec2(content_avail.x, content_avail.x), ImVec2(0.0f, 1.0f), diff --git a/src/modules/RenderModule.h b/src/modules/RenderModule.h index 04dc367..191da13 100644 --- a/src/modules/RenderModule.h +++ b/src/modules/RenderModule.h @@ -14,94 +14,40 @@ #include "Globals.h" #include "RenderUtils.h" -struct Camera { - Vector3f mEye; - Vector3f mPoi; - Vector3f mUp; - - float mNear; - float mFar; - float mFov; - bool mIsOrthographic; - float mWidth; - float mHeight; - - Matrix44f mProjectionMatrix; - Matrix44f mViewMatrix; - - Camera() : - mEye {5.f, 4.f, 5.f}, - mPoi {0.f, 2.f, 0.f}, - mUp {0.f, 1.f, 0.f}, - mNear (0.1f), - mFar (150.f), - mFov (60.f), - mIsOrthographic (false), - mWidth (-1.f), - mHeight (-1.f), - - mProjectionMatrix ( - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f), - mViewMatrix ( - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f) - {} - - void UpdateMatrices(); - void DrawGui(); -}; - struct Light { Vector3f mPosition; Vector3f mDirection; - float mViewMatrix[16]; - float mProjectionMatrix[16]; - float mtxLight[16]; - float mtxShadow[16]; + RenderTarget mShadowMapTarget; + RenderProgram mShadowMapProgram; - float shadowMapBias; - uint16_t shadowMapSize; + float mShadowMapBias; + uint16_t mShadowMapSize; - bool enabled; - float near; - float far; - float area; + float mNear; + float mFar; + float mBBoxSize; + + Matrix44f mLightProjection; + Matrix44f mLightView; + Matrix44f mLightSpaceMatrix; Light() : mPosition (Vector3f(0.f, 10.f, 10.f)), mDirection (Vector3f(-1.f, -1.f, -1.f)), - mViewMatrix { - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - mProjectionMatrix { - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - mtxShadow { - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - shadowMapBias (0.004f), - shadowMapSize (2048), - near (0.1f), - far (100.f), - area (10.f), - enabled (false) + mShadowMapBias (0.004f), + mShadowMapSize (1024), + mNear (0.1f), + mFar (100.f), + mBBoxSize (10.f), + mLightProjection(Matrix44f::Identity()), + mLightView(Matrix44f::Identity()), + mLightSpaceMatrix(Matrix44f::Identity()) { } + + void Initialize(); + void UpdateMatrices(); }; struct RendererSettings; @@ -151,5 +97,6 @@ struct Renderer { void Initialize(int width, int height); void Shutdown(); void RenderGl(); + void RenderScene(RenderProgram &program); void RenderGui(); }; diff --git a/src/modules/RenderUtils.cc b/src/modules/RenderUtils.cc index 1b5024e..63e9929 100644 --- a/src/modules/RenderUtils.cc +++ b/src/modules/RenderUtils.cc @@ -9,11 +9,46 @@ #include "Globals.h" #include "FileModificationObserver.h" +#include "imgui/imgui.h" +#include "imgui_dock.h" + #define STB_IMAGE_IMPLEMENTATION #include "stb/stb_image.h" using namespace SimpleMath; +using namespace SimpleMath::GL; + +// +// Camera +// +void Camera::UpdateMatrices() { + mViewMatrix = LookAt(mEye, mPoi, mUp); + + if (mIsOrthographic) { + mProjectionMatrix = Ortho(-1.0f, 1.0f, -1.0f, 1.0f, mNear, mFar); + } else { + mProjectionMatrix = Perspective(mFov, mWidth / mHeight, mNear, mFar); + } +} + +void Camera::DrawGui() { + ImGui::Text("Width %3.4f, Height %3.4f", mWidth, mHeight); + + ImGui::InputFloat3("Eye", mEye.data(), -10.0f, 10.0f); + ImGui::SliderFloat3("EyeS", mEye.data(), -10.0f, 10.0f); + + ImGui::InputFloat3("Poi", mPoi.data(), -10.0f, 10.0f); + ImGui::InputFloat3("Up", mUp.data(), -10.0f, 10.0f); + ImGui::Checkbox("Orthographic", &mIsOrthographic); + ImGui::SliderFloat("Fov", &mFov, 5, 160); + ImGui::SliderFloat("Near", &mNear, -10, 10); + ImGui::SliderFloat("Far", &mFar, -20, 50); + if (ImGui::Button("Reset")) { + *this = Camera(); + } +} + // // RenderProgram @@ -230,15 +265,21 @@ bool RenderProgram::OnFileChanged(const std::string& filename) { // // RenderTarget // -RenderTarget::RenderTarget(int width, int height, int flags) { +RenderTarget::~RenderTarget() { + Cleanup(); +} + +void RenderTarget::Initialize(int width, int height, int flags) { + Cleanup(); + mFlags = flags; - Cleanup(); Resize(width, height); } -RenderTarget::~RenderTarget() { - Cleanup(); +void RenderTarget::Bind() { + assert(glIsFramebuffer(mFrameBufferId)); + glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferId); } void RenderTarget::Cleanup() { @@ -277,7 +318,7 @@ void RenderTarget::Resize(int width, int height) { Cleanup(); - gLog("Resizing RenderTarget"); + gLog("Resizing RenderTarget to %d,%d", width, height); mWidth = width; mHeight = height; @@ -294,7 +335,7 @@ void RenderTarget::Resize(int width, int height) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture, 0); } if (mFlags & EnableDepthTexture) { @@ -310,7 +351,7 @@ void RenderTarget::Resize(int width, int height) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTexture, 0); if (mFlags & EnableLinearizedDepthTexture) { glGenTextures(1, &mLinearizedDepthTexture); @@ -329,15 +370,64 @@ void RenderTarget::Resize(int width, int height) { glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthBuffer); } + + GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (result != GL_FRAMEBUFFER_COMPLETE) { + switch (result) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: gLog("Error: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + break; + case GL_FRAMEBUFFER_UNDEFINED: gLog("Error: GL_FRAMEBUFFER_UNDEFINED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: gLog("Error: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); + break; + default: gLog("Error when creating Framebuffer: %d", result); + } + } + + assert(result == GL_FRAMEBUFFER_COMPLETE); } -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); - } +void RenderTarget::RenderToLinearizedDepth(const Camera& camera) { + assert(mFlags & EnableLinearizedDepthTexture); + assert(mLinearizedDepthTexture != -1); + assert(mQuadVertexArray != -1); + assert(mQuadVertexBuffer != -1); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mLinearizedDepthTexture, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferId); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_DEPTH_TEST); + + Matrix44f model_view_projection = Matrix44f::Identity(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mDepthTexture); + + // render depth texture + glUseProgram(mLinearizeDepthProgram.mProgramId); + mLinearizeDepthProgram.SetMat44("uModelViewProj", model_view_projection); + mLinearizeDepthProgram.SetFloat("uNear", camera.mNear); + mLinearizeDepthProgram.SetFloat("uFar", camera.mFar); + mLinearizeDepthProgram.SetFloat("uIsOrthographic", camera.mIsOrthographic ? 1.0f : 0.0f); + mLinearizeDepthProgram.SetInt("uDepthTexture", 0); + + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer); + 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 + + if (mFlags & EnableColor) + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTexture, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } // diff --git a/src/modules/RenderUtils.h b/src/modules/RenderUtils.h index 428f8a0..ab1194f 100644 --- a/src/modules/RenderUtils.h +++ b/src/modules/RenderUtils.h @@ -129,6 +129,50 @@ struct Transform { } }; +struct Camera { + Vector3f mEye; + Vector3f mPoi; + Vector3f mUp; + + float mNear; + float mFar; + float mFov; + bool mIsOrthographic; + float mWidth; + float mHeight; + + Matrix44f mProjectionMatrix; + Matrix44f mViewMatrix; + + Camera() : + mEye {5.f, 4.f, 5.f}, + mPoi {0.f, 2.f, 0.f}, + mUp {0.f, 1.f, 0.f}, + mNear (0.1f), + mFar (150.f), + mFov (60.f), + mIsOrthographic (false), + mWidth (-1.f), + mHeight (-1.f), + + mProjectionMatrix ( + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f), + mViewMatrix ( + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, 0.f, 0.f, 1.f) + {} + + void UpdateMatrices(); + void DrawGui(); +}; + + + struct RenderProgram : AFileModificationListener { std::string mVertexShaderFilename; std::string mFragmentShaderFilename; @@ -153,6 +197,14 @@ struct RenderProgram : AFileModificationListener { GLuint CompileFragmentShader(); GLuint LinkProgram(GLuint vertex_shader, GLuint fragment_shader); + void SetInt(const char* name, const GLint& val) { + GLint location = glGetUniformLocation(mProgramId, name); + glUniform1i(location, val); + } + void SetFloat(const char* name, const float& val) { + GLint location = glGetUniformLocation(mProgramId, name); + glUniform1f(location, val); + } void SetVec3(const char* name, const Vector3f& vec) { GLint location = glGetUniformLocation(mProgramId, name); glUniform3fv(location, 1, vec.data()); @@ -179,7 +231,7 @@ struct RenderProgram : AFileModificationListener { }; struct RenderSettings; - +struct RenderProgram; struct RenderTarget { int mWidth = 0; @@ -199,13 +251,19 @@ struct RenderTarget { int mFlags = 0; + RenderProgram mLinearizeDepthProgram; + GLuint mQuadVertexArray = -1; + GLuint mQuadVertexBuffer = -1; + RenderTarget() {}; - RenderTarget(int width, int height, int flags); ~RenderTarget(); + void Initialize(int width, int height, int flags); + void Bind(); void Cleanup(); void Resize(int width, int height); - void RenderToLinearizedDepth(bool render_to_depth); + + void RenderToLinearizedDepth(const Camera &camera); }; struct Texture {