Graphics/Shader: Make texture units statics

Provides better performances and prevents the sampler type bug to happen
This commit is contained in:
Lynix 2016-12-18 01:13:46 +01:00
parent 1a8805aad1
commit 682dab32b3
10 changed files with 203 additions and 183 deletions

View File

@ -148,6 +148,26 @@ namespace Nz
ShaderFlags_Max = ShaderFlags_VertexColor * 2 - 1 ShaderFlags_Max = ShaderFlags_VertexColor * 2 - 1
}; };
enum TextureMap
{
TextureMap_Alpha,
TextureMap_Diffuse,
TextureMap_Emissive,
TextureMap_Height,
TextureMap_ReflectionCube,
TextureMap_Normal,
TextureMap_Overlay,
TextureMap_Shadow2D_1,
TextureMap_Shadow2D_2,
TextureMap_Shadow2D_3,
TextureMap_ShadowCube_1,
TextureMap_ShadowCube_2,
TextureMap_ShadowCube_3,
TextureMap_Specular,
TextureMap_Max = TextureMap_Specular
};
} }
#endif // NAZARA_ENUMS_GRAPHICS_HPP #endif // NAZARA_ENUMS_GRAPHICS_HPP

View File

@ -46,7 +46,7 @@ namespace Nz
void DrawTransparentModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawTransparentModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const; const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
void OnShaderInvalidated(const Shader* shader) const; void OnShaderInvalidated(const Shader* shader) const;
void SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int uniformOffset, UInt8 availableTextureUnit) const; void SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int lightIndex, unsigned int uniformOffset) const;
static float ComputeDirectionalLightScore(const Spheref& object, const AbstractRenderQueue::DirectionalLight& light); static float ComputeDirectionalLightScore(const Spheref& object, const AbstractRenderQueue::DirectionalLight& light);
static float ComputePointLightScore(const Spheref& object, const AbstractRenderQueue::PointLight& light); static float ComputePointLightScore(const Spheref& object, const AbstractRenderQueue::PointLight& light);

View File

