Commit 76547f8f authored by hybrid's avatar hybrid

Added support for proxy meshes as source of the shadow volume. This enables...

Added support for proxy meshes as source of the shadow volume. This enables the use of a simplified version of a mesh for the generation of the shadow volume, which can significantly improve the render performance with shadow volumes. Patch provided by tonic.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1477 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 3c45d6f4
...@@ -91,6 +91,7 @@ namespace scene ...@@ -91,6 +91,7 @@ namespace scene
creation is easier, but with this method there occur ugly creation is easier, but with this method there occur ugly
looking artifacs when the camera is inside the shadow volume. looking artifacs when the camera is inside the shadow volume.
These error do not occur with the ZFail method. These error do not occur with the ZFail method.
\param shadowMesh: Optional custom mesh for shadow volume.
\param id: Id of the shadow scene node. This id can be used to \param id: Id of the shadow scene node. This id can be used to
identify the node later. identify the node later.
\param zfailmethod: If set to true, the shadow will use the \param zfailmethod: If set to true, the shadow will use the
...@@ -100,8 +101,8 @@ namespace scene ...@@ -100,8 +101,8 @@ namespace scene
\return Pointer to the created shadow scene node. This pointer \return Pointer to the created shadow scene node. This pointer
should not be dropped. See IReferenceCounted::drop() for more should not be dropped. See IReferenceCounted::drop() for more
information. */ information. */
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(s32 id=-1, virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=0,
bool zfailmethod=true, f32 infinity=10000.0f) = 0; s32 id=-1, bool zfailmethod=true, f32 infinity=10000.0f) = 0;
//! Get a pointer to a joint in the mesh (if the mesh is a bone based mesh). //! Get a pointer to a joint in the mesh (if the mesh is a bone based mesh).
......
...@@ -22,8 +22,13 @@ namespace scene ...@@ -22,8 +22,13 @@ namespace scene
IShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) IShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
: ISceneNode(parent, mgr, id) {} : ISceneNode(parent, mgr, id) {}
//! sets the mesh from which the shadow volume should be generated. //! Sets the mesh from which the shadow volume should be generated.
virtual void setMeshToRenderFrom(const IMesh* mesh) = 0; /** To optimize shadow rendering, use a simpler mesh for shadows.
*/
virtual void setShadowMesh(const IMesh* mesh) = 0;
//! Updates the shadow volumes for current light positions.
virtual void updateShadowVolumes() = 0;
}; };
} // end namespace scene } // end namespace scene
......
...@@ -270,7 +270,7 @@ void CAnimatedMeshSceneNode::render() ...@@ -270,7 +270,7 @@ void CAnimatedMeshSceneNode::render()
if (Shadow && PassCount==1) if (Shadow && PassCount==1)
Shadow->setMeshToRenderFrom(m); Shadow->updateShadowVolumes();
// for debug purposes only: // for debug purposes only:
...@@ -559,8 +559,8 @@ u32 CAnimatedMeshSceneNode::getMaterialCount() const ...@@ -559,8 +559,8 @@ u32 CAnimatedMeshSceneNode::getMaterialCount() const
//! Creates shadow volume scene node as child of this node //! Creates shadow volume scene node as child of this node
//! and returns a pointer to it. //! and returns a pointer to it.
IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(s32 id, IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(const IMesh* shadowMesh,
bool zfailmethod, f32 infinity) s32 id, bool zfailmethod, f32 infinity)
{ {
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0; return 0;
...@@ -571,7 +571,10 @@ IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(s32 id, ...@@ -571,7 +571,10 @@ IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(s32 id,
return 0; return 0;
} }
Shadow = new CShadowVolumeSceneNode(this, SceneManager, id, zfailmethod, infinity); if (!shadowMesh)
shadowMesh = Mesh; // if null is given, use the mesh of node
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
return Shadow; return Shadow;
} }
......
...@@ -72,8 +72,8 @@ namespace scene ...@@ -72,8 +72,8 @@ namespace scene
//! Creates shadow volume scene node as child of this node //! Creates shadow volume scene node as child of this node
//! and returns a pointer to it. //! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(s32 id, virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
bool zfailmethod=true, f32 infinity=10000.0f); s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! Returns a pointer to a child node, which has the same transformation as //! Returns a pointer to a child node, which has the same transformation as
//! the corrsesponding joint, if the mesh in this scene node is a skinned mesh. //! the corrsesponding joint, if the mesh in this scene node is a skinned mesh.
......
...@@ -15,27 +15,28 @@ namespace scene ...@@ -15,27 +15,28 @@ namespace scene
//! constructor //! constructor
CShadowVolumeSceneNode::CShadowVolumeSceneNode(ISceneNode* parent, CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent,
ISceneManager* mgr, s32 id, ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity)
bool zfailmethod, f32 infinity) : IShadowVolumeSceneNode(parent, mgr, id), Vertices(0), Indices(0),
: IShadowVolumeSceneNode(parent, mgr, id), Indices(0), Vertices(0), Adjacency(0), Edges(0), FaceData(0), ShadowMesh(0),
Adjacency(0), FaceData(0), UseZFailMethod(zfailmethod),
IndexCountAllocated(0), VertexCountAllocated(0), IndexCountAllocated(0), VertexCountAllocated(0),
IndexCount(0), VertexCount(0), ShadowVolumesUsed(0), IndexCount(0), VertexCount(0), EdgeCount(0), ShadowVolumesUsed(0),
Edges(0), EdgeCount(0), Infinity(infinity) Infinity(infinity), UseZFailMethod(zfailmethod)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CShadowVolumeSceneNode"); setDebugName("CShadowVolumeSceneNode");
#endif #endif
setShadowMesh(shadowMesh);
setAutomaticCulling(scene::EAC_OFF); setAutomaticCulling(scene::EAC_OFF);
} }
//! destructor //! destructor
CShadowVolumeSceneNode::~CShadowVolumeSceneNode() CShadowVolumeSceneNode::~CShadowVolumeSceneNode()
{ {
if (ShadowMesh)
ShadowMesh->drop();
delete [] Edges; delete [] Edges;
for (u32 i=0; i<ShadowVolumes.size(); ++i) for (u32 i=0; i<ShadowVolumes.size(); ++i)
...@@ -48,7 +49,6 @@ CShadowVolumeSceneNode::~CShadowVolumeSceneNode() ...@@ -48,7 +49,6 @@ CShadowVolumeSceneNode::~CShadowVolumeSceneNode()
} }
void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light) void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light)
{ {
SShadowVolume* svp = 0; SShadowVolume* svp = 0;
...@@ -251,17 +251,26 @@ void CShadowVolumeSceneNode::createZPassVolume(s32 faceCount, ...@@ -251,17 +251,26 @@ void CShadowVolumeSceneNode::createZPassVolume(s32 faceCount,
} }
//! sets the mesh from which the shadow volume should be generated. void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh)
void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh)
{ {
ShadowVolumesUsed = 0; if (ShadowMesh)
ShadowMesh->drop();
ShadowMesh = mesh;
if (ShadowMesh)
ShadowMesh->grab();
}
s32 oldIndexCount = IndexCount;
s32 oldVertexCount = VertexCount; void CShadowVolumeSceneNode::updateShadowVolumes()
{
const s32 oldIndexCount = IndexCount;
const s32 oldVertexCount = VertexCount;
VertexCount = 0; VertexCount = 0;
IndexCount = 0; IndexCount = 0;
ShadowVolumesUsed = 0;
const IMesh* const mesh = ShadowMesh;
if (!mesh) if (!mesh)
return; return;
...@@ -270,7 +279,7 @@ void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh) ...@@ -270,7 +279,7 @@ void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh)
u32 i; u32 i;
s32 totalVertices = 0; s32 totalVertices = 0;
s32 totalIndices = 0; s32 totalIndices = 0;
u32 bufcnt = mesh->getMeshBufferCount(); const u32 bufcnt = mesh->getMeshBufferCount();
for (i=0; i<bufcnt; ++i) for (i=0; i<bufcnt; ++i)
{ {
...@@ -350,9 +359,10 @@ void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh) ...@@ -350,9 +359,10 @@ void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh)
void CShadowVolumeSceneNode::OnRegisterSceneNode() void CShadowVolumeSceneNode::OnRegisterSceneNode()
{ {
if (IsVisible) if (IsVisible)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW); SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW);
ISceneNode::OnRegisterSceneNode();
ISceneNode::OnRegisterSceneNode(); }
} }
......
...@@ -18,14 +18,19 @@ namespace scene ...@@ -18,14 +18,19 @@ namespace scene
public: public:
//! constructor //! constructor
CShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr, CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, ISceneManager* mgr,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f); s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! destructor //! destructor
virtual ~CShadowVolumeSceneNode(); virtual ~CShadowVolumeSceneNode();
//! sets the mesh from which the shadow volume should be generated. //! Sets the mesh from which the shadow volume should be generated.
virtual void setMeshToRenderFrom(const IMesh* mesh); /** To optimize shadow rendering, use a simpler mesh for shadows.
*/
virtual void setShadowMesh(const IMesh* mesh);
//! Updates the shadow volumes for current light positions.
virtual void updateShadowVolumes();
//! pre render method //! pre render method
virtual void OnRegisterSceneNode(); virtual void OnRegisterSceneNode();
...@@ -58,24 +63,30 @@ namespace scene ...@@ -58,24 +63,30 @@ namespace scene
core::aabbox3d<f32> Box; core::aabbox3d<f32> Box;
u16* Indices; // a shadow volume for every light
core::array<SShadowVolume> ShadowVolumes;
core::vector3df* Vertices; core::vector3df* Vertices;
u16* Indices;
u16* Adjacency; u16* Adjacency;
bool* FaceData; // used for zfail method, if face is front facing u16* Edges;
bool UseZFailMethod; // used for zfail method, if face is front facing
bool* FaceData;
const scene::IMesh* ShadowMesh;
s32 IndexCountAllocated; s32 IndexCountAllocated;
s32 VertexCountAllocated; s32 VertexCountAllocated;
s32 IndexCount; s32 IndexCount;
s32 VertexCount; s32 VertexCount;
core::array<SShadowVolume> ShadowVolumes; // a shadow volume for every light
s32 ShadowVolumesUsed;
u16* Edges;
s32 EdgeCount; s32 EdgeCount;
s32 ShadowVolumesUsed;
f32 Infinity; f32 Infinity;
bool UseZFailMethod;
}; };
} // end namespace scene } // end namespace scene
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment