mirror of
https://github.com/minetest/irrlicht.git
synced 2025-06-28 06:20:21 +02:00
Unify checks if materials should use transparent render pass with new IVideoDriver::needsTransparentRenderPass function.
Fix bug that AnimatedMeshSceneNode ignored ReadOnlyMaterials flag when checking materials for transparent render passes. Make IVideoDriver::getMaterialRenderer const. Fix bugs in COctreeSceneNode, CMeshSceneNode and CAnimatedMeshSceneNode where check for transparency in OnRegisterSceneNode() and in render() where no longer identical (those got added after Irrlicht 1.8). Some notes for future: - Maybe we should have a getRenderPass instead of just needsTransparentRenderPass, but this way the code didn't need so much changes and behaves (aside from fixes) pretty much as before. - Still wondering if the default implementation in CNullDriver::needsTransparentRenderPass should always return false when SMaterial.ZWriteEnable is set to EZW_ON. This might be nicer with another material flag. Thought then we might want a material enum to choose the renderpass and that's more work. And we get some recursion as needsTransparentRenderPass might want to check result of getWriteZBuffer which calls needsTransparentRenderPass, so we might need a second function or an additional flag there. But return false when SMaterial.ZWriteEnable == EZW_ON could still be done as EZW_ON is a new flag so existing behavior shouldn't break. I just don't know right now if having an extra render pass for transparent nodes might still make sense even when zbuffer is not written or if that's really the only reason to do that. Any feedback anyone? git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6033 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
@ -149,7 +149,7 @@ void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
|
||||
|
||||
void CAnimatedMeshSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
if (IsVisible && Mesh)
|
||||
{
|
||||
// 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
|
||||
@ -163,12 +163,12 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
|
||||
int solidCount = 0;
|
||||
|
||||
// count transparent and solid materials in this scene node
|
||||
for (u32 i=0; i<Materials.size(); ++i)
|
||||
const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size();
|
||||
for (u32 i=0; i<numMaterials; ++i)
|
||||
{
|
||||
video::IMaterialRenderer* rnd =
|
||||
driver->getMaterialRenderer(Materials[i].MaterialType);
|
||||
const video::SMaterial& material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
|
||||
|
||||
if ((rnd && rnd->isTransparent()) || Materials[i].isTransparent())
|
||||
if ( driver->needsTransparentRenderPass(Materials[i]) )
|
||||
++transparentCount;
|
||||
else
|
||||
++solidCount;
|
||||
@ -274,7 +274,7 @@ void CAnimatedMeshSceneNode::render()
|
||||
return;
|
||||
|
||||
|
||||
bool isTransparentPass =
|
||||
const bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
++PassCount;
|
||||
@ -329,8 +329,7 @@ void CAnimatedMeshSceneNode::render()
|
||||
{
|
||||
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
|
||||
{
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType);
|
||||
bool transparent = (rnd && rnd->isTransparent());
|
||||
const bool transparent = driver->needsTransparentRenderPass(Materials[i]);
|
||||
|
||||
// only render transparent buffer if this is the transparent render pass
|
||||
// and solid only in solid pass
|
||||
|
@ -3580,6 +3580,11 @@ bool CD3D9Driver::queryTextureFormat(ECOLOR_FORMAT format) const
|
||||
return getD3DFormatFromColorFormat(format) != D3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
bool CD3D9Driver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
|
||||
{
|
||||
return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation();
|
||||
}
|
||||
|
||||
u32 CD3D9Driver::getD3DBlend(E_BLEND_FACTOR factor) const
|
||||
{
|
||||
u32 r = 0;
|
||||
|
@ -300,6 +300,9 @@ namespace video
|
||||
//! Check if the driver supports creating textures with the given color format
|
||||
virtual bool queryTextureFormat(ECOLOR_FORMAT format) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Used by some SceneNodes to check if a material should be rendered in the transparent render pass
|
||||
virtual bool needsTransparentRenderPass(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer as D3D color value. */
|
||||
D3DFORMAT getD3DColorFormat() const;
|
||||
|
@ -52,7 +52,7 @@ CMeshSceneNode::~CMeshSceneNode()
|
||||
//! frame
|
||||
void CMeshSceneNode::OnRegisterSceneNode()
|
||||
{
|
||||
if (IsVisible)
|
||||
if (IsVisible && Mesh)
|
||||
{
|
||||
// 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
|
||||
@ -66,41 +66,18 @@ void CMeshSceneNode::OnRegisterSceneNode()
|
||||
int solidCount = 0;
|
||||
|
||||
// count transparent and solid materials in this scene node
|
||||
if (ReadOnlyMaterials && Mesh)
|
||||
const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size();
|
||||
for (u32 i=0; i<numMaterials; ++i)
|
||||
{
|
||||
// count mesh materials
|
||||
const video::SMaterial& material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
|
||||
|
||||
for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
video::IMaterialRenderer* rnd = mb ? driver->getMaterialRenderer(mb->getMaterial().MaterialType) : 0;
|
||||
if ( driver->needsTransparentRenderPass(Materials[i]) )
|
||||
++transparentCount;
|
||||
else
|
||||
++solidCount;
|
||||
|
||||
if (rnd && rnd->isTransparent())
|
||||
++transparentCount;
|
||||
else
|
||||
++solidCount;
|
||||
|
||||
if (solidCount && transparentCount)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// count copied materials
|
||||
|
||||
for (u32 i=0; i<Materials.size(); ++i)
|
||||
{
|
||||
video::IMaterialRenderer* rnd =
|
||||
driver->getMaterialRenderer(Materials[i].MaterialType);
|
||||
|
||||
if ((rnd && rnd->isTransparent()) || Materials[i].isTransparent())
|
||||
++transparentCount;
|
||||
else
|
||||
++solidCount;
|
||||
|
||||
if (solidCount && transparentCount)
|
||||
break;
|
||||
}
|
||||
if (solidCount && transparentCount)
|
||||
break;
|
||||
}
|
||||
|
||||
// register according to material types counted
|
||||
@ -124,7 +101,7 @@ void CMeshSceneNode::render()
|
||||
if (!Mesh || !driver)
|
||||
return;
|
||||
|
||||
bool isTransparentPass =
|
||||
const bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
++PassCount;
|
||||
@ -165,8 +142,7 @@ void CMeshSceneNode::render()
|
||||
{
|
||||
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
|
||||
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType);
|
||||
bool transparent = (rnd && rnd->isTransparent());
|
||||
const bool transparent = driver->needsTransparentRenderPass(material);
|
||||
|
||||
// only render transparent buffer if this is the transparent render pass
|
||||
// and solid only in solid pass
|
||||
|
@ -2325,7 +2325,7 @@ void CNullDriver::deleteMaterialRenders()
|
||||
|
||||
|
||||
//! Returns pointer to material renderer or null
|
||||
IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx)
|
||||
IMaterialRenderer* CNullDriver::getMaterialRenderer(u32 idx) const
|
||||
{
|
||||
if ( idx < MaterialRenderers.size() )
|
||||
return MaterialRenderers[idx].Renderer;
|
||||
@ -2749,6 +2749,22 @@ core::dimension2du CNullDriver::getMaxTextureSize() const
|
||||
return core::dimension2du(0x10000,0x10000); // maybe large enough
|
||||
}
|
||||
|
||||
bool CNullDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
|
||||
{
|
||||
// TODO: I suspect it would be nice if the material had an enum for further control.
|
||||
// Especially it probably makes sense to allow disabling transparent render pass as soon as material.ZWriteEnable is on.
|
||||
// But then we might want an enum for the renderpass in material instead of just a transparency flag in material - and that's more work.
|
||||
// Or we could at least set return false when material.ZWriteEnable is EZW_ON? Still considering that...
|
||||
// Be careful - this function is deeply connected to getWriteZBuffer as transparent render passes are usually about rendering with
|
||||
// zwrite disabled and getWriteZBuffer calls this function.
|
||||
|
||||
video::IMaterialRenderer* rnd = getMaterialRenderer(material.MaterialType);
|
||||
if (rnd && rnd->isTransparent())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//! Color conversion convenience function
|
||||
/** Convert an image (as array of pixels) from source to destination
|
||||
|
@ -533,7 +533,7 @@ namespace video
|
||||
s32 userData=0) _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns pointer to material renderer or null
|
||||
virtual IMaterialRenderer* getMaterialRenderer(u32 idx) _IRR_OVERRIDE_;
|
||||
virtual IMaterialRenderer* getMaterialRenderer(u32 idx) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Returns amount of currently available material renderers.
|
||||
virtual u32 getMaterialRendererCount() const _IRR_OVERRIDE_;
|
||||
@ -667,6 +667,9 @@ namespace video
|
||||
//! Returns the maximum texture size supported.
|
||||
virtual core::dimension2du getMaxTextureSize() const _IRR_OVERRIDE_;
|
||||
|
||||
//! Used by some SceneNodes to check if a material should be rendered in the transparent render pass
|
||||
virtual bool needsTransparentRenderPass(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Color conversion convenience function
|
||||
/** Convert an image (as array of pixels) from source to destination
|
||||
array, thereby converting the color format. The pixel size is
|
||||
@ -743,14 +746,14 @@ namespace video
|
||||
return (f32) getAverage ( p[(y * pitch) + x] );
|
||||
}
|
||||
|
||||
inline bool getWriteZBuffer(const SMaterial&material) const
|
||||
inline bool getWriteZBuffer(const SMaterial& material) const
|
||||
{
|
||||
switch ( material.ZWriteEnable )
|
||||
{
|
||||
case video::EZW_OFF:
|
||||
return false;
|
||||
case video::EZW_AUTO:
|
||||
return AllowZWriteOnTransparent || !material.isTransparent();
|
||||
return AllowZWriteOnTransparent || ! needsTransparentRenderPass(material);
|
||||
case video::EZW_ON:
|
||||
return true;
|
||||
}
|
||||
|
@ -79,10 +79,7 @@ void COctreeSceneNode::OnRegisterSceneNode()
|
||||
// count transparent and solid materials in this scene node
|
||||
for (u32 i=0; i<Materials.size(); ++i)
|
||||
{
|
||||
const video::IMaterialRenderer* const rnd =
|
||||
driver->getMaterialRenderer(Materials[i].MaterialType);
|
||||
|
||||
if ((rnd && rnd->isTransparent()) || Materials[i].isTransparent())
|
||||
if (driver->needsTransparentRenderPass(Materials[i]))
|
||||
++transparentCount;
|
||||
else
|
||||
++solidCount;
|
||||
@ -145,7 +142,7 @@ void COctreeSceneNode::render()
|
||||
if (!camera)
|
||||
return;
|
||||
|
||||
bool isTransparentPass =
|
||||
const bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
++PassCount;
|
||||
|
||||
@ -188,8 +185,7 @@ void COctreeSceneNode::render()
|
||||
if ( 0 == d[i].CurrentSize )
|
||||
continue;
|
||||
|
||||
const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType);
|
||||
const bool transparent = (rnd && rnd->isTransparent());
|
||||
const bool transparent = driver->needsTransparentRenderPass(Materials[i]);
|
||||
|
||||
// only render transparent buffer if this is the transparent render pass
|
||||
// and solid only in solid pass
|
||||
|
@ -3617,6 +3617,11 @@ bool COpenGLDriver::queryTextureFormat(ECOLOR_FORMAT format) const
|
||||
return getColorFormatParameters(format, dummyInternalFormat, dummyPixelFormat, dummyPixelType, &dummyConverter);
|
||||
}
|
||||
|
||||
bool COpenGLDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
|
||||
{
|
||||
return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation();
|
||||
}
|
||||
|
||||
//! Only used by the internal engine. Used to notify the driver that
|
||||
//! the window was resized.
|
||||
void COpenGLDriver::OnResize(const core::dimension2d<u32>& size)
|
||||
|
@ -382,6 +382,9 @@ namespace video
|
||||
//! Check if the driver supports creating textures with the given color format
|
||||
virtual bool queryTextureFormat(ECOLOR_FORMAT format) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Used by some SceneNodes to check if a material should be rendered in the transparent render pass
|
||||
virtual bool needsTransparentRenderPass(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Convert E_PRIMITIVE_TYPE to OpenGL equivalent
|
||||
GLenum primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const;
|
||||
|
||||
|
@ -1377,9 +1377,7 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE
|
||||
taken = 0;
|
||||
for (u32 i=0; i<count; ++i)
|
||||
{
|
||||
video::IMaterialRenderer* rnd =
|
||||
Driver->getMaterialRenderer(node->getMaterial(i).MaterialType);
|
||||
if ((rnd && rnd->isTransparent()) || node->getMaterial(i).isTransparent())
|
||||
if (Driver->needsTransparentRenderPass(node->getMaterial(i)))
|
||||
{
|
||||
// register as transparent node
|
||||
TransparentNodeEntry e(node, camWorldPos);
|
||||
|
@ -178,7 +178,7 @@ void CBurningVideoDriver::setCurrentShader()
|
||||
|
||||
bool zMaterialTest = Material.org.ZBuffer != ECFN_DISABLED &&
|
||||
Material.org.ZWriteEnable != video::EZW_OFF &&
|
||||
getWriteZBuffer(Material.org);
|
||||
( AllowZWriteOnTransparent || !Material.org.isTransparent() );
|
||||
|
||||
EBurningFFShader shader = zMaterialTest ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ;
|
||||
|
||||
@ -2381,6 +2381,11 @@ bool CBurningVideoDriver::queryTextureFormat(ECOLOR_FORMAT format) const
|
||||
return format == BURNINGSHADER_COLOR_FORMAT;
|
||||
}
|
||||
|
||||
bool CBurningVideoDriver::needsTransparentRenderPass(const irr::video::SMaterial& material) const
|
||||
{
|
||||
return CNullDriver::needsTransparentRenderPass(material) || material.isTransparent();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
@ -164,6 +164,9 @@ namespace video
|
||||
//! Check if the driver supports creating textures with the given color format
|
||||
virtual bool queryTextureFormat(ECOLOR_FORMAT format) const _IRR_OVERRIDE_;
|
||||
|
||||
//! Used by some SceneNodes to check if a material should be rendered in the transparent render pass
|
||||
virtual bool needsTransparentRenderPass(const irr::video::SMaterial& material) const _IRR_OVERRIDE_;
|
||||
|
||||
IDepthBuffer * getDepthBuffer () { return DepthBuffer; }
|
||||
IStencilBuffer * getStencilBuffer () { return StencilBuffer; }
|
||||
|
||||
|
Reference in New Issue
Block a user