@ -6,135 +6,6 @@
namespace Nz namespace Nz
{ {
/*!
* \brief Sens the uniforms for light
*
* \param shader Shader to send uniforms to
* \param uniforms Uniforms to send
* \param index Index of the light
* \param uniformOffset Offset for the uniform
* \param availableTextureUnit Unit texture available
*/
inline void ForwardRenderTechnique::SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int uniformOffset, UInt8 availableTextureUnit) const
{
// If anyone got a better idea..
int dummyCubemap = Renderer::GetMaxTextureUnits() - 1;
int dummyTexture = Renderer::GetMaxTextureUnits() - 2;
if (index < m_lights.size())
{
const LightIndex& lightIndex = m_lights[index];
shader->SendInteger(uniforms.locations.type + uniformOffset, lightIndex.type); //< Sends the light type
switch (lightIndex.type)
{
case LightType_Directional:
{
const auto& light = m_renderQueue.directionalLights[lightIndex.index];
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.direction));
if (uniforms.locations.shadowMapping != -1)
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
if (light.shadowMap)
{
Renderer::SetTexture(availableTextureUnit, light.shadowMap);
Renderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
if (uniforms.locations.lightViewProjMatrix != -1)
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit);
}
else if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
break;
}
case LightType_Point:
{
const auto& light = m_renderQueue.pointLights[lightIndex.index];
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.position, light.attenuation));
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, Vector4f(0.f, 0.f, 0.f, light.invRadius));
if (uniforms.locations.shadowMapping != -1)
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
if (light.shadowMap)
{
Renderer::SetTexture(availableTextureUnit, light.shadowMap);
Renderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
if (uniforms.locations.pointLightShadowMap != -1)
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, availableTextureUnit);
}
else if (uniforms.locations.pointLightShadowMap != -1)
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
break;
}
case LightType_Spot:
{
const auto& light = m_renderQueue.spotLights[lightIndex.index];
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.position, light.attenuation));
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, Vector4f(light.direction, light.invRadius));
shader->SendVector(uniforms.locations.parameters3 + uniformOffset, Vector2f(light.innerAngleCosine, light.outerAngleCosine));
if (uniforms.locations.shadowMapping != -1)
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
if (light.shadowMap)
{
Renderer::SetTexture(availableTextureUnit, light.shadowMap);
Renderer::SetTextureSampler(availableTextureUnit, s_shadowSampler);
if (uniforms.locations.lightViewProjMatrix != -1)
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, availableTextureUnit);
}
else if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
if (uniforms.locations.pointLightShadowMap != -1)
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
break;
}
}
}
else
{
if (uniforms.locations.type != -1)
shader->SendInteger(uniforms.locations.type + uniformOffset, -1); //< Disable the light in the shader
if (uniforms.locations.directionalSpotLightShadowMap != -1)
shader->SendInteger(uniforms.locations.directionalSpotLightShadowMap + index, dummyTexture);
if (uniforms.locations.pointLightShadowMap != -1)
shader->SendInteger(uniforms.locations.pointLightShadowMap + index, dummyCubemap);
}
}
/*! /*!
* \brief Computes the score for directional light * \brief Computes the score for directional light
* \return 0.f * \return 0.f

View File

@ -102,13 +102,11 @@ namespace Nz
{ {
int type; int type;
int color; int color;
int directionalSpotLightShadowMap;
int factors; int factors;
int lightViewProjMatrix; int lightViewProjMatrix;
int parameters1; int parameters1;
int parameters2; int parameters2;
int parameters3; int parameters3;
int pointLightShadowMap;
int shadowMapping; int shadowMapping;
}; };

View File

@ -64,7 +64,7 @@ namespace Nz
inline Material(const Material& material); inline Material(const Material& material);
inline ~Material(); inline ~Material();
void Apply(const MaterialPipeline::Instance& instance, UInt8 textureUnit = 0, UInt8* lastUsedUnit = nullptr) const; void Apply(const MaterialPipeline::Instance& instance) const;
void BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams = MaterialParams()); void BuildFromParameters(const ParameterList& matData, const MaterialParams& matParams = MaterialParams());
@ -174,6 +174,7 @@ namespace Nz
inline Material& operator=(const Material& material); inline Material& operator=(const Material& material);
inline static MaterialRef GetDefault(); inline static MaterialRef GetDefault();
inline static int GetTextureUnit(TextureMap textureMap);
template<typename... Args> static MaterialRef New(Args&&... args); template<typename... Args> static MaterialRef New(Args&&... args);
// Signals: // Signals:
@ -207,6 +208,7 @@ namespace Nz
float m_alphaThreshold; float m_alphaThreshold;
float m_shininess; float m_shininess;
static std::array<int, TextureMap_Max + 1> s_textureUnits;
static MaterialLibrary::LibraryMap s_library; static MaterialLibrary::LibraryMap s_library;
static MaterialLoader::LoaderList s_loaders; static MaterialLoader::LoaderList s_loaders;
static MaterialManager::ManagerMap s_managerMap; static MaterialManager::ManagerMap s_managerMap;

View File

@ -1356,6 +1356,11 @@ namespace Nz
return s_defaultMaterial; return s_defaultMaterial;
} }
inline int Material::GetTextureUnit(TextureMap textureMap)
{
return s_textureUnits[textureMap];
}
inline void Material::InvalidatePipeline() inline void Material::InvalidatePipeline()
{ {
m_pipelineUpdated = false; m_pipelineUpdated = false;

View File

@ -249,13 +249,12 @@ namespace Nz
if (matEntry.enabled) if (matEntry.enabled)
{ {
UInt8 overlayUnit; unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
material->Apply(pipelineInstance, 0, &overlayUnit); material->Apply(pipelineInstance);
overlayUnit++;
shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit); shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
Renderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler()); Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
auto& overlayMap = matEntry.overlayMap; auto& overlayMap = matEntry.overlayMap;
for (auto& overlayIt : overlayMap) for (auto& overlayIt : overlayMap)
@ -266,7 +265,7 @@ namespace Nz
std::size_t spriteChainCount = spriteChainVector.size(); std::size_t spriteChainCount = spriteChainVector.size();
if (spriteChainCount > 0) if (spriteChainCount > 0)
{ {
Renderer::SetTexture(overlayUnit, (overlay) ? overlay : &m_whiteTexture); Renderer::SetTexture(overlayTextureUnit, (overlay) ? overlay : &m_whiteTexture);
std::size_t spriteChain = 0; // Which chain of sprites are we treating std::size_t spriteChain = 0; // Which chain of sprites are we treating
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
@ -525,8 +524,7 @@ namespace Nz
if (matEntry.enabled) if (matEntry.enabled)
{ {
UInt8 freeTextureUnit; material->Apply(pipelineInstance);
material->Apply(pipelineInstance, 0, &freeTextureUnit);
ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap; ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap;

View File

@ -318,7 +318,7 @@ namespace Nz
// Index of uniforms in the shader // Index of uniforms in the shader
shaderUniforms = GetShaderUniforms(shader); shaderUniforms = GetShaderUniforms(shader);
// Ambiant color of the scene // Ambient color of the scene
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor); shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
// Position of the camera // Position of the camera
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition()); shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
@ -333,13 +333,13 @@ namespace Nz
if (matEntry.enabled) if (matEntry.enabled)
{ {
UInt8 overlayUnit; material->Apply(pipelineInstance);
material->Apply(pipelineInstance, 0, &overlayUnit);
overlayUnit++;
shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit); unsigned int overlayTextureUnit = Material::GetTextureUnit(TextureMap_Overlay);
Renderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler()); shader->SendInteger(shaderUniforms->textureOverlay, overlayTextureUnit);
Renderer::SetTextureSampler(overlayTextureUnit, material->GetDiffuseSampler());
auto& overlayMap = matEntry.overlayMap; auto& overlayMap = matEntry.overlayMap;
for (auto& overlayIt : overlayMap) for (auto& overlayIt : overlayMap)
@ -350,7 +350,7 @@ namespace Nz
std::size_t spriteChainCount = spriteChainVector.size(); std::size_t spriteChainCount = spriteChainVector.size();
if (spriteChainCount > 0) if (spriteChainCount > 0)
{ {
Renderer::SetTexture(overlayUnit, (overlay) ? overlay : &m_whiteTexture); Renderer::SetTexture(overlayTextureUnit, (overlay) ? overlay : &m_whiteTexture);
std::size_t spriteChain = 0; // Which chain of sprites are we treating std::size_t spriteChain = 0; // Which chain of sprites are we treating
std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain std::size_t spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
@ -616,8 +616,7 @@ namespace Nz
if (matEntry.enabled) if (matEntry.enabled)
{ {
UInt8 freeTextureUnit; material->Apply(pipelineInstance);
material->Apply(pipelineInstance, 0, &freeTextureUnit);
ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap; ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap;
@ -688,8 +687,8 @@ namespace Nz
} }
// Sends the uniforms // Sends the uniforms
for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset * i, freeTextureUnit + i); SendLightUniforms(shader, shaderUniforms->lightUniforms, i, lightIndex++, shaderUniforms->lightOffset * i);
} }
const Matrix4f* instanceMatrices = &instances[0]; const Matrix4f* instanceMatrices = &instances[0];
@ -747,8 +746,8 @@ namespace Nz
} }
// Sends the light uniforms to the shader // Sends the light uniforms to the shader
for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i); SendLightUniforms(shader, shaderUniforms->lightUniforms, i, lightIndex++, shaderUniforms->lightOffset*i);
// And we draw // And we draw
drawFunc(meshData.primitiveMode, 0, indexCount); drawFunc(meshData.primitiveMode, 0, indexCount);
@ -812,8 +811,7 @@ namespace Nz
} }
// We begin to apply the material // We begin to apply the material
UInt8 freeTextureUnit; material->Apply(*pipelineInstance);
material->Apply(*pipelineInstance, 0, &freeTextureUnit);
// Uniforms are conserved in our program, there's no point to send them back until they change // Uniforms are conserved in our program, there's no point to send them back until they change
const Shader* shader = pipelineInstance->uberInstance->GetShader(); const Shader* shader = pipelineInstance->uberInstance->GetShader();
@ -833,7 +831,7 @@ namespace Nz
lightCount = std::min(m_renderQueue.directionalLights.size(), static_cast<decltype(m_renderQueue.directionalLights.size())>(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS)); lightCount = std::min(m_renderQueue.directionalLights.size(), static_cast<decltype(m_renderQueue.directionalLights.size())>(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
for (std::size_t i = 0; i < lightCount; ++i) for (std::size_t i = 0; i < lightCount; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset * i, freeTextureUnit++); SendLightUniforms(shader, shaderUniforms->lightUniforms, i, i, shaderUniforms->lightOffset * i);
} }
lastShader = shader; lastShader = shader;
@ -872,7 +870,7 @@ namespace Nz
ChooseLights(Spheref(position, radius), false); ChooseLights(Spheref(position, radius), false);
for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i) for (std::size_t i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, shaderUniforms->lightOffset*i, freeTextureUnit++); SendLightUniforms(shader, shaderUniforms->lightUniforms, i, i, shaderUniforms->lightOffset*i);
} }
Renderer::SetMatrix(MatrixType_World, matrix); Renderer::SetMatrix(MatrixType_World, matrix);
@ -915,9 +913,7 @@ namespace Nz
uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1"); uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2"); uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
uniforms.lightUniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3"); uniforms.lightUniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3");
uniforms.lightUniforms.locations.pointLightShadowMap = shader->GetUniformLocation("PointLightShadowMap[0]");
uniforms.lightUniforms.locations.shadowMapping = shader->GetUniformLocation("Lights[0].shadowMapping"); uniforms.lightUniforms.locations.shadowMapping = shader->GetUniformLocation("Lights[0].shadowMapping");
uniforms.lightUniforms.locations.directionalSpotLightShadowMap = shader->GetUniformLocation("DirectionalSpotLightShadowMap[0]");
} }
else else
uniforms.hasLightUniforms = false; uniforms.hasLightUniforms = false;
@ -939,6 +935,107 @@ namespace Nz
m_shaderUniforms.erase(shader); m_shaderUniforms.erase(shader);
} }
/*!
* \brief Sends the uniforms for light
*
* \param shader Shader to send uniforms to
* \param uniforms Uniforms to send
* \param index Index of the light
* \param uniformOffset Offset for the uniform
* \param availableTextureUnit Unit texture available
*/
void ForwardRenderTechnique::SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int lightIndex, unsigned int uniformOffset) const
{
if (lightIndex < m_lights.size())
{
const LightIndex& lightInfo = m_lights[lightIndex];
shader->SendInteger(uniforms.locations.type + uniformOffset, lightInfo.type); //< Sends the light type
switch (lightInfo.type)
{
case LightType_Directional:
{
const auto& light = m_renderQueue.directionalLights[lightInfo.index];
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.direction));
if (uniforms.locations.shadowMapping != -1)
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
if (light.shadowMap)
{
unsigned int textureUnit2D = Material::GetTextureUnit(static_cast<TextureMap>(TextureMap_Shadow2D_1 + index));
Renderer::SetTexture(textureUnit2D, light.shadowMap);
Renderer::SetTextureSampler(textureUnit2D, s_shadowSampler);
if (uniforms.locations.lightViewProjMatrix != -1)
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
}
break;
}
case LightType_Point:
{
const auto& light = m_renderQueue.pointLights[lightInfo.index];
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.position, light.attenuation));
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, Vector4f(0.f, 0.f, 0.f, light.invRadius));
if (uniforms.locations.shadowMapping != -1)
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
unsigned int textureUnit = Material::GetTextureUnit(static_cast<TextureMap>(TextureMap_ShadowCube_1 + index));
if (light.shadowMap)
{
unsigned int textureUnitCube = Material::GetTextureUnit(static_cast<TextureMap>(TextureMap_ShadowCube_1 + index));
Renderer::SetTexture(textureUnitCube, light.shadowMap);
Renderer::SetTextureSampler(textureUnitCube, s_shadowSampler);
}
break;
}
case LightType_Spot:
{
const auto& light = m_renderQueue.spotLights[lightInfo.index];
shader->SendColor(uniforms.locations.color + uniformOffset, light.color);
shader->SendVector(uniforms.locations.factors + uniformOffset, Vector2f(light.ambientFactor, light.diffuseFactor));
shader->SendVector(uniforms.locations.parameters1 + uniformOffset, Vector4f(light.position, light.attenuation));
shader->SendVector(uniforms.locations.parameters2 + uniformOffset, Vector4f(light.direction, light.invRadius));
shader->SendVector(uniforms.locations.parameters3 + uniformOffset, Vector2f(light.innerAngleCosine, light.outerAngleCosine));
if (uniforms.locations.shadowMapping != -1)
shader->SendBoolean(uniforms.locations.shadowMapping + uniformOffset, light.shadowMap != nullptr);
unsigned int textureUnit = Material::GetTextureUnit(static_cast<TextureMap>(TextureMap_Shadow2D_1 + index));
if (light.shadowMap)
{
unsigned int textureUnit2D = Material::GetTextureUnit(static_cast<TextureMap>(TextureMap_Shadow2D_1 + index));
Renderer::SetTexture(textureUnit2D, light.shadowMap);
Renderer::SetTextureSampler(textureUnit2D, s_shadowSampler);
if (uniforms.locations.lightViewProjMatrix != -1)
shader->SendMatrix(uniforms.locations.lightViewProjMatrix + index, light.transformMatrix);
}
break;
}
}
}
else
{
if (uniforms.locations.type != -1)
shader->SendInteger(uniforms.locations.type + uniformOffset, -1); //< Disable the light in the shader
}
}
IndexBuffer ForwardRenderTechnique::s_quadIndexBuffer; IndexBuffer ForwardRenderTechnique::s_quadIndexBuffer;
TextureSampler ForwardRenderTechnique::s_shadowSampler; TextureSampler ForwardRenderTechnique::s_shadowSampler;
VertexBuffer ForwardRenderTechnique::s_quadVertexBuffer; VertexBuffer ForwardRenderTechnique::s_quadVertexBuffer;

