Merging r6468 through r6486 from trunk to ogl-es branch

Also updating ES&ES2 interface to work with removal of IMaterialRendererServices::setBasicRenderStates


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/branches/ogl-es@6487 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
cutealien 2023-05-05 19:28:40 +00:00
parent e4bb544079
commit 1670db617b
34 changed files with 700 additions and 433 deletions

@ -11,6 +11,8 @@ Changes in ogl-es (not yet released - will be merged with trunk at some point)
--------------------------
Changes in 1.9 (not yet released)
- Add IMeshSceneNode::setNodeRegistration to allow registering MeshSceneNodes to the SceneManager per buffer instead of per node
- Add SMaterialLayer::hasSetTextureMatrix and SMaterialLayer::resetTextureMatrix
- Add IShaderConstantSetCallBack::OnCreate to allow earlier access to IMaterialRendererServices
- CIrrDeviceWin32::yield() now uses Sleep(0) instead of Sleep(1).
We had Sleep(1) to allow yielding to all processes back in Windows XP time.

@ -255,7 +255,7 @@ void loadModel(const io::path& filename)
// that's not so simple. so we do it brute force
gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)Device->getGUIEnvironment()->getRootGUIElement()->getElementFromId(GUI_ID_TOGGLE_DEBUG_INFO, true);
if (menu)
for(int item = 1; item < 6; ++item)
for(int item = 1; item < 7; ++item)
menu->setItemChecked(item, false);
updateScaleInfo(Model);
}

@ -17,7 +17,11 @@ namespace scene
//! Only transform the position of the node transformation matrix
//! by the parent transformation matrix.
//! Parent will not affect the rotation/scale of the node transformation.
ESNUA_TRANSFORM_POSITION
ESNUA_TRANSFORM_POSITION,
//! Use the relative matrix as absolute transformation matrix
//! Parent node transformation is ignored just like when the parent is set to 0
ESNUA_RELATIVE
};
//! Names for culling type
@ -25,6 +29,7 @@ namespace scene
{
"matrix",
"pos",
"relative",
0
};

@ -24,20 +24,6 @@ public:
//! Destructor
virtual ~IMaterialRendererServices() {}
//! Can be called by an IMaterialRenderer to make its work easier.
/** Sets all basic renderstates if needed.
Basic render states are diffuse, ambient, specular, and emissive color,
specular power, bilinear and trilinear filtering, wireframe mode,
gouraudshading, lighting, zbuffer, zwriteenable, backfaceculling and
fog enabling.
\param material The new material to be used.
\param lastMaterial The material used until now.
\param resetAllRenderstates Set to true if all renderstates should be
set, regardless of their current state. */
virtual void setBasicRenderStates(const SMaterial& material,
const SMaterial& lastMaterial,
bool resetAllRenderstates) = 0;
//! Return an index constant for the vertex shader based on a name.
virtual s32 getVertexShaderConstantID(const c8* name) = 0;

@ -15,6 +15,20 @@ namespace scene
class IShadowVolumeSceneNode;
class IMesh;
//! Option for nodes how to register themeselves at the SceneManager
enum ENodeRegistration
{
//! Each node registers once and renders all it's mesh-buffers
ENR_DEFAULT,
//! Register a new node per mesh-buffer at the SceneManager
//! It allows the SceneManager to sort in each render stage per buffer instead of per node.
//! This can be useful when having several transparent buffers in a mesh.
//! Depending on the scene (and hardware) this can have a positive or negative effect on performance.
//! It can avoid texture-switches, but adds nodes to sort and more matrix transformations are set.
ENR_PER_MESH_BUFFER
};
//! A scene node displaying a static mesh
class IMeshSceneNode : public ISceneNode
@ -28,9 +42,11 @@ public:
const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1,1,1))
: ISceneNode(parent, mgr, id, position, rotation, scale) {}
: ISceneNode(parent, mgr, id, position, rotation, scale)
, NodeRegistration(ENR_DEFAULT)
{}
//! Sets a new mesh to display
//! Sets a new mesh to display or update mesh when it changed
/** \param mesh Mesh to display. */
virtual void setMesh(IMesh* mesh) = 0;
@ -73,6 +89,23 @@ public:
/** This flag can be set by setReadOnlyMaterials().
\return Whether the materials are read-only. */
virtual bool isReadOnlyMaterials() const = 0;
//! Set how the node registers itself to the SceneManager
/** Note: Derived classes can ignore this flag, so think of it as a hint. */
virtual void setNodeRegistration(ENodeRegistration nodeRegistration)
{
NodeRegistration = nodeRegistration;
}
//! How does a node register itself to the SceneManager
/** Note: Derived classes may ignore this flag */
virtual ENodeRegistration getNodeRegistration() const
{
return NodeRegistration;
}
protected:
ENodeRegistration NodeRegistration;
};
} // end namespace scene

