diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h index 687adc7b..5d5b255e 100644 --- a/src/graphics/core/material.h +++ b/src/graphics/core/material.h @@ -45,33 +45,56 @@ enum class CullFace : unsigned char BOTH, }; -//! Remains of the legacy material structure, to be reused +//! PBR material struct Material { - // Albedo + //! Albedo color Color albedoColor = Color{ 1.0f, 1.0f, 1.0f, 1.0f }; + //! Albedo texture std::string albedoTexture = ""; - // Dirt - bool variableDetail = false; - std::string detailTexture = ""; - // Alpha mode + //! Roughness + float roughness = 1.0; + //! Metalness + float metalness = 0.0; + //! AO-roughness-metalness texture + std::string materialTexture = ""; + //! Emissive color + Color emissiveColor = Color{ 0.0f, 0.0f, 0.0f, 0.0f }; + //! Emissive texture + std::string emissiveTexture = ""; + //! Normal map + std::string normalTexture = ""; + //! Alpha mode AlphaMode alphaMode = AlphaMode::OPAQUE; + //! Alpha threshold float alphaThreshold = 0.0; // Cull face CullFace cullFace = CullFace::BACK; // Special tag std::string tag = ""; + // Legacy functionality + //! Variable detail texture + bool variableDetail = false; + //! Detail texture + std::string detailTexture = ""; + bool operator==(const Material& other) const { return albedoColor == other.albedoColor && albedoTexture == other.albedoTexture - && variableDetail == other.variableDetail - && detailTexture == other.detailTexture + && roughness == other.roughness + && metalness == other.metalness + && materialTexture == other.materialTexture + && emissiveColor == other.emissiveColor + && emissiveTexture == other.emissiveTexture + && normalTexture == other.normalTexture && alphaMode == other.alphaMode && alphaThreshold == other.alphaThreshold && cullFace == other.cullFace - && tag == other.tag; + && tag == other.tag + && variableDetail == other.variableDetail + && detailTexture == other.detailTexture; } bool operator!=(const Material& other) const diff --git a/src/graphics/core/renderers.h b/src/graphics/core/renderers.h index 98caddc0..28daa4ad 100644 --- a/src/graphics/core/renderers.h +++ b/src/graphics/core/renderers.h @@ -140,13 +140,21 @@ public: //! Sets model matrix virtual void SetModelMatrix(const glm::mat4& matrix) = 0; - //! Sets color - virtual void SetColor(const glm::vec4& color) = 0; + //! Sets albedo color + virtual void SetAlbedoColor(const Color& color) = 0; + //! Sets albedo texture + virtual void SetAlbedoTexture(const Texture& texture) = 0; + //! Sets emissive color + virtual void SetEmissiveColor(const Color& color) = 0; + //! Sets emissive texture + virtual void SetEmissiveTexture(const Texture& texture) = 0; + //! Sets material parameters + virtual void SetMaterialParams(float roughness, float metalness) = 0; + //! Sets material texture + virtual void SetMaterialTexture(const Texture& texture) = 0; - //! Sets primary texture - virtual void SetPrimaryTexture(const Texture& texture) = 0; - //! Sets secondary texture - virtual void SetSecondaryTexture(const Texture& texture) = 0; + //! Sets detail texture + virtual void SetDetailTexture(const Texture& texture) = 0; //! Sets shadow map virtual void SetShadowMap(const Texture& texture) = 0; @@ -154,6 +162,8 @@ public: virtual void SetLighting(bool enabled) = 0; //! Sets light parameters virtual void SetLight(const glm::vec4& position, const float& intensity, const glm::vec3& color) = 0; + //! Sets sky parameters + virtual void SetSky(const Color& color, float intensity) = 0; //! Sets shadow parameters virtual void SetShadowParams(int count, const ShadowParam* params) = 0; @@ -174,13 +184,10 @@ public: //! Sets UV transform virtual void SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) = 0; - virtual void SetPrimaryTextureEnabled(bool enabled) = 0; //! Sets triplanar mode virtual void SetTriplanarMode(bool enabled) = 0; //! Sets triplanar scale virtual void SetTriplanarScale(float scale) = 0; - //! Sets amount of dirt (second texture) to apply - virtual void SetDirty(float amount) = 0; //! Draws an object virtual void DrawObject(const CVertexBuffer* buffer) = 0; diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index 9465e2de..c721fa0d 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -121,8 +121,8 @@ void CCloud::Draw() renderer->SetViewMatrix(m_engine->GetMatView()); auto texture = m_engine->LoadTexture(m_fileName); - renderer->SetPrimaryTexture(texture); - renderer->SetSecondaryTexture(Texture{}); + renderer->SetAlbedoTexture(texture); + renderer->SetDetailTexture(Texture{}); renderer->SetLighting(false); renderer->SetTransparency(TransparencyMode::BLACK); diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index f9dd5bf7..41e0f4bb 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -1777,12 +1777,6 @@ bool CEngine::TransformPoint(glm::vec3& p2D, int objRank, glm::vec3 p3D) *******************************************************/ - -void CEngine::SetMaterial(const Material& mat) -{ - m_lastMaterial = mat; -} - void CEngine::SetViewParams(const glm::vec3 &eyePt, const glm::vec3 &lookatPt, const glm::vec3 &upVec) { m_eyePt = eyePt; @@ -1957,135 +1951,6 @@ static bool IsExcludeColor(glm::vec2* exclude, int x, int y) return false; // point to include } - -bool CEngine::ChangeTextureColor(const std::string& texName, - const std::string& srcName, - Color colorRef1, Color colorNew1, - Color colorRef2, Color colorNew2, - float tolerance1, float tolerance2, - const glm::vec2& ts, const glm::vec2& ti, - glm::vec2* exclude, float shift, bool hsv) -{ - CImage img; - if (!img.Load(srcName)) - { - std::string error = img.GetError(); - GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", srcName.c_str(), error.c_str()); - m_texBlacklist.insert(srcName); - return false; - } - - bool changeColorsNeeded = true; - - if (colorRef1.r == colorNew1.r && - colorRef1.g == colorNew1.g && - colorRef1.b == colorNew1.b && - colorRef2.r == colorNew2.r && - colorRef2.g == colorNew2.g && - colorRef2.b == colorNew2.b) - { - changeColorsNeeded = false; - } - - - int dx = img.GetSize().x; - int dy = img.GetSize().y; - - int sx = static_cast(Math::Max(ts.x*dx, 0)); - int sy = static_cast(Math::Max(ts.y*dy, 0)); - - int ex = static_cast(Math::Min(ti.x*dx, dx)); - int ey = static_cast(Math::Min(ti.y*dy, dy)); - - - ColorHSV cr1 = RGB2HSV(colorRef1); - ColorHSV cn1 = RGB2HSV(colorNew1); - ColorHSV cr2 = RGB2HSV(colorRef2); - ColorHSV cn2 = RGB2HSV(colorNew2); - - if (changeColorsNeeded) - { - for (int y = sy; y < ey; y++) - { - for (int x = sx; x < ex; x++) - { - if (exclude != nullptr && IsExcludeColor(exclude, x,y) ) - continue; - - Color color = img.GetPixel({ x, y }); - - if (hsv) - { - ColorHSV c = RGB2HSV(color); - if (c.s > 0.01f && fabs(c.h - cr1.h) < tolerance1) - { - c.h += cn1.h - cr1.h; - c.s += cn1.s - cr1.s; - c.v += cn1.v - cr1.v; - if (c.h < 0.0f) c.h -= 1.0f; - if (c.h > 1.0f) c.h += 1.0f; - color = HSV2RGB(c); - color.r = Math::Norm(color.r + shift); - color.g = Math::Norm(color.g + shift); - color.b = Math::Norm(color.b + shift); - img.SetPixel({ x, y }, color); - } - else if (tolerance2 != -1.0f && - c.s > 0.01f && fabs(c.h - cr2.h) < tolerance2) - { - c.h += cn2.h - cr2.h; - c.s += cn2.s - cr2.s; - c.v += cn2.v - cr2.v; - if (c.h < 0.0f) c.h -= 1.0f; - if (c.h > 1.0f) c.h += 1.0f; - color = HSV2RGB(c); - color.r = Math::Norm(color.r + shift); - color.g = Math::Norm(color.g + shift); - color.b = Math::Norm(color.b + shift); - img.SetPixel({ x, y }, color); - } - } - else - { - if ( fabs(color.r - colorRef1.r) + - fabs(color.g - colorRef1.g) + - fabs(color.b - colorRef1.b) < tolerance1 * 3.0f) - { - color.r = Math::Norm(colorNew1.r + color.r - colorRef1.r + shift); - color.g = Math::Norm(colorNew1.g + color.g - colorRef1.g + shift); - color.b = Math::Norm(colorNew1.b + color.b - colorRef1.b + shift); - img.SetPixel({ x, y }, color); - } - else if (tolerance2 != -1 && - fabs(color.r - colorRef2.r) + - fabs(color.g - colorRef2.g) + - fabs(color.b - colorRef2.b) < tolerance2 * 3.0f) - { - color.r = Math::Norm(colorNew2.r + color.r - colorRef2.r + shift); - color.g = Math::Norm(colorNew2.g + color.g - colorRef2.g + shift); - color.b = Math::Norm(colorNew2.b + color.b - colorRef2.b + shift); - img.SetPixel({ x, y }, color); - } - } - } - } - } - - CreateOrUpdateTexture(texName, &img); - - return true; -} - -bool CEngine::ChangeTextureColor(const std::string& texName, - Color colorRef1, Color colorNew1, - Color colorRef2, Color colorNew2, - float tolerance1, float tolerance2, - const glm::vec2& ts, const glm::vec2& ti, - glm::vec2* exclude, float shift, bool hsv) -{ - return ChangeTextureColor(texName, texName, colorRef1, colorNew1, colorRef2, colorNew2, tolerance1, tolerance2, ts, ti, exclude, shift, hsv); -} - void CEngine::DeleteTexture(const std::string& texName) { auto it = m_texNameMap.find(texName); @@ -2904,7 +2769,8 @@ void CEngine::Draw3DScene() objectRenderer->SetViewMatrix(m_matView); objectRenderer->SetShadowMap(m_shadowMap); objectRenderer->SetLighting(true); - objectRenderer->SetLight(glm::vec4(1.0, 1.0, -1.0, 0.0), 1.0f, glm::vec3(1.0)); + objectRenderer->SetLight(glm::vec4(1.0, 1.0, -1.0, 0.0), 0.8f, glm::vec3(1.0)); + objectRenderer->SetSky(Color(1.0, 1.0, 1.0), 0.5f); objectRenderer->SetTransparency(TransparencyMode::NONE); objectRenderer->SetFog(fogStart, fogEnd, { fogColor.r, fogColor.g, fogColor.b }); @@ -2958,9 +2824,6 @@ void CEngine::Draw3DScene() continue; } - objectRenderer->SetPrimaryTexture(data.albedoTexture); - objectRenderer->SetSecondaryTexture(data.detailTexture); - if (data.material.alphaMode != AlphaMode::OPAQUE) { objectRenderer->SetAlphaScissor(data.material.alphaThreshold); @@ -2970,13 +2833,16 @@ void CEngine::Draw3DScene() objectRenderer->SetAlphaScissor(0.0f); } - objectRenderer->SetPrimaryTextureEnabled(true); + objectRenderer->SetAlbedoColor(data.material.albedoColor); + objectRenderer->SetAlbedoTexture(data.albedoTexture); + objectRenderer->SetDetailTexture(data.detailTexture); + + objectRenderer->SetEmissiveColor(data.material.emissiveColor); + objectRenderer->SetEmissiveTexture(data.emissiveTexture); + + objectRenderer->SetMaterialParams(data.material.roughness, data.material.metalness); + objectRenderer->SetMaterialTexture(data.materialTexture); - float dirty = ((data.material.variableDetail - || !data.material.detailTexture.empty()) && m_dirty) - ? 1.0 : 0.0; - objectRenderer->SetDirty(dirty); - objectRenderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); objectRenderer->SetCullFace(data.material.cullFace); objectRenderer->SetUVTransform(data.uvOffset, data.uvScale); objectRenderer->DrawObject(data.buffer); @@ -3009,6 +2875,9 @@ void CEngine::Draw3DScene() if (! m_objects[objRank].drawWorld) continue; + if (!m_objects[objRank].ghost) + continue; + auto combinedMatrix = projectionViewMatrix * m_objects[objRank].transform; if (! IsVisible(combinedMatrix, objRank)) @@ -3028,15 +2897,9 @@ void CEngine::Draw3DScene() for (auto& data : p1.next) { - objectRenderer->SetPrimaryTexture(data.albedoTexture); - objectRenderer->SetSecondaryTexture(data.detailTexture); - - if (!m_objects[objRank].ghost) - continue; - - float dirty = 1.0f;// (data.state& ENG_RSTATE_DUAL_BLACK) && m_dirty ? 1.0 : 0.0; - objectRenderer->SetDirty(dirty); - objectRenderer->SetColor(tColor); + objectRenderer->SetAlbedoColor(tColor); + objectRenderer->SetAlbedoTexture(data.albedoTexture); + objectRenderer->SetDetailTexture(data.detailTexture); objectRenderer->SetUVTransform(data.uvOffset, data.uvScale); objectRenderer->DrawObject(data.buffer); } @@ -3347,8 +3210,8 @@ void CEngine::RenderPendingDebugDraws() renderer->SetTransparency(TransparencyMode::NONE); renderer->SetLighting(false); renderer->SetModelMatrix(glm::mat4(1.0f)); - renderer->SetPrimaryTexture(Texture{}); - renderer->SetSecondaryTexture(Texture{}); + renderer->SetAlbedoTexture(Texture{}); + renderer->SetDetailTexture(Texture{}); renderer->DrawPrimitives(PrimitiveType::LINE_STRIP, m_pendingDebugDraws.counts.size(), @@ -3631,9 +3494,8 @@ void CEngine::DrawInterface() renderer->SetTransparency(TransparencyMode::NONE); renderer->SetAlphaScissor(0.0f); renderer->SetShadowParams(0, nullptr); - renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + renderer->SetAlbedoColor(Color{ 1.0f, 1.0f, 1.0f, 1.0f }); renderer->SetCullFace(CullFace::BACK); - renderer->SetPrimaryTextureEnabled(true); renderer->SetTriplanarMode(m_triplanarMode); renderer->SetTriplanarScale(m_triplanarScale); @@ -3672,8 +3534,8 @@ void CEngine::DrawInterface() for (auto& data : p1.next) { - renderer->SetPrimaryTexture(data.albedoTexture); - renderer->SetSecondaryTexture(data.detailTexture); + renderer->SetAlbedoTexture(data.albedoTexture); + renderer->SetDetailTexture(data.detailTexture); renderer->DrawObject(data.buffer); } diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 39dbadb4..330029fd 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -133,6 +133,9 @@ struct EngineBaseObjDataTier bool updateStaticBuffer = false; Texture albedoTexture; + Texture emissiveTexture; + Texture materialTexture; + Texture normalTexture; Texture detailTexture; glm::vec2 uvOffset = { 0.0f, 0.0f }; @@ -742,17 +745,11 @@ public: /* *************** Mode setting *************** */ - //! Sets the current rendering state - //void SetState(int state, const Color& color = Color(1.0f, 1.0f, 1.0f, 1.0f)); - - //! Sets the current material - void SetMaterial(const Material& mat); - //! Specifies the location and direction of view - void SetViewParams(const glm::vec3 &eyePt, const glm::vec3 &lookatPt, const glm::vec3 &upVec); + void SetViewParams(const glm::vec3 &eyePt, const glm::vec3 &lookatPt, const glm::vec3 &upVec); //! Updates the textures used for drawing ground spot - void UpdateGroundSpotTextures(); + void UpdateGroundSpotTextures(); //! Loads texture, creating it if not already present Texture LoadTexture(const std::string& name); @@ -763,25 +760,6 @@ public: //! Loads all necessary textures bool LoadAllTextures(); - //! Changes colors in a texture - //@{ - bool ChangeTextureColor(const std::string& texName, - const std::string& srcName, - Color colorRef1, Color colorNew1, - Color colorRef2, Color colorNew2, - float tolerance1, float tolerance2, - const glm::vec2& ts, const glm::vec2& ti, - glm::vec2* exclude = nullptr, - float shift = 0.0f, bool hsv = false); - bool ChangeTextureColor(const std::string& texName, - Color colorRef1, Color colorNew1, - Color colorRef2, Color colorNew2, - float tolerance1, float tolerance2, - const glm::vec2& ts, const glm::vec2& ti, - glm::vec2* exclude = nullptr, - float shift = 0.0f, bool hsv = false); - //@} - //! Deletes the given texture, unloading it and removing from cache void DeleteTexture(const std::string& texName); //! Deletes the given texture, unloading it and removing from cache diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp index 8238fdaf..8f237df5 100644 --- a/src/graphics/engine/planet.cpp +++ b/src/graphics/engine/planet.cpp @@ -112,7 +112,7 @@ void CPlanet::Draw() auto texture = m_engine->LoadTexture(planet.name); - renderer->SetPrimaryTexture(texture); + renderer->SetAlbedoTexture(texture); if (planet.transparent) renderer->SetTransparency(TransparencyMode::ALPHA); @@ -155,7 +155,7 @@ void CPlanet::Draw() { glm::vec3(p2.x, p2.y, 0.0f), white, { u2, v1 } } }; - renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + renderer->SetAlbedoColor(Color{ 1.0f, 1.0f, 1.0f, 1.0f }); renderer->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, 4, quad); m_engine->AddStatisticTriangle(2); diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 80870c46..14d4e887 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -340,28 +340,28 @@ void CWater::DrawSurf() auto texture = m_engine->LoadTexture(m_fileName); - renderer->SetPrimaryTexture(texture); - renderer->SetSecondaryTexture(Texture{}); + renderer->SetAlbedoTexture(texture); + renderer->SetDetailTexture(Texture{}); if (m_type[rankview] == WATER_TT) { renderer->SetTransparency(TransparencyMode::BLACK); - renderer->SetColor(m_color); + renderer->SetAlbedoColor(m_color); } else if (m_type[rankview] == WATER_TO) { renderer->SetTransparency(TransparencyMode::NONE); - renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + renderer->SetAlbedoColor(Color{ 1.0f, 1.0f, 1.0f, 1.0f }); } else if (m_type[rankview] == WATER_CT) { renderer->SetTransparency(TransparencyMode::BLACK); - renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + renderer->SetAlbedoColor(Color{ 1.0f, 1.0f, 1.0f, 1.0f }); } else if (m_type[rankview] == WATER_CO) { renderer->SetTransparency(TransparencyMode::NONE); - renderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + renderer->SetAlbedoColor(Color{ 1.0f, 1.0f, 1.0f, 1.0f }); } float size = m_brickSize/2.0f; diff --git a/src/graphics/opengl/gl33objectrenderer.cpp b/src/graphics/opengl/gl33objectrenderer.cpp index bb8d8c34..ee15a354 100644 --- a/src/graphics/opengl/gl33objectrenderer.cpp +++ b/src/graphics/opengl/gl33objectrenderer.cpp @@ -38,20 +38,20 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device) { GetLogger()->Info("Creating CGL33ObjectRenderer\n"); - std::string preamble = LoadSource("shaders/gl33/preamble.glsl"); std::string shadowSource = LoadSource("shaders/gl33/shadow.glsl"); + std::string lightingSource = LoadSource("shaders/gl33/lighting.glsl"); std::string vsSource = LoadSource("shaders/gl33/object_vs.glsl"); std::string fsSource = LoadSource("shaders/gl33/object_fs.glsl"); - GLint vsShader = CreateShader(GL_VERTEX_SHADER, { preamble, shadowSource, vsSource }); + GLint vsShader = CreateShader(GL_VERTEX_SHADER, { preamble, lightingSource, shadowSource, vsSource }); if (vsShader == 0) { GetLogger()->Error("Cound not create vertex shader from file 'object_vs.glsl'\n"); return; } - GLint fsShader = CreateShader(GL_FRAGMENT_SHADER, { preamble, shadowSource, fsSource }); + GLint fsShader = CreateShader(GL_FRAGMENT_SHADER, { preamble, lightingSource, shadowSource, fsSource }); if (fsShader == 0) { GetLogger()->Error("Cound not create fragment shader from file 'object_fs.glsl'\n"); @@ -70,21 +70,29 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device) m_projectionMatrix = glGetUniformLocation(m_program, "uni_ProjectionMatrix"); m_viewMatrix = glGetUniformLocation(m_program, "uni_ViewMatrix"); - m_cameraMatrix = glGetUniformLocation(m_program, "uni_CameraMatrix"); m_shadowMatrix = glGetUniformLocation(m_program, "uni_ShadowMatrix"); m_modelMatrix = glGetUniformLocation(m_program, "uni_ModelMatrix"); m_normalMatrix = glGetUniformLocation(m_program, "uni_NormalMatrix"); + m_lighting = glGetUniformLocation(m_program, "uni_Lighting"); + m_cameraPosition = glGetUniformLocation(m_program, "uni_CameraPosition"); m_lightPosition = glGetUniformLocation(m_program, "uni_LightPosition"); m_lightIntensity = glGetUniformLocation(m_program, "uni_LightIntensity"); m_lightColor = glGetUniformLocation(m_program, "uni_LightColor"); + + m_skyColor = glGetUniformLocation(m_program, "uni_SkyColor"); + m_skyIntensity = glGetUniformLocation(m_program, "uni_SkyIntensity"); + m_fogRange = glGetUniformLocation(m_program, "uni_FogRange"); m_fogColor = glGetUniformLocation(m_program, "uni_FogColor"); - m_color = glGetUniformLocation(m_program, "uni_Color"); - m_primaryEnabled = glGetUniformLocation(m_program, "uni_PrimaryEnabled"); + + m_albedoColor = glGetUniformLocation(m_program, "uni_AlbedoColor"); + m_emissiveColor = glGetUniformLocation(m_program, "uni_EmissiveColor"); + m_roughness = glGetUniformLocation(m_program, "uni_Roughness"); + m_metalness = glGetUniformLocation(m_program, "uni_Metalness"); + m_triplanarMode = glGetUniformLocation(m_program, "uni_TriplanarMode"); m_triplanarScale = glGetUniformLocation(m_program, "uni_TriplanarScale"); - m_dirty = glGetUniformLocation(m_program, "uni_Dirty"); m_alphaScissor = glGetUniformLocation(m_program, "uni_AlphaScissor"); m_uvOffset = glGetUniformLocation(m_program, "uni_UVOffset"); m_uvScale = glGetUniformLocation(m_program, "uni_UVScale"); @@ -106,14 +114,20 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device) } // Set texture units - auto texture = glGetUniformLocation(m_program, "uni_PrimaryTexture"); - glUniform1i(texture, 10); + auto texture = glGetUniformLocation(m_program, "uni_AlbedoTexture"); + glUniform1i(texture, m_albedoIndex); - texture = glGetUniformLocation(m_program, "uni_SecondaryTexture"); - glUniform1i(texture, 11); + texture = glGetUniformLocation(m_program, "uni_DetailTexture"); + glUniform1i(texture, m_detailIndex); + + texture = glGetUniformLocation(m_program, "uni_EmissiveTexture"); + glUniform1i(texture, m_emissiveIndex); + + texture = glGetUniformLocation(m_program, "uni_MaterialTexture"); + glUniform1i(texture, m_materialIndex); texture = glGetUniformLocation(m_program, "uni_ShadowMap"); - glUniform1i(texture, 12); + glUniform1i(texture, m_shadowIndex); // White texture glActiveTexture(GL_TEXTURE0); @@ -128,6 +142,7 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ONE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ONE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE); + glBindTexture(GL_TEXTURE_2D, 0); glUseProgram(0); @@ -161,17 +176,25 @@ void CGL33ObjectRenderer::CGL33ObjectRenderer::Begin() glUseProgram(m_program); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glActiveTexture(GL_TEXTURE10); + glActiveTexture(GL_TEXTURE0 + m_albedoIndex); glBindTexture(GL_TEXTURE_2D, m_whiteTexture); - glActiveTexture(GL_TEXTURE11); + glActiveTexture(GL_TEXTURE0 + m_detailIndex); glBindTexture(GL_TEXTURE_2D, m_whiteTexture); - glActiveTexture(GL_TEXTURE12); + glActiveTexture(GL_TEXTURE0 + m_emissiveIndex); + glBindTexture(GL_TEXTURE_2D, m_whiteTexture); + + glActiveTexture(GL_TEXTURE0 + m_materialIndex); + glBindTexture(GL_TEXTURE_2D, m_whiteTexture); + + glActiveTexture(GL_TEXTURE0 + m_shadowIndex); glBindTexture(GL_TEXTURE_2D, 0); - m_primaryTexture = 0; - m_secondaryTexture = 0; + m_albedoTexture = 0; + m_detailTexture = 0; + m_emissiveTexture = 0; + m_materialTexture = 0; m_shadowMap = 0; m_device->SetDepthTest(true); @@ -184,17 +207,25 @@ void CGL33ObjectRenderer::CGL33ObjectRenderer::Begin() void CGL33ObjectRenderer::CGL33ObjectRenderer::End() { - glActiveTexture(GL_TEXTURE10); + glActiveTexture(GL_TEXTURE0 + m_albedoIndex); glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE11); + glActiveTexture(GL_TEXTURE0 + m_detailIndex); glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE12); + glActiveTexture(GL_TEXTURE0 + m_emissiveIndex); glBindTexture(GL_TEXTURE_2D, 0); - m_primaryTexture = 0; - m_secondaryTexture = 0; + glActiveTexture(GL_TEXTURE0 + m_materialIndex); + glBindTexture(GL_TEXTURE_2D, 0); + + glActiveTexture(GL_TEXTURE0 + m_shadowIndex); + glBindTexture(GL_TEXTURE_2D, 0); + + m_albedoTexture = 0; + m_detailTexture = 0; + m_emissiveTexture = 0; + m_materialTexture = 0; m_shadowMap = 0; } @@ -210,9 +241,10 @@ void CGL33ObjectRenderer::SetViewMatrix(const glm::mat4& matrix) auto viewMatrix = scale * matrix; auto cameraMatrix = glm::inverse(viewMatrix); + auto cameraPos = cameraMatrix[3]; glUniformMatrix4fv(m_viewMatrix, 1, GL_FALSE, value_ptr(viewMatrix)); - glUniformMatrix4fv(m_cameraMatrix, 1, GL_FALSE, value_ptr(cameraMatrix)); + glUniform3f(m_cameraPosition, cameraPos.x, cameraPos.y, cameraPos.z); } void CGL33ObjectRenderer::SetModelMatrix(const glm::mat4& matrix) @@ -223,18 +255,18 @@ void CGL33ObjectRenderer::SetModelMatrix(const glm::mat4& matrix) glUniformMatrix3fv(m_normalMatrix, 1, GL_FALSE, value_ptr(normalMatrix)); } -void CGL33ObjectRenderer::SetColor(const glm::vec4& color) +void CGL33ObjectRenderer::SetAlbedoColor(const Color& color) { - glUniform4fv(m_color, 1, glm::value_ptr(color)); + glUniform4f(m_albedoColor, color.r, color.g, color.b, color.a); } -void CGL33ObjectRenderer::SetPrimaryTexture(const Texture& texture) +void CGL33ObjectRenderer::SetAlbedoTexture(const Texture& texture) { - if (m_primaryTexture == texture.id) return; + if (m_albedoTexture == texture.id) return; - m_primaryTexture = texture.id; + m_albedoTexture = texture.id; - glActiveTexture(GL_TEXTURE10); + glActiveTexture(GL_TEXTURE0 + m_albedoIndex); if (texture.id == 0) glBindTexture(GL_TEXTURE_2D, m_whiteTexture); @@ -242,13 +274,52 @@ void CGL33ObjectRenderer::SetPrimaryTexture(const Texture& texture) glBindTexture(GL_TEXTURE_2D, texture.id); } -void CGL33ObjectRenderer::SetSecondaryTexture(const Texture& texture) +void CGL33ObjectRenderer::SetEmissiveColor(const Color& color) { - if (m_secondaryTexture == texture.id) return; + glUniform3f(m_emissiveColor, color.r, color.g, color.b); +} - m_secondaryTexture = texture.id; +void CGL33ObjectRenderer::SetEmissiveTexture(const Texture& texture) +{ + if (m_emissiveTexture == texture.id) return; - glActiveTexture(GL_TEXTURE11); + m_emissiveTexture = texture.id; + + glActiveTexture(GL_TEXTURE0 + m_emissiveIndex); + + if (texture.id == 0) + glBindTexture(GL_TEXTURE_2D, m_whiteTexture); + else + glBindTexture(GL_TEXTURE_2D, texture.id); +} + +void CGL33ObjectRenderer::SetMaterialParams(float roughness, float metalness) +{ + glUniform1f(m_roughness, roughness); + glUniform1f(m_metalness, metalness); +} + +void CGL33ObjectRenderer::SetMaterialTexture(const Texture& texture) +{ + if (m_materialTexture == texture.id) return; + + m_materialTexture = texture.id; + + glActiveTexture(GL_TEXTURE0 + m_materialIndex); + + if (texture.id == 0) + glBindTexture(GL_TEXTURE_2D, m_whiteTexture); + else + glBindTexture(GL_TEXTURE_2D, texture.id); +} + +void CGL33ObjectRenderer::SetDetailTexture(const Texture& texture) +{ + if (m_detailTexture == texture.id) return; + + m_detailTexture = texture.id; + + glActiveTexture(GL_TEXTURE0 + m_detailIndex); if (texture.id == 0) glBindTexture(GL_TEXTURE_2D, m_whiteTexture); @@ -262,10 +333,10 @@ void CGL33ObjectRenderer::SetShadowMap(const Texture& texture) m_shadowMap = texture.id; - glActiveTexture(GL_TEXTURE12); + glActiveTexture(GL_TEXTURE0 + m_shadowIndex); if (texture.id == 0) - glBindTexture(GL_TEXTURE_2D, m_whiteTexture); + glBindTexture(GL_TEXTURE_2D, 0); else glBindTexture(GL_TEXTURE_2D, texture.id); } @@ -279,7 +350,13 @@ void CGL33ObjectRenderer::SetLight(const glm::vec4& position, const float& inten { glUniform4fv(m_lightPosition, 1, glm::value_ptr(position)); glUniform1f(m_lightIntensity, intensity); - glUniform3fv(m_lightColor, 1, glm::value_ptr(color)); + glUniform3f(m_lightColor, color.r, color.g, color.b); +} + +void CGL33ObjectRenderer::SetSky(const Color& color, float intensity) +{ + glUniform3f(m_skyColor, color.r, color.g, color.b); + glUniform1f(m_skyIntensity, intensity); } void CGL33ObjectRenderer::SetShadowParams(int count, const ShadowParam* params) @@ -326,11 +403,6 @@ void CGL33ObjectRenderer::SetUVTransform(const glm::vec2& offset, const glm::vec glUniform2fv(m_uvScale, 1, glm::value_ptr(scale)); } -void CGL33ObjectRenderer::SetPrimaryTextureEnabled(bool enabled) -{ - glUniform1f(m_primaryEnabled, enabled ? 1.0f : 0.0f); -} - void CGL33ObjectRenderer::SetTriplanarMode(bool enabled) { glUniform1i(m_triplanarMode, enabled ? 1 : 0); @@ -341,11 +413,6 @@ void CGL33ObjectRenderer::SetTriplanarScale(float scale) glUniform1f(m_triplanarScale, scale); } -void CGL33ObjectRenderer::SetDirty(float amount) -{ - glUniform1f(m_dirty, amount); -} - void CGL33ObjectRenderer::SetAlphaScissor(float alpha) { glUniform1f(m_alphaScissor, alpha); diff --git a/src/graphics/opengl/gl33objectrenderer.h b/src/graphics/opengl/gl33objectrenderer.h index 580fa245..37d15b72 100644 --- a/src/graphics/opengl/gl33objectrenderer.h +++ b/src/graphics/opengl/gl33objectrenderer.h @@ -54,13 +54,21 @@ public: //! Sets model matrix virtual void SetModelMatrix(const glm::mat4& matrix) override; - //! Sets color - virtual void SetColor(const glm::vec4& color) override; + //! Sets albedo color + virtual void SetAlbedoColor(const Color& color) override; + //! Sets albedo texture + virtual void SetAlbedoTexture(const Texture& texture) override; + //! Sets emissive color + virtual void SetEmissiveColor(const Color& color) override; + //! Sets emissive texture + virtual void SetEmissiveTexture(const Texture& texture) override; + //! Sets material parameters + virtual void SetMaterialParams(float roughness, float metalness) override; + //! Sets material texture + virtual void SetMaterialTexture(const Texture& texture) override; - //! Sets primary texture - virtual void SetPrimaryTexture(const Texture& texture) override; - //! Sets secondary texture - virtual void SetSecondaryTexture(const Texture& texture) override; + //! Sets detail texture + virtual void SetDetailTexture(const Texture& texture) override; //! Sets shadow map virtual void SetShadowMap(const Texture& texture) override; @@ -68,6 +76,8 @@ public: virtual void SetLighting(bool enabled) override; //! Sets light parameters virtual void SetLight(const glm::vec4& position, const float& intensity, const glm::vec3& color) override; + //! Sets sky parameters + virtual void SetSky(const Color& color, float intensity) override; //! Sets shadow parameters virtual void SetShadowParams(int count, const ShadowParam* params) override; @@ -87,14 +97,10 @@ public: //! Sets UV transform virtual void SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) override; - virtual void SetPrimaryTextureEnabled(bool enabled) override; - //! Sets triplanar mode virtual void SetTriplanarMode(bool enabled) override; //! Sets triplanar scale virtual void SetTriplanarScale(float scale) override; - //! Sets amount of dirt (second texture) to apply - virtual void SetDirty(float amount) override; //! Draws an object virtual void DrawObject(const CVertexBuffer* buffer) override; @@ -109,22 +115,31 @@ private: // Uniform data GLint m_projectionMatrix = -1; GLint m_viewMatrix = -1; - GLint m_cameraMatrix = -1; GLint m_shadowMatrix = -1; GLint m_modelMatrix = -1; GLint m_normalMatrix = -1; + GLint m_lighting = -1; + GLint m_cameraPosition = -1; GLint m_lightPosition = -1; GLint m_lightIntensity = -1; GLint m_lightColor = -1; + + GLint m_skyColor = -1; + GLint m_skyIntensity = -1; + GLint m_fogRange = -1; GLint m_fogColor = -1; - GLint m_color = -1; - GLint m_primaryEnabled = -1; + + GLint m_albedoColor = -1; + GLint m_emissiveColor = -1; + GLint m_roughness = -1; + GLint m_metalness = -1; + GLint m_triplanarMode = -1; GLint m_triplanarScale = -1; - GLint m_dirty = -1; GLint m_alphaScissor = -1; + GLint m_uvOffset = -1; GLint m_uvScale = -1; @@ -135,18 +150,29 @@ private: GLint scale; }; - GLint m_shadowRegions; - ShadowUniforms m_shadows[4]; + GLint m_shadowRegions = 0; + ShadowUniforms m_shadows[4] = {}; // Shader program GLuint m_program = 0; + // Texture unit bindings + const int m_albedoIndex = 4; + const int m_detailIndex = 5; + const int m_emissiveIndex = 6; + const int m_materialIndex = 7; + const int m_shadowIndex = 8; + // 1x1 white texture GLuint m_whiteTexture = 0; - // Currently bound primary texture - GLuint m_primaryTexture = 0; - // Currently bound secondary texture - GLuint m_secondaryTexture = 0; + // Currently bound albedo texture + GLuint m_albedoTexture = 0; + // Currently bound detail texture + GLuint m_detailTexture = 0; + // Currently bound emissive texture + GLuint m_emissiveTexture = 0; + // Currently bound material texture + GLuint m_materialTexture = 0; // Currently bound shadow map GLuint m_shadowMap = 0; diff --git a/src/graphics/opengl/shaders/gl33/lighting.glsl b/src/graphics/opengl/shaders/gl33/lighting.glsl new file mode 100644 index 00000000..01380169 --- /dev/null +++ b/src/graphics/opengl/shaders/gl33/lighting.glsl @@ -0,0 +1,89 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2022, 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 + */ + +// PBR lighting calculations + +uniform bool uni_Lighting; + +uniform vec3 uni_CameraPosition; + +uniform float uni_LightIntensity; +uniform vec4 uni_LightPosition; +uniform vec3 uni_LightColor; + +uniform float uni_SkyIntensity; +uniform vec3 uni_SkyColor; + +const float PI = 3.1415926; + +vec3 SchlickFresnel(float LdH, float metalness, vec3 color) +{ + vec3 f = mix(vec3(0.04), color, metalness); + + return f + (1.0 - f) * pow(1.0 - LdH, 5.0); +} + +float GeometrySmith(float dotProd, float roughness) +{ + float k = (roughness + 1.0) * (roughness + 1.0) / 8.0; + float denom = dotProd * (1 - k) + k; + return 1.0 / denom; +} + +float GGXDistribution(float NdH, float roughness) +{ + float alpha2 = roughness * roughness * roughness * roughness; + float d = (NdH * NdH) * (alpha2 - 1) + 1.0; + return alpha2 / (PI * d * d); +} + +vec3 CalculateLighting( + vec3 position, + vec3 normal, + vec3 albedo, + vec3 emissive, + float shadow, + float ambientOcclusion, + float roughness, + float metalness) +{ + vec3 diffuseBrdf = mix(albedo, vec3(0.0), metalness); + + vec3 light = normalize(uni_LightPosition.xyz); + float lightIntensity = uni_LightIntensity; + + vec3 view = normalize(uni_CameraPosition - position); + vec3 halfway = normalize(view + light); + + float NdH = dot(normal, halfway); + float LdH = dot(light, halfway); + float NdL = max(dot(normal, light), 0.0); + float NdV = dot(normal, view); + + vec3 specBrdf = 0.25 + * GGXDistribution(NdH, roughness) + * SchlickFresnel(LdH, metalness, albedo) + * GeometrySmith(NdL, roughness) + * GeometrySmith(NdV, roughness); + + vec3 diffuseSpecular = (diffuseBrdf + PI * specBrdf) * uni_LightIntensity * uni_LightColor * NdL * shadow; + vec3 ambient = albedo * uni_SkyColor * uni_SkyIntensity * ambientOcclusion; + + return ambient + emissive + diffuseSpecular; +} diff --git a/src/graphics/opengl/shaders/gl33/object_fs.glsl b/src/graphics/opengl/shaders/gl33/object_fs.glsl index 43bb3585..95ca4209 100644 --- a/src/graphics/opengl/shaders/gl33/object_fs.glsl +++ b/src/graphics/opengl/shaders/gl33/object_fs.glsl @@ -19,26 +19,24 @@ // FRAGMENT SHADER - TERRAIN RENDERER -uniform bool uni_Lighting; -uniform mat4 uni_CameraMatrix; -uniform vec4 uni_LightPosition; -uniform float uni_LightIntensity; -uniform vec3 uni_LightColor; - uniform vec2 uni_FogRange; uniform vec3 uni_FogColor; -uniform sampler2D uni_PrimaryTexture; -uniform sampler2D uni_SecondaryTexture; +uniform vec4 uni_AlbedoColor; +uniform sampler2D uni_AlbedoTexture; +uniform sampler2D uni_DetailTexture; + +uniform float uni_Roughness; +uniform float uni_Metalness; +uniform sampler2D uni_MaterialTexture; + +uniform vec3 uni_EmissiveColor; +uniform sampler2D uni_EmissiveTexture; -uniform vec4 uni_Color; -uniform float uni_PrimaryEnabled; uniform bool uni_TriplanarMode; uniform float uni_TriplanarScale; -uniform float uni_Dirty; -uniform float uni_AlphaScissor; -const float PI = 3.1415926; +uniform float uni_AlphaScissor; in VertexData { @@ -54,68 +52,22 @@ in VertexData out vec4 out_FragColor; -vec3 schlickFresnel(float LdH, float metalness, vec3 color) -{ - vec3 f = mix(vec3(0.04), color, metalness); - - return f + (1.0 - f) * pow(1.0 - LdH, 5.0); -} - -float geomSmith(float dotProd, float roughness) -{ - float k = (roughness + 1.0) * (roughness + 1.0) / 8.0; - float denom = dotProd * (1 - k) + k; - return 1.0 / denom; -} - -float ggxDistribution(float NdH, float roughness) -{ - float alpha2 = roughness * roughness * roughness * roughness; - float d = (NdH * NdH) * (alpha2 - 1) + 1.0; - return alpha2 / (PI * d * d); -} - -vec3 PBR(vec3 position, vec3 color, vec3 normal, float roughness, float metalness) -{ - vec3 diffuseBrdf = mix(color, vec3(0.0), metalness); - - vec3 light = normalize(uni_LightPosition.xyz); - float lightIntensity = 1.0; - - vec3 view = normalize(uni_CameraMatrix[3].xyz - position); - vec3 halfway = normalize(view + light); - - float NdH = dot(normal, halfway); - float LdH = dot(light, halfway); - float NdL = max(dot(normal, light), 0.0); - float NdV = dot(normal, view); - - vec3 specBrdf = 0.25 * ggxDistribution(NdH, roughness) - * schlickFresnel(LdH, metalness, color) - * geomSmith(NdL, roughness) - * geomSmith(NdV, roughness); - - return (diffuseBrdf + PI * specBrdf) * lightIntensity * uni_LightColor * NdL; -} - vec3 Triplanar(vec3 position, vec3 normal) { vec3 weights = normal * normal; - vec3 sum = texture(uni_SecondaryTexture, position.yz).rgb * weights.x; - sum += texture(uni_SecondaryTexture, position.zx).rgb * weights.y; - sum += texture(uni_SecondaryTexture, position.xy).rgb * weights.z; + vec3 sum = texture(uni_DetailTexture, position.yz).rgb * weights.x; + sum += texture(uni_DetailTexture, position.zx).rgb * weights.y; + sum += texture(uni_DetailTexture, position.xy).rgb * weights.z; return sum; } void main() { - vec4 albedo = data.Color * uni_Color; + vec4 albedo = data.Color * uni_AlbedoColor; - vec4 primary = texture(uni_PrimaryTexture, data.TexCoord0); - primary = mix(vec4(1.0), primary, uni_PrimaryEnabled); - albedo *= primary; + albedo *= texture(uni_AlbedoTexture, data.TexCoord0); vec3 dirty = vec3(0.0); @@ -125,39 +77,47 @@ void main() } else { - dirty = texture(uni_SecondaryTexture, data.TexCoord1).rgb; + dirty = texture(uni_DetailTexture, data.TexCoord1).rgb; } - dirty = mix(vec3(1.0), dirty, uni_Dirty); albedo.rgb *= dirty; vec3 color = albedo.rgb; + float alpha = albedo.a; if (uni_Lighting) { - float roughness = 0.9; - float metalness = 0.0; - float shadow = CalculateShadow(data.ShadowCoords); shadow = mix(0.5, 1.0, shadow); vec3 normal = mix(-data.Normal, data.Normal, float(gl_FrontFacing)); - vec3 lighting = PBR(data.Position, color.rgb, normal, roughness, metalness); + vec3 emissive = uni_EmissiveColor * texture(uni_EmissiveTexture, data.TexCoord0).rgb; - vec3 skyColor = vec3(1.0); - float skyIntensity = 0.25; + vec3 params = texture(uni_MaterialTexture, data.TexCoord0).xyz; - color = lighting * shadow * (1.0 - skyIntensity) + color.rgb * skyColor * skyIntensity; + float ambientOcclusion = params.r; + float roughness = uni_Roughness * params.g; + float metalness = uni_Metalness * params.b; + + color = CalculateLighting( + data.Position, + normal, + color, + emissive, + shadow, + ambientOcclusion, + roughness, + metalness); } - float dist = length(uni_CameraMatrix[3].xyz - data.Position); + float dist = length(uni_CameraPosition - data.Position); float fogAmount = clamp((dist - uni_FogRange.x) / (uni_FogRange.y - uni_FogRange.x), 0.0, 1.0); color = mix(color, uni_FogColor, fogAmount); - if (albedo.a < uni_AlphaScissor) discard; + if (alpha < uni_AlphaScissor) discard; - out_FragColor = vec4(color, albedo.a); + out_FragColor = vec4(color, alpha); }