diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 4f6aef54..a311aa7b 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -52,6 +52,7 @@ namespace Gfx class CFramebuffer; class CUIRenderer; class CTerrainRenderer; +class CShadowRenderer; struct FramebufferParams; struct Light; struct Material; @@ -169,16 +170,6 @@ enum RenderState RENDER_STATE_SHADOW_MAPPING, }; -/** -* \enum RenderMode -* \brief Render modes the graphics device can be in -*/ -enum RenderMode -{ - RENDER_MODE_NORMAL, - RENDER_MODE_SHADOW, -}; - /** * \enum CompFunc * \brief Type of function used to compare values @@ -460,12 +451,12 @@ public: //! Clears the screen to blank virtual void Clear() = 0; - //! Sets current rendering mode - virtual void SetRenderMode(RenderMode mode) = 0; //! Returns UI renderer virtual CUIRenderer* GetUIRenderer() = 0; //! Returns terrain renderer virtual CTerrainRenderer* GetTerrainRenderer() = 0; + //! Returns shadow renderer + virtual CShadowRenderer* GetShadowRenderer() = 0; //! Restores device rendering mode virtual void Restore() = 0; diff --git a/src/graphics/core/renderers.h b/src/graphics/core/renderers.h index b9d9490b..12b67cad 100644 --- a/src/graphics/core/renderers.h +++ b/src/graphics/core/renderers.h @@ -101,4 +101,27 @@ public: virtual void DrawObject(const glm::mat4& matrix, const CVertexBuffer* buffer) = 0; }; +class CShadowRenderer : public CRenderer +{ +public: + virtual ~CShadowRenderer() { } + + virtual void Begin() = 0; + + virtual void End() = 0; + + //! Sets projection matrix + virtual void SetProjectionMatrix(const glm::mat4& matrix) = 0; + //! Sets view matrix + virtual void SetViewMatrix(const glm::mat4& matrix) = 0; + //! Sets model matrix + virtual void SetModelMatrix(const glm::mat4& matrix) = 0; + + //! Sets texture + virtual void SetTexture(const Texture& texture) = 0; + + //! Draws terrain object + virtual void DrawObject(const CVertexBuffer* buffer, bool transparent) = 0; +}; + } // namespace Gfx diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 62576c58..010c5fa2 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -3954,7 +3954,6 @@ void CEngine::RenderShadowMap() m_device->GetFramebuffer("shadow")->Bind(); } - m_device->SetRenderMode(RENDER_MODE_SHADOW); m_device->Clear(); // change state to rendering shadow maps @@ -4028,8 +4027,16 @@ void CEngine::RenderShadowMap() m_device->SetTexture(1, 0); m_device->SetTexture(2, 0); + m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, true); + m_device->SetRenderState(RENDER_STATE_CULLING, false); + auto projectionViewMatrix = Math::MultiplyMatrices(m_shadowProjMat, m_shadowViewMat); + auto renderer = m_device->GetShadowRenderer(); + renderer->Begin(); + renderer->SetProjectionMatrix(m_shadowProjMat); + renderer->SetViewMatrix(m_shadowViewMat); + // render objects into shadow map for (int objRank = 0; objRank < static_cast(m_objects.size()); objRank++) { @@ -4038,24 +4045,8 @@ void CEngine::RenderShadowMap() bool terrain = (m_objects[objRank].type == ENG_OBJTYPE_TERRAIN); - if (terrain) - { - if (m_terrainShadows) - { - m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false); - m_device->SetRenderState(RENDER_STATE_CULLING, true); - m_device->SetCullMode(CULL_CCW); - } - else - continue; - } - else - { - m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, true); - m_device->SetRenderState(RENDER_STATE_CULLING, false); - } + if (terrain && !m_terrainShadows) continue; - m_device->SetTransform(TRANSFORM_WORLD, m_objects[objRank].transform); auto combinedMatrix = Math::MultiplyMatrices(projectionViewMatrix, m_objects[objRank].transform); if (!IsVisible(combinedMatrix, objRank)) @@ -4071,21 +4062,25 @@ void CEngine::RenderShadowMap() if (!p1.used) continue; + renderer->SetModelMatrix(m_objects[objRank].transform); + for (int l2 = 0; l2 < static_cast(p1.next.size()); l2++) { EngineBaseObjTexTier& p2 = p1.next[l2]; - SetTexture(p2.tex1, 0); + renderer->SetTexture(p2.tex1); for (int l3 = 0; l3 < static_cast(p2.next.size()); l3++) { EngineBaseObjDataTier& p3 = p2.next[l3]; - DrawObject(p3); + renderer->DrawObject(p3.buffer, true); } } } + renderer->End(); + m_device->SetRenderState(RENDER_STATE_DEPTH_BIAS, false); m_device->SetDepthBias(0.0f, 0.0f); m_device->SetRenderState(RENDER_STATE_ALPHA_TEST, false); @@ -4109,7 +4104,7 @@ void CEngine::RenderShadowMap() CProfiler::StopPerformanceCounter(PCNT_RENDER_SHADOW_MAP); - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false); } @@ -4219,7 +4214,7 @@ void CEngine::DrawObject(const EngineBaseObjDataTier& p4) void CEngine::DrawInterface() { - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, false); m_device->SetRenderState(RENDER_STATE_LIGHTING, false); @@ -4253,7 +4248,7 @@ void CEngine::DrawInterface() // 3D objects drawn in front of interface if (m_drawFront) { - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); // Display the objects m_device->SetRenderState(RENDER_STATE_DEPTH_TEST, true); @@ -4327,7 +4322,7 @@ void CEngine::DrawInterface() m_device->SetRenderState(RENDER_STATE_LIGHTING, false); m_device->SetRenderState(RENDER_STATE_FOG, false); - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); SetInterfaceCoordinates(); } @@ -4346,7 +4341,7 @@ void CEngine::DrawInterface() if (m_renderInterface) DrawMouse(); - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); } void CEngine::UpdateGroundSpotTextures() @@ -4858,7 +4853,7 @@ void CEngine::DrawShadowSpots() void CEngine::DrawBackground() { - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); if (m_cloud->GetLevel() != 0.0f) // clouds ? { @@ -4876,7 +4871,7 @@ void CEngine::DrawBackground() DrawBackgroundImage(); // image } - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); } void CEngine::DrawBackgroundGradient(const Color& up, const Color& down) @@ -5033,7 +5028,7 @@ void CEngine::DrawForegroundImage() SetTexture(m_foregroundTex); SetState(ENG_RSTATE_CLAMP | ENG_RSTATE_TTEXTURE_BLACK); - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); m_device->SetTransform(TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(TRANSFORM_PROJECTION, m_matProjInterface); @@ -5059,7 +5054,7 @@ void CEngine::DrawOverColor() Color(0.0f, 0.0f, 0.0f, 0.0f) }; - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); SetState(m_overMode); @@ -5079,7 +5074,7 @@ void CEngine::DrawOverColor() m_device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertex, 4); AddStatisticTriangle(2); - m_device->SetRenderMode(RENDER_MODE_NORMAL); + m_device->Restore(); } void CEngine::DrawHighlight() diff --git a/src/graphics/opengl/gl33device.cpp b/src/graphics/opengl/gl33device.cpp index 154694fd..fccc4d91 100644 --- a/src/graphics/opengl/gl33device.cpp +++ b/src/graphics/opengl/gl33device.cpp @@ -337,42 +337,11 @@ bool CGL33Device::Create() glDeleteShader(shaders[0]); glDeleteShader(shaders[1]); - // Create program for shadow rendering - strcpy(filename, "shaders/gl33/vs_shadow.glsl"); - shaders[0] = LoadShader(GL_VERTEX_SHADER, filename); - if (shaders[0] == 0) - { - m_errorMessage = GetLastShaderError(); - GetLogger()->Error("Cound not create vertex shader from file '%s'\n", filename); - return false; - } - - strcpy(filename, "shaders/gl33/fs_shadow.glsl"); - shaders[1] = LoadShader(GL_FRAGMENT_SHADER, filename); - if (shaders[1] == 0) - { - m_errorMessage = GetLastShaderError(); - GetLogger()->Error("Cound not create fragment shader from file '%s'\n", filename); - return false; - } - - m_shadowProgram = LinkProgram(2, shaders); - if (m_shadowProgram == 0) - { - m_errorMessage = GetLastShaderError(); - GetLogger()->Error("Cound not link shader program for shadow rendering\n"); - return false; - } - - glDeleteShader(shaders[0]); - glDeleteShader(shaders[1]); - // Obtain uniform locations - // Obtain uniform locations for normal program glUseProgram(m_normalProgram); { - UniformLocations &uni = m_uniforms[0]; + UniformLocations &uni = m_uniforms; uni.projectionMatrix = glGetUniformLocation(m_normalProgram, "uni_ProjectionMatrix"); uni.viewMatrix = glGetUniformLocation(m_normalProgram, "uni_ViewMatrix"); @@ -463,45 +432,11 @@ bool CGL33Device::Create() glUniform1i(uni.lightCount, 0); } - // Obtain uniform locations for shadow program - glUseProgram(m_shadowProgram); - - { - UniformLocations &uni = m_uniforms[1]; - - uni.projectionMatrix = glGetUniformLocation(m_shadowProgram, "uni_ProjectionMatrix"); - uni.viewMatrix = glGetUniformLocation(m_shadowProgram, "uni_ViewMatrix"); - uni.modelMatrix = glGetUniformLocation(m_shadowProgram, "uni_ModelMatrix"); - - uni.primaryTexture = glGetUniformLocation(m_shadowProgram, "uni_Texture"); - - uni.textureEnabled[0] = glGetUniformLocation(m_shadowProgram, "uni_TextureEnabled"); - uni.textureEnabled[1] = -1; - uni.textureEnabled[2] = -1; - - uni.alphaTestEnabled = glGetUniformLocation(m_shadowProgram, "uni_AlphaTestEnabled"); - uni.alphaReference = glGetUniformLocation(m_shadowProgram, "uni_AlphaReference"); - - // Set default uniform values - Math::Matrix matrix; - matrix.LoadIdentity(); - - glUniformMatrix4fv(uni.projectionMatrix, 1, GL_FALSE, matrix.Array()); - glUniformMatrix4fv(uni.viewMatrix, 1, GL_FALSE, matrix.Array()); - glUniformMatrix4fv(uni.modelMatrix, 1, GL_FALSE, matrix.Array()); - - glUniform1i(uni.primaryTexture, 0); - - glUniform1i(uni.textureEnabled[0], 0); - - glUniform1i(uni.alphaTestEnabled, 0); - glUniform1f(uni.alphaReference, 1.0f); - } - m_uiRenderer = std::make_unique(this); m_terrainRenderer = std::make_unique(this); + m_shadowRenderer = std::make_unique(this); - SetRenderMode(RENDER_MODE_NORMAL); + glUseProgram(m_normalProgram); // create default framebuffer object FramebufferParams framebufferParams; @@ -535,7 +470,6 @@ void CGL33Device::Destroy() // delete shader program glUseProgram(0); glDeleteProgram(m_normalProgram); - glDeleteProgram(m_shadowProgram); // delete framebuffers for (auto& framebuffer : m_framebuffers) @@ -592,9 +526,9 @@ void CGL33Device::BeginScene() { Clear(); - glUniformMatrix4fv(m_uni->projectionMatrix, 1, GL_FALSE, m_projectionMat.Array()); - glUniformMatrix4fv(m_uni->viewMatrix, 1, GL_FALSE, m_viewMat.Array()); - glUniformMatrix4fv(m_uni->modelMatrix, 1, GL_FALSE, m_worldMat.Array()); + glUniformMatrix4fv(m_uniforms.projectionMatrix, 1, GL_FALSE, m_projectionMat.Array()); + glUniformMatrix4fv(m_uniforms.viewMatrix, 1, GL_FALSE, m_viewMat.Array()); + glUniformMatrix4fv(m_uniforms.modelMatrix, 1, GL_FALSE, m_worldMat.Array()); } void CGL33Device::EndScene() @@ -612,32 +546,6 @@ void CGL33Device::Clear() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void CGL33Device::SetRenderMode(RenderMode mode) -{ - m_uiRenderer->Flush(); - - switch (mode) - { - case RENDER_MODE_NORMAL: - glUseProgram(m_normalProgram); - m_mode = 0; - break; - case RENDER_MODE_SHADOW: - glUseProgram(m_shadowProgram); - m_mode = 1; - break; - default: - assert(false); - return; - } - - m_uni = &m_uniforms[m_mode]; - - UpdateTextureState(0); - UpdateTextureState(1); - UpdateTextureState(2); -} - CUIRenderer* CGL33Device::GetUIRenderer() { return m_uiRenderer.get(); @@ -648,17 +556,19 @@ CTerrainRenderer* CGL33Device::GetTerrainRenderer() return m_terrainRenderer.get(); } +CShadowRenderer* CGL33Device::GetShadowRenderer() +{ + return m_shadowRenderer.get(); +} + void CGL33Device::Restore() { - switch (m_mode) - { - case 0: - glUseProgram(m_normalProgram); - break; - case 1: - glUseProgram(m_shadowProgram); - break; - } + m_uiRenderer->Flush(); + glUseProgram(m_normalProgram); + + //UpdateTextureState(0); + //UpdateTextureState(1); + //UpdateTextureState(2); } void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) @@ -666,7 +576,7 @@ void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) if (type == TRANSFORM_WORLD) { m_worldMat = matrix; - glUniformMatrix4fv(m_uni->modelMatrix, 1, GL_FALSE, m_worldMat.Array()); + glUniformMatrix4fv(m_uniforms.modelMatrix, 1, GL_FALSE, m_worldMat.Array()); m_modelviewMat = Math::MultiplyMatrices(m_viewMat, m_worldMat); m_combinedMatrixOutdated = true; @@ -677,7 +587,7 @@ void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) if (fabs(normalMat.Det()) > 1e-6) normalMat = normalMat.Inverse(); - glUniformMatrix4fv(m_uni->normalMatrix, 1, GL_TRUE, normalMat.Array()); + glUniformMatrix4fv(m_uniforms.normalMatrix, 1, GL_TRUE, normalMat.Array()); } else if (type == TRANSFORM_VIEW) { @@ -689,13 +599,13 @@ void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) m_modelviewMat = Math::MultiplyMatrices(m_viewMat, m_worldMat); m_combinedMatrixOutdated = true; - glUniformMatrix4fv(m_uni->viewMatrix, 1, GL_FALSE, m_viewMat.Array()); + glUniformMatrix4fv(m_uniforms.viewMatrix, 1, GL_FALSE, m_viewMat.Array()); - if (m_uni->cameraPosition >= 0) + if (m_uniforms.cameraPosition >= 0) { cameraPosition.LoadZero(); cameraPosition = MatrixVectorMultiply(m_viewMat.Inverse(), cameraPosition); - glUniform3fv(m_uni->cameraPosition, 1, cameraPosition.Array()); + glUniform3fv(m_uniforms.cameraPosition, 1, cameraPosition.Array()); } } else if (type == TRANSFORM_PROJECTION) @@ -703,12 +613,12 @@ void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) m_projectionMat = matrix; m_combinedMatrixOutdated = true; - glUniformMatrix4fv(m_uni->projectionMatrix, 1, GL_FALSE, m_projectionMat.Array()); + glUniformMatrix4fv(m_uniforms.projectionMatrix, 1, GL_FALSE, m_projectionMat.Array()); } else if (type == TRANSFORM_SHADOW) { Math::Matrix temp = matrix; - glUniformMatrix4fv(m_uni->shadowMatrix, 1, GL_FALSE, temp.Array()); + glUniformMatrix4fv(m_uniforms.shadowMatrix, 1, GL_FALSE, temp.Array()); } else { @@ -720,9 +630,9 @@ void CGL33Device::SetMaterial(const Material &material) { m_material = material; - glUniform4fv(m_uni->ambientColor, 1, m_material.ambient.Array()); - glUniform4fv(m_uni->diffuseColor, 1, m_material.diffuse.Array()); - glUniform4fv(m_uni->specularColor, 1, m_material.specular.Array()); + glUniform4fv(m_uniforms.ambientColor, 1, m_material.ambient.Array()); + glUniform4fv(m_uniforms.diffuseColor, 1, m_material.diffuse.Array()); + glUniform4fv(m_uniforms.specularColor, 1, m_material.specular.Array()); } int CGL33Device::GetMaxLightCount() @@ -1513,19 +1423,19 @@ void CGL33Device::SetRenderState(RenderState state, bool enabled) m_updateLights = true; - //glUniform1i(m_uni->lightingEnabled, enabled ? 1 : 0); + //glUniform1i(m_uniforms.lightingEnabled, enabled ? 1 : 0); return; } else if (state == RENDER_STATE_FOG) { - glUniform1i(m_uni->fogEnabled, enabled ? 1 : 0); + glUniform1i(m_uniforms.fogEnabled, enabled ? 1 : 0); return; } else if (state == RENDER_STATE_ALPHA_TEST) { - glUniform1i(m_uni->alphaTestEnabled, enabled ? 1 : 0); + glUniform1i(m_uniforms.alphaTestEnabled, enabled ? 1 : 0); return; } @@ -1570,7 +1480,7 @@ void CGL33Device::SetDepthBias(float factor, float units) void CGL33Device::SetAlphaTestFunc(CompFunc func, float refValue) { - glUniform1f(m_uni->alphaReference, refValue); + glUniform1f(m_uniforms.alphaReference, refValue); } void CGL33Device::SetBlendFunc(BlendFunc srcBlend, BlendFunc dstBlend) @@ -1592,8 +1502,8 @@ void CGL33Device::SetFogParams(FogMode mode, const Color &color, float start, fl { // TODO: reimplement - glUniform2f(m_uni->fogRange, start, end); - glUniform4f(m_uni->fogColor, color.r, color.g, color.b, color.a); + glUniform2f(m_uniforms.fogRange, start, end); + glUniform4f(m_uniforms.fogColor, color.r, color.g, color.b, color.a); /* if (mode == FOG_LINEAR) glFogi(GL_FOG_MODE, GL_LINEAR); @@ -1624,7 +1534,7 @@ void CGL33Device::SetShadeModel(ShadeModel model) void CGL33Device::SetShadowColor(float value) { - glUniform1f(m_uni->shadowColor, value); + glUniform1f(m_uniforms.shadowColor, value); } void CGL33Device::SetFillMode(FillMode mode) @@ -1690,7 +1600,7 @@ void CGL33Device::DeleteFramebuffer(std::string name) inline void CGL33Device::UpdateTextureState(int index) { bool enabled = m_texturesEnabled[index] && (m_currentTextures[index].id != 0); - glUniform1i(m_uni->textureEnabled[index], enabled ? 1 : 0); + glUniform1i(m_uniforms.textureEnabled[index], enabled ? 1 : 0); } void CGL33Device::UpdateLights() @@ -1715,7 +1625,7 @@ void CGL33Device::UpdateLights() if (m_lights[i].type != LIGHT_DIRECTIONAL) continue; Light &light = m_lights[i]; - LightLocations &uni = m_uni->lights[index]; + LightLocations &uni = m_uniforms.lights[index]; glUniform4fv(uni.ambient, 1, light.ambient.Array()); glUniform4fv(uni.diffuse, 1, light.diffuse.Array()); @@ -1726,12 +1636,12 @@ void CGL33Device::UpdateLights() index++; } - glUniform1i(m_uni->lightCount, index); + glUniform1i(m_uniforms.lightCount, index); } // Lighting disabled else { - glUniform1i(m_uni->lightCount, 0); + glUniform1i(m_uniforms.lightCount, 0); } } diff --git a/src/graphics/opengl/gl33device.h b/src/graphics/opengl/gl33device.h index 11043058..fa157849 100644 --- a/src/graphics/opengl/gl33device.h +++ b/src/graphics/opengl/gl33device.h @@ -82,6 +82,7 @@ public: class CGL33UIRenderer; class CGL33TerrainRenderer; +class CGL33ShadowRenderer; /** \class CGL33Device @@ -115,9 +116,9 @@ public: void Clear() override; - void SetRenderMode(RenderMode mode) override; CUIRenderer* GetUIRenderer() override; CTerrainRenderer* GetTerrainRenderer() override; + CShadowRenderer* GetShadowRenderer() override; void Restore() override; @@ -296,22 +297,20 @@ private: //! Shader program for normal rendering GLuint m_normalProgram = 0; - //! Shader program for shadow rendering - GLuint m_shadowProgram = 0; DynamicBuffer m_dynamicBuffer; //! Current mode unsigned int m_mode = 0; //! Uniform locations for all modes - UniformLocations m_uniforms[3]; - //! Uniform locations for current mode - UniformLocations* m_uni = nullptr; + UniformLocations m_uniforms; //! Interface renderer std::unique_ptr m_uiRenderer; //! Terrain renderer std::unique_ptr m_terrainRenderer; + //! Shadow renderer + std::unique_ptr m_shadowRenderer; }; } // namespace Gfx diff --git a/src/graphics/opengl/gl33renderers.cpp b/src/graphics/opengl/gl33renderers.cpp index c8891a4e..3b6d024a 100644 --- a/src/graphics/opengl/gl33renderers.cpp +++ b/src/graphics/opengl/gl33renderers.cpp @@ -415,4 +415,116 @@ void CGL33TerrainRenderer::Flush() } +CGL33ShadowRenderer::CGL33ShadowRenderer(CGL33Device* device) + : m_device(device) +{ + GetLogger()->Info("Creating CGL33ShadowRenderer\n"); + + GLint shaders[2] = {}; + + shaders[0] = LoadShader(GL_VERTEX_SHADER, "shaders/gl33/shadow_vs.glsl"); + if (shaders[0] == 0) + { + GetLogger()->Error("Cound not create vertex shader from file 'shadow_vs.glsl'\n"); + return; + } + + shaders[1] = LoadShader(GL_FRAGMENT_SHADER, "shaders/gl33/shadow_fs.glsl"); + if (shaders[1] == 0) + { + GetLogger()->Error("Cound not create fragment shader from file 'shadow_fs.glsl'\n"); + return; + } + + m_program = LinkProgram(2, shaders); + if (m_program == 0) + { + GetLogger()->Error("Cound not link shader program for terrain renderer\n"); + return; + } + + glDeleteShader(shaders[0]); + glDeleteShader(shaders[1]); + + glUseProgram(m_program); + + // Setup uniforms + auto texture = glGetUniformLocation(m_program, "uni_Texture"); + glUniform1i(texture, 0); + + auto identity = glm::identity(); + + m_projectionMatrix = glGetUniformLocation(m_program, "uni_ProjectionMatrix"); + m_viewMatrix = glGetUniformLocation(m_program, "uni_ViewMatrix"); + m_modelMatrix = glGetUniformLocation(m_program, "uni_ModelMatrix"); + m_alphaScissor = glGetUniformLocation(m_program, "uni_AlphaScissor"); + + glUseProgram(0); + + GetLogger()->Info("CGL33ShadowRenderer created successfully\n"); +} + +CGL33ShadowRenderer::~CGL33ShadowRenderer() +{ + glDeleteProgram(m_program); +} + +void CGL33ShadowRenderer::Begin() +{ + glUseProgram(m_program); +} + +void CGL33ShadowRenderer::End() +{ + m_device->Restore(); +} + +void CGL33ShadowRenderer::SetProjectionMatrix(const glm::mat4& matrix) +{ + glUniformMatrix4fv(m_projectionMatrix, 1, GL_FALSE, value_ptr(matrix)); +} + +void CGL33ShadowRenderer::SetViewMatrix(const glm::mat4& matrix) +{ + glm::mat4 scale(1.0f); + scale[2][2] = -1.0f; + + auto viewMatrix = scale * matrix; + + glUniformMatrix4fv(m_viewMatrix, 1, GL_FALSE, value_ptr(viewMatrix)); +} + +void CGL33ShadowRenderer::SetModelMatrix(const glm::mat4& matrix) +{ + glUniformMatrix4fv(m_modelMatrix, 1, GL_FALSE, value_ptr(matrix)); +} + +void CGL33ShadowRenderer::SetTexture(const Texture& texture) +{ + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, texture.id); +} + +void CGL33ShadowRenderer::DrawObject(const CVertexBuffer* buffer, bool transparent) +{ + auto b = dynamic_cast(buffer); + + if (b == nullptr) + { + GetLogger()->Error("No vertex buffer"); + return; + } + + glUniform1i(m_alphaScissor, transparent ? 1 : 0); + + glBindVertexArray(b->GetVAO()); + + glDrawArrays(TranslateGfxPrimitive(b->GetType()), 0, b->Size()); +} + +void CGL33ShadowRenderer::Flush() +{ + +} + } // namespace Gfx diff --git a/src/graphics/opengl/gl33renderers.h b/src/graphics/opengl/gl33renderers.h index 2a01d568..5592e72b 100644 --- a/src/graphics/opengl/gl33renderers.h +++ b/src/graphics/opengl/gl33renderers.h @@ -153,4 +153,42 @@ private: GLuint m_shadowMap = 0; }; +class CGL33ShadowRenderer : public CShadowRenderer +{ +public: + CGL33ShadowRenderer(CGL33Device* device); + virtual ~CGL33ShadowRenderer(); + + virtual void Begin() override; + + virtual void End() override; + + //! Sets projection matrix + virtual void SetProjectionMatrix(const glm::mat4& matrix) override; + //! Sets view matrix + virtual void SetViewMatrix(const glm::mat4& matrix) override; + //! Sets model matrix + virtual void SetModelMatrix(const glm::mat4& matrix) override; + + //! Sets texture + virtual void SetTexture(const Texture& texture) override; + + //! Draws terrain object + virtual void DrawObject(const CVertexBuffer* buffer, bool transparent) override; + + virtual void Flush() override; + +private: + CGL33Device* const m_device; + + // Uniform data + GLint m_projectionMatrix = -1; + GLint m_viewMatrix = -1; + GLint m_modelMatrix = -1; + GLint m_alphaScissor = -1; + + // Shader program + GLuint m_program = 0; +}; + } // namespace Gfx diff --git a/src/graphics/opengl/shaders/gl33/shadow_fs.glsl b/src/graphics/opengl/shaders/gl33/shadow_fs.glsl new file mode 100644 index 00000000..d347881d --- /dev/null +++ b/src/graphics/opengl/shaders/gl33/shadow_fs.glsl @@ -0,0 +1,44 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +// FRAGMENT SHADER - SHADOW MODE +#version 330 core + +uniform sampler2D uni_Texture; + +uniform bool uni_AlphaScissor; + +in VertexData +{ + vec2 TexCoord; +} data; + +out vec4 out_FragColor; + +void main() +{ + if (uni_AlphaScissor) + { + float alpha = texture(uni_Texture, data.TexCoord).a; + + if (alpha < 0.5) discard; + } + + out_FragColor = vec4(1.0f); +} diff --git a/src/graphics/opengl/shaders/gl33/shadow_vs.glsl b/src/graphics/opengl/shaders/gl33/shadow_vs.glsl new file mode 100644 index 00000000..08707d4d --- /dev/null +++ b/src/graphics/opengl/shaders/gl33/shadow_vs.glsl @@ -0,0 +1,40 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +// VERTEX SHADER - SHADOW MODE +#version 330 core + +uniform mat4 uni_ProjectionMatrix; +uniform mat4 uni_ViewMatrix; +uniform mat4 uni_ModelMatrix; + +layout(location = 0) in vec4 in_VertexCoord; +layout(location = 3) in vec2 in_TexCoord0; + +out VertexData +{ + vec2 TexCoord; +} data; + +void main() +{ + gl_Position = uni_ProjectionMatrix * uni_ViewMatrix * uni_ModelMatrix * in_VertexCoord; + + data.TexCoord = in_TexCoord0; +}