@ -66,7 +66,7 @@ namespace scene
//! In this pass, lights are transformed into camera space and added to the driver
ESNRP_LIGHT =2,
//! This is used for sky boxes.
//! This is mostly used for sky boxes. Stage between light and solid.
ESNRP_SKY_BOX =4,
//! All normal objects can use this for registering themselves.

@ -79,7 +79,7 @@ namespace scene
//! This method is called just before the rendering process of the whole scene.
/** Nodes may register themselves in the render pipeline during this call,
precalculate the geometry which should be rendered, and prevent their
pre-calculate the geometry which should be rendered, and prevent their
children from being able to register themselves if they are clipped by simply
not calling their OnRegisterSceneNode method.
If you are implementing your own scene node, you should overwrite this method
@ -95,7 +95,7 @@ namespace scene
{
if (IsVisible)
{
ISceneNodeList::Iterator it = Children.begin();
ISceneNodeList::ConstIterator it = Children.begin();
for (; it != Children.end(); ++it)
(*it)->OnRegisterSceneNode();
}
@ -114,7 +114,7 @@ namespace scene
{
// animate this node with all animators
ISceneNodeAnimatorList::Iterator ait = Animators.begin();
ISceneNodeAnimatorList::ConstIterator ait = Animators.begin();
while (ait != Animators.end())
{
// continue to the next node before calling animateNode()
@ -133,7 +133,7 @@ namespace scene
// perform the post render process on all children
ISceneNodeList::Iterator it = Children.begin();
ISceneNodeList::ConstIterator it = Children.begin();
for (; it != Children.end(); ++it)
(*it)->OnAnimate(timeMs);
}
@ -543,7 +543,7 @@ namespace scene
//! Set a culling style or disable culling completely.
/** Box cullling (EAC_BOX) is set by default. Note that not
/** Box culling (EAC_BOX) is set by default. Note that not
all SceneNodes support culling and that some nodes always cull
their geometry because it is their only reason for existence,
for example the OctreeSceneNode.
@ -682,16 +682,24 @@ namespace scene
{
if (Parent)
{
if ( AbsPosUpdateBehavior == ESNUA_TRANSFORM_MATRIX )
switch ( AbsPosUpdateBehavior )
{
case ESNUA_TRANSFORM_MATRIX:
{
AbsoluteTransformation =
Parent->getAbsoluteTransformation() * getRelativeTransformation();
}
else if ( AbsPosUpdateBehavior == ESNUA_TRANSFORM_POSITION )
break;
case ESNUA_TRANSFORM_POSITION:
{
AbsoluteTransformation = getRelativeTransformation();
Parent->getAbsoluteTransformation().transformVect(reinterpret_cast<irr::core::vector3df&>(AbsoluteTransformation[12]));
}
break;
case ESNUA_RELATIVE:
AbsoluteTransformation = getRelativeTransformation();
break;
}
}
else
AbsoluteTransformation = getRelativeTransformation();
@ -821,7 +829,7 @@ namespace scene
// clone children
ISceneNodeList::Iterator it = toCopyFrom->Children.begin();
ISceneNodeList::ConstIterator it = toCopyFrom->Children.begin();
for (; it != toCopyFrom->Children.end(); ++it)
(*it)->clone(this, newManager);

@ -45,7 +45,7 @@ namespace video
"texture_clamp_mirror_clamp_to_border", 0};
//! Struct for holding material parameters which exist per texture layer
// Note for implementors: Serialization is in CNullDriver
// Note for implementers: Serialization is in CNullDriver
class SMaterialLayer
{
public:
@ -153,6 +153,25 @@ namespace video
*TextureMatrix = mat;
}
//! Check if we have set a custom texture matrix
//! Note that otherwise we get an IdentityMatrix as default
inline bool hasSetTextureMatrix() const
{
return TextureMatrix != 0;
}
//! Reset texture matrix to identity matrix
//! Releases memory, which is expensive, but ver rarely useful for optimizations
void resetTextureMatrix()
{
if ( TextureMatrix )
{
MatrixAllocator.destruct(TextureMatrix);
MatrixAllocator.deallocate(TextureMatrix);
TextureMatrix = 0;
}
}
//! Inequality operator
/** \param b Layer to compare to.
\return True if layers are different, else false. */

