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

@@ -318,7 +318,7 @@ namespace Nz
// Index of uniforms in the shader
shaderUniforms = GetShaderUniforms(shader);
// Ambiant color of the scene
// Ambient color of the scene
shader->SendColor(shaderUniforms->sceneAmbient, sceneData.ambientColor);
// Position of the camera
shader->SendVector(shaderUniforms->eyePosition, sceneData.viewer->GetEyePosition());
@@ -333,13 +333,13 @@ namespace Nz
if (matEntry.enabled)
{
UInt8 overlayUnit;
material->Apply(pipelineInstance, 0, &overlayUnit);
overlayUnit++;
material->Apply(pipelineInstance);
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;
for (auto& overlayIt : overlayMap)
@@ -350,7 +350,7 @@ namespace Nz
std::size_t spriteChainCount = spriteChainVector.size();
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 spriteChainOffset = 0; // Where was the last offset where we stopped in the last chain
@@ -616,8 +616,7 @@ namespace Nz
if (matEntry.enabled)
{
UInt8 freeTextureUnit;
material->Apply(pipelineInstance, 0, &freeTextureUnit);
material->Apply(pipelineInstance);
ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap;
@@ -688,8 +687,8 @@ namespace Nz
}
// Sends the uniforms
for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset * i, freeTextureUnit + i);
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, lightIndex++, shaderUniforms->lightOffset * i);
}
const Matrix4f* instanceMatrices = &instances[0];
@@ -747,8 +746,8 @@ namespace Nz
}
// Sends the light uniforms to the shader
for (std::size_t i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, lightIndex++, shaderUniforms->lightOffset*i, freeTextureUnit + i);
for (unsigned int i = 0; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
SendLightUniforms(shader, shaderUniforms->lightUniforms, i, lightIndex++, shaderUniforms->lightOffset*i);
// And we draw
drawFunc(meshData.primitiveMode, 0, indexCount);
@@ -812,8 +811,7 @@ namespace Nz
}
// We begin to apply the material
UInt8 freeTextureUnit;
material->Apply(*pipelineInstance, 0, &freeTextureUnit);
material->Apply(*pipelineInstance);
// Uniforms are conserved in our program, there's no point to send them back until they change
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));
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;
@@ -872,7 +870,7 @@ namespace Nz
ChooseLights(Spheref(position, radius), false);
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);
@@ -915,9 +913,7 @@ namespace Nz
uniforms.lightUniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
uniforms.lightUniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
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.directionalSpotLightShadowMap = shader->GetUniformLocation("DirectionalSpotLightShadowMap[0]");
}
else
uniforms.hasLightUniforms = false;
@@ -939,6 +935,107 @@ namespace Nz
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;
TextureSampler ForwardRenderTechnique::s_shadowSampler;
VertexBuffer ForwardRenderTechnique::s_quadVertexBuffer;