Added sprite overlay rendering

Former-commit-id: 1e25a7d85f06f4a4bc3ed0ead76df01db440671d
This commit is contained in:
Lynix
2015-01-07 19:27:15 +01:00
parent 6c4f8e7396
commit 9293022e71
14 changed files with 192 additions and 111 deletions

View File

@@ -166,6 +166,7 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const NzShader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
NzRenderer::SetIndexBuffer(m_indexBuffer);
NzRenderer::SetMatrix(nzMatrixType_World, NzMatrix4f::Identity());
@@ -174,61 +175,84 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
for (auto& matIt : m_renderQueue.basicSprites)
{
const NzMaterial* material = matIt.first;
auto& spriteChainVector = matIt.second;
auto& overlayMap = matIt.second;
unsigned int spriteChainCount = spriteChainVector.size();
if (spriteChainCount > 0)
for (auto& overlayIt : overlayMap)
{
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
const NzShader* shader = material->Apply(nzShaderFlags_VertexColor);
const NzTexture* overlay = overlayIt.first;
auto& spriteChainVector = overlayIt.second;
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (shader != lastShader)
unsigned int spriteChainCount = spriteChainVector.size();
if (spriteChainCount > 0)
{
// Couleur ambiante de la scène
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
// On commence par appliquer du matériau (et récupérer le shader ainsi activé)
nzUInt32 flags = nzShaderFlags_VertexColor;
if (overlay)
flags |= nzShaderFlags_TextureOverlay;
lastShader = shader;
}
nzUInt8 overlayUnit;
const NzShader* shader = material->Apply(flags, 0, &overlayUnit);
unsigned int spriteChain = 0; // Quelle chaîne de sprite traitons-nous
unsigned int spriteChainOffset = 0; // À quel offset dans la dernière chaîne nous sommes-nous arrêtés
do
{
// On ouvre le buffer en écriture
NzBufferMapper<NzVertexBuffer> vertexMapper(m_spriteBuffer, nzBufferAccess_DiscardAndWrite);
NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<NzVertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
unsigned int spriteCount = 0;
if (overlay)
{
NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
unsigned int count = std::min(s_maxSprites - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::memcpy(vertices, currentChain.vertices + spriteChainOffset*4, 4*count*sizeof(NzVertexStruct_XYZ_Color_UV));
vertices += count*4;
spriteCount += count;
spriteChainOffset += count;
// Avons-nous traité la chaîne entière ?
if (spriteChainOffset == currentChain.spriteCount)
{
spriteChain++;
spriteChainOffset = 0;
}
overlayUnit++;
NzRenderer::SetTexture(overlayUnit, overlay);
NzRenderer::SetTextureSampler(overlayUnit, material->GetDiffuseSampler());
}
while (spriteCount < s_maxSprites && spriteChain < spriteChainCount);
vertexMapper.Unmap();
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (shader != lastShader)
{
// Index des uniformes dans le shader
shaderUniforms = GetShaderUniforms(shader);
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6);
// Couleur ambiante de la scène
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Overlay
shader->SendInteger(shaderUniforms->textureOverlay, overlayUnit);
// Position de la caméra
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
lastShader = shader;
}
unsigned int spriteChain = 0; // Quelle chaîne de sprite traitons-nous
unsigned int spriteChainOffset = 0; // À quel offset dans la dernière chaîne nous sommes-nous arrêtés
do
{
// On ouvre le buffer en écriture
NzBufferMapper<NzVertexBuffer> vertexMapper(m_spriteBuffer, nzBufferAccess_DiscardAndWrite);
NzVertexStruct_XYZ_Color_UV* vertices = reinterpret_cast<NzVertexStruct_XYZ_Color_UV*>(vertexMapper.GetPointer());
unsigned int spriteCount = 0;
{
NzForwardRenderQueue::SpriteChain_XYZ_Color_UV& currentChain = spriteChainVector[spriteChain];
unsigned int count = std::min(s_maxSprites - spriteCount, currentChain.spriteCount - spriteChainOffset);
std::memcpy(vertices, currentChain.vertices + spriteChainOffset*4, 4*count*sizeof(NzVertexStruct_XYZ_Color_UV));
vertices += count*4;
spriteCount += count;
spriteChainOffset += count;
// Avons-nous traité la chaîne entière ?
if (spriteChainOffset == currentChain.spriteCount)
{
spriteChain++;
spriteChainOffset = 0;
}
}
while (spriteCount < s_maxSprites && spriteChain < spriteChainCount);
vertexMapper.Unmap();
NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode_TriangleList, 0, spriteCount*6);
}
while (spriteChain < spriteChainCount);
spriteChainVector.clear();
}
while (spriteChain < spriteChainCount);
spriteChainVector.clear();
}
}
}
@@ -236,8 +260,8 @@ void NzForwardRenderTechnique::DrawBasicSprites(const NzScene* scene) const
void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const LightUniforms* lightUniforms = nullptr;
const NzShader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
for (auto& matIt : m_renderQueue.opaqueModels)
{
@@ -262,14 +286,14 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (shader != lastShader)
{
// Index des uniformes dans le shader
shaderUniforms = GetShaderUniforms(shader);
// Couleur ambiante de la scène
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
// Index des uniformes d'éclairage dans le shader
lightUniforms = GetLightUniforms(shader);
lastShader = shader;
}
@@ -321,7 +345,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
unsigned int passCount = (lightCount == 0) ? 1 : (lightCount-1)/NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS + 1;
for (unsigned int pass = 0; pass < passCount; ++pass)
{
if (lightUniforms->exists)
if (shaderUniforms->hasLightUniforms)
{
unsigned int renderedLightCount = std::min(lightCount, NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
lightCount -= renderedLightCount;
@@ -338,10 +362,10 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
}
for (unsigned int i = 0; i < renderedLightCount; ++i)
m_directionalLights.GetLight(lightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
m_directionalLights.GetLight(lightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
}
const NzMatrix4f* instanceMatrices = &instances[0];
@@ -369,7 +393,7 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
}
else
{
if (lightUniforms->exists)
if (shaderUniforms->hasLightUniforms)
{
for (const NzMatrix4f& matrix : instances)
{
@@ -403,14 +427,14 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
for (unsigned int i = 0; i < renderedLightCount; ++i)
{
if (directionalLightIndex >= directionalLightCount)
m_lights.GetResult(otherLightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
m_lights.GetResult(otherLightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
else
m_directionalLights.GetLight(directionalLightIndex++)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
m_directionalLights.GetLight(directionalLightIndex++)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
}
// On désactive l'éventuel surplus
for (unsigned int i = renderedLightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
// Et on passe à l'affichage
DrawFunc(meshData.primitiveMode, 0, indexCount);
@@ -438,8 +462,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
}
// Et on remet à zéro les données
renderQueueInstancing = false;
used = false;
renderQueueInstancing = false;
}
}
}
@@ -447,8 +471,8 @@ void NzForwardRenderTechnique::DrawOpaqueModels(const NzScene* scene) const
void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
{
NzAbstractViewer* viewer = scene->GetViewer();
const LightUniforms* lightUniforms = nullptr;
const NzShader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
unsigned int lightCount = 0;
for (unsigned int index : m_renderQueue.transparentModels)
@@ -464,18 +488,18 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
// Les uniformes sont conservées au sein d'un programme, inutile de les renvoyer tant qu'il ne change pas
if (shader != lastShader)
{
// Index des uniformes dans le shader
shaderUniforms = GetShaderUniforms(shader);
// Couleur ambiante de la scène
shader->SendColor(shader->GetUniformLocation(nzShaderUniform_SceneAmbient), scene->GetAmbientColor());
// Position de la caméra
shader->SendVector(shader->GetUniformLocation(nzShaderUniform_EyePosition), viewer->GetEyePosition());
// Index des uniformes d'éclairage dans le shader
lightUniforms = GetLightUniforms(shader);
// On envoie les lumières directionnelles s'il y a (Les mêmes pour tous)
lightCount = std::min(m_directionalLights.GetLightCount(), NazaraSuffixMacro(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS, U));
for (unsigned int i = 0; i < lightCount; ++i)
m_directionalLights.GetLight(i)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
m_directionalLights.GetLight(i)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
lastShader = shader;
}
@@ -510,45 +534,46 @@ void NzForwardRenderTechnique::DrawTransparentModels(const NzScene* scene) const
{
unsigned int count = std::min(NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS - lightCount, m_lights.ComputeClosestLights(matrix.GetTranslation() + modelData.boundingSphere.GetPosition(), modelData.boundingSphere.radius, NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS));
for (unsigned int i = 0; i < count; ++i)
m_lights.GetResult(i)->Enable(shader, lightUniforms->uniforms, lightUniforms->offset*(lightCount++));
m_lights.GetResult(i)->Enable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*(lightCount++));
}
for (unsigned int i = lightCount; i < NAZARA_GRAPHICS_MAX_LIGHT_PER_PASS; ++i)
NzLight::Disable(shader, lightUniforms->uniforms, lightUniforms->offset*i);
NzLight::Disable(shader, shaderUniforms->lightUniforms, shaderUniforms->lightOffset*i);
NzRenderer::SetMatrix(nzMatrixType_World, matrix);
DrawFunc(meshData.primitiveMode, 0, indexCount);
}
}
const NzForwardRenderTechnique::LightUniforms* NzForwardRenderTechnique::GetLightUniforms(const NzShader* shader) const
const NzForwardRenderTechnique::ShaderUniforms* NzForwardRenderTechnique::GetShaderUniforms(const NzShader* shader) const
{
auto it = m_lightUniforms.find(shader);
if (it != m_lightUniforms.end())
auto it = m_shaderUniforms.find(shader);
if (it != m_shaderUniforms.end())
return &(it->second);
else
{
ShaderUniforms uniforms;
uniforms.textureOverlay = shader->GetUniformLocation("TextureOverlay");
int type0Location = shader->GetUniformLocation("Lights[0].type");
int type1Location = shader->GetUniformLocation("Lights[1].type");
LightUniforms lightUniforms;
if (type0Location > 0 && type1Location > 0)
{
lightUniforms.exists = true;
lightUniforms.offset = type1Location - type0Location;
lightUniforms.uniforms.ubo = false;
lightUniforms.uniforms.locations.type = type0Location;
lightUniforms.uniforms.locations.color = shader->GetUniformLocation("Lights[0].color");
lightUniforms.uniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors");
lightUniforms.uniforms.locations.parameters1 = shader->GetUniformLocation("Lights[0].parameters1");
lightUniforms.uniforms.locations.parameters2 = shader->GetUniformLocation("Lights[0].parameters2");
lightUniforms.uniforms.locations.parameters3 = shader->GetUniformLocation("Lights[0].parameters3");
uniforms.hasLightUniforms = true;
uniforms.lightOffset = type1Location - type0Location;
uniforms.lightUniforms.ubo = false;
uniforms.lightUniforms.locations.type = type0Location;
uniforms.lightUniforms.locations.color = shader->GetUniformLocation("Lights[0].color");
uniforms.lightUniforms.locations.factors = shader->GetUniformLocation("Lights[0].factors");
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");
}
else
lightUniforms.exists = false;
uniforms.hasLightUniforms = false;
auto pair = m_lightUniforms.emplace(shader, lightUniforms);
auto pair = m_shaderUniforms.emplace(shader, uniforms);
return &(pair.first->second);
}
}