@ -0,0 +1,185 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IMeshSceneNode.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "ISceneNode.h"
namespace irr
{
namespace scene
{
// A node which helps rendering a single buffer of an IMeshSceneNode
// It solves several problems:
// - Allowing the scene manager to sort meshbuffers. Currently it only sorts nodes, so we have to put each meshbuffer in an extra node to allow that
// The reason we want that is
// a) Better sorting when a node has several transparent buffers (without it they will be just drawn in original order)
// b) It can allow to avoid texture changes in the render-pipeline which can make quite a bit of a performance difference
// - It buffers the RenderPass. Bit of an abuse of this interface maybe?
// Strangely the check for finding out the correct render pass constantly shows up in profilers.
// Not exactly sure why as the check looks pretty cheap. My best guess is that there are some cache misses going on due to several virtual
// function pointers being involved in the transparency check.
//
// For now (added pre Irrlicht 1.9) this interface is still a bit experimental. Maybe could go into public headers later, not sure yet.
// Or maybe the SceneManager shouldn't work with nodes at all but a simplified interface to render buffers from which Nodes can derive?
// CBufferRenderNode isn't really a node - it has to work around nearly all the ISceneNode functions, it only has to be one because
// the SceneManager can't sort anything else but nodes.
class CBufferRenderNode : public ISceneNode
{
public:
CBufferRenderNode(irr::scene::IMeshSceneNode& parent, irr::scene::ISceneManager* mgr, irr::u32 bufferIdx)
: ISceneNode(0, mgr) // we don't want it in the scenegraph
, MeshNodeParent(parent)
, BufferIdx(bufferIdx)
, RenderPass(ESNRP_NONE)
, ParentDoesRender(true)
{
// While it's not the parent in the SceneGraph, we still want to allow accessing it
// That can be useful p.E. in a light manager
// Arguably if it's a good idea as it's a bit going against the ISceneNode interface - having a parent which doesn't have this node as child.
// But the alternative is adding another member to the ISceneNode or having SceneManager not use the ISceneNode for rendering
// So for now it should be fine, but if that interface ever get's public... we might have to reconsider
Parent = &MeshNodeParent;
}
u32 prepareRendering(E_SCENE_NODE_RENDER_PASS pass, bool parentDoesRender)
{
RenderPass = pass;
ParentDoesRender = parentDoesRender;
if ( !ParentDoesRender )
return SceneManager->registerNodeForRendering(this, pass);
return 0;
}
E_SCENE_NODE_RENDER_PASS getRenderPass() const
{
return RenderPass;
}
// When true render() this node hasn't registered itself for rendering, but expects it's owner to do the rendering
bool getDoesParentRender() const
{
return ParentDoesRender;
}
// Render meshbuffer, but don't set transformation
// It's assumed that this function is only called from within the correct render stage
void renderBuffer(video::IVideoDriver* driver)
{
const IMeshBuffer* mb = MeshNodeParent.getMesh()->getMeshBuffer(BufferIdx);
if (mb)
{
const video::SMaterial& material = MeshNodeParent.getMaterial(BufferIdx);
driver->setMaterial(material);
driver->drawMeshBuffer(mb);
}
}
//! Renders the node.
virtual void render() IRR_OVERRIDE
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, MeshNodeParent.getAbsoluteTransformation());
renderBuffer(driver);
// resetting each time so direct calls to render() for parent node continue to work
RenderPass = ESNRP_NONE;
ParentDoesRender = true;
}
virtual const core::aabbox3d<f32>& getBoundingBox() const IRR_OVERRIDE
{
return MeshNodeParent.getMesh()->getMeshBuffer(BufferIdx)->getBoundingBox();
}
virtual video::SMaterial& getMaterial(u32 num) IRR_OVERRIDE
{
return MeshNodeParent.getMaterial(BufferIdx);
}
virtual u32 getMaterialCount() const IRR_OVERRIDE
{
return 1;
}
virtual const core::matrix4& getAbsoluteTransformation() const IRR_OVERRIDE
{
return MeshNodeParent.getAbsoluteTransformation();
}
virtual const core::aabbox3d<f32> getTransformedBoundingBox() const IRR_OVERRIDE
{
core::aabbox3d<f32> box = getBoundingBox();
getAbsoluteTransformation().transformBoxEx(box);
return box;
}
virtual void getTransformedBoundingBoxEdges(core::array< core::vector3d<f32> >& edges) const IRR_OVERRIDE
{
edges.set_used(8);
getBoundingBox().getEdges( edges.pointer() );
for ( u32 i=0; i<8; ++i )
getAbsoluteTransformation().transformVect( edges[i] );
}
virtual core::matrix4 getRelativeTransformation() const IRR_OVERRIDE
{
return MeshNodeParent.getRelativeTransformation();
}
virtual s32 getID() const IRR_OVERRIDE
{
return MeshNodeParent.getID();
}
virtual const core::vector3df& getScale() const IRR_OVERRIDE
{
return MeshNodeParent.getScale();
}
virtual const core::vector3df& getRotation() const IRR_OVERRIDE
{
return MeshNodeParent.getRotation();
}
virtual const core::vector3df& getPosition() const IRR_OVERRIDE
{
return MeshNodeParent.getPosition();
}
virtual core::vector3df getAbsolutePosition() const IRR_OVERRIDE
{
return MeshNodeParent.getAbsolutePosition();
}
virtual ITriangleSelector* getTriangleSelector() const IRR_OVERRIDE
{
return MeshNodeParent.getTriangleSelector();
}
// Not allowing any of that stuff
virtual void OnRegisterSceneNode()IRR_OVERRIDE {}
virtual void OnAnimate(u32 timeMs) IRR_OVERRIDE {}
virtual void addChild(ISceneNode* child) IRR_OVERRIDE {}
virtual void addAnimator(ISceneNodeAnimator* animator) IRR_OVERRIDE {}
virtual void setScale(const core::vector3df& scale) IRR_OVERRIDE {}
virtual void setRotation(const core::vector3df& rotation) IRR_OVERRIDE {}
virtual void setPosition(const core::vector3df& newpos) IRR_OVERRIDE {}
virtual void setParent(ISceneNode* newParent) IRR_OVERRIDE {}
virtual void setTriangleSelector(ITriangleSelector* selector) IRR_OVERRIDE {}
virtual void updateAbsolutePosition() IRR_OVERRIDE {}
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const IRR_OVERRIDE {}
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) IRR_OVERRIDE {}
private:
irr::scene::IMeshSceneNode& MeshNodeParent;
irr::u32 BufferIdx; // Note: Not saving the meshbuffer pointer as meshes can add/remove buffers and we don't want to keep track of that
E_SCENE_NODE_RENDER_PASS RenderPass;
bool ParentDoesRender;
};
} // end namespace scene
} // end namespace irr

@ -20,11 +20,12 @@
#include "IAttributes.h"
#include "IMeshCache.h"
#include "IMeshSceneNode.h"
#include "SMeshBufferLightMap.h"
#include "CDynamicMeshBuffer.h"
#include "irrMap.h"
#ifdef _DEBUG
#define COLLADA_READER_DEBUG
// Lots of messages, with how slow some consoles are loading can then take minutes
// #define COLLADA_READER_DEBUG
#endif
namespace irr
{
@ -2123,16 +2124,16 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
{
// standard mesh buffer
scene::SMeshBuffer* mbuffer = new SMeshBuffer();
scene::CDynamicMeshBuffer* mbuffer = new CDynamicMeshBuffer(video::EVT_STANDARD, IndexTypeHint == EITH_16BIT ? video::EIT_16BIT : video::EIT_32BIT);
buffer = mbuffer;
core::map<video::S3DVertex, int> vertMap;
for (u32 i=0; i<polygons.size(); ++i)
{
core::array<u16> indices;
core::array<u32> indices;
const u32 vertexCount = polygons[i].Indices.size() / maxOffset;
mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount);
mbuffer->getVertexBuffer().reallocate(mbuffer->getVertexBuffer().size()+vertexCount);
// for all index/semantic groups
for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset)
@ -2208,7 +2209,7 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
else
{
indices.push_back(mbuffer->getVertexCount());
mbuffer->Vertices.push_back(vtx);
mbuffer->getVertexBuffer().push_back(vtx);
vertMap.insert(vtx, mbuffer->getVertexCount()-1);
}
} // end for all vertices
@ -2221,9 +2222,9 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
// as full tessellation is problematic
for (u32 ind = 0; ind+2 < indices.size(); ++ind)
{
mbuffer->Indices.push_back(indices[0]);
mbuffer->Indices.push_back(indices[ind+2]);
mbuffer->Indices.push_back(indices[ind+1]);
mbuffer->getIndexBuffer().push_back(indices[0]);
mbuffer->getIndexBuffer().push_back(indices[ind+2]);
mbuffer->getIndexBuffer().push_back(indices[ind+1]);
}
}
else
@ -2231,25 +2232,30 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
// it's just triangles
for (u32 ind = 0; ind < indices.size(); ind+=3)
{
mbuffer->Indices.push_back(indices[ind+2]);
mbuffer->Indices.push_back(indices[ind+1]);
mbuffer->Indices.push_back(indices[ind+0]);
mbuffer->getIndexBuffer().push_back(indices[ind+2]);
mbuffer->getIndexBuffer().push_back(indices[ind+1]);
mbuffer->getIndexBuffer().push_back(indices[ind+0]);
}
}
} // end for all polygons
if ( getIndexTypeHint() == EITH_OPTIMAL && mbuffer->getVertexCount() <= 65536 )
{
mbuffer->getIndexBuffer().setType(video::EIT_16BIT); // from 32 to 16 bit
}
}
else
{
// lightmap mesh buffer
scene::SMeshBufferLightMap* mbuffer = new SMeshBufferLightMap();
scene::CDynamicMeshBuffer* mbuffer = new CDynamicMeshBuffer(video::EVT_2TCOORDS, IndexTypeHint == EITH_16BIT ? video::EIT_16BIT : video::EIT_32BIT);
buffer = mbuffer;
for (u32 i=0; i<polygons.size(); ++i)
{
const u32 vertexCount = polygons[i].Indices.size() / maxOffset;
mbuffer->Vertices.reallocate(mbuffer->Vertices.size()+vertexCount);
mbuffer->getVertexBuffer().reallocate(mbuffer->getVertexBuffer().size()+vertexCount);
// for all vertices in array
for (u32 v=0; v<polygons[i].Indices.size(); v+=maxOffset)
{
@ -2321,31 +2327,34 @@ void CColladaFileLoader::readPolygonSection(io::IXMLReaderUTF8* reader,
}
}
mbuffer->Vertices.push_back(vtx);
mbuffer->getVertexBuffer().push_back(vtx);
} // end for all vertices
// add vertex indices
const u32 oldVertexCount = mbuffer->Vertices.size() - vertexCount;
const u32 oldVertexCount = mbuffer->getVertexBuffer().size() - vertexCount;
for (u32 face=0; face<vertexCount-2; ++face)
{
mbuffer->Indices.push_back(oldVertexCount + 0);
mbuffer->Indices.push_back(oldVertexCount + 1 + face);
mbuffer->Indices.push_back(oldVertexCount + 2 + face);
mbuffer->getIndexBuffer().push_back(oldVertexCount + 0);
mbuffer->getIndexBuffer().push_back(oldVertexCount + 1 + face);
mbuffer->getIndexBuffer().push_back(oldVertexCount + 2 + face);
}
} // end for all polygons
if ( getIndexTypeHint() == EITH_OPTIMAL && mbuffer->getVertexCount() <= 65536 )
{
mbuffer->getIndexBuffer().setType(video::EIT_16BIT); // from 32 to 16 bit
}
}
const SColladaMaterial* m = findMaterial(materialName);
if (m)
{
buffer->getMaterial() = m->Mat;
SMesh tmpmesh;
tmpmesh.addMeshBuffer(buffer);
SceneManager->getMeshManipulator()->setVertexColors(&tmpmesh,m->Mat.DiffuseColor);
SceneManager->getMeshManipulator()->setVertexColors(buffer,m->Mat.DiffuseColor);
if (m->Transparency != 1.0f)
SceneManager->getMeshManipulator()->setVertexColorAlpha(&tmpmesh,core::floor32(m->Transparency*255.0f));
SceneManager->getMeshManipulator()->setVertexColorAlpha(buffer,core::floor32(m->Transparency*255.0f));
}
// add future bind reference for the material
core::stringc meshbufferReference = geometryId+"/"+materialName;

