diff --git a/data/shaders/fs_depthbuffer.glsl b/data/shaders/fs_depthbuffer.glsl index 4c8a50d..3c9d0b7 100644 --- a/data/shaders/fs_depthbuffer.glsl +++ b/data/shaders/fs_depthbuffer.glsl @@ -13,7 +13,7 @@ void main() { float z = texture(uDepthTexture, ioUV).r; float c; if (uIsOrthographic == 1.0) { - c = (z - uNear) / (uFar - uNear); + c = z; } else { c = (2.0 * uNear) / (uFar + uNear - z * (uFar - uNear)); } diff --git a/data/shaders/vs_passthrough.glsl b/data/shaders/vs_passthrough.glsl index bddaa12..286c571 100644 --- a/data/shaders/vs_passthrough.glsl +++ b/data/shaders/vs_passthrough.glsl @@ -1,6 +1,7 @@ #version 330 core in vec3 inVertex; + uniform mat4 uModelViewProj; uniform float uTime; diff --git a/src/modules/RenderModule.cc b/src/modules/RenderModule.cc index 9f8fb20..8c6c09a 100644 --- a/src/modules/RenderModule.cc +++ b/src/modules/RenderModule.cc @@ -13,6 +13,7 @@ struct Renderer; struct RendererSettings { bool DrawDepth = false; + bool DrawLightDepth = false; }; static RendererSettings sRendererSettings; @@ -78,6 +79,7 @@ static void module_serialize ( struct module_state *state, Serializer* serializer) { SerializeBool(*serializer, "protot.RenderModule.DrawDepth", sRendererSettings.DrawDepth); + SerializeBool(*serializer, "protot.RenderModule.DrawLightDepth", sRendererSettings.DrawLightDepth); SerializeBool(*serializer, "protot.RenderModule.Camera.mIsOrthographic", gRenderer->mCamera.mIsOrthographic); SerializeFloat(*serializer, "protot.RenderModule.Camera.mFov", gRenderer->mCamera.mFov); SerializeVec3(*serializer, "protot.RenderModule.Camera.mEye", gRenderer->mCamera.mEye); @@ -86,6 +88,8 @@ static void module_serialize ( SerializeFloat(*serializer, "protot.RenderModule.Camera.mNear", gRenderer->mCamera.mNear); SerializeFloat(*serializer, "protot.RenderModule.Camera.mFar", gRenderer->mCamera.mFar); SerializeVec3(*serializer, "protot.RenderModule.mLight.mDirection", gRenderer->mLight.mDirection); + SerializeFloat(*serializer, "protot.RenderModule.mLight.mNear", gRenderer->mLight.mNear); + SerializeFloat(*serializer, "protot.RenderModule.mLight.mFar", gRenderer->mLight.mFar); // SerializeBool (*serializer, "protot.RenderModule.draw_floor", gRenderer->drawFloor); // SerializeBool (*serializer, "protot.RenderModule.draw_skybox", gRenderer->drawSkybox); @@ -167,16 +171,21 @@ void Light::Initialize() { 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 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; + mCamera.mIsOrthographic = true; + mCamera.mWidth = mShadowMapSize; + mCamera.mHeight = mShadowMapSize; + mCamera.mNear = mNear; + mCamera.mFar = mFar; + + mCamera.mEye = mDirection * mBBoxSize * 0.5; + mCamera.mPoi = mCamera.mEye - mDirection; + + mCamera.UpdateMatrices(); + + mLightSpaceMatrix = mCamera.mProjectionMatrix * mCamera.mViewMatrix; } // @@ -331,9 +340,14 @@ void Renderer::Initialize(int width, int height) { mRenderTarget.mQuadVertexArray = mRenderQuadVertexArrayId; mRenderTarget.mQuadVertexBuffer = mRenderQuadVertexBufferId; mRenderTarget.mLinearizeDepthProgram = mRenderQuadProgramDepth; + mRenderTarget.mLinearizeDepthProgram.RegisterFileModification(); // Light mLight.Initialize(); + mLight.mShadowMapTarget.mQuadVertexArray = mRenderQuadVertexArrayId; + mLight.mShadowMapTarget.mQuadVertexBuffer = mRenderQuadVertexBufferId; + mLight.mShadowMapTarget.mLinearizeDepthProgram = mRenderQuadProgramDepth; + mLight.mShadowMapTarget.mLinearizeDepthProgram.RegisterFileModification(); } void Renderer::Shutdown() { @@ -345,19 +359,24 @@ void Renderer::RenderGl() { mSceneAreaHeight = mSceneAreaHeight < 1 ? 1 : mSceneAreaHeight; if (mSceneAreaWidth != mRenderTarget.mWidth || mSceneAreaHeight != mRenderTarget.mHeight) { mRenderTarget.Resize(mSceneAreaWidth, mSceneAreaHeight); + } + + if (mCamera.mWidth != mSceneAreaWidth + || mCamera.mHeight != mSceneAreaHeight) { mCamera.mWidth = mSceneAreaWidth; mCamera.mHeight = mSceneAreaHeight; } // Shadow Map - glViewport(0, 0, mLight.mShadowMapSize, mLight.mShadowMapSize); mLight.mShadowMapTarget.Bind(); + glViewport(0, 0, mLight.mShadowMapSize, mLight.mShadowMapSize); + mLight.UpdateMatrices(); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); glUseProgram(mLight.mShadowMapProgram.mProgramId); - RenderScene(mLight.mShadowMapProgram); + RenderScene(mLight.mShadowMapProgram, mLight.mCamera); + mLight.mShadowMapTarget.RenderToLinearizedDepth(mLight.mCamera.mNear, mLight.mCamera.mFar, mLight.mCamera.mIsOrthographic); glBindFramebuffer(GL_FRAMEBUFFER, 0); - // TODO: render linearized depth for the light - // mLight.mShadowMapTarget.RenderToLinearizedDepth(mCamera); // Regular rendering glEnable(GL_LINE_SMOOTH); @@ -375,7 +394,7 @@ void Renderer::RenderGl() { * mCamera.mProjectionMatrix; // enable the render target - glBindFramebuffer(GL_FRAMEBUFFER, mRenderTarget.mFrameBufferId); + mRenderTarget.Bind(); GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, DrawBuffers); @@ -416,29 +435,31 @@ void Renderer::RenderGl() { glBindTexture(GL_TEXTURE_2D, mLight.mShadowMapTarget.mDepthTexture); glEnable(GL_DEPTH_TEST); - RenderScene(mDefaultProgram); + RenderScene(mDefaultProgram, mCamera); if (mSettings->DrawDepth) { - mRenderTarget.RenderToLinearizedDepth(mCamera); + mRenderTarget.RenderToLinearizedDepth(mCamera.mNear, mCamera.mFar, mCamera.mIsOrthographic); } glDisableVertexAttribArray(0); glBindFramebuffer(GL_FRAMEBUFFER, 0); } -void Renderer::RenderScene(RenderProgram &program) { +void Renderer::RenderScene(RenderProgram &program, const Camera& camera) { + glUseProgram(program.mProgramId); + 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.SetMat44("uViewMatrix", camera.mViewMatrix); + program.SetMat44("uProjectionMatrix", camera.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); + program.SetVec3("uViewPosition", camera.mEye); gVertexArray.Bind(); gUnitCubeMesh.Draw(GL_TRIANGLES); } @@ -468,20 +489,35 @@ void Renderer::RenderGui() { ImGui::EndDock(); - if (ImGui::BeginDock("Render Settings")) { - ImGui::Text("Light"); + if (ImGui::BeginDock("Light Settings")) { + mLight.mCamera.DrawGui(); ImGui::SliderFloat3("Direction", mLight.mDirection.data(), -10.0f, 10.0f); ImVec2 content_avail = ImGui::GetContentRegionAvail(); - ImGui::Image((void*) mLight.mShadowMapTarget.mLinearizedDepthTexture, + + ImGui::SliderFloat("Light Near", &mLight.mNear, -10.0f, 10.0f); + ImGui::SliderFloat("Light Far", &mLight.mFar, -10.0f, 50.0f); + ImGui::Checkbox("Draw Light Depth", &mSettings->DrawLightDepth); + void* texture; + if (mSettings->DrawLightDepth) { + texture = (void*) mLight.mShadowMapTarget.mLinearizedDepthTexture; + } else { + texture = (void*) mLight.mShadowMapTarget.mColorTexture; + } + + ImGui::Image(texture, ImVec2(content_avail.x, content_avail.x), ImVec2(0.0f, 1.0f), ImVec2(1.0f, 0.0f) ); + } + ImGui::EndDock(); + + if (ImGui::BeginDock("Render Settings")) { ImGui::Text("Camera"); mCamera.DrawGui(); ImGui::Text("Default Texture"); - content_avail = ImGui::GetContentRegionAvail(); + ImVec2 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 191da13..fb3969e 100644 --- a/src/modules/RenderModule.h +++ b/src/modules/RenderModule.h @@ -21,6 +21,8 @@ struct Light { RenderTarget mShadowMapTarget; RenderProgram mShadowMapProgram; + Camera mCamera; + float mShadowMapBias; uint16_t mShadowMapSize; @@ -28,8 +30,6 @@ struct Light { float mFar; float mBBoxSize; - Matrix44f mLightProjection; - Matrix44f mLightView; Matrix44f mLightSpaceMatrix; Light() : @@ -37,11 +37,9 @@ struct Light { mDirection (Vector3f(-1.f, -1.f, -1.f)), mShadowMapBias (0.004f), mShadowMapSize (1024), - mNear (0.1f), - mFar (100.f), - mBBoxSize (10.f), - mLightProjection(Matrix44f::Identity()), - mLightView(Matrix44f::Identity()), + mNear (0.01f), + mFar (6.f), + mBBoxSize (5.f), mLightSpaceMatrix(Matrix44f::Identity()) { } @@ -97,6 +95,6 @@ struct Renderer { void Initialize(int width, int height); void Shutdown(); void RenderGl(); - void RenderScene(RenderProgram &program); + void RenderScene(RenderProgram &program, const Camera& camera); void RenderGui(); }; diff --git a/src/modules/RenderUtils.cc b/src/modules/RenderUtils.cc index 63e9929..be76051 100644 --- a/src/modules/RenderUtils.cc +++ b/src/modules/RenderUtils.cc @@ -26,7 +26,10 @@ void Camera::UpdateMatrices() { mViewMatrix = LookAt(mEye, mPoi, mUp); if (mIsOrthographic) { - mProjectionMatrix = Ortho(-1.0f, 1.0f, -1.0f, 1.0f, mNear, mFar); + float width = mWidth * 0.5f * (mFar - mNear * 0.5f) * 0.001f; + float height = width * mHeight / mWidth; + + mProjectionMatrix = Ortho(-width * 0.5f, width * 0.5f, -height * 0.5f, height * 0.5f, mNear, mFar); } else { mProjectionMatrix = Perspective(mFov, mWidth / mHeight, mNear, mFar); } @@ -280,6 +283,8 @@ void RenderTarget::Initialize(int width, int height, int flags) { void RenderTarget::Bind() { assert(glIsFramebuffer(mFrameBufferId)); glBindFramebuffer(GL_FRAMEBUFFER, mFrameBufferId); + GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, DrawBuffers); } void RenderTarget::Cleanup() { @@ -362,6 +367,8 @@ void RenderTarget::Resize(int width, int height) { 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); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mLinearizedDepthTexture, 0); } } else if (mFlags & EnableDepth) { assert((mFlags & EnableDepthTexture) == false); @@ -387,15 +394,16 @@ void RenderTarget::Resize(int width, int height) { assert(result == GL_FRAMEBUFFER_COMPLETE); } -void RenderTarget::RenderToLinearizedDepth(const Camera& camera) { +void RenderTarget::RenderToLinearizedDepth(const float& near, const float& far, bool is_orthographic) { 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); + GLenum draw_attachment_1[] = { GL_COLOR_ATTACHMENT1 }; + glDrawBuffers(1, draw_attachment_1); + glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_DEPTH_TEST); @@ -407,9 +415,9 @@ void RenderTarget::RenderToLinearizedDepth(const Camera& camera) { // 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.SetFloat("uNear", near); + mLinearizeDepthProgram.SetFloat("uFar", far); + mLinearizeDepthProgram.SetFloat("uIsOrthographic", is_orthographic ? 1.0f : 0.0f); mLinearizeDepthProgram.SetInt("uDepthTexture", 0); glEnableVertexAttribArray(0); @@ -425,8 +433,10 @@ void RenderTarget::RenderToLinearizedDepth(const Camera& camera) { 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); + if (mFlags & EnableColor) { + GLenum draw_attachment_0[] = { GL_COLOR_ATTACHMENT1 }; + glDrawBuffers(1, draw_attachment_0); + } glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/src/modules/RenderUtils.h b/src/modules/RenderUtils.h index ab1194f..9a78c67 100644 --- a/src/modules/RenderUtils.h +++ b/src/modules/RenderUtils.h @@ -152,8 +152,8 @@ struct Camera { mFar (150.f), mFov (60.f), mIsOrthographic (false), - mWidth (-1.f), - mHeight (-1.f), + mWidth (100.0f), + mHeight (100.0f), mProjectionMatrix ( 1.f, 0.f, 0.f, 0.f, @@ -263,7 +263,7 @@ struct RenderTarget { void Cleanup(); void Resize(int width, int height); - void RenderToLinearizedDepth(const Camera &camera); + void RenderToLinearizedDepth(const float& near, const float& far, bool is_orthographic); }; struct Texture {