From e3293c6fe18c429c11f8d2eb1da2d13b525c60a4 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 9 Jan 2013 01:36:18 +0100 Subject: [PATCH] Added normal mapping Former-commit-id: 7e54b1f01de7d5cf99c42d08d13ba606f73c453d --- include/Nazara/Renderer/Material.hpp | 6 ++ src/Nazara/Renderer/Material.cpp | 92 ++++++++++++++++++++++++++- src/Nazara/Renderer/ShaderBuilder.cpp | 58 +++++++++++++---- 3 files changed, 141 insertions(+), 15 deletions(-) diff --git a/include/Nazara/Renderer/Material.hpp b/include/Nazara/Renderer/Material.hpp index 9b1422618..6cadc0d3c 100644 --- a/include/Nazara/Renderer/Material.hpp +++ b/include/Nazara/Renderer/Material.hpp @@ -50,6 +50,8 @@ class NAZARA_API NzMaterial : public NzResource nzBlendFunc GetDstBlend() const; nzFaceCulling GetFaceCulling() const; nzFaceFilling GetFaceFilling() const; + const NzTexture* GetHeightMap() const; + const NzTexture* GetNormalMap() const; float GetShininess() const; NzColor GetSpecularColor() const; const NzTexture* GetSpecularMap() const; @@ -75,6 +77,8 @@ class NAZARA_API NzMaterial : public NzResource void SetDstBlend(nzBlendFunc func); void SetFaceCulling(nzFaceCulling culling); void SetFaceFilling(nzFaceFilling filling); + void SetHeightMap(const NzTexture* map); + void SetNormalMap(const NzTexture* map); void SetSamplerWrap(nzSamplerWrap wrapMode); void SetShininess(float shininess); void SetSpecularColor(const NzColor& specular); @@ -100,6 +104,8 @@ class NAZARA_API NzMaterial : public NzResource NzTextureSampler m_diffuseSampler; NzTextureSampler m_specularSampler; const NzTexture* m_diffuseMap; + const NzTexture* m_heightMap; + const NzTexture* m_normalMap; const NzTexture* m_specularMap; bool m_alphaBlendingEnabled; bool m_zTestEnabled; diff --git a/src/Nazara/Renderer/Material.cpp b/src/Nazara/Renderer/Material.cpp index 59781eeeb..2a49c218a 100644 --- a/src/Nazara/Renderer/Material.cpp +++ b/src/Nazara/Renderer/Material.cpp @@ -15,6 +15,8 @@ bool NzMaterialParams::IsValid() const NzMaterial::NzMaterial() : m_diffuseMap(nullptr), +m_heightMap(nullptr), +m_normalMap(nullptr), m_specularMap(nullptr) { Reset(); @@ -28,6 +30,12 @@ NzResource() if (m_diffuseMap) m_diffuseMap->AddResourceReference(); + if (m_heightMap) + m_heightMap->AddResourceReference(); + + if (m_normalMap) + m_normalMap->AddResourceReference(); + if (m_specularMap) m_specularMap->AddResourceReference(); } @@ -37,6 +45,12 @@ NzMaterial::NzMaterial(NzMaterial&& material) if (m_diffuseMap) m_diffuseMap->RemoveResourceReference(); + if (m_heightMap) + m_heightMap->AddResourceReference(); + + if (m_normalMap) + m_normalMap->AddResourceReference(); + if (m_specularMap) m_specularMap->RemoveResourceReference(); @@ -44,6 +58,8 @@ NzMaterial::NzMaterial(NzMaterial&& material) // Comme ça nous volons la référence du matériau material.m_diffuseMap = nullptr; + material.m_heightMap = nullptr; + material.m_normalMap = nullptr; material.m_specularMap = nullptr; } @@ -52,6 +68,12 @@ NzMaterial::~NzMaterial() if (m_diffuseMap) m_diffuseMap->RemoveResourceReference(); + if (m_heightMap) + m_heightMap->RemoveResourceReference(); + + if (m_normalMap) + m_normalMap->RemoveResourceReference(); + if (m_specularMap) m_specularMap->RemoveResourceReference(); } @@ -91,6 +113,32 @@ void NzMaterial::Apply() const } } + if (m_heightMap) + { + int heightMapLocation = shader->GetUniformLocation("MaterialHeightMap"); + if (heightMapLocation != -1) + { + nzUInt8 textureUnit; + if (shader->SendTexture(heightMapLocation, m_heightMap, &textureUnit)) + NzRenderer::SetTextureSampler(textureUnit, m_diffuseSampler); + else + NazaraWarning("Failed to send height map"); + } + } + + if (m_normalMap) + { + int normalMapLocation = shader->GetUniformLocation("MaterialNormalMap"); + if (normalMapLocation != -1) + { + nzUInt8 textureUnit; + if (shader->SendTexture(normalMapLocation, m_normalMap, &textureUnit)) + NzRenderer::SetTextureSampler(textureUnit, m_diffuseSampler); + else + NazaraWarning("Failed to send normal map"); + } + } + if (shininessLocation != -1) shader->SendFloat(shininessLocation, m_shininess); @@ -106,7 +154,7 @@ void NzMaterial::Apply() const if (shader->SendTexture(specularMapLocation, m_specularMap, &textureUnit)) NzRenderer::SetTextureSampler(textureUnit, m_specularSampler); else - NazaraWarning("Failed to send diffuse map"); + NazaraWarning("Failed to send specular map"); } } @@ -183,6 +231,16 @@ nzFaceFilling NzMaterial::GetFaceFilling() const return m_faceFilling; } +const NzTexture* NzMaterial::GetHeightMap() const +{ + return m_diffuseMap; +} + +const NzTexture* NzMaterial::GetNormalMap() const +{ + return m_diffuseMap; +} + float NzMaterial::GetShininess() const { return m_shininess; @@ -256,6 +314,18 @@ void NzMaterial::Reset() m_diffuseMap = nullptr; } + if (m_heightMap) + { + m_heightMap->RemoveResourceReference(); + m_heightMap = nullptr; + } + + if (m_normalMap) + { + m_normalMap->RemoveResourceReference(); + m_normalMap = nullptr; + } + if (m_specularMap) { m_specularMap->RemoveResourceReference(); @@ -318,6 +388,26 @@ void NzMaterial::SetFaceFilling(nzFaceFilling filling) m_faceFilling = filling; } +void NzMaterial::SetHeightMap(const NzTexture* map) +{ + if (m_heightMap) + m_heightMap->RemoveResourceReference(); + + m_heightMap = map; + if (m_heightMap) + m_heightMap->AddResourceReference(); +} + +void NzMaterial::SetNormalMap(const NzTexture* map) +{ + if (m_normalMap) + m_normalMap->RemoveResourceReference(); + + m_normalMap = map; + if (m_normalMap) + m_normalMap->AddResourceReference(); +} + void NzMaterial::SetShininess(float shininess) { m_shininess = shininess; diff --git a/src/Nazara/Renderer/ShaderBuilder.cpp b/src/Nazara/Renderer/ShaderBuilder.cpp index c0c6d506e..352e22cdc 100644 --- a/src/Nazara/Renderer/ShaderBuilder.cpp +++ b/src/Nazara/Renderer/ShaderBuilder.cpp @@ -79,23 +79,30 @@ namespace if (flags & nzShaderBuilder_Lighting) { + if (flags & nzShaderBuilder_NormalMapping) + sourceCode += "uniform sampler2D MaterialNormalMap;\n"; + sourceCode += "uniform float MaterialShininess;\n" "uniform vec4 MaterialSpecular;\n"; - } - if (flags & nzShaderBuilder_SpecularMapping) - sourceCode += "uniform sampler2D MaterialSpecularMap;\n"; + if (flags & nzShaderBuilder_SpecularMapping) + sourceCode += "uniform sampler2D MaterialSpecularMap;\n"; - if (flags & nzShaderBuilder_Lighting) sourceCode += "uniform vec4 SceneAmbient;\n"; + } sourceCode += '\n'; /********************Entrant********************/ if (flags & nzShaderBuilder_Lighting) - sourceCode += inKW + " vec3 vNormal;\n"; + { + if (flags & nzShaderBuilder_NormalMapping) + sourceCode += inKW + " mat3 vLightToWorld;\n"; - if (flags & nzShaderBuilder_DiffuseMapping) + sourceCode += inKW + " vec3 vNormal;\n"; + } + + if (flags & nzShaderBuilder_DiffuseMapping || flags & nzShaderBuilder_NormalMapping) sourceCode += inKW + " vec2 vTexCoord;\n"; if (flags & nzShaderBuilder_Lighting) @@ -120,8 +127,12 @@ namespace if (flags & nzShaderBuilder_SpecularMapping) sourceCode += "vec3 si = vec3(0.0, 0.0, 0.0);\n"; - sourceCode += "vec3 normal = normalize(vNormal);\n" - "\n" + if (flags & nzShaderBuilder_NormalMapping) + sourceCode += "vec3 normal = normalize(vLightToWorld * (2.0 * vec3(texture2D(MaterialNormalMap, vTexCoord)) - 1.0));\n"; + else + sourceCode += "vec3 normal = normalize(vNormal);\n"; + + sourceCode += "\n" "for (int i = 0; i < LightCount; ++i)\n" "{\n"; @@ -303,10 +314,10 @@ namespace sourceCode += inKW + " vec3 VertexPosition;\n"; if (flags & nzShaderBuilder_Lighting) + { sourceCode += inKW + " vec3 VertexNormal;\n"; - - if (flags & nzShaderBuilder_Lighting) sourceCode += inKW + " vec3 VertexTangent;\n"; + } if (flags & nzShaderBuilder_DiffuseMapping) sourceCode += inKW + " vec2 VertexTexCoord0;\n"; @@ -315,9 +326,14 @@ namespace /********************Sortant********************/ if (flags & nzShaderBuilder_Lighting) - sourceCode += outKW + " vec3 vNormal;\n"; + { + if (flags & nzShaderBuilder_NormalMapping) + sourceCode += outKW + " mat3 vLightToWorld;"; - if (flags & nzShaderBuilder_DiffuseMapping) + sourceCode += outKW + " vec3 vNormal;\n"; + } + + if (flags & nzShaderBuilder_DiffuseMapping || flags & nzShaderBuilder_NormalMapping) sourceCode += outKW + " vec2 vTexCoord;\n"; if (flags & nzShaderBuilder_Lighting) @@ -331,9 +347,23 @@ namespace "gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n"; if (flags & nzShaderBuilder_Lighting) - sourceCode += "vNormal = normalize(mat3(WorldMatrix) * VertexNormal);\n"; + { + sourceCode += "mat3 RotationMatrix = mat3(WorldMatrix);\n"; - if (flags & nzShaderBuilder_DiffuseMapping) + if (flags & nzShaderBuilder_NormalMapping) + { + sourceCode += "\n" + "vec3 binormal = cross(VertexNormal, VertexTangent);\n" + "vLightToWorld[0] = VertexTangent * RotationMatrix;\n" + "vLightToWorld[1] = binormal * RotationMatrix;\n" + "vLightToWorld[2] = normalize(VertexNormal * RotationMatrix);\n" + "\n"; + } + + sourceCode += "vNormal = normalize(RotationMatrix * VertexNormal);\n"; + } + + if (flags & nzShaderBuilder_DiffuseMapping || flags & nzShaderBuilder_NormalMapping) sourceCode += "vTexCoord = VertexTexCoord0;\n"; if (flags & nzShaderBuilder_Lighting)