@ -10,7 +10,6 @@
#include "IVideoDriver.h"
#include "irrString.h"
#include "SMesh.h"
#include "SMeshBuffer.h"
#include "ISceneManager.h"
#include "irrMap.h"
#include "CAttributes.h"

@ -222,8 +222,8 @@ namespace video
virtual void OnResize(const core::dimension2d<u32>& size) IRR_OVERRIDE;
//! Can be called by an IMaterialRenderer to make its work easier.
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates) IRR_OVERRIDE;
void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates);
//! Returns type of video driver
virtual E_DRIVER_TYPE getDriverType() const IRR_OVERRIDE;

@ -275,11 +275,6 @@ bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderPro
return false;
}
void CD3D9HLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates)
{
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
s32 CD3D9HLSLMaterialRenderer::getVertexShaderConstantID(const c8* name)
{
return getVariableID(true, name);

@ -47,7 +47,6 @@ public:
bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype) IRR_OVERRIDE;
// implementations for IMaterialRendererServices
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE;
virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE;
virtual s32 getPixelShaderConstantID(const c8* name) IRR_OVERRIDE;
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1) IRR_OVERRIDE;

@ -82,7 +82,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -105,7 +105,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
// if (material.MaterialType != lastMaterial.MaterialType ||
// material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
@ -175,7 +175,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -199,7 +199,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_ONE, D3DBLEND_INVSRCCOLOR);
@ -238,7 +238,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
@ -278,7 +278,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
@ -325,7 +325,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -367,7 +367,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -411,7 +411,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -436,7 +436,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -471,7 +471,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -507,7 +507,7 @@ public:
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
bool resetAllRenderstates, IMaterialRendererServices* services) IRR_OVERRIDE
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);

