diff --git a/src/graphics/core/renderers.h b/src/graphics/core/renderers.h index af55c1fd..3fe169ce 100644 --- a/src/graphics/core/renderers.h +++ b/src/graphics/core/renderers.h @@ -101,15 +101,28 @@ public: //! Sets model matrix virtual void SetModelMatrix(const glm::mat4& matrix) = 0; - //! Sets primary texture, setting texture 0 means using white texture - virtual void SetPrimaryTexture(const Texture& texture) = 0; - //! Sets secondary texture - virtual void SetSecondaryTexture(const Texture& texture) = 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 detail texture + virtual void SetDetailTexture(const Texture& texture) = 0; //! Sets shadow map virtual void SetShadowMap(const Texture& texture) = 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; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index ae3cee38..b21ff56a 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -2747,6 +2747,7 @@ void CEngine::Draw3DScene() terrainRenderer->SetViewMatrix(m_matView); terrainRenderer->SetShadowMap(m_shadowMap); terrainRenderer->SetLight(glm::vec4(1.0, 1.0, -1.0, 0.0), 1.0f, glm::vec3(1.0)); + terrainRenderer->SetSky(Color(1.0, 1.0, 1.0), 0.2f); if (m_shadowMapping) terrainRenderer->SetShadowParams(m_shadowRegions, shadowParams); @@ -2790,8 +2791,15 @@ void CEngine::Draw3DScene() for (auto& data : p1.next) { - terrainRenderer->SetPrimaryTexture(data.albedoTexture); - terrainRenderer->SetSecondaryTexture(data.detailTexture); + terrainRenderer->SetAlbedoColor(data.material.albedoColor); + terrainRenderer->SetAlbedoTexture(data.albedoTexture); + terrainRenderer->SetDetailTexture(data.detailTexture); + + terrainRenderer->SetEmissiveColor(data.material.emissiveColor); + terrainRenderer->SetEmissiveTexture(data.emissiveTexture); + + terrainRenderer->SetMaterialParams(data.material.roughness, data.material.metalness); + terrainRenderer->SetMaterialTexture(data.materialTexture); terrainRenderer->DrawObject(m_objects[objRank].transform, data.buffer); } @@ -2817,7 +2825,7 @@ void CEngine::Draw3DScene() objectRenderer->SetShadowMap(m_shadowMap); objectRenderer->SetLighting(true); 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->SetSky(Color(1.0, 1.0, 1.0), 0.2f); objectRenderer->SetTransparency(TransparencyMode::NONE); objectRenderer->SetFog(fogStart, fogEnd, { fogColor.r, fogColor.g, fogColor.b }); diff --git a/src/graphics/opengl/gl33renderers.cpp b/src/graphics/opengl/gl33renderers.cpp index 1e5550b0..b8b18df3 100644 --- a/src/graphics/opengl/gl33renderers.cpp +++ b/src/graphics/opengl/gl33renderers.cpp @@ -281,17 +281,18 @@ CGL33TerrainRenderer::CGL33TerrainRenderer(CGL33Device* device) 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/terrain_vs.glsl"); std::string fsSource = LoadSource("shaders/gl33/terrain_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 'terrain_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 'terrain_vs.glsl'\n"); @@ -315,16 +316,26 @@ CGL33TerrainRenderer::CGL33TerrainRenderer(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_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_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_shadowRegions = glGetUniformLocation(m_program, "uni_ShadowRegions"); GLchar name[64]; @@ -341,15 +352,21 @@ CGL33TerrainRenderer::CGL33TerrainRenderer(CGL33Device* device) m_shadows[i].scale = glGetUniformLocation(m_program, name); } - // Set texture units to 10th and 11th - auto texture = glGetUniformLocation(m_program, "uni_PrimaryTexture"); - glUniform1i(texture, 10); + // Set texture units + 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); @@ -386,33 +403,56 @@ void CGL33TerrainRenderer::Begin() m_device->SetTransparency(TransparencyMode::NONE); - 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); + m_device->SetDepthMask(true); + m_device->SetTransparency(TransparencyMode::NONE); + m_device->SetCullFace(CullFace::BACK); + + SetFog(1e+6f, 1e+6, {}); } void CGL33TerrainRenderer::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; } @@ -428,9 +468,10 @@ void CGL33TerrainRenderer::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 CGL33TerrainRenderer::SetModelMatrix(const glm::mat4& matrix) @@ -441,13 +482,18 @@ void CGL33TerrainRenderer::SetModelMatrix(const glm::mat4& matrix) glUniformMatrix3fv(m_normalMatrix, 1, GL_FALSE, value_ptr(normalMatrix)); } -void CGL33TerrainRenderer::SetPrimaryTexture(const Texture& texture) +void CGL33TerrainRenderer::SetAlbedoColor(const Color& color) { - if (m_primaryTexture == texture.id) return; + glUniform4f(m_albedoColor, color.r, color.g, color.b, color.a); +} - m_primaryTexture = texture.id; +void CGL33TerrainRenderer::SetAlbedoTexture(const Texture& texture) +{ + if (m_albedoTexture == texture.id) return; - glActiveTexture(GL_TEXTURE10); + m_albedoTexture = texture.id; + + glActiveTexture(GL_TEXTURE0 + m_albedoIndex); if (texture.id == 0) glBindTexture(GL_TEXTURE_2D, m_whiteTexture); @@ -455,13 +501,52 @@ void CGL33TerrainRenderer::SetPrimaryTexture(const Texture& texture) glBindTexture(GL_TEXTURE_2D, texture.id); } -void CGL33TerrainRenderer::SetSecondaryTexture(const Texture& texture) +void CGL33TerrainRenderer::SetEmissiveColor(const Color& color) { - if (m_secondaryTexture == texture.id) return; + glUniform3f(m_emissiveColor, color.r, color.g, color.b); +} - m_secondaryTexture = texture.id; +void CGL33TerrainRenderer::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 CGL33TerrainRenderer::SetMaterialParams(float roughness, float metalness) +{ + glUniform1f(m_roughness, roughness); + glUniform1f(m_metalness, metalness); +} + +void CGL33TerrainRenderer::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 CGL33TerrainRenderer::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); @@ -475,10 +560,10 @@ void CGL33TerrainRenderer::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); } @@ -490,6 +575,12 @@ void CGL33TerrainRenderer::SetLight(const glm::vec4& position, const float& inte glUniform3fv(m_lightColor, 1, glm::value_ptr(color)); } +void CGL33TerrainRenderer::SetSky(const Color& color, float intensity) +{ + glUniform3f(m_skyColor, color.r, color.g, color.b); + glUniform1f(m_skyIntensity, intensity); +} + void CGL33TerrainRenderer::SetShadowParams(int count, const ShadowParam* params) { glUniform1i(m_shadowRegions, count); diff --git a/src/graphics/opengl/gl33renderers.h b/src/graphics/opengl/gl33renderers.h index 952a5119..5bed93fc 100644 --- a/src/graphics/opengl/gl33renderers.h +++ b/src/graphics/opengl/gl33renderers.h @@ -126,16 +126,29 @@ public: //! Sets model matrix virtual void SetModelMatrix(const glm::mat4& matrix) override; - //! Sets primary texture, setting texture 0 means using white texture - virtual void SetPrimaryTexture(const Texture& texture) override; - //! Sets secondary texture - virtual void SetSecondaryTexture(const Texture& texture) 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 detail texture + virtual void SetDetailTexture(const Texture& texture) override; //! Sets shadow map virtual void SetShadowMap(const Texture& texture) 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; //! Sets fog parameters @@ -148,17 +161,27 @@ private: CGL33Device* const m_device; // Uniform data - GLint m_projectionMatrix; - GLint m_viewMatrix; - GLint m_cameraMatrix; - GLint m_shadowMatrix; - GLint m_modelMatrix; - GLint m_normalMatrix; - GLint m_lightPosition; - GLint m_lightIntensity; - GLint m_lightColor; - GLint m_fogRange; - GLint m_fogColor; + GLint m_projectionMatrix = -1; + GLint m_viewMatrix = -1; + GLint m_shadowMatrix = -1; + GLint m_modelMatrix = -1; + GLint m_normalMatrix = -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_albedoColor = -1; + GLint m_emissiveColor = -1; + GLint m_roughness = -1; + GLint m_metalness = -1; struct ShadowUniforms { @@ -167,18 +190,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/terrain_fs.glsl b/src/graphics/opengl/shaders/gl33/terrain_fs.glsl index 28172655..59ec61e2 100644 --- a/src/graphics/opengl/shaders/gl33/terrain_fs.glsl +++ b/src/graphics/opengl/shaders/gl33/terrain_fs.glsl @@ -19,18 +19,19 @@ // FRAGMENT SHADER - TERRAIN RENDERER -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; -const float PI = 3.1415926; +uniform float uni_Roughness; +uniform float uni_Metalness; +uniform sampler2D uni_MaterialTexture; + +uniform vec3 uni_EmissiveColor; +uniform sampler2D uni_EmissiveTexture; in VertexData { @@ -44,72 +45,43 @@ 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; -} - void main() { - vec3 albedo = data.Color.rgb; + vec4 albedo = data.Color * uni_AlbedoColor; - albedo *= texture(uni_PrimaryTexture, data.TexCoord0).rgb; - albedo *= texture(uni_SecondaryTexture, data.TexCoord1).rgb; + albedo *= texture(uni_AlbedoTexture, data.TexCoord0); - float roughness = 0.7; - float metalness = 0.0; + vec3 detail = texture(uni_DetailTexture, data.TexCoord1).rgb; + + albedo.rgb *= detail; float shadow = CalculateShadow(data.ShadowCoords); shadow = mix(0.5, 1.0, shadow); - vec3 lighting = PBR(data.Position, albedo, data.Normal, roughness, metalness); + vec3 normal = mix(-data.Normal, data.Normal, float(gl_FrontFacing)); - vec3 skyColor = vec3(1.0); - float skyIntensity = 0.10; + vec3 emissive = uni_EmissiveColor * texture(uni_EmissiveTexture, data.TexCoord0).rgb; - vec3 color = lighting * shadow + albedo * skyColor * skyIntensity; + vec3 params = texture(uni_MaterialTexture, data.TexCoord0).xyz; - float dist = length(uni_CameraMatrix[3].xyz - data.Position); + float ambientOcclusion = params.r; + float roughness = uni_Roughness * params.g; + float metalness = uni_Metalness * params.b; + + vec3 color = albedo.rgb; + + color = CalculateLighting( + data.Position, + normal, + color, + emissive, + shadow, + ambientOcclusion, + roughness, + metalness); + + 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);