diff --git a/include/Nazara/Graphics/RenderQueue.hpp b/include/Nazara/Graphics/RenderQueue.hpp index 44c9370ff..a5d2f3a7e 100644 --- a/include/Nazara/Graphics/RenderQueue.hpp +++ b/include/Nazara/Graphics/RenderQueue.hpp @@ -21,6 +21,36 @@ class NzStaticMesh; class NAZARA_API NzRenderQueue { public: + NzRenderQueue() = default; + ~NzRenderQueue() = default; + + void Clear(); + + struct SkeletalData + { + NzMatrix4f transformMatrix; + + ///TODO: Déplacer vers un container séparé qui ne serait pas sujet à Clear(); + std::vector skinnedVertices; + }; + + struct TransparentModel + { + NzMatrix4f transformMatrix; + NzMaterial* material; + }; + + struct TransparentSkeletalModel : public TransparentModel + { + ///TODO: Déplacer vers un container séparé qui ne serait pas sujet à Clear(); + std::vector skinnedVertices; + }; + + struct TransparentStaticModel : public TransparentModel + { + NzStaticMesh* mesh; + }; + struct MaterialComparator { bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); @@ -36,24 +66,13 @@ class NAZARA_API NzRenderQueue bool operator()(const NzStaticMesh* subMesh1, const NzStaticMesh* subMesh2); }; - NzRenderQueue() = default; - ~NzRenderQueue() = default; - - void Clear(); - - struct SkeletalData - { - NzMatrix4f transformMatrix; - - ///TODO: Déplacer vers un container séparé qui ne serait pas sujer à Clear(); - std::vector skinnedVertices; - }; - typedef std::map, SkeletalMeshComparator> SkeletalMeshContainer; typedef std::map, StaticMeshComparator> StaticMeshContainer; std::map visibleSkeletalModels; std::map visibleStaticModels; + std::vector visibleTransparentSkeletalModels; + std::vector visibleTransparentStaticModels; std::vector otherDrawables; std::vector directionnalLights; std::vector visibleLights; diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 31fac2fe5..38b9d6508 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -149,15 +149,16 @@ enum nzShaderFlags { nzShaderFlags_None = 0, - nzShaderFlags_Deferred = 0x001, - nzShaderFlags_DiffuseMapping = 0x002, - nzShaderFlags_EmissiveMapping = 0x004, - nzShaderFlags_FlipUVs = 0x008, - nzShaderFlags_Instancing = 0x010, - nzShaderFlags_Lighting = 0x020, - nzShaderFlags_NormalMapping = 0x040, - nzShaderFlags_ParallaxMapping = 0x080, - nzShaderFlags_SpecularMapping = 0x100 + nzShaderFlags_AlphaMapping = 0x001, + nzShaderFlags_Deferred = 0x002, + nzShaderFlags_DiffuseMapping = 0x004, + nzShaderFlags_EmissiveMapping = 0x008, + nzShaderFlags_FlipUVs = 0x010, + nzShaderFlags_Instancing = 0x020, + nzShaderFlags_Lighting = 0x040, + nzShaderFlags_NormalMapping = 0x080, + nzShaderFlags_ParallaxMapping = 0x100, + nzShaderFlags_SpecularMapping = 0x200 }; enum nzShaderLanguage @@ -174,6 +175,7 @@ enum nzShaderUniform { nzShaderUniform_CameraPosition, nzShaderUniform_LightCount, + nzShaderUniform_MaterialAlphaMap, nzShaderUniform_MaterialAmbient, nzShaderUniform_MaterialDiffuse, nzShaderUniform_MaterialDiffuseMap, diff --git a/include/Nazara/Renderer/Material.hpp b/include/Nazara/Renderer/Material.hpp index 526379c37..1e870c792 100644 --- a/include/Nazara/Renderer/Material.hpp +++ b/include/Nazara/Renderer/Material.hpp @@ -53,6 +53,7 @@ class NAZARA_API NzMaterial : public NzResource NzColor GetAmbientColor() const; const NzShader* GetCustomShader() const; NzColor GetDiffuseColor() const; + NzTexture* GetAlphaMap() const; NzTexture* GetDiffuseMap() const; NzTextureSampler& GetDiffuseSampler(); const NzTextureSampler& GetDiffuseSampler() const; @@ -85,6 +86,8 @@ class NAZARA_API NzMaterial : public NzResource void Reset(); + bool SetAlphaMap(const NzString& texturePath); + void SetAlphaMap(NzTexture* map); void SetAmbientColor(const NzColor& ambient); void SetDiffuseColor(const NzColor& diffuse); bool SetDiffuseMap(const NzString& texturePath); @@ -128,6 +131,7 @@ class NAZARA_API NzMaterial : public NzResource NzTextureSampler m_diffuseSampler; NzTextureSampler m_specularSampler; mutable NzShaderConstRef m_customShader; + NzTextureRef m_alphaMap; NzTextureRef m_diffuseMap; NzTextureRef m_emissiveMap; NzTextureRef m_heightMap; diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 469026b38..1d3f0f2fa 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -61,10 +61,12 @@ bool NzGLSLShader::Compile() static NzString successStr("Linkage successful"); m_log = successStr; + // Pour éviter de se tromper entre le nom et la constante #define CacheUniform(name) m_uniformLocations[nzShaderUniform_##name] = GetUniformLocation(#name) CacheUniform(CameraPosition); CacheUniform(LightCount); + CacheUniform(MaterialAlphaMap); CacheUniform(MaterialAmbient); CacheUniform(MaterialDiffuse); CacheUniform(MaterialDiffuseMap); diff --git a/src/Nazara/Renderer/Material.cpp b/src/Nazara/Renderer/Material.cpp index 436784dcc..a6d140add 100644 --- a/src/Nazara/Renderer/Material.cpp +++ b/src/Nazara/Renderer/Material.cpp @@ -31,6 +31,7 @@ NzMaterial::NzMaterial(NzMaterial&& material) Copy(material); // Nous "volons" la référence du matériau + material.m_alphaMap = nullptr; material.m_customShader = nullptr; material.m_diffuseMap = nullptr; material.m_emissiveMap = nullptr; @@ -46,6 +47,19 @@ void NzMaterial::Apply(const NzShader* shader) const int shininessLocation = shader->GetUniformLocation(nzShaderUniform_MaterialShininess); int specularColorLocation = shader->GetUniformLocation(nzShaderUniform_MaterialSpecular); + if (m_alphaMap) + { + int alphaMapLocation = shader->GetUniformLocation(nzShaderUniform_MaterialAlphaMap); + if (alphaMapLocation != -1) + { + nzUInt8 textureUnit; + if (shader->SendTexture(alphaMapLocation, m_alphaMap, &textureUnit)) + NzRenderer::SetTextureSampler(textureUnit, m_diffuseSampler); + else + NazaraWarning("Failed to send diffuse map"); + } + } + if (ambientColorLocation != -1) shader->SendColor(ambientColorLocation, m_ambientColor); @@ -327,6 +341,7 @@ bool NzMaterial::LoadFromStream(NzInputStream& stream, const NzMaterialParams& p void NzMaterial::Reset() { + m_alphaMap.Reset(); m_customShader.Reset(); m_diffuseMap.Reset(); m_emissiveMap.Reset(); @@ -353,6 +368,32 @@ void NzMaterial::Reset() m_zWriteEnabled = true; } +bool NzMaterial::SetAlphaMap(const NzString& texturePath) +{ + std::unique_ptr texture(new NzTexture); + if (!texture->LoadFromFile(texturePath)) + { + NazaraError("Failed to load texture from \"" + texturePath + '"'); + return false; + } + + texture->SetPersistent(false); + + SetAlphaMap(texture.get()); + texture.release(); + + return true; +} + +void NzMaterial::SetAlphaMap(NzTexture* map) +{ + m_alphaMap = map; + if (m_alphaMap) + m_shaderFlags |= nzShaderFlags_AlphaMapping; + else + m_shaderFlags &= ~nzShaderFlags_AlphaMapping; +} + void NzMaterial::SetAmbientColor(const NzColor& ambient) { m_ambientColor = ambient; @@ -551,6 +592,7 @@ NzMaterial& NzMaterial::operator=(NzMaterial&& material) Copy(material); // Comme ça nous volons la référence du matériau + material.m_alphaMap = nullptr; material.m_customShader = nullptr; material.m_diffuseMap = nullptr; material.m_emissiveMap = nullptr; @@ -581,6 +623,7 @@ NzMaterial* NzMaterial::GetDefault() void NzMaterial::Copy(const NzMaterial& material) { + m_alphaMap.Reset(); m_customShader.Reset(); m_diffuseMap.Reset(); m_emissiveMap.Reset(); @@ -591,6 +634,7 @@ void NzMaterial::Copy(const NzMaterial& material) std::memcpy(this, &material, sizeof(NzMaterial)); // Autorisé dans notre cas, et bien plus rapide // Ensuite une petite astuce pour récupérer correctement les références + m_alphaMap.Release(); m_customShader.Release(); m_diffuseMap.Release(); m_emissiveMap.Release(); @@ -598,6 +642,7 @@ void NzMaterial::Copy(const NzMaterial& material) m_normalMap.Release(); m_specularMap.Release(); + m_alphaMap = material.m_alphaMap; m_customShader = material.m_customShader; m_diffuseMap = material.m_diffuseMap; m_heightMap = material.m_heightMap; diff --git a/src/Nazara/Renderer/ShaderBuilder.cpp b/src/Nazara/Renderer/ShaderBuilder.cpp index 2abfa2fd8..ff30aef3a 100644 --- a/src/Nazara/Renderer/ShaderBuilder.cpp +++ b/src/Nazara/Renderer/ShaderBuilder.cpp @@ -75,6 +75,9 @@ namespace "uniform vec4 MaterialAmbient;\n"; } + if (flags & nzShaderFlags_AlphaMapping) + sourceCode += "uniform sampler2D MaterialAlphaMap;\n"; + if ((flags & nzShaderFlags_DiffuseMapping) == 0 || flags & nzShaderFlags_Lighting) sourceCode += "uniform vec4 MaterialDiffuse;\n"; @@ -280,17 +283,27 @@ namespace sourceCode += ";\n"; + if (flags & nzShaderFlags_AlphaMapping) + sourceCode += "float alpha = " + textureLookupKW + "(MaterialAlphaMap, vTexCoord).r;\n"; + else + sourceCode += "float alpha = MaterialDiffuse.a;\n"; + if (flags & nzShaderFlags_EmissiveMapping) { sourceCode += "vec3 emission = vec3(" + textureLookupKW + "(MaterialEmissiveMap, vTexCoord));\n" - + fragmentColorKW + " = vec4(mix(lighting, emission, length(emission)), MaterialDiffuse.a);"; + + fragmentColorKW + " = vec4(mix(lighting, emission, length(emission)), alpha);\n"; ///NOTE: Pour un shader avec un coût réduit avec une qualité moyenne, il est possible de remplacer "length(emission)" par "dot(emission, emission)" } else - sourceCode += fragmentColorKW + " = vec4(lighting, MaterialDiffuse.a);"; + sourceCode += fragmentColorKW + " = vec4(lighting, alpha);\n"; } else if (flags & nzShaderFlags_DiffuseMapping) - sourceCode += fragmentColorKW + " = " + textureLookupKW + "(MaterialDiffuseMap, vTexCoord);\n"; + { + if (flags & nzShaderFlags_AlphaMapping) + sourceCode += fragmentColorKW + " = vec4(" + textureLookupKW + "(MaterialDiffuseMap, vTexCoord).rgb, " + textureLookupKW + "(MaterialAlphaMap, vTexCoord).r);\n"; + else + sourceCode += fragmentColorKW + " = " + textureLookupKW + "(MaterialDiffuseMap, vTexCoord);\n"; + } else sourceCode += fragmentColorKW + " = MaterialDiffuse;\n";