@ -132,7 +132,7 @@ void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material
}
}
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (BaseMaterial)
BaseMaterial->OnSetMaterial(material, lastMaterial, resetAllRenderstates, services);

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "CMeshSceneNode.h"
#include "CBufferRenderNode.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "S3DVertex.h"
@ -22,14 +23,12 @@ namespace irr
namespace scene
{
//! constructor
CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0),
PassCount(0), ReadOnlyMaterials(false)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale)
, Mesh(0), Shadow(0), ReadOnlyMaterials(false)
{
#ifdef _DEBUG
setDebugName("CMeshSceneNode");
@ -42,6 +41,7 @@ CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* m
//! destructor
CMeshSceneNode::~CMeshSceneNode()
{
setUsedBufferRenderNodes(0);
if (Shadow)
Shadow->drop();
if (Mesh)
@ -54,39 +54,60 @@ void CMeshSceneNode::OnRegisterSceneNode()
{
if (IsVisible && Mesh)
{
// because this node supports rendering of mixed mode meshes consisting of
Box = Mesh->getBoundingBox(); // in case mesh was modified, as clipping happens when registering nodes for rendering
// Because this node supports rendering of mixed mode meshes consisting of
// transparent and solid material at the same time, we need to go through all
// materials, check of what type they are and register this node for the right
// render pass according to that.
// Also some buffers might register into their own render node
video::IVideoDriver* driver = SceneManager->getVideoDriver();
PassCount = 0;
int transparentCount = 0;
int solidCount = 0;
if ( !(DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) )
{
// count transparent and solid materials in this scene node
const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size();
const bool parentRenders = NodeRegistration == ENR_DEFAULT || numMaterials < 2;
for (u32 i=0; i<numMaterials; ++i)
{
const video::SMaterial& material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
if ( driver->needsTransparentRenderPass(material) )
{
BufferRenderNodes[i]->prepareRendering(ESNRP_TRANSPARENT, parentRenders);
if ( parentRenders )
{
++transparentCount;
}
}
else
{
BufferRenderNodes[i]->prepareRendering(ESNRP_SOLID, parentRenders);
if ( parentRenders )
{
++solidCount;
if (solidCount && transparentCount)
break;
}
}
}
}
// register according to material types counted
if (solidCount)
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
SceneManager->registerNodeForRendering(this, ESNRP_SOLID);
if (transparentCount)
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
if (Shadow) // update (not render) shadow node after lights have been set up
SceneManager->registerNodeForRendering(this, ESNRP_SKY_BOX);
if (DebugDataVisible) // debug data has it's own render-stage between solid and transparence
SceneManager->registerNodeForRendering(this, ESNRP_SHADOW);
ISceneNode::OnRegisterSceneNode();
}
@ -96,68 +117,36 @@ void CMeshSceneNode::OnRegisterSceneNode()
//! renders the node.
void CMeshSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (!Mesh || !driver)
if (!Mesh )
return;
const bool isTransparentPass =
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
const E_SCENE_NODE_RENDER_PASS renderPass = SceneManager->getSceneNodeRenderPass();
++PassCount;
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
Box = Mesh->getBoundingBox();
if (Shadow && PassCount==1)
Shadow->updateShadowVolumes();
// for debug purposes only:
bool renderMeshes = true;
video::SMaterial mat;
if (DebugDataVisible && PassCount==1)
if ( renderPass == ESNRP_SKY_BOX )
{
// overwrite half transparency
if (Shadow )
Shadow->updateShadowVolumes();
}
else if ( renderPass == ESNRP_SHADOW )
{
// for debug purposes only
if ( DebugDataVisible )
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
// render with half transparency
if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
{
for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
{
mat = Materials[g];
irr::video::SMaterial mat = Materials[g];
mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
driver->setMaterial(mat);
driver->drawMeshBuffer(Mesh->getMeshBuffer(g));
}
renderMeshes = false;
}
}
// render original meshes
if (renderMeshes)
{
for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
{
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
if (mb)
{
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
const bool transparent = driver->needsTransparentRenderPass(material);
// only render transparent buffer if this is the transparent render pass
// and solid only in solid pass
if (transparent == isTransparentPass)
{
driver->setMaterial(material);
driver->drawMeshBuffer(mb);
}
}
}
}
// for debug purposes only:
if (DebugDataVisible && PassCount==1)
{
video::SMaterial m;
m.Lighting = false;
m.AntiAliasing=0;
@ -203,11 +192,44 @@ void CMeshSceneNode::render()
}
}
}
else // solid, transparent or unknown (none when render is called without SceneManager) render stages
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
// render buffers, or at least those which don't render in their own node
for (u32 i=0; i<BufferRenderNodes.size(); ++i)
{
CBufferRenderNode* bufRenderNode = BufferRenderNodes[i];
if ( bufRenderNode->getDoesParentRender())
{
E_SCENE_NODE_RENDER_PASS bufferRenderPass = bufRenderNode->getRenderPass();
// render() called without OnRegisterSceneNode, but still wants to render in a specific render stage
// Note: Not checking transparency every time, as check got slightly expensive (I think it's prone to cache-misses)
if ( bufferRenderPass == ESNRP_NONE && renderPass > ESNRP_NONE )
{
if ( driver->needsTransparentRenderPass(getMaterial(i)) )
{
bufferRenderPass = ESNRP_TRANSPARENT;
}
else
{
bufferRenderPass = ESNRP_SOLID;
}
}
if ( bufRenderNode->getRenderPass() == renderPass )
bufRenderNode->renderBuffer(driver);
}
}
}
}
//! Removes a child from this scene node.
//! Implemented here, to be able to remove the shadow properly, if there is one,
//! or to remove attached childs.
//! or to remove attached children.
bool CMeshSceneNode::removeChild(ISceneNode* child)
{
if (child && Shadow == child)
@ -256,6 +278,22 @@ u32 CMeshSceneNode::getMaterialCount() const
return Materials.size();
}
void CMeshSceneNode::setUsedBufferRenderNodes(irr::u32 num)
{
if ( BufferRenderNodes.size() > num )
{
for ( irr::u32 i=num; i<BufferRenderNodes.size(); ++i )
BufferRenderNodes[i]->drop();
BufferRenderNodes.erase(num, BufferRenderNodes.size()-num);
}
else if ( BufferRenderNodes.size() < num )
{
for ( irr::u32 i=BufferRenderNodes.size(); i < num; ++i )
{
BufferRenderNodes.push_back( new CBufferRenderNode(*this, SceneManager, i) );
}
}
}
//! Sets a new mesh
void CMeshSceneNode::setMesh(IMesh* mesh)
@ -264,10 +302,16 @@ void CMeshSceneNode::setMesh(IMesh* mesh)
{
mesh->grab();
if (Mesh)
{
Mesh->drop();
}
Mesh = mesh;
// Note: Mesh can change amount of meshbuffers later and we don't handle that so far so that would cause trouble
// For now assuming users call setMesh again in that case
copyMaterials();
setUsedBufferRenderNodes(Mesh ? Mesh->getMeshBufferCount() : 0);
}
}

@ -12,6 +12,7 @@ namespace irr
{
namespace scene
{
class CBufferRenderNode;
class CMeshSceneNode : public IMeshSceneNode
{
@ -83,6 +84,7 @@ namespace scene
protected:
void setUsedBufferRenderNodes(irr::u32 num);
void copyMaterials();
core::array<video::SMaterial> Materials;
@ -92,8 +94,9 @@ namespace scene
IMesh* Mesh;
IShadowVolumeSceneNode* Shadow;
s32 PassCount;
bool ReadOnlyMaterials;
core::array<scene::CBufferRenderNode*> BufferRenderNodes;
};
} // end namespace scene

@ -207,7 +207,7 @@ namespace video
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const IRR_OVERRIDE;
//! Can be called by an IMaterialRenderer to make its work easier.
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) IRR_OVERRIDE;
void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates);
//! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call.
void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates);

@ -340,14 +340,6 @@ bool COGLES2MaterialRenderer::linkProgram()
return true;
}
void COGLES2MaterialRenderer::setBasicRenderStates(const SMaterial& material,
const SMaterial& lastMaterial,
bool resetAllRenderstates)
{
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
void COGLES2MaterialRenderer::startUseProgram()
{
Driver->getCacheHandler()->setProgram(Program);

@ -53,8 +53,6 @@ public:
virtual s32 getRenderCapability() const IRR_OVERRIDE;
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE;
virtual void startUseProgram() IRR_OVERRIDE;
virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE;

@ -201,8 +201,8 @@ namespace video
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const IRR_OVERRIDE;
//! Can be called by an IMaterialRenderer to make its work easier.
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
bool resetAllRenderstates) IRR_OVERRIDE;
void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
bool resetAllRenderstates);
//! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call.
virtual void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates);

@ -272,8 +272,8 @@ namespace video
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const IRR_OVERRIDE;
//! Can be called by an IMaterialRenderer to make its work easier.
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
bool resetAllRenderstates) IRR_OVERRIDE;
void setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial,
bool resetAllRenderstates);
//! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call.
virtual void setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates);

@ -563,15 +563,6 @@ bool COpenGLSLMaterialRenderer::linkProgram()
return true;
}
void COpenGLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material,
const SMaterial& lastMaterial,
bool resetAllRenderstates)
{
// forward
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
void COpenGLSLMaterialRenderer::startUseProgram()
{
if (Program2)

@ -72,7 +72,6 @@ public:
}
// implementations for IMaterialRendererServices
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE;
virtual void startUseProgram() IRR_OVERRIDE;
virtual void stopUseProgram() IRR_OVERRIDE;
virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE;

@ -264,9 +264,9 @@ namespace video
//IMaterialRendererService
virtual void setBasicRenderStates(const SMaterial& material,
void setBasicRenderStates(const SMaterial& material,
const SMaterial& lastMaterial,
bool resetAllRenderstates) IRR_OVERRIDE;
bool resetAllRenderstates);
//pass BaseMaterialID
void setFallback_Material(E_MATERIAL_TYPE fallback_MaterialType

@ -299,7 +299,7 @@ void IBurningShader::OnSetMaterial(const SMaterial& material, const SMaterial& l
{
if (Driver)
Driver->setFallback_Material(BaseMaterial, VertexShaderProgram_buildin);
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
if (CallBack)
CallBack->OnSetMaterial(material);
@ -331,13 +331,6 @@ IShaderConstantSetCallBack* IBurningShader::getShaderConstantSetCallBack() const
return CallBack;
}
// implementations for the render services
void IBurningShader::setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates)
{
// forward
Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
}
static BurningUniform _empty = { "null",BL_VERTEX_FLOAT,{0.f,0.f,0.f,0.f} };
const f32* IBurningShader::getUniform(const c8* name, EBurningUniformFlags flags) const
{

@ -334,7 +334,6 @@ public:
virtual IShaderConstantSetCallBack* getShaderConstantSetCallBack() const IRR_OVERRIDE;
// implementations for the render services
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial, bool resetAllRenderstates) IRR_OVERRIDE;
virtual s32 getVertexShaderConstantID(const c8* name) IRR_OVERRIDE;
virtual s32 getPixelShaderConstantID(const c8* name) IRR_OVERRIDE;
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount = 1) IRR_OVERRIDE;

@ -1038,6 +1038,7 @@
<ClInclude Include="burning_shader_compile_verify.h" />
<ClInclude Include="CB3DMeshWriter.h" />
<ClInclude Include="CBlit.h" />
<ClInclude Include="CBufferRenderNode.h" />
<ClInclude Include="CD3D9RenderTarget.h" />
<ClInclude Include="CDefaultSceneNodeAnimatorFactory.h" />
<ClInclude Include="CDefaultSceneNodeFactory.h" />

@ -1489,6 +1489,9 @@
<ClInclude Include="..\..\include\ESceneNodeUpdateAbs.h">
<Filter>include\scene</Filter>
</ClInclude>
<ClInclude Include="CBufferRenderNode.h">
<Filter>Irrlicht\scene\sceneNodes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\changes.txt">

@ -776,6 +776,7 @@
<ClInclude Include="burning_shader_compile_verify.h" />
<ClInclude Include="CB3DMeshWriter.h" />
<ClInclude Include="CBlit.h" />
<ClInclude Include="CBufferRenderNode.h" />
<ClInclude Include="CD3D9RenderTarget.h" />
<ClInclude Include="CDefaultSceneNodeAnimatorFactory.h" />
<ClInclude Include="CDefaultSceneNodeFactory.h" />

@ -1438,6 +1438,9 @@
<ClInclude Include="..\..\include\EDeviceTypes.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="CBufferRenderNode.h">
<Filter>Irrlicht\scene\sceneNodes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\changes.txt">

@ -1,4 +1,4 @@
Tests finished. 72 tests of 72 passed.
Compiled as DEBUG
Test suite pass at GMT Fri Apr 21 14:37:22 2023
Test suite pass at GMT Fri May 05 18:39:44 2023