Graphics/Shader: Make texture units statics
Provides better performances and prevents the sampler type bug to happen
This commit is contained in:
parent
1a8805aad1
commit
682dab32b3
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -178,4 +192,4 @@ namespace Nz
|
||||||
|
|
||||||
MaterialPipelineLibrary::LibraryMap MaterialPipeline::s_library;
|
MaterialPipelineLibrary::LibraryMap MaterialPipeline::s_library;
|
||||||
MaterialPipeline::PipelineCache MaterialPipeline::s_pipelineCache;
|
MaterialPipeline::PipelineCache MaterialPipeline::s_pipelineCache;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue