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
master
hybrid 2008-08-08 19:39:24 +00:00
parent 3c45d6f44a
commit 76547f8f97
6 changed files with 68 additions and 38 deletions

View File

@ -91,6 +91,7 @@ namespace scene
creation is easier, but with this method there occur ugly
looking artifacs when the camera is inside the shadow volume.
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
identify the node later.
\param zfailmethod: If set to true, the shadow will use the
@ -100,8 +101,8 @@ namespace scene
\return Pointer to the created shadow scene node. This pointer
should not be dropped. See IReferenceCounted::drop() for more
information. */
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(s32 id=-1,
bool zfailmethod=true, f32 infinity=10000.0f) = 0;
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh=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).

View File

@ -22,8 +22,13 @@ namespace scene
IShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id)
: ISceneNode(parent, mgr, id) {}
//! sets the mesh from which the shadow volume should be generated.
virtual void setMeshToRenderFrom(const IMesh* mesh) = 0;
//! Sets the mesh from which the shadow volume should be generated.
/** 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

View File

@ -270,7 +270,7 @@ void CAnimatedMeshSceneNode::render()
if (Shadow && PassCount==1)
Shadow->setMeshToRenderFrom(m);
Shadow->updateShadowVolumes();
// for debug purposes only:
@ -559,8 +559,8 @@ u32 CAnimatedMeshSceneNode::getMaterialCount() const
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(s32 id,
bool zfailmethod, f32 infinity)
IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod, f32 infinity)
{
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
return 0;
@ -571,7 +571,10 @@ IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(s32 id,
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;
}

View File

@ -72,8 +72,8 @@ namespace scene
//! Creates shadow volume scene node as child of this node
//! and returns a pointer to it.
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(s32 id,
bool zfailmethod=true, f32 infinity=10000.0f);
virtual IShadowVolumeSceneNode* addShadowVolumeSceneNode(const IMesh* shadowMesh,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! 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.

View File

@ -15,27 +15,28 @@ namespace scene
//! constructor
CShadowVolumeSceneNode::CShadowVolumeSceneNode(ISceneNode* parent,
ISceneManager* mgr, s32 id,
bool zfailmethod, f32 infinity)
: IShadowVolumeSceneNode(parent, mgr, id), Indices(0), Vertices(0),
Adjacency(0), FaceData(0), UseZFailMethod(zfailmethod),
CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent,
ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity)
: IShadowVolumeSceneNode(parent, mgr, id), Vertices(0), Indices(0),
Adjacency(0), Edges(0), FaceData(0), ShadowMesh(0),
IndexCountAllocated(0), VertexCountAllocated(0),
IndexCount(0), VertexCount(0), ShadowVolumesUsed(0),
Edges(0), EdgeCount(0), Infinity(infinity)
IndexCount(0), VertexCount(0), EdgeCount(0), ShadowVolumesUsed(0),
Infinity(infinity), UseZFailMethod(zfailmethod)
{
#ifdef _DEBUG
setDebugName("CShadowVolumeSceneNode");
#endif
setShadowMesh(shadowMesh);
setAutomaticCulling(scene::EAC_OFF);
}
//! destructor
CShadowVolumeSceneNode::~CShadowVolumeSceneNode()
{
if (ShadowMesh)
ShadowMesh->drop();
delete [] Edges;
for (u32 i=0; i<ShadowVolumes.size(); ++i)
@ -48,7 +49,6 @@ CShadowVolumeSceneNode::~CShadowVolumeSceneNode()
}
void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light)
{
SShadowVolume* svp = 0;
@ -251,17 +251,26 @@ void CShadowVolumeSceneNode::createZPassVolume(s32 faceCount,
}
//! sets the mesh from which the shadow volume should be generated.
void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh)
void CShadowVolumeSceneNode::setShadowMesh(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;
IndexCount = 0;
ShadowVolumesUsed = 0;
const IMesh* const mesh = ShadowMesh;
if (!mesh)
return;
@ -270,7 +279,7 @@ void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh)
u32 i;
s32 totalVertices = 0;
s32 totalIndices = 0;
u32 bufcnt = mesh->getMeshBufferCount();
const u32 bufcnt = mesh->getMeshBufferCount();
for (i=0; i<bufcnt; ++i)
{
@ -350,9 +359,10 @@ void CShadowVolumeSceneNode::setMeshToRenderFrom(const IMesh* mesh)
void CShadowVolumeSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
{
SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW);
ISceneNode::OnRegisterSceneNode();
ISceneNode::OnRegisterSceneNode();
}
}

View File

@ -18,14 +18,19 @@ namespace scene
public:
//! constructor
CShadowVolumeSceneNode(ISceneNode* parent, ISceneManager* mgr,
CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, ISceneManager* mgr,
s32 id, bool zfailmethod=true, f32 infinity=10000.0f);
//! destructor
virtual ~CShadowVolumeSceneNode();
//! sets the mesh from which the shadow volume should be generated.
virtual void setMeshToRenderFrom(const IMesh* mesh);
//! Sets the mesh from which the shadow volume should be generated.
/** 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
virtual void OnRegisterSceneNode();
@ -58,24 +63,30 @@ namespace scene
core::aabbox3d<f32> Box;
u16* Indices;
// a shadow volume for every light
core::array<SShadowVolume> ShadowVolumes;
core::vector3df* Vertices;
u16* Indices;
u16* Adjacency;
bool* FaceData; // used for zfail method, if face is front facing
bool UseZFailMethod;
u16* Edges;
// used for zfail method, if face is front facing
bool* FaceData;
const scene::IMesh* ShadowMesh;
s32 IndexCountAllocated;
s32 VertexCountAllocated;
s32 IndexCount;
s32 VertexCount;
core::array<SShadowVolume> ShadowVolumes; // a shadow volume for every light
s32 ShadowVolumesUsed;
u16* Edges;
s32 EdgeCount;
s32 ShadowVolumesUsed;
f32 Infinity;
bool UseZFailMethod;
};
} // end namespace scene