Graphics/Light: Update to Renderable
Former-commit-id: 6766d036eb4c79fd0d5cdb718b06d6e4812ac660
This commit is contained in:
parent
e1a25a8885
commit
6f06383ab0
|
|
@ -10,24 +10,24 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/Color.hpp>
|
#include <Nazara/Core/Color.hpp>
|
||||||
#include <Nazara/Graphics/Enums.hpp>
|
#include <Nazara/Graphics/Enums.hpp>
|
||||||
#include <Nazara/Graphics/SceneNode.hpp>
|
#include <Nazara/Graphics/Renderable.hpp>
|
||||||
|
|
||||||
class NzShader;
|
class NzShader;
|
||||||
struct NzLightUniforms;
|
struct NzLightUniforms;
|
||||||
|
|
||||||
class NAZARA_API NzLight : public NzSceneNode
|
class NAZARA_API NzLight : public NzRenderable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NzLight(nzLightType type = nzLightType_Point);
|
NzLight(nzLightType type = nzLightType_Point);
|
||||||
NzLight(const NzLight& light);
|
NzLight(const NzLight& light) = default;
|
||||||
~NzLight() = default;
|
~NzLight() = default;
|
||||||
|
|
||||||
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const override;
|
void AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const override;
|
||||||
|
|
||||||
NzLight* Clone() const;
|
NzLight* Clone() const;
|
||||||
NzLight* Create() const;
|
NzLight* Create() const;
|
||||||
|
|
||||||
void Enable(const NzShader* shader, const NzLightUniforms& uniforms, int offset = 0) const;
|
bool Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, const NzMatrix4f& transformMatrix) const override;
|
||||||
|
|
||||||
float GetAmbientFactor() const;
|
float GetAmbientFactor() const;
|
||||||
float GetAttenuation() const;
|
float GetAttenuation() const;
|
||||||
|
|
@ -37,9 +37,6 @@ class NAZARA_API NzLight : public NzSceneNode
|
||||||
nzLightType GetLightType() const;
|
nzLightType GetLightType() const;
|
||||||
float GetOuterAngle() const;
|
float GetOuterAngle() const;
|
||||||
float GetRadius() const;
|
float GetRadius() const;
|
||||||
nzSceneNodeType GetSceneNodeType() const;
|
|
||||||
|
|
||||||
bool IsDrawable() const;
|
|
||||||
|
|
||||||
void SetAmbientFactor(float factor);
|
void SetAmbientFactor(float factor);
|
||||||
void SetAttenuation(float attenuation);
|
void SetAttenuation(float attenuation);
|
||||||
|
|
@ -50,16 +47,12 @@ class NAZARA_API NzLight : public NzSceneNode
|
||||||
void SetOuterAngle(float outerAngle);
|
void SetOuterAngle(float outerAngle);
|
||||||
void SetRadius(float radius);
|
void SetRadius(float radius);
|
||||||
|
|
||||||
NzLight& operator=(const NzLight& light);
|
void UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMatrix4f& transformMatrix) const;
|
||||||
|
|
||||||
static void Disable(const NzShader* program, const NzLightUniforms& uniforms, int offset = 0);
|
NzLight& operator=(const NzLight& light) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool FrustumCull(const NzFrustumf& frustum) const override;
|
|
||||||
void MakeBoundingVolume() const override;
|
void MakeBoundingVolume() const override;
|
||||||
void Register() override;
|
|
||||||
void Unregister() override;
|
|
||||||
void UpdateBoundingVolume() const;
|
|
||||||
|
|
||||||
nzLightType m_type;
|
nzLightType m_type;
|
||||||
NzColor m_color;
|
NzColor m_color;
|
||||||
|
|
|
||||||
|
|
@ -28,23 +28,25 @@ m_radius(5.f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NzLight::NzLight(const NzLight& light) :
|
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue, const NzMatrix4f& transformMatrix) const
|
||||||
NzSceneNode(light),
|
|
||||||
m_type(light.m_type),
|
|
||||||
m_color(light.m_color),
|
|
||||||
m_ambientFactor(light.m_ambientFactor),
|
|
||||||
m_attenuation(light.m_attenuation),
|
|
||||||
m_diffuseFactor(light.m_diffuseFactor),
|
|
||||||
m_innerAngle(light.m_innerAngle),
|
|
||||||
m_outerAngle(light.m_outerAngle),
|
|
||||||
m_radius(light.m_radius)
|
|
||||||
{
|
{
|
||||||
SetParent(light.GetParent());
|
switch (m_type)
|
||||||
}
|
{
|
||||||
|
case nzLightType_Directional:
|
||||||
|
renderQueue->AddDirectionalLight(m_color, m_ambientFactor, m_diffuseFactor, transformMatrix.Transform(NzVector3f::Forward(), 0.f));
|
||||||
|
break;
|
||||||
|
|
||||||
void NzLight::AddToRenderQueue(NzAbstractRenderQueue* renderQueue) const
|
case nzLightType_Point:
|
||||||
{
|
renderQueue->AddPointLight(m_color, m_ambientFactor, m_diffuseFactor, transformMatrix.GetTranslation(), m_radius, m_attenuation);
|
||||||
renderQueue->AddLight(this);
|
|
||||||
|
case nzLightType_Spot:
|
||||||
|
renderQueue->AddSpotLight(m_color, m_ambientFactor, m_diffuseFactor, transformMatrix.GetTranslation(), transformMatrix.Transform(NzVector3f::Forward(), 0.f), m_radius, m_attenuation, m_innerAngle, m_outerAngle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
NazaraError("Invalid light type (0x" + NzString::Number(m_type, 16) + ')');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NzLight* NzLight::Clone() const
|
NzLight* NzLight::Clone() const
|
||||||
|
|
@ -57,57 +59,22 @@ NzLight* NzLight::Create() const
|
||||||
return new NzLight;
|
return new NzLight;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzLight::Enable(const NzShader* shader, const NzLightUniforms& uniforms, int offset) const
|
bool NzLight::Cull(const NzFrustumf& frustum, const NzBoundingVolumef& volume, const NzMatrix4f& transformMatrix) const
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
struct Light
|
|
||||||
{
|
|
||||||
int type;
|
|
||||||
vec4 color;
|
|
||||||
vec2 factors;
|
|
||||||
|
|
||||||
vec4 parameters1;
|
|
||||||
vec4 parameters2;
|
|
||||||
vec2 parameters3;
|
|
||||||
};
|
|
||||||
|
|
||||||
Directional
|
|
||||||
-P1: vec3 direction
|
|
||||||
|
|
||||||
Point
|
|
||||||
-P1: vec3 position + float attenuation
|
|
||||||
-P2: vec3 NON-USED + float invRadius
|
|
||||||
|
|
||||||
Spot
|
|
||||||
-P1: vec3 position + float attenuation
|
|
||||||
-P2: vec3 direction + float invRadius
|
|
||||||
-P3: float cosInnerAngle + float cosOuterAngle
|
|
||||||
*/
|
|
||||||
|
|
||||||
shader->SendInteger(uniforms.locations.type + offset, m_type);
|
|
||||||
shader->SendColor(uniforms.locations.color + offset, m_color);
|
|
||||||
shader->SendVector(uniforms.locations.factors + offset, NzVector2f(m_ambientFactor, m_diffuseFactor));
|
|
||||||
|
|
||||||
if (!m_derivedUpdated)
|
|
||||||
UpdateDerived();
|
|
||||||
|
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case nzLightType_Directional:
|
case nzLightType_Directional:
|
||||||
shader->SendVector(uniforms.locations.parameters1 + offset, NzVector4f(m_derivedRotation * NzVector3f::Forward()));
|
return true; // Always visible
|
||||||
break;
|
|
||||||
|
|
||||||
case nzLightType_Point:
|
case nzLightType_Point:
|
||||||
shader->SendVector(uniforms.locations.parameters1 + offset, NzVector4f(m_derivedPosition, m_attenuation));
|
return frustum.Contains(NzSpheref(transformMatrix.GetTranslation(), m_radius)); // A sphere test is much faster (and precise)
|
||||||
shader->SendVector(uniforms.locations.parameters2 + offset, NzVector4f(0.f, 0.f, 0.f, 1.f/m_radius));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzLightType_Spot:
|
case nzLightType_Spot:
|
||||||
shader->SendVector(uniforms.locations.parameters1 + offset, NzVector4f(m_derivedPosition, m_attenuation));
|
return frustum.Contains(volume);
|
||||||
shader->SendVector(uniforms.locations.parameters2 + offset, NzVector4f(m_derivedRotation * NzVector3f::Forward(), 1.f/m_radius));
|
|
||||||
shader->SendVector(uniforms.locations.parameters3 + offset, NzVector2f(std::cos(NzDegreeToRadian(m_innerAngle)), std::cos(NzDegreeToRadian(m_outerAngle))));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NazaraError("Invalid light type (0x" + NzString::Number(m_type, 16) + ')');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float NzLight::GetAmbientFactor() const
|
float NzLight::GetAmbientFactor() const
|
||||||
|
|
@ -150,16 +117,6 @@ float NzLight::GetRadius() const
|
||||||
return m_radius;
|
return m_radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
nzSceneNodeType NzLight::GetSceneNodeType() const
|
|
||||||
{
|
|
||||||
return nzSceneNodeType_Light;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzLight::IsDrawable() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzLight::SetAmbientFactor(float factor)
|
void NzLight::SetAmbientFactor(float factor)
|
||||||
{
|
{
|
||||||
m_ambientFactor = factor;
|
m_ambientFactor = factor;
|
||||||
|
|
@ -194,61 +151,37 @@ void NzLight::SetOuterAngle(float outerAngle)
|
||||||
{
|
{
|
||||||
m_outerAngle = outerAngle;
|
m_outerAngle = outerAngle;
|
||||||
|
|
||||||
m_boundingVolume.MakeNull();
|
InvalidateBoundingVolume();
|
||||||
m_boundingVolumeUpdated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzLight::SetRadius(float radius)
|
void NzLight::SetRadius(float radius)
|
||||||
{
|
{
|
||||||
m_radius = radius;
|
m_radius = radius;
|
||||||
|
|
||||||
m_boundingVolume.MakeNull();
|
InvalidateBoundingVolume();
|
||||||
m_boundingVolumeUpdated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NzLight& NzLight::operator=(const NzLight& light)
|
void NzLight::UpdateBoundingVolume(NzBoundingVolumef* boundingVolume, const NzMatrix4f& transformMatrix) const
|
||||||
{
|
{
|
||||||
NzSceneNode::operator=(light);
|
NazaraAssert(boundingVolume, "Invalid bounding volume");
|
||||||
|
|
||||||
m_ambientFactor = light.m_ambientFactor;
|
|
||||||
m_attenuation = light.m_attenuation;
|
|
||||||
m_boundingVolume = light.m_boundingVolume;
|
|
||||||
m_boundingVolumeUpdated = light.m_boundingVolumeUpdated;
|
|
||||||
m_color = light.m_color;
|
|
||||||
m_diffuseFactor = light.m_diffuseFactor;
|
|
||||||
m_innerAngle = light.m_innerAngle;
|
|
||||||
m_outerAngle = light.m_outerAngle;
|
|
||||||
m_radius = light.m_radius;
|
|
||||||
m_type = light.m_type;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzLight::Disable(const NzShader* shader, const NzLightUniforms& uniforms, int offset)
|
|
||||||
{
|
|
||||||
shader->SendInteger(uniforms.locations.type + offset, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NzLight::FrustumCull(const NzFrustumf& frustum) const
|
|
||||||
{
|
|
||||||
switch (m_type)
|
switch (m_type)
|
||||||
{
|
{
|
||||||
case nzLightType_Directional:
|
case nzLightType_Directional:
|
||||||
return true; // Toujours visible
|
break; // Nothing to do (bounding volume should be infinite)
|
||||||
|
|
||||||
case nzLightType_Point:
|
case nzLightType_Point:
|
||||||
if (!m_derivedUpdated)
|
boundingVolume->Update(transformMatrix.GetTranslation()); // The bounding volume only needs to be shifted
|
||||||
UpdateDerived();
|
break;
|
||||||
|
|
||||||
// Un test sphérique est bien plus rapide et précis que celui de la bounding box
|
|
||||||
return frustum.Contains(NzSpheref(m_derivedPosition, m_radius));
|
|
||||||
|
|
||||||
case nzLightType_Spot:
|
case nzLightType_Spot:
|
||||||
return NzSceneNode::FrustumCull(frustum);
|
boundingVolume->Update(transformMatrix);
|
||||||
}
|
break;
|
||||||
|
|
||||||
NazaraError("Invalid light type (0x" + NzString::Number(m_type, 16) + ')');
|
default:
|
||||||
return false;
|
NazaraError("Invalid light type (0x" + NzString::Number(m_type, 16) + ')');
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NzLight::MakeBoundingVolume() const
|
void NzLight::MakeBoundingVolume() const
|
||||||
|
|
@ -261,7 +194,7 @@ void NzLight::MakeBoundingVolume() const
|
||||||
|
|
||||||
case nzLightType_Point:
|
case nzLightType_Point:
|
||||||
{
|
{
|
||||||
NzVector3f radius(m_radius);
|
NzVector3f radius(m_radius); ///FIXME: Incorrect
|
||||||
m_boundingVolume.Set(-radius, radius);
|
m_boundingVolume.Set(-radius, radius);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -289,41 +222,9 @@ void NzLight::MakeBoundingVolume() const
|
||||||
m_boundingVolume.Set(box);
|
m_boundingVolume.Set(box);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzLight::Register()
|
default:
|
||||||
{
|
NazaraError("Invalid light type (0x" + NzString::Number(m_type, 16) + ')');
|
||||||
}
|
|
||||||
|
|
||||||
void NzLight::Unregister()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void NzLight::UpdateBoundingVolume() const
|
|
||||||
{
|
|
||||||
if (m_boundingVolume.IsNull())
|
|
||||||
MakeBoundingVolume();
|
|
||||||
|
|
||||||
switch (m_type)
|
|
||||||
{
|
|
||||||
case nzLightType_Directional:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzLightType_Point:
|
|
||||||
if (!m_derivedUpdated)
|
|
||||||
UpdateDerived();
|
|
||||||
|
|
||||||
m_boundingVolume.Update(NzMatrix4f::Translate(m_derivedPosition)); // Notre BoundingBox ne changera que selon la position
|
|
||||||
break;
|
|
||||||
|
|
||||||
case nzLightType_Spot:
|
|
||||||
if (!m_derivedUpdated)
|
|
||||||
UpdateDerived();
|
|
||||||
|
|
||||||
m_boundingVolume.Update(NzMatrix4f::Transform(m_derivedPosition, m_derivedRotation));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_boundingVolumeUpdated = true;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue