Graphics: Add basic reflection mapping

This commit is contained in:
Lynix 2016-12-18 01:18:48 +01:00
parent 459c5e7a09
commit 37d36a89a6
10 changed files with 104 additions and 26 deletions

View File

@ -92,6 +92,7 @@ namespace Ndk
material.BindMethod("EnableDepthSorting", &Nz::Material::EnableDepthSorting);
material.BindMethod("EnableDepthWrite", &Nz::Material::EnableDepthWrite);
material.BindMethod("EnableFaceCulling", &Nz::Material::EnableFaceCulling);
material.BindMethod("EnableReflectionMapping", &Nz::Material::EnableReflectionMapping);
material.BindMethod("EnableScissorTest", &Nz::Material::EnableScissorTest);
material.BindMethod("EnableShadowCasting", &Nz::Material::EnableShadowCasting);
material.BindMethod("EnableShadowReceive", &Nz::Material::EnableShadowReceive);
@ -139,6 +140,7 @@ namespace Ndk
material.BindMethod("IsDepthSortingEnabled", &Nz::Material::IsDepthSortingEnabled);
material.BindMethod("IsDepthWriteEnabled", &Nz::Material::IsDepthWriteEnabled);
material.BindMethod("IsFaceCullingEnabled", &Nz::Material::IsFaceCullingEnabled);
material.BindMethod("IsReflectionMappingEnabled", &Nz::Material::IsReflectionMappingEnabled);
material.BindMethod("IsScissorTestEnabled", &Nz::Material::IsScissorTestEnabled);
material.BindMethod("IsStencilTestEnabled", &Nz::Material::IsStencilTestEnabled);
material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled);

View File

@ -4,6 +4,7 @@
#include <NDK/Systems/RenderSystem.hpp>
#include <Nazara/Graphics/ColorBackground.hpp>
#include <Nazara/Graphics/SkyboxBackground.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <NDK/Components/CameraComponent.hpp>
@ -181,7 +182,7 @@ namespace Ndk
GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();
graphicsComponent.EnsureBoundingVolumeUpdate();
}
bool forceInvalidation = false;
std::size_t visibilityHash = m_drawableCulling.Cull(camComponent.GetFrustum(), &forceInvalidation);
@ -220,8 +221,12 @@ namespace Ndk
Nz::SceneData sceneData;
sceneData.ambientColor = Nz::Color(25, 25, 25);
sceneData.background = m_background;
sceneData.globalReflectionTexture = nullptr;
sceneData.viewer = &camComponent;
if (m_background && m_background->GetBackgroundType() == Nz::BackgroundType_Skybox)
sceneData.globalReflectionTexture = static_cast<Nz::SkyboxBackground*>(m_background.Get())->GetTexture();
m_renderTechnique->Clear(sceneData);
m_renderTechnique->Draw(sceneData);
}

View File

@ -76,6 +76,7 @@ namespace Nz
// Other uniforms
int eyePosition;
int reflectionMap;
int sceneAmbient;
int textureOverlay;
};
@ -90,6 +91,8 @@ namespace Nz
unsigned int m_maxLightPassPerObject;
static IndexBuffer s_quadIndexBuffer;
static Texture s_dummyReflection;
static TextureSampler s_reflectionSampler;
static TextureSampler s_shadowSampler;
static VertexBuffer s_quadVertexBuffer;
static VertexDeclaration s_billboardInstanceDeclaration;

View File

@ -79,6 +79,7 @@ namespace Nz
inline void EnableDepthSorting(bool depthSorting);
inline void EnableDepthWrite(bool depthWrite);
inline void EnableFaceCulling(bool faceCulling);
inline void EnableReflectionMapping(bool reflection);
inline void EnableScissorTest(bool scissorTest);
inline void EnableShadowCasting(bool castShadows);
inline void EnableShadowReceive(bool receiveShadows);
@ -128,6 +129,7 @@ namespace Nz
inline bool IsDepthSortingEnabled() const;
inline bool IsDepthWriteEnabled() const;
inline bool IsFaceCullingEnabled() const;
inline bool IsReflectionMappingEnabled() const;
inline bool IsScissorTestEnabled() const;
inline bool IsStencilTestEnabled() const;
inline bool IsShadowCastingEnabled() const;