View File

@ -36,7 +36,7 @@ namespace Nz
* \param textureUnit Unit for the texture GL_TEXTURE"i" * \param textureUnit Unit for the texture GL_TEXTURE"i"
* \param lastUsedUnit Optional argument to get the last texture unit * \param lastUsedUnit Optional argument to get the last texture unit
*/ */
void Material::Apply(const MaterialPipeline::Instance& instance, UInt8 textureUnit, UInt8* lastUsedUnit) const void Material::Apply(const MaterialPipeline::Instance& instance) const
{ {
const Shader* shader = instance.renderPipeline.GetInfo().shader; const Shader* shader = instance.renderPipeline.GetInfo().shader;
@ -57,54 +57,51 @@ namespace Nz
if (m_alphaMap && instance.uniforms[MaterialUniform_AlphaMap] != -1) if (m_alphaMap && instance.uniforms[MaterialUniform_AlphaMap] != -1)
{ {
unsigned int textureUnit = s_textureUnits[TextureMap_Alpha];
Renderer::SetTexture(textureUnit, m_alphaMap); Renderer::SetTexture(textureUnit, m_alphaMap);
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
shader->SendInteger(instance.uniforms[MaterialUniform_AlphaMap], textureUnit);
textureUnit++;
} }
if (m_diffuseMap && instance.uniforms[MaterialUniform_DiffuseMap] != -1) if (m_diffuseMap && instance.uniforms[MaterialUniform_DiffuseMap] != -1)
{ {
unsigned int textureUnit = s_textureUnits[TextureMap_Diffuse];
Renderer::SetTexture(textureUnit, m_diffuseMap); Renderer::SetTexture(textureUnit, m_diffuseMap);
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
shader->SendInteger(instance.uniforms[MaterialUniform_DiffuseMap], textureUnit);
textureUnit++;
} }
if (m_emissiveMap && instance.uniforms[MaterialUniform_EmissiveMap] != -1) if (m_emissiveMap && instance.uniforms[MaterialUniform_EmissiveMap] != -1)
{ {
unsigned int textureUnit = s_textureUnits[TextureMap_Emissive];
Renderer::SetTexture(textureUnit, m_emissiveMap); Renderer::SetTexture(textureUnit, m_emissiveMap);
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
shader->SendInteger(instance.uniforms[MaterialUniform_EmissiveMap], textureUnit);
textureUnit++;
} }
if (m_heightMap && instance.uniforms[MaterialUniform_HeightMap] != -1) if (m_heightMap && instance.uniforms[MaterialUniform_HeightMap] != -1)
{ {
unsigned int textureUnit = s_textureUnits[TextureMap_Height];
Renderer::SetTexture(textureUnit, m_heightMap); Renderer::SetTexture(textureUnit, m_heightMap);
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
shader->SendInteger(instance.uniforms[MaterialUniform_HeightMap], textureUnit);
textureUnit++;
} }
if (m_normalMap && instance.uniforms[MaterialUniform_NormalMap] != -1) if (m_normalMap && instance.uniforms[MaterialUniform_NormalMap] != -1)
{ {
unsigned int textureUnit = s_textureUnits[TextureMap_Normal];
Renderer::SetTexture(textureUnit, m_normalMap); Renderer::SetTexture(textureUnit, m_normalMap);
Renderer::SetTextureSampler(textureUnit, m_diffuseSampler); Renderer::SetTextureSampler(textureUnit, m_diffuseSampler);
shader->SendInteger(instance.uniforms[MaterialUniform_NormalMap], textureUnit);
textureUnit++;
} }
if (m_specularMap && instance.uniforms[MaterialUniform_SpecularMap] != -1) if (m_specularMap && instance.uniforms[MaterialUniform_SpecularMap] != -1)
{ {
unsigned int textureUnit = s_textureUnits[TextureMap_Specular];
Renderer::SetTexture(textureUnit, m_specularMap); Renderer::SetTexture(textureUnit, m_specularMap);
Renderer::SetTextureSampler(textureUnit, m_specularSampler); Renderer::SetTextureSampler(textureUnit, m_specularSampler);
shader->SendInteger(instance.uniforms[MaterialUniform_SpecularMap], textureUnit);
textureUnit++;
} }
if (lastUsedUnit)
*lastUsedUnit = textureUnit;
} }
/*! /*!
@ -459,6 +456,23 @@ namespace Nz
s_defaultMaterial->SetFaceFilling(FaceFilling_Line); s_defaultMaterial->SetFaceFilling(FaceFilling_Line);
MaterialLibrary::Register("Default", s_defaultMaterial); MaterialLibrary::Register("Default", s_defaultMaterial);
unsigned int textureUnit = 0;
s_textureUnits[TextureMap_Diffuse] = textureUnit++;
s_textureUnits[TextureMap_Alpha] = textureUnit++;
s_textureUnits[TextureMap_Specular] = textureUnit++;
s_textureUnits[TextureMap_Normal] = textureUnit++;
s_textureUnits[TextureMap_Emissive] = textureUnit++;
s_textureUnits[TextureMap_Overlay] = textureUnit++;
s_textureUnits[TextureMap_ReflectionCube] = textureUnit++;
s_textureUnits[TextureMap_Height] = textureUnit++;
s_textureUnits[TextureMap_Shadow2D_1] = textureUnit++;
s_textureUnits[TextureMap_ShadowCube_1] = textureUnit++;
s_textureUnits[TextureMap_Shadow2D_2] = textureUnit++;
s_textureUnits[TextureMap_ShadowCube_2] = textureUnit++;
s_textureUnits[TextureMap_Shadow2D_3] = textureUnit++;
s_textureUnits[TextureMap_ShadowCube_3] = textureUnit++;
return true; return true;
} }
@ -473,6 +487,7 @@ namespace Nz
MaterialLibrary::Uninitialize(); MaterialLibrary::Uninitialize();
} }
std::array<int, TextureMap_Max + 1> Material::s_textureUnits;
MaterialLibrary::LibraryMap Material::s_library; MaterialLibrary::LibraryMap Material::s_library;
MaterialLoader::LoaderList Material::s_loaders; MaterialLoader::LoaderList Material::s_loaders;
MaterialManager::ManagerMap Material::s_managerMap; MaterialManager::ManagerMap Material::s_managerMap;

View File

@ -3,12 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/MaterialPipeline.hpp> #include <Nazara/Graphics/MaterialPipeline.hpp>
#include <Nazara/Graphics/Material.hpp>
#ifndef NAZARA_RENDERER_OPENGL
#define NAZARA_RENDERER_OPENGL // Mandatory to include the OpenGL headers
#endif
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/UberShaderPreprocessor.hpp> #include <Nazara/Renderer/UberShaderPreprocessor.hpp>
#include <Nazara/Graphics/Debug.hpp> #include <Nazara/Graphics/Debug.hpp>
@ -106,6 +101,25 @@ namespace Nz
CacheUniform(SpecularMap); CacheUniform(SpecularMap);
#undef CacheUniform #undef CacheUniform
// Send texture units (those never changes)
renderPipelineInfo.shader->SendInteger(instance.uniforms[MaterialUniform_AlphaMap], Material::GetTextureUnit(TextureMap_Alpha));
renderPipelineInfo.shader->SendInteger(instance.uniforms[MaterialUniform_DiffuseMap], Material::GetTextureUnit(TextureMap_Diffuse));
renderPipelineInfo.shader->SendInteger(instance.uniforms[MaterialUniform_EmissiveMap], Material::GetTextureUnit(TextureMap_Emissive));
renderPipelineInfo.shader->SendInteger(instance.uniforms[MaterialUniform_HeightMap], Material::GetTextureUnit(TextureMap_Height));
renderPipelineInfo.shader->SendInteger(instance.uniforms[MaterialUniform_NormalMap], Material::GetTextureUnit(TextureMap_Normal));
renderPipelineInfo.shader->SendInteger(instance.uniforms[MaterialUniform_SpecularMap], Material::GetTextureUnit(TextureMap_Specular));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("ReflectionMap"), Material::GetTextureUnit(TextureMap_ReflectionCube));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("TextureOverlay"), Material::GetTextureUnit(TextureMap_Overlay));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[0]"), Material::GetTextureUnit(TextureMap_Shadow2D_1));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[1]"), Material::GetTextureUnit(TextureMap_Shadow2D_2));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("DirectionalSpotLightShadowMap[2]"), Material::GetTextureUnit(TextureMap_Shadow2D_3));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[0]"), Material::GetTextureUnit(TextureMap_ShadowCube_1));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[1]"), Material::GetTextureUnit(TextureMap_ShadowCube_2));
renderPipelineInfo.shader->SendInteger(renderPipelineInfo.shader->GetUniformLocation("PointLightShadowMap[2]"), Material::GetTextureUnit(TextureMap_ShadowCube_3));
} }
bool MaterialPipeline::Initialize() bool MaterialPipeline::Initialize()