Added alpha-mapping support

Former-commit-id: ba4598e9e5efc47e04e72dc709d64d214d77e9a1
This commit is contained in:
Lynix 2013-05-16 22:47:25 +02:00
parent 0b66452e33
commit 4b68ff0118
6 changed files with 110 additions and 25 deletions

View File

@ -21,6 +21,36 @@ class NzStaticMesh;
class NAZARA_API NzRenderQueue class NAZARA_API NzRenderQueue
{ {
public: 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<NzMeshVertex> 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<NzMeshVertex> skinnedVertices;
};
struct TransparentStaticModel : public TransparentModel
{
NzStaticMesh* mesh;
};
struct MaterialComparator struct MaterialComparator
{ {
bool operator()(const NzMaterial* mat1, const NzMaterial* mat2); bool operator()(const NzMaterial* mat1, const NzMaterial* mat2);
@ -36,24 +66,13 @@ class NAZARA_API NzRenderQueue
bool operator()(const NzStaticMesh* subMesh1, const NzStaticMesh* subMesh2); 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<NzMeshVertex> skinnedVertices;
};
typedef std::map<NzSkeletalMesh*, std::vector<SkeletalData>, SkeletalMeshComparator> SkeletalMeshContainer; typedef std::map<NzSkeletalMesh*, std::vector<SkeletalData>, SkeletalMeshComparator> SkeletalMeshContainer;
typedef std::map<NzStaticMesh*, std::vector<NzMatrix4f>, StaticMeshComparator> StaticMeshContainer; typedef std::map<NzStaticMesh*, std::vector<NzMatrix4f>, StaticMeshComparator> StaticMeshContainer;
std::map<NzMaterial*, SkeletalMeshContainer, MaterialComparator> visibleSkeletalModels; std::map<NzMaterial*, SkeletalMeshContainer, MaterialComparator> visibleSkeletalModels;
std::map<NzMaterial*, StaticMeshContainer, MaterialComparator> visibleStaticModels; std::map<NzMaterial*, StaticMeshContainer, MaterialComparator> visibleStaticModels;
std::vector<TransparentSkeletalModel> visibleTransparentSkeletalModels;
std::vector<TransparentStaticModel> visibleTransparentStaticModels;
std::vector<const NzDrawable*> otherDrawables; std::vector<const NzDrawable*> otherDrawables;
std::vector<const NzLight*> directionnalLights; std::vector<const NzLight*> directionnalLights;
std::vector<const NzLight*> visibleLights; std::vector<const NzLight*> visibleLights;

View File

@ -149,15 +149,16 @@ enum nzShaderFlags
{ {
nzShaderFlags_None = 0, nzShaderFlags_None = 0,
nzShaderFlags_Deferred = 0x001, nzShaderFlags_AlphaMapping = 0x001,
nzShaderFlags_DiffuseMapping = 0x002, nzShaderFlags_Deferred = 0x002,
nzShaderFlags_EmissiveMapping = 0x004, nzShaderFlags_DiffuseMapping = 0x004,
nzShaderFlags_FlipUVs = 0x008, nzShaderFlags_EmissiveMapping = 0x008,
nzShaderFlags_Instancing = 0x010, nzShaderFlags_FlipUVs = 0x010,
nzShaderFlags_Lighting = 0x020, nzShaderFlags_Instancing = 0x020,
nzShaderFlags_NormalMapping = 0x040, nzShaderFlags_Lighting = 0x040,
nzShaderFlags_ParallaxMapping = 0x080, nzShaderFlags_NormalMapping = 0x080,
nzShaderFlags_SpecularMapping = 0x100 nzShaderFlags_ParallaxMapping = 0x100,
nzShaderFlags_SpecularMapping = 0x200
}; };
enum nzShaderLanguage enum nzShaderLanguage
@ -174,6 +175,7 @@ enum nzShaderUniform
{ {
nzShaderUniform_CameraPosition, nzShaderUniform_CameraPosition,
nzShaderUniform_LightCount, nzShaderUniform_LightCount,
nzShaderUniform_MaterialAlphaMap,
nzShaderUniform_MaterialAmbient, nzShaderUniform_MaterialAmbient,
nzShaderUniform_MaterialDiffuse, nzShaderUniform_MaterialDiffuse,
nzShaderUniform_MaterialDiffuseMap, nzShaderUniform_MaterialDiffuseMap,

View File

@ -53,6 +53,7 @@ class NAZARA_API NzMaterial : public NzResource
NzColor GetAmbientColor() const; NzColor GetAmbientColor() const;
const NzShader* GetCustomShader() const; const NzShader* GetCustomShader() const;
NzColor GetDiffuseColor() const; NzColor GetDiffuseColor() const;
NzTexture* GetAlphaMap() const;
NzTexture* GetDiffuseMap() const; NzTexture* GetDiffuseMap() const;
NzTextureSampler& GetDiffuseSampler(); NzTextureSampler& GetDiffuseSampler();
const NzTextureSampler& GetDiffuseSampler() const; const NzTextureSampler& GetDiffuseSampler() const;
@ -85,6 +86,8 @@ class NAZARA_API NzMaterial : public NzResource
void Reset(); void Reset();
bool SetAlphaMap(const NzString& texturePath);
void SetAlphaMap(NzTexture* map);
void SetAmbientColor(const NzColor& ambient); void SetAmbientColor(const NzColor& ambient);
void SetDiffuseColor(const NzColor& diffuse); void SetDiffuseColor(const NzColor& diffuse);
bool SetDiffuseMap(const NzString& texturePath); bool SetDiffuseMap(const NzString& texturePath);
@ -128,6 +131,7 @@ class NAZARA_API NzMaterial : public NzResource
NzTextureSampler m_diffuseSampler; NzTextureSampler m_diffuseSampler;
NzTextureSampler m_specularSampler; NzTextureSampler m_specularSampler;
mutable NzShaderConstRef m_customShader; mutable NzShaderConstRef m_customShader;
NzTextureRef m_alphaMap;
NzTextureRef m_diffuseMap; NzTextureRef m_diffuseMap;
NzTextureRef m_emissiveMap; NzTextureRef m_emissiveMap;
NzTextureRef m_heightMap; NzTextureRef m_heightMap;

View File

@ -61,10 +61,12 @@ bool NzGLSLShader::Compile()
static NzString successStr("Linkage successful"); static NzString successStr("Linkage successful");
m_log = successStr; m_log = successStr;
// Pour éviter de se tromper entre le nom et la constante
#define CacheUniform(name) m_uniformLocations[nzShaderUniform_##name] = GetUniformLocation(#name) #define CacheUniform(name) m_uniformLocations[nzShaderUniform_##name] = GetUniformLocation(#name)
CacheUniform(CameraPosition); CacheUniform(CameraPosition);
CacheUniform(LightCount); CacheUniform(LightCount);
CacheUniform(MaterialAlphaMap);
CacheUniform(MaterialAmbient); CacheUniform(MaterialAmbient);
CacheUniform(MaterialDiffuse); CacheUniform(MaterialDiffuse);
CacheUniform(MaterialDiffuseMap); CacheUniform(MaterialDiffuseMap);

View File

@ -31,6 +31,7 @@ NzMaterial::NzMaterial(NzMaterial&& material)
Copy(material); Copy(material);
// Nous "volons" la référence du matériau // Nous "volons" la référence du matériau
material.m_alphaMap = nullptr;
material.m_customShader = nullptr; material.m_customShader = nullptr;
material.m_diffuseMap = nullptr; material.m_diffuseMap = nullptr;
material.m_emissiveMap = nullptr; material.m_emissiveMap = nullptr;
@ -46,6 +47,19 @@ void NzMaterial::Apply(const NzShader* shader) const
int shininessLocation = shader->GetUniformLocation(nzShaderUniform_MaterialShininess); int shininessLocation = shader->GetUniformLocation(nzShaderUniform_MaterialShininess);
int specularColorLocation = shader->GetUniformLocation(nzShaderUniform_MaterialSpecular); 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) if (ambientColorLocation != -1)
shader->SendColor(ambientColorLocation, m_ambientColor); shader->SendColor(ambientColorLocation, m_ambientColor);
@ -327,6 +341,7 @@ bool NzMaterial::LoadFromStream(NzInputStream& stream, const NzMaterialParams& p
void NzMaterial::Reset() void NzMaterial::Reset()
{ {
m_alphaMap.Reset();
m_customShader.Reset(); m_customShader.Reset();
m_diffuseMap.Reset(); m_diffuseMap.Reset();
m_emissiveMap.Reset(); m_emissiveMap.Reset();
@ -353,6 +368,32 @@ void NzMaterial::Reset()
m_zWriteEnabled = true; m_zWriteEnabled = true;
} }
bool NzMaterial::SetAlphaMap(const NzString& texturePath)
{
std::unique_ptr<NzTexture> 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) void NzMaterial::SetAmbientColor(const NzColor& ambient)
{ {
m_ambientColor = ambient; m_ambientColor = ambient;
@ -551,6 +592,7 @@ NzMaterial& NzMaterial::operator=(NzMaterial&& material)
Copy(material); Copy(material);
// Comme ça nous volons la référence du matériau // Comme ça nous volons la référence du matériau
material.m_alphaMap = nullptr;
material.m_customShader = nullptr; material.m_customShader = nullptr;
material.m_diffuseMap = nullptr; material.m_diffuseMap = nullptr;
material.m_emissiveMap = nullptr; material.m_emissiveMap = nullptr;
@ -581,6 +623,7 @@ NzMaterial* NzMaterial::GetDefault()
void NzMaterial::Copy(const NzMaterial& material) void NzMaterial::Copy(const NzMaterial& material)
{ {
m_alphaMap.Reset();
m_customShader.Reset(); m_customShader.Reset();
m_diffuseMap.Reset(); m_diffuseMap.Reset();
m_emissiveMap.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 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 // Ensuite une petite astuce pour récupérer correctement les références
m_alphaMap.Release();
m_customShader.Release(); m_customShader.Release();
m_diffuseMap.Release(); m_diffuseMap.Release();
m_emissiveMap.Release(); m_emissiveMap.Release();
@ -598,6 +642,7 @@ void NzMaterial::Copy(const NzMaterial& material)
m_normalMap.Release(); m_normalMap.Release();
m_specularMap.Release(); m_specularMap.Release();
m_alphaMap = material.m_alphaMap;
m_customShader = material.m_customShader; m_customShader = material.m_customShader;
m_diffuseMap = material.m_diffuseMap; m_diffuseMap = material.m_diffuseMap;
m_heightMap = material.m_heightMap; m_heightMap = material.m_heightMap;

View File

@ -75,6 +75,9 @@ namespace
"uniform vec4 MaterialAmbient;\n"; "uniform vec4 MaterialAmbient;\n";
} }
if (flags & nzShaderFlags_AlphaMapping)
sourceCode += "uniform sampler2D MaterialAlphaMap;\n";
if ((flags & nzShaderFlags_DiffuseMapping) == 0 || flags & nzShaderFlags_Lighting) if ((flags & nzShaderFlags_DiffuseMapping) == 0 || flags & nzShaderFlags_Lighting)
sourceCode += "uniform vec4 MaterialDiffuse;\n"; sourceCode += "uniform vec4 MaterialDiffuse;\n";
@ -280,17 +283,27 @@ namespace
sourceCode += ";\n"; 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) if (flags & nzShaderFlags_EmissiveMapping)
{ {
sourceCode += "vec3 emission = vec3(" + textureLookupKW + "(MaterialEmissiveMap, vTexCoord));\n" 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)" ///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 else
sourceCode += fragmentColorKW + " = vec4(lighting, MaterialDiffuse.a);"; sourceCode += fragmentColorKW + " = vec4(lighting, alpha);\n";
} }
else if (flags & nzShaderFlags_DiffuseMapping) else if (flags & nzShaderFlags_DiffuseMapping)
{
if (flags & nzShaderFlags_AlphaMapping)
sourceCode += fragmentColorKW + " = vec4(" + textureLookupKW + "(MaterialDiffuseMap, vTexCoord).rgb, " + textureLookupKW + "(MaterialAlphaMap, vTexCoord).r);\n";
else
sourceCode += fragmentColorKW + " = " + textureLookupKW + "(MaterialDiffuseMap, vTexCoord);\n"; sourceCode += fragmentColorKW + " = " + textureLookupKW + "(MaterialDiffuseMap, vTexCoord);\n";
}
else else
sourceCode += fragmentColorKW + " = MaterialDiffuse;\n"; sourceCode += fragmentColorKW + " = MaterialDiffuse;\n";