Graphics: Separate pipeline state from Material into a new class, MaterialPipeline
This allows much more efficient batching, along with pipeline reusage and preparation for the Vulkan API Former-commit-id: fd2de2f0e9612ea275ee69c5578c68e7169cd05b [formerly 53bd8a5ed5695311b7543ad717df63f93fad2da6] [formerly 171740929652ac9fe30e84983709388859cedd6b [formerly 25096a76678f1052e76f67d26b458077a0632cc3]] Former-commit-id: 7978dbeb87af2eac9e5501a97afa83849648bf6e [formerly 81b6cce1ee81a2ca8873d3c70d468b2c71510c95] Former-commit-id: 6663e2721c3f79d5f1e3f33c6183174378b502f4
This commit is contained in:
@@ -2,40 +2,15 @@
|
||||
// This file is part of the "Nazara Engine - Graphics module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#ifndef NAZARA_RENDERER_OPENGL
|
||||
#define NAZARA_RENDERER_OPENGL // Mandatory to include the OpenGL headers
|
||||
#endif
|
||||
|
||||
#include <Nazara/Graphics/Material.hpp>
|
||||
#include <Nazara/Core/ErrorFlags.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/UberShaderPreprocessor.hpp>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <Nazara/Graphics/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const UInt8 r_basicFragmentShader[] = {
|
||||
#include <Nazara/Graphics/Resources/Shaders/Basic/core.frag.h>
|
||||
};
|
||||
|
||||
const UInt8 r_basicVertexShader[] = {
|
||||
#include <Nazara/Graphics/Resources/Shaders/Basic/core.vert.h>
|
||||
};
|
||||
|
||||
const UInt8 r_phongLightingFragmentShader[] = {
|
||||
#include <Nazara/Graphics/Resources/Shaders/PhongLighting/core.frag.h>
|
||||
};
|
||||
|
||||
const UInt8 r_phongLightingVertexShader[] = {
|
||||
#include <Nazara/Graphics/Resources/Shaders/PhongLighting/core.vert.h>
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* \ingroup graphics
|
||||
* \class Nz::Material
|
||||
@@ -46,7 +21,6 @@ namespace Nz
|
||||
* \brief Checks whether the parameters for the material are correct
|
||||
* \return true If parameters are valid
|
||||
*/
|
||||
|
||||
bool MaterialParams::IsValid() const
|
||||
{
|
||||
if (!UberShaderLibrary::Has(shaderName))
|
||||
@@ -57,41 +31,35 @@ namespace Nz
|
||||
|
||||
/*!
|
||||
* \brief Applies shader to the material
|
||||
* \return Constant pointer to the shader
|
||||
*
|
||||
* \param shaderFlags Flags for the shader
|
||||
* \param instance Pipeline instance to update
|
||||
* \param textureUnit Unit for the texture GL_TEXTURE"i"
|
||||
* \param lastUsedUnit Optional argument to get the last texture unit
|
||||
*/
|
||||
|
||||
const Shader* Material::Apply(UInt32 shaderFlags, UInt8 textureUnit, UInt8* lastUsedUnit) const
|
||||
void Material::Apply(const MaterialPipeline::Instance& instance, UInt8 textureUnit, UInt8* lastUsedUnit) const
|
||||
{
|
||||
const ShaderInstance& instance = m_shaders[shaderFlags];
|
||||
if (!instance.uberInstance)
|
||||
GenerateShader(shaderFlags);
|
||||
|
||||
instance.uberInstance->Activate();
|
||||
const Shader* shader = instance.renderPipeline.GetInfo().shader;
|
||||
|
||||
if (instance.uniforms[MaterialUniform_AlphaThreshold] != -1)
|
||||
instance.shader->SendFloat(instance.uniforms[MaterialUniform_AlphaThreshold], m_alphaThreshold);
|
||||
shader->SendFloat(instance.uniforms[MaterialUniform_AlphaThreshold], m_alphaThreshold);
|
||||
|
||||
if (instance.uniforms[MaterialUniform_Ambient] != -1)
|
||||
instance.shader->SendColor(instance.uniforms[MaterialUniform_Ambient], m_ambientColor);
|
||||
shader->SendColor(instance.uniforms[MaterialUniform_Ambient], m_ambientColor);
|
||||
|
||||
if (instance.uniforms[MaterialUniform_Diffuse] != -1)
|
||||
instance.shader->SendColor(instance.uniforms[MaterialUniform_Diffuse], m_diffuseColor);
|
||||
shader->SendColor(instance.uniforms[MaterialUniform_Diffuse], m_diffuseColor);
|
||||
|
||||
if (instance.uniforms[MaterialUniform_Shininess] != -1)
|
||||
instance.shader->SendFloat(instance.uniforms[MaterialUniform_Shininess], m_shininess);
|
||||
shader->SendFloat(instance.uniforms[MaterialUniform_Shininess], m_shininess);
|
||||
|
||||
if (instance.uniforms[MaterialUniform_Specular] != -1)
|
||||
instance.shader->SendColor(instance.uniforms[MaterialUniform_Specular], m_specularColor);
|
||||
shader->SendColor(instance.uniforms[MaterialUniform_Specular], m_specularColor);
|
||||
|
||||
if (m_alphaMap && instance.uniforms[MaterialUniform_AlphaMap] != -1)
|
||||
{
|
||||
Renderer::SetTexture(textureUnit, m_alphaMap);
|
||||
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
|
||||
instance.shader->SendInteger(instance.uniforms[MaterialUniform_AlphaMap], textureUnit);
|
||||
shader->SendInteger(instance.uniforms[MaterialUniform_AlphaMap], textureUnit);
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
@@ -99,7 +67,7 @@ namespace Nz
|
||||
{
|
||||
Renderer::SetTexture(textureUnit, m_diffuseMap);
|
||||
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
|
||||
instance.shader->SendInteger(instance.uniforms[MaterialUniform_DiffuseMap], textureUnit);
|
||||
shader->SendInteger(instance.uniforms[MaterialUniform_DiffuseMap], textureUnit);
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
@@ -107,7 +75,7 @@ namespace Nz
|
||||
{
|
||||
Renderer::SetTexture(textureUnit, m_emissiveMap);
|
||||
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
|
||||
instance.shader->SendInteger(instance.uniforms[MaterialUniform_EmissiveMap], textureUnit);
|
||||
shader->SendInteger(instance.uniforms[MaterialUniform_EmissiveMap], textureUnit);
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
@@ -115,7 +83,7 @@ namespace Nz
|
||||
{
|
||||
Renderer::SetTexture(textureUnit, m_heightMap);
|
||||
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
|
||||
instance.shader->SendInteger(instance.uniforms[MaterialUniform_HeightMap], textureUnit);
|
||||
shader->SendInteger(instance.uniforms[MaterialUniform_HeightMap], textureUnit);
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
@@ -123,7 +91,7 @@ namespace Nz
|
||||
{
|
||||
Renderer::SetTexture(textureUnit, m_normalMap);
|
||||
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
|
||||
instance.shader->SendInteger(instance.uniforms[MaterialUniform_NormalMap], textureUnit);
|
||||
shader->SendInteger(instance.uniforms[MaterialUniform_NormalMap], textureUnit);
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
@@ -131,25 +99,20 @@ namespace Nz
|
||||
{
|
||||
Renderer::SetTexture(textureUnit, m_specularMap);
|
||||
Renderer::SetTextureSampler(textureUnit, m_specularSampler);
|
||||
instance.shader->SendInteger(instance.uniforms[MaterialUniform_SpecularMap], textureUnit);
|
||||
shader->SendInteger(instance.uniforms[MaterialUniform_SpecularMap], textureUnit);
|
||||
textureUnit++;
|
||||
}
|
||||
|
||||
Renderer::SetRenderStates(m_states);
|
||||
|
||||
if (lastUsedUnit)
|
||||
*lastUsedUnit = textureUnit;
|
||||
|
||||
return instance.shader;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Builds the material from parameters
|
||||
* \brief Builds the material from a parameter list
|
||||
*
|
||||
* \param matData Data information for the material
|
||||
* \param matParams Parameters for the material
|
||||
* \param matParams Additional parameters for the material
|
||||
*/
|
||||
|
||||
void Material::BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams)
|
||||
{
|
||||
Color color;
|
||||
@@ -160,7 +123,6 @@ namespace Nz
|
||||
|
||||
ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled, true);
|
||||
|
||||
|
||||
if (matData.GetFloatParameter(MaterialData::AlphaThreshold, &fValue))
|
||||
SetAlphaThreshold(fValue);
|
||||
|
||||
@@ -188,14 +150,11 @@ namespace Nz
|
||||
if (matData.GetIntegerParameter(MaterialData::FaceFilling, &iValue))
|
||||
SetFaceFilling(static_cast<FaceFilling>(iValue));
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::Lighting, &isEnabled))
|
||||
EnableLighting(isEnabled);
|
||||
|
||||
if (matData.GetFloatParameter(MaterialData::LineWidth, &fValue))
|
||||
m_states.lineWidth = fValue;
|
||||
SetLineWidth(fValue);
|
||||
|
||||
if (matData.GetFloatParameter(MaterialData::PointSize, &fValue))
|
||||
m_states.pointSize = fValue;
|
||||
SetPointSize(fValue);
|
||||
|
||||
if (matData.GetColorParameter(MaterialData::SpecularColor, &color))
|
||||
SetSpecularColor(color);
|
||||
@@ -206,30 +165,27 @@ namespace Nz
|
||||
if (matData.GetIntegerParameter(MaterialData::SrcBlend, &iValue))
|
||||
SetSrcBlend(static_cast<BlendFunc>(iValue));
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::Transform, &isEnabled))
|
||||
EnableTransform(isEnabled);
|
||||
|
||||
// RendererParameter
|
||||
if (matData.GetBooleanParameter(MaterialData::Blending, &isEnabled))
|
||||
Enable(RendererParameter_Blend, isEnabled);
|
||||
EnableBlending(isEnabled);
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::ColorWrite, &isEnabled))
|
||||
Enable(RendererParameter_ColorWrite, isEnabled);
|
||||
EnableColorWrite(isEnabled);
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::DepthBuffer, &isEnabled))
|
||||
Enable(RendererParameter_DepthBuffer, isEnabled);
|
||||
EnableDepthBuffer(isEnabled);
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::DepthWrite, &isEnabled))
|
||||
Enable(RendererParameter_DepthWrite, isEnabled);
|
||||
EnableDepthWrite(isEnabled);
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::FaceCulling, &isEnabled))
|
||||
Enable(RendererParameter_FaceCulling, isEnabled);
|
||||
EnableFaceCulling(isEnabled);
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::ScissorTest, &isEnabled))
|
||||
Enable(RendererParameter_ScissorTest, isEnabled);
|
||||
EnableScissorTest(isEnabled);
|
||||
|
||||
if (matData.GetBooleanParameter(MaterialData::StencilTest, &isEnabled))
|
||||
Enable(RendererParameter_StencilTest, isEnabled);
|
||||
EnableStencilTest(isEnabled);
|
||||
|
||||
// Samplers
|
||||
if (matData.GetIntegerParameter(MaterialData::DiffuseAnisotropyLevel, &iValue))
|
||||
@@ -252,41 +208,43 @@ namespace Nz
|
||||
|
||||
// Stencil
|
||||
if (matData.GetIntegerParameter(MaterialData::StencilCompare, &iValue))
|
||||
m_states.stencilCompare.front = static_cast<RendererComparison>(iValue);
|
||||
m_pipelineInfo.stencilCompare.front = static_cast<RendererComparison>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::StencilFail, &iValue))
|
||||
m_states.stencilFail.front = static_cast<StencilOperation>(iValue);
|
||||
m_pipelineInfo.stencilFail.front = static_cast<StencilOperation>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::StencilPass, &iValue))
|
||||
m_states.stencilPass.front = static_cast<StencilOperation>(iValue);
|
||||
m_pipelineInfo.stencilPass.front = static_cast<StencilOperation>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::StencilZFail, &iValue))
|
||||
m_states.stencilDepthFail.front = static_cast<StencilOperation>(iValue);
|
||||
m_pipelineInfo.stencilDepthFail.front = static_cast<StencilOperation>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::StencilMask, &iValue))
|
||||
m_states.stencilWriteMask.front = static_cast<UInt32>(iValue);
|
||||
m_pipelineInfo.stencilWriteMask.front = static_cast<UInt32>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::StencilReference, &iValue))
|
||||
m_states.stencilReference.front = static_cast<unsigned int>(iValue);
|
||||
m_pipelineInfo.stencilReference.front = static_cast<unsigned int>(iValue);
|
||||
|
||||
// Stencil (back)
|
||||
if (matData.GetIntegerParameter(MaterialData::BackFaceStencilCompare, &iValue))
|
||||
m_states.stencilCompare.back = static_cast<RendererComparison>(iValue);
|
||||
m_pipelineInfo.stencilCompare.back = static_cast<RendererComparison>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::BackFaceStencilFail, &iValue))
|
||||
m_states.stencilFail.back = static_cast<StencilOperation>(iValue);
|
||||
m_pipelineInfo.stencilFail.back = static_cast<StencilOperation>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::BackFaceStencilPass, &iValue))
|
||||
m_states.stencilPass.back = static_cast<StencilOperation>(iValue);
|
||||
m_pipelineInfo.stencilPass.back = static_cast<StencilOperation>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::BackFaceStencilZFail, &iValue))
|
||||
m_states.stencilDepthFail.back = static_cast<StencilOperation>(iValue);
|
||||
m_pipelineInfo.stencilDepthFail.back = static_cast<StencilOperation>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::BackFaceStencilMask, &iValue))
|
||||
m_states.stencilWriteMask.back = static_cast<UInt32>(iValue);
|
||||
m_pipelineInfo.stencilWriteMask.back = static_cast<UInt32>(iValue);
|
||||
|
||||
if (matData.GetIntegerParameter(MaterialData::BackFaceStencilReference, &iValue))
|
||||
m_states.stencilReference.back = static_cast<unsigned int>(iValue);
|
||||
m_pipelineInfo.stencilReference.back = static_cast<unsigned int>(iValue);
|
||||
|
||||
InvalidatePipeline();
|
||||
|
||||
// Textures
|
||||
if (matParams.loadAlphaMap && matData.GetStringParameter(MaterialData::AlphaTexturePath, &path))
|
||||
@@ -310,6 +268,11 @@ namespace Nz
|
||||
SetShader(matParams.shaderName);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Builds a ParameterList with material data
|
||||
*
|
||||
* \param matData Destination parameter list which will receive material data
|
||||
*/
|
||||
void Material::SaveToParameters(ParameterList* matData)
|
||||
{
|
||||
NazaraAssert(matData, "Invalid ParameterList");
|
||||
@@ -323,22 +286,20 @@ namespace Nz
|
||||
matData->SetParameter(MaterialData::DiffuseColor, GetDiffuseColor());
|
||||
matData->SetParameter(MaterialData::DstBlend, int(GetDstBlend()));
|
||||
matData->SetParameter(MaterialData::FaceFilling, int(GetFaceFilling()));
|
||||
matData->SetParameter(MaterialData::Lighting, IsLightingEnabled());
|
||||
matData->SetParameter(MaterialData::LineWidth, GetRenderStates().lineWidth);
|
||||
matData->SetParameter(MaterialData::PointSize, GetRenderStates().pointSize);
|
||||
matData->SetParameter(MaterialData::LineWidth, GetLineWidth());
|
||||
matData->SetParameter(MaterialData::PointSize, GetPointSize());
|
||||
matData->SetParameter(MaterialData::Shininess, GetShininess());
|
||||
matData->SetParameter(MaterialData::SpecularColor, GetSpecularColor());
|
||||
matData->SetParameter(MaterialData::SrcBlend, int(GetSrcBlend()));
|
||||
matData->SetParameter(MaterialData::Transform, IsTransformEnabled());
|
||||
|
||||
// RendererParameter
|
||||
matData->SetParameter(MaterialData::Blending, GetRenderStates().blending);
|
||||
matData->SetParameter(MaterialData::ColorWrite, GetRenderStates().colorWrite);
|
||||
matData->SetParameter(MaterialData::DepthBuffer, GetRenderStates().depthBuffer);
|
||||
matData->SetParameter(MaterialData::DepthWrite, GetRenderStates().depthWrite);
|
||||
matData->SetParameter(MaterialData::FaceCulling, GetRenderStates().faceCulling);
|
||||
matData->SetParameter(MaterialData::ScissorTest, GetRenderStates().scissorTest);
|
||||
matData->SetParameter(MaterialData::StencilTest, GetRenderStates().stencilTest);
|
||||
matData->SetParameter(MaterialData::Blending, IsBlendingEnabled());
|
||||
matData->SetParameter(MaterialData::ColorWrite, IsColorWriteEnabled());
|
||||
matData->SetParameter(MaterialData::DepthBuffer, IsDepthBufferEnabled());
|
||||
matData->SetParameter(MaterialData::DepthWrite, IsDepthWriteEnabled());
|
||||
matData->SetParameter(MaterialData::FaceCulling, IsFaceCullingEnabled());
|
||||
matData->SetParameter(MaterialData::ScissorTest, IsScissorTestEnabled());
|
||||
matData->SetParameter(MaterialData::StencilTest, IsStencilTestEnabled());
|
||||
|
||||
// Samplers
|
||||
matData->SetParameter(MaterialData::DiffuseAnisotropyLevel, int(GetDiffuseSampler().GetAnisotropicLevel()));
|
||||
@@ -350,20 +311,20 @@ namespace Nz
|
||||
matData->SetParameter(MaterialData::SpecularWrap, int(GetSpecularSampler().GetWrapMode()));
|
||||
|
||||
// Stencil
|
||||
matData->SetParameter(MaterialData::StencilCompare, int(GetRenderStates().stencilCompare.front));
|
||||
matData->SetParameter(MaterialData::StencilFail, int(GetRenderStates().stencilFail.front));
|
||||
matData->SetParameter(MaterialData::StencilPass, int(GetRenderStates().stencilPass.front));
|
||||
matData->SetParameter(MaterialData::StencilZFail, int(GetRenderStates().stencilDepthFail.front));
|
||||
matData->SetParameter(MaterialData::StencilMask, int(GetRenderStates().stencilWriteMask.front));
|
||||
matData->SetParameter(MaterialData::StencilReference, int(GetRenderStates().stencilReference.front));
|
||||
matData->SetParameter(MaterialData::StencilCompare, int(GetPipelineInfo().stencilCompare.front));
|
||||
matData->SetParameter(MaterialData::StencilFail, int(GetPipelineInfo().stencilFail.front));
|
||||
matData->SetParameter(MaterialData::StencilPass, int(GetPipelineInfo().stencilPass.front));
|
||||
matData->SetParameter(MaterialData::StencilZFail, int(GetPipelineInfo().stencilDepthFail.front));
|
||||
matData->SetParameter(MaterialData::StencilMask, int(GetPipelineInfo().stencilWriteMask.front));
|
||||
matData->SetParameter(MaterialData::StencilReference, int(GetPipelineInfo().stencilReference.front));
|
||||
|
||||
// Stencil (back)
|
||||
matData->SetParameter(MaterialData::BackFaceStencilCompare, int(GetRenderStates().stencilCompare.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilFail, int(GetRenderStates().stencilFail.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilPass, int(GetRenderStates().stencilPass.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilZFail, int(GetRenderStates().stencilDepthFail.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilMask, int(GetRenderStates().stencilWriteMask.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilReference, int(GetRenderStates().stencilReference.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilCompare, int(GetPipelineInfo().stencilCompare.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilFail, int(GetPipelineInfo().stencilFail.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilPass, int(GetPipelineInfo().stencilPass.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilZFail, int(GetPipelineInfo().stencilDepthFail.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilMask, int(GetPipelineInfo().stencilWriteMask.back));
|
||||
matData->SetParameter(MaterialData::BackFaceStencilReference, int(GetPipelineInfo().stencilReference.back));
|
||||
|
||||
// Textures
|
||||
if (HasAlphaMap())
|
||||
@@ -411,6 +372,8 @@ namespace Nz
|
||||
|
||||
/*!
|
||||
* \brief Resets the material, cleans everything
|
||||
*
|
||||
* \remark Invalidates the pipeline
|
||||
*/
|
||||
void Material::Reset()
|
||||
{
|
||||
@@ -423,29 +386,22 @@ namespace Nz
|
||||
m_heightMap.Reset();
|
||||
m_normalMap.Reset();
|
||||
m_specularMap.Reset();
|
||||
m_uberShader.Reset();
|
||||
|
||||
for (ShaderInstance& instance : m_shaders)
|
||||
instance.uberInstance = nullptr;
|
||||
|
||||
m_alphaThreshold = 0.2f;
|
||||
m_alphaTestEnabled = false;
|
||||
m_ambientColor = Color(128, 128, 128);
|
||||
m_depthSortingEnabled = false;
|
||||
m_diffuseColor = Color::White;
|
||||
m_diffuseSampler = TextureSampler();
|
||||
m_lightingEnabled = true;
|
||||
m_shadowCastingEnabled = true;
|
||||
m_shadowReceiveEnabled = true;
|
||||
m_shininess = 50.f;
|
||||
m_specularColor = Color::White;
|
||||
m_specularSampler = TextureSampler();
|
||||
m_states = RenderStates();
|
||||
m_states.depthBuffer = true;
|
||||
m_states.faceCulling = true;
|
||||
m_transformEnabled = true;
|
||||
m_pipelineInfo = MaterialPipelineInfo();
|
||||
m_pipelineInfo.depthBuffer = true;
|
||||
m_pipelineInfo.faceCulling = true;
|
||||
|
||||
SetShader("Basic");
|
||||
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -453,24 +409,18 @@ namespace Nz
|
||||
*
|
||||
* \param material Material to copy into this
|
||||
*/
|
||||
|
||||
void Material::Copy(const Material& material)
|
||||
{
|
||||
// Copy of base states
|
||||
m_alphaTestEnabled = material.m_alphaTestEnabled;
|
||||
m_alphaThreshold = material.m_alphaThreshold;
|
||||
m_ambientColor = material.m_ambientColor;
|
||||
m_depthSortingEnabled = material.m_depthSortingEnabled;
|
||||
m_diffuseColor = material.m_diffuseColor;
|
||||
m_diffuseSampler = material.m_diffuseSampler;
|
||||
m_lightingEnabled = material.m_lightingEnabled;
|
||||
m_pipelineInfo = material.m_pipelineInfo;
|
||||
m_shininess = material.m_shininess;
|
||||
m_shadowCastingEnabled = material.m_shadowCastingEnabled;
|
||||
m_shadowReceiveEnabled = material.m_shadowReceiveEnabled;
|
||||
m_specularColor = material.m_specularColor;
|
||||
m_specularSampler = material.m_specularSampler;
|
||||
m_states = material.m_states;
|
||||
m_transformEnabled = material.m_transformEnabled;
|
||||
|
||||
// Copy of reference to the textures
|
||||
m_alphaMap = material.m_alphaMap;
|
||||
@@ -480,61 +430,8 @@ namespace Nz
|
||||
m_heightMap = material.m_heightMap;
|
||||
m_normalMap = material.m_normalMap;
|
||||
m_specularMap = material.m_specularMap;
|
||||
m_uberShader = material.m_uberShader;
|
||||
|
||||
// We copy the instances of the shader too
|
||||
std::memcpy(&m_shaders[0], &material.m_shaders[0], (ShaderFlags_Max + 1) * sizeof(ShaderInstance));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Generates the shader based on flag
|
||||
*
|
||||
* \param flags Flag for the shaer
|
||||
*/
|
||||
|
||||
void Material::GenerateShader(UInt32 flags) const
|
||||
{
|
||||
ParameterList list;
|
||||
list.SetParameter("ALPHA_MAPPING", m_alphaMap.IsValid());
|
||||
list.SetParameter("ALPHA_TEST", m_alphaTestEnabled);
|
||||
list.SetParameter("COMPUTE_TBNMATRIX", m_normalMap.IsValid() || m_heightMap.IsValid());
|
||||
list.SetParameter("DIFFUSE_MAPPING", m_diffuseMap.IsValid());
|
||||
list.SetParameter("EMISSIVE_MAPPING", m_emissiveMap.IsValid());
|
||||
list.SetParameter("LIGHTING", m_lightingEnabled);
|
||||
list.SetParameter("NORMAL_MAPPING", m_normalMap.IsValid());
|
||||
list.SetParameter("PARALLAX_MAPPING", m_heightMap.IsValid());
|
||||
list.SetParameter("SHADOW_MAPPING", m_shadowReceiveEnabled);
|
||||
list.SetParameter("SPECULAR_MAPPING", m_specularMap.IsValid());
|
||||
list.SetParameter("TEXTURE_MAPPING", m_alphaMap.IsValid() || m_diffuseMap.IsValid() || m_emissiveMap.IsValid() ||
|
||||
m_normalMap.IsValid() || m_heightMap.IsValid() || m_specularMap.IsValid() ||
|
||||
flags & ShaderFlags_TextureOverlay);
|
||||
list.SetParameter("TRANSFORM", m_transformEnabled);
|
||||
|
||||
list.SetParameter("FLAG_BILLBOARD", static_cast<bool>((flags & ShaderFlags_Billboard) != 0));
|
||||
list.SetParameter("FLAG_DEFERRED", static_cast<bool>((flags & ShaderFlags_Deferred) != 0));
|
||||
list.SetParameter("FLAG_INSTANCING", static_cast<bool>((flags & ShaderFlags_Instancing) != 0));
|
||||
list.SetParameter("FLAG_TEXTUREOVERLAY", static_cast<bool>((flags & ShaderFlags_TextureOverlay) != 0));
|
||||
list.SetParameter("FLAG_VERTEXCOLOR", static_cast<bool>((flags & ShaderFlags_VertexColor) != 0));
|
||||
|
||||
ShaderInstance& instance = m_shaders[flags];
|
||||
instance.uberInstance = m_uberShader->Get(list);
|
||||
instance.shader = instance.uberInstance->GetShader();
|
||||
|
||||
#define CacheUniform(name) instance.uniforms[MaterialUniform_##name] = instance.shader->GetUniformLocation("Material" #name)
|
||||
|
||||
CacheUniform(AlphaMap);
|
||||
CacheUniform(AlphaThreshold);
|
||||
CacheUniform(Ambient);
|
||||
CacheUniform(Diffuse);
|
||||
CacheUniform(DiffuseMap);
|
||||
CacheUniform(EmissiveMap);
|
||||
CacheUniform(HeightMap);
|
||||
CacheUniform(NormalMap);
|
||||
CacheUniform(Shininess);
|
||||
CacheUniform(Specular);
|
||||
CacheUniform(SpecularMap);
|
||||
|
||||
#undef CacheUniform
|
||||
InvalidatePipeline();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -543,7 +440,6 @@ namespace Nz
|
||||
*
|
||||
* \remark Produces a NazaraError if the material library failed to be initialized
|
||||
*/
|
||||
|
||||
bool Material::Initialize()
|
||||
{
|
||||
if (!MaterialLibrary::Initialize())
|
||||
@@ -558,67 +454,21 @@ namespace Nz
|
||||
return false;
|
||||
}
|
||||
|
||||
// Basic shader
|
||||
{
|
||||
UberShaderPreprocessorRef uberShader = UberShaderPreprocessor::New();
|
||||
|
||||
String fragmentShader(reinterpret_cast<const char*>(r_basicFragmentShader), sizeof(r_basicFragmentShader));
|
||||
String vertexShader(reinterpret_cast<const char*>(r_basicVertexShader), sizeof(r_basicVertexShader));
|
||||
|
||||
uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING");
|
||||
uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_INSTANCING FLAG_VERTEXCOLOR TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
|
||||
|
||||
UberShaderLibrary::Register("Basic", uberShader);
|
||||
}
|
||||
|
||||
// PhongLighting shader
|
||||
{
|
||||
UberShaderPreprocessorRef uberShader = UberShaderPreprocessor::New();
|
||||
|
||||
String fragmentShader(reinterpret_cast<const char*>(r_phongLightingFragmentShader), sizeof(r_phongLightingFragmentShader));
|
||||
String vertexShader(reinterpret_cast<const char*>(r_phongLightingVertexShader), sizeof(r_phongLightingVertexShader));
|
||||
|
||||
uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING EMISSIVE_MAPPING LIGHTING NORMAL_MAPPING PARALLAX_MAPPING SHADOW_MAPPING SPECULAR_MAPPING");
|
||||
uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX LIGHTING PARALLAX_MAPPING SHADOW_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
|
||||
|
||||
UberShaderLibrary::Register("PhongLighting", uberShader);
|
||||
}
|
||||
|
||||
// Once the base shaders are registered, we can now set some default materials
|
||||
s_defaultMaterial = New();
|
||||
s_defaultMaterial->Enable(RendererParameter_FaceCulling, false);
|
||||
s_defaultMaterial->EnableFaceCulling(false);
|
||||
s_defaultMaterial->SetFaceFilling(FaceFilling_Line);
|
||||
MaterialLibrary::Register("Default", s_defaultMaterial);
|
||||
|
||||
MaterialRef mat;
|
||||
|
||||
mat = New();
|
||||
mat->Enable(RendererParameter_DepthWrite, false);
|
||||
mat->Enable(RendererParameter_FaceCulling, false);
|
||||
mat->EnableLighting(false);
|
||||
MaterialLibrary::Register("Basic2D", std::move(mat));
|
||||
|
||||
mat = New();
|
||||
mat->Enable(RendererParameter_Blend, true);
|
||||
mat->Enable(RendererParameter_DepthWrite, false);
|
||||
mat->Enable(RendererParameter_FaceCulling, false);
|
||||
mat->EnableLighting(false);
|
||||
mat->SetDstBlend(BlendFunc_InvSrcAlpha);
|
||||
mat->SetSrcBlend(BlendFunc_SrcAlpha);
|
||||
MaterialLibrary::Register("Translucent2D", std::move(mat));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Uninitializes the material librairies
|
||||
*/
|
||||
|
||||
void Material::Uninitialize()
|
||||
{
|
||||
s_defaultMaterial.Reset();
|
||||
UberShaderLibrary::Unregister("PhongLighting");
|
||||
UberShaderLibrary::Unregister("Basic");
|
||||
|
||||
MaterialManager::Uninitialize();
|
||||
MaterialLibrary::Uninitialize();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user