View File

@ -146,7 +146,7 @@ namespace Nz
/*!
* \brief Enable/Disable alpha test for this material
*
* When enabled, all objects using this material will be rendered using alpha testing,
* When enabled, all objects using this material will be rendered using alpha testing,
* rejecting pixels if their alpha component is under a defined threshold.
* This allows some kind of transparency with a much cheaper cost as it doesn't prevent any optimization (as deferred rendering or batching).
*
@ -252,7 +252,7 @@ namespace Nz
* When enabled, and if depth buffer is enabled and present, all fragments generated with this material will write
* to the depth buffer if they pass depth test.
*
* This is usually disabled with translucent objects, as depth test is wanted to prevent them from rendering on top of opaque objects but
* This is usually disabled with translucent objects, as depth test is wanted to prevent them from rendering on top of opaque objects but
* not depth writing (which could make other translucent fragments to fail depth test)
*
* \param depthBuffer Defines if this material will use depth write
@ -291,6 +291,31 @@ namespace Nz
InvalidatePipeline();
}
/*!
* \brief Enable/Disable reflection mapping for this material
*
* When enabled, the material will render reflections from the object environment according to the reflection mode.
* Whether or not this is expensive depends of the reflection mode and size.
*
* Please note this is only a hint for the render technique, and reflections can be forcefully enabled or disabled depending on the material shader.
*
* Use SetReflectionMode and SetReflectionSize to control reflection quality.
*
* \param reflection Defines if this material should use reflection mapping
*
* \remark May invalidates the pipeline
*
* \see IsReflectionMappingEnabled
* \see SetReflectionMode
* \see SetReflectionSize
*/
inline void Material::EnableReflectionMapping(bool reflection)
{
m_pipelineInfo.reflectionMapping = reflection;
InvalidatePipeline();
}
/*!
* \brief Enable/Disable scissor test for this material
*
@ -782,6 +807,17 @@ namespace Nz
return m_pipelineInfo.faceCulling;
}
/*!
* \brief Checks whether this material has reflection mapping enabled
* \return true If it is the case
*
* \see EnableReflectionMapping
*/
inline bool Material::IsReflectionMappingEnabled() const
{
return m_pipelineInfo.reflectionMapping;
}
/*!
* \brief Checks whether this material has scissor test enabled
* \return true If it is the case

View File

@ -20,15 +20,16 @@ namespace Nz
{
struct MaterialPipelineInfo : RenderStates
{
bool alphaTest = false;
bool depthSorting = false;
bool hasAlphaMap = false;
bool hasDiffuseMap = false;
bool hasEmissiveMap = false;
bool hasHeightMap = false;
bool hasNormalMap = false;
bool hasSpecularMap = false;
bool shadowReceive = true;
bool alphaTest = false;
bool depthSorting = false;
bool hasAlphaMap = false;
bool hasDiffuseMap = false;
bool hasEmissiveMap = false;
bool hasHeightMap = false;
bool hasNormalMap = false;
bool hasSpecularMap = false;
bool reflectionMapping = false;
bool shadowReceive = true;
UberShaderConstRef uberShader;
};

View File

@ -72,6 +72,7 @@ namespace Nz
NazaraPipelineBoolMember(hasHeightMap);
NazaraPipelineBoolMember(hasNormalMap);
NazaraPipelineBoolMember(hasSpecularMap);
NazaraPipelineBoolMember(reflectionMapping);
NazaraPipelineBoolMember(shadowReceive);
NazaraPipelineMember(uberShader);
@ -127,6 +128,7 @@ namespace std
NazaraPipelineBoolMember(hasHeightMap);
NazaraPipelineBoolMember(hasNormalMap);
NazaraPipelineBoolMember(hasSpecularMap);
NazaraPipelineBoolMember(reflectionMapping);
NazaraPipelineBoolMember(shadowReceive);
NazaraPipelineMember(uberShader);

View File

@ -13,12 +13,14 @@ namespace Nz
{
class AbstractBackground;
class AbstractViewer;
class Texture;
struct SceneData
{
Color ambientColor;
const AbstractBackground* background;
const AbstractViewer* viewer;
Texture* globalReflectionTexture;
};
}

View File

@ -214,8 +214,15 @@ namespace Nz
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData1, ComponentType_Float4, NazaraOffsetOf(ForwardRenderQueue::BillboardData, size)); // Englobe sincos
s_billboardInstanceDeclaration.EnableComponent(VertexComponent_InstanceData2, ComponentType_Color, NazaraOffsetOf(ForwardRenderQueue::BillboardData, color));
s_reflectionSampler.SetFilterMode(SamplerFilter_Bilinear);
s_reflectionSampler.SetWrapMode(SamplerWrap_Clamp);
s_shadowSampler.SetFilterMode(SamplerFilter_Bilinear);
s_shadowSampler.SetWrapMode(SamplerWrap_Clamp);
std::array<UInt8, 6> whitePixels = { { 255, 255, 255, 255, 255, 255 } };
s_dummyReflection.Create(ImageType_Cubemap, PixelFormatType_L8, 1, 1);
s_dummyReflection.Update(whitePixels.data());
}
catch (const std::exception& e)
{
@ -232,6 +239,7 @@ namespace Nz
void ForwardRenderTechnique::Uninitialize()
{
s_dummyReflection.Destroy();
s_quadIndexBuffer.Reset();
s_quadVertexBuffer.Reset();
}
@ -583,6 +591,10 @@ namespace Nz
const Shader* lastShader = nullptr;
const ShaderUniforms* shaderUniforms = nullptr;
Texture* reflectionMap = sceneData.globalReflectionTexture;
if (!reflectionMap)
reflectionMap = &s_dummyReflection;
for (auto& pipelinePair : layer.opaqueModels)
{
const MaterialPipeline* pipeline = pipelinePair.first;
@ -618,6 +630,15 @@ namespace Nz
{
material->Apply(pipelineInstance);
if (shaderUniforms->reflectionMap != -1)
{
unsigned int textureUnit = Material::GetTextureUnit(TextureMap_ReflectionCube);
shader->SendInteger(shaderUniforms->reflectionMap, textureUnit);
Renderer::SetTexture(textureUnit, reflectionMap);
Renderer::SetTextureSampler(textureUnit, s_reflectionSampler);
}
ForwardRenderQueue::MeshInstanceContainer& meshInstances = matEntry.meshMap;
// Meshes
@ -895,6 +916,7 @@ namespace Nz
uniforms.shaderUniformInvalidatedSlot.Connect(shader->OnShaderUniformInvalidated, this, &ForwardRenderTechnique::OnShaderInvalidated);
uniforms.eyePosition = shader->GetUniformLocation("EyePosition");
uniforms.reflectionMap = shader->GetUniformLocation("ReflectionMap");
uniforms.sceneAmbient = shader->GetUniformLocation("SceneAmbient");
uniforms.textureOverlay = shader->GetUniformLocation("TextureOverlay");
@ -1037,6 +1059,8 @@ namespace Nz
}
IndexBuffer ForwardRenderTechnique::s_quadIndexBuffer;
Texture ForwardRenderTechnique::s_dummyReflection;
TextureSampler ForwardRenderTechnique::s_reflectionSampler;
TextureSampler ForwardRenderTechnique::s_shadowSampler;
VertexBuffer ForwardRenderTechnique::s_quadVertexBuffer;
VertexDeclaration ForwardRenderTechnique::s_billboardInstanceDeclaration;

View File

@ -77,19 +77,20 @@ namespace Nz
NazaraAssert(m_pipelineInfo.uberShader, "Material pipeline has no uber shader");
ParameterList list;
list.SetParameter("ALPHA_MAPPING", m_pipelineInfo.hasAlphaMap);
list.SetParameter("ALPHA_TEST", m_pipelineInfo.alphaTest);
list.SetParameter("COMPUTE_TBNMATRIX", m_pipelineInfo.hasNormalMap || m_pipelineInfo.hasHeightMap);
list.SetParameter("DIFFUSE_MAPPING", m_pipelineInfo.hasDiffuseMap);
list.SetParameter("EMISSIVE_MAPPING", m_pipelineInfo.hasEmissiveMap);
list.SetParameter("NORMAL_MAPPING", m_pipelineInfo.hasNormalMap);
list.SetParameter("PARALLAX_MAPPING", m_pipelineInfo.hasHeightMap);
list.SetParameter("SHADOW_MAPPING", m_pipelineInfo.shadowReceive);
list.SetParameter("SPECULAR_MAPPING", m_pipelineInfo.hasSpecularMap);
list.SetParameter("TEXTURE_MAPPING", m_pipelineInfo.hasAlphaMap || m_pipelineInfo.hasDiffuseMap || m_pipelineInfo.hasEmissiveMap ||
m_pipelineInfo.hasNormalMap || m_pipelineInfo.hasHeightMap || m_pipelineInfo.hasSpecularMap ||
flags & ShaderFlags_TextureOverlay);
list.SetParameter("TRANSFORM", true);
list.SetParameter("ALPHA_MAPPING", m_pipelineInfo.hasAlphaMap);
list.SetParameter("ALPHA_TEST", m_pipelineInfo.alphaTest);
list.SetParameter("COMPUTE_TBNMATRIX", m_pipelineInfo.hasNormalMap || m_pipelineInfo.hasHeightMap);
list.SetParameter("DIFFUSE_MAPPING", m_pipelineInfo.hasDiffuseMap);
list.SetParameter("EMISSIVE_MAPPING", m_pipelineInfo.hasEmissiveMap);
list.SetParameter("NORMAL_MAPPING", m_pipelineInfo.hasNormalMap);
list.SetParameter("PARALLAX_MAPPING", m_pipelineInfo.hasHeightMap);
list.SetParameter("REFLECTION_MAPPING", m_pipelineInfo.reflectionMapping);
list.SetParameter("SHADOW_MAPPING", m_pipelineInfo.shadowReceive);
list.SetParameter("SPECULAR_MAPPING", m_pipelineInfo.hasSpecularMap);
list.SetParameter("TEXTURE_MAPPING", m_pipelineInfo.hasAlphaMap || m_pipelineInfo.hasDiffuseMap || m_pipelineInfo.hasEmissiveMap ||
m_pipelineInfo.hasNormalMap || m_pipelineInfo.hasHeightMap || m_pipelineInfo.hasSpecularMap ||
m_pipelineInfo.reflectionMapping || flags & ShaderFlags_TextureOverlay);
list.SetParameter("TRANSFORM", true);
list.SetParameter("FLAG_BILLBOARD", static_cast<bool>((flags & ShaderFlags_Billboard) != 0));
list.SetParameter("FLAG_DEFERRED", static_cast<bool>((flags & ShaderFlags_Deferred) != 0));
@ -175,7 +176,7 @@ namespace Nz
OverrideShader("Shaders/PhongLighting/core.vert", &vertexShader);
#endif
uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING EMISSIVE_MAPPING NORMAL_MAPPING PARALLAX_MAPPING SHADOW_MAPPING SPECULAR_MAPPING");
uberShader->SetShader(ShaderStageType_Fragment, fragmentShader, "FLAG_DEFERRED FLAG_TEXTUREOVERLAY ALPHA_MAPPING ALPHA_TEST AUTO_TEXCOORDS DIFFUSE_MAPPING EMISSIVE_MAPPING NORMAL_MAPPING PARALLAX_MAPPING REFLECTION_MAPPING SHADOW_MAPPING SPECULAR_MAPPING");
uberShader->SetShader(ShaderStageType_Vertex, vertexShader, "FLAG_BILLBOARD FLAG_DEFERRED FLAG_INSTANCING FLAG_VERTEXCOLOR COMPUTE_TBNMATRIX PARALLAX_MAPPING SHADOW_MAPPING TEXTURE_MAPPING TRANSFORM UNIFORM_VERTEX_DEPTH");
UberShaderLibrary::Register("PhongLighting", uberShader);