- Added separate blending support for both OpenGL and D3D9.

- Added blend factor to SMaterial.
- Improved transparent nodes handling.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4794 dfc29bdd-3216-0410-991c-e03cc46cb475
master
nadro 2014-04-25 01:19:38 +00:00
parent 6058c27631
commit 9bad8de603
19 changed files with 800 additions and 358 deletions

View File

@ -1,6 +1,10 @@
--------------------------
Changes in 1.9 (not yet released)
- Added support for separate blending in OpenGL and D3D9 drivers.
- Added pack_textureBlendFuncSeparate and unpack_textureBlendFuncSeparate functions, which allow to use separate blending functions in OpenGL.
- Added BlendFactor field to SMaterial which allow user to set blending factor per SMaterial set call without use EMT_ONETEXTURE_BLEND type.
- Fixed issue with blending operation set to EBO_NONE and some transparent material types.
- Add a code profiler (stop-watch style)
- Add override font to IGUITable
- IGUITable can now disable the active column.

View File

@ -115,6 +115,9 @@ namespace video
//! Support for different blend functions. Without, only ADD is available
EVDF_BLEND_OPERATIONS,
//! Support for separate blending for RGB and Alpha.
EVDF_BLEND_SEPARATE,
//! Support for texture coord transformation via texture matrix
EVDF_TEXTURE_MATRIX,

View File

@ -84,7 +84,10 @@ namespace video
EMF_BLEND_OPERATION = 0x40000,
//! Flag for polygon offset
EMF_POLYGON_OFFSET = 0x80000
EMF_POLYGON_OFFSET = 0x80000,
//! Flag for blend factor
EMF_BLEND_FACTOR = 0x160000
};
} // end namespace video

View File

@ -197,6 +197,7 @@ namespace video
case EMF_COLOR_MATERIAL: material.ColorMaterial = Material.ColorMaterial; break;
case EMF_USE_MIP_MAPS: material.UseMipMaps = Material.UseMipMaps; break;
case EMF_BLEND_OPERATION: material.BlendOperation = Material.BlendOperation; break;
case EMF_BLEND_FACTOR: material.BlendFactor = Material.BlendFactor; break;
case EMF_POLYGON_OFFSET:
material.PolygonOffsetDirection = Material.PolygonOffsetDirection;
material.PolygonOffsetFactor = Material.PolygonOffsetFactor; break;

View File

@ -113,27 +113,53 @@ namespace video
EAS_TEXTURE
};
//! EMT_ONETEXTURE_BLEND: pack srcFact, dstFact, Modulate and alpha source to MaterialTypeParam
//! Pack srcFact, dstFact, Modulate and alpha source to MaterialTypeParam or BlendFactor
/** alpha source can be an OR'ed combination of E_ALPHA_SOURCE values. */
inline f32 pack_textureBlendFunc ( const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact, const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE )
inline f32 pack_textureBlendFunc(const E_BLEND_FACTOR srcFact, const E_BLEND_FACTOR dstFact,
const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE)
{
const u32 tmp = (alphaSource << 12) | (modulate << 8) | (srcFact << 4) | dstFact;
const u32 tmp = (alphaSource << 20) | (modulate << 16) | (srcFact << 12) | (dstFact << 8) | (srcFact << 4) | dstFact;
return FR(tmp);
}
//! EMT_ONETEXTURE_BLEND: unpack srcFact & dstFact and Modulo to MaterialTypeParam
//! Pack srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, Modulate and alpha source to MaterialTypeParam or BlendFactor
/** alpha source can be an OR'ed combination of E_ALPHA_SOURCE values. */
inline f32 pack_textureBlendFuncSeparate(const E_BLEND_FACTOR srcRGBFact, const E_BLEND_FACTOR dstRGBFact,
const E_BLEND_FACTOR srcAlphaFact, const E_BLEND_FACTOR dstAlphaFact,
const E_MODULATE_FUNC modulate=EMFN_MODULATE_1X, const u32 alphaSource=EAS_TEXTURE)
{
const u32 tmp = (alphaSource << 20) | (modulate << 16) | (srcAlphaFact << 12) | (dstAlphaFact << 8) | (srcRGBFact << 4) | dstRGBFact;
return FR(tmp);
}
//! Unpack srcFact, dstFact, modulo and alphaSource factors
/** The fields don't use the full byte range, so we could pack even more... */
inline void unpack_textureBlendFunc ( E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact,
E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param )
inline void unpack_textureBlendFunc(E_BLEND_FACTOR &srcFact, E_BLEND_FACTOR &dstFact,
E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param)
{
const u32 state = IR(param);
alphaSource = (state & 0x0000F000) >> 12;
modulo = E_MODULATE_FUNC( ( state & 0x00000F00 ) >> 8 );
alphaSource = (state & 0x00F00000) >> 20;
modulo = E_MODULATE_FUNC( ( state & 0x000F0000 ) >> 16 );
srcFact = E_BLEND_FACTOR ( ( state & 0x000000F0 ) >> 4 );
dstFact = E_BLEND_FACTOR ( ( state & 0x0000000F ) );
}
//! EMT_ONETEXTURE_BLEND: has BlendFactor Alphablending
//! Unpack srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo and alphaSource factors
/** The fields don't use the full byte range, so we could pack even more... */
inline void unpack_textureBlendFuncSeparate(E_BLEND_FACTOR &srcRGBFact, E_BLEND_FACTOR &dstRGBFact,
E_BLEND_FACTOR &srcAlphaFact, E_BLEND_FACTOR &dstAlphaFact,
E_MODULATE_FUNC &modulo, u32& alphaSource, const f32 param)
{
const u32 state = IR(param);
alphaSource = (state & 0x00F00000) >> 20;
modulo = E_MODULATE_FUNC( ( state & 0x000F0000 ) >> 16 );
srcAlphaFact = E_BLEND_FACTOR ( ( state & 0x0000F000 ) >> 12 );
dstAlphaFact = E_BLEND_FACTOR ( ( state & 0x00000F00 ) >> 8 );
srcRGBFact = E_BLEND_FACTOR ( ( state & 0x000000F0 ) >> 4 );
dstRGBFact = E_BLEND_FACTOR ( ( state & 0x0000000F ) );
}
//! has blend factor alphablending
inline bool textureBlendFunc_hasAlpha ( const E_BLEND_FACTOR factor )
{
switch ( factor )
@ -234,7 +260,7 @@ namespace video
EmissiveColor(0,0,0,0), SpecularColor(255,255,255,255),
Shininess(0.0f), MaterialTypeParam(0.0f), MaterialTypeParam2(0.0f), Thickness(1.0f),
ZBuffer(ECFN_LESSEQUAL), AntiAliasing(EAAM_SIMPLE), ColorMask(ECP_ALL),
ColorMaterial(ECM_DIFFUSE), BlendOperation(EBO_NONE),
ColorMaterial(ECM_DIFFUSE), BlendOperation(EBO_NONE), BlendFactor(0.0f),
PolygonOffsetFactor(0), PolygonOffsetDirection(EPO_FRONT),
Wireframe(false), PointCloud(false), GouraudShading(true),
Lighting(true), ZWriteEnable(true), BackfaceCulling(true), FrontfaceCulling(false),
@ -288,6 +314,7 @@ namespace video
ColorMask = other.ColorMask;
ColorMaterial = other.ColorMaterial;
BlendOperation = other.BlendOperation;
BlendFactor = other.BlendFactor;
PolygonOffsetFactor = other.PolygonOffsetFactor;
PolygonOffsetDirection = other.PolygonOffsetDirection;
UseMipMaps = other.UseMipMaps;
@ -391,10 +418,15 @@ namespace video
u8 ColorMaterial:3;
//! Store the blend operation of choice
/** Values to be chosen from E_BLEND_OPERATION. The actual way to use this value
is not yet determined, so ignore it for now. */
/** Values to be chosen from E_BLEND_OPERATION. */
E_BLEND_OPERATION BlendOperation:4;
//! Store the blend factors
/** textureBlendFunc/textureBlendFuncSeparate functions should be used to write
properly blending factors to this parameter. If you use EMT_ONETEXTURE_BLEND
type for this material, this field should be equal to MaterialTypeParam. */
f32 BlendFactor;
//! Factor specifying how far the polygon offset should be made
/** Specifying 0 disables the polygon offset. The direction is specified spearately.
The factor can be from 0 to 7.*/
@ -559,6 +591,8 @@ namespace video
UseMipMaps = value; break;
case EMF_BLEND_OPERATION:
BlendOperation = value?EBO_ADD:EBO_NONE; break;
case EMF_BLEND_FACTOR:
break;
case EMF_POLYGON_OFFSET:
PolygonOffsetFactor = value?1:0;
PolygonOffsetDirection = EPO_BACK;
@ -620,6 +654,8 @@ namespace video
return UseMipMaps;
case EMF_BLEND_OPERATION:
return BlendOperation != EBO_NONE;
case EMF_BLEND_FACTOR:
return BlendFactor != 0.f;
case EMF_POLYGON_OFFSET:
return PolygonOffsetFactor != 0;
}
@ -656,6 +692,7 @@ namespace video
ColorMask != b.ColorMask ||
ColorMaterial != b.ColorMaterial ||
BlendOperation != b.BlendOperation ||
BlendFactor != b.BlendFactor ||
PolygonOffsetFactor != b.PolygonOffsetFactor ||
PolygonOffsetDirection != b.PolygonOffsetDirection ||
UseMipMaps != b.UseMipMaps;
@ -671,6 +708,31 @@ namespace video
\return True if the materials are equal, else false. */
inline bool operator==(const SMaterial& b) const
{ return !(b!=*this); }
bool isTransparent() const
{
bool status = false;
if (BlendOperation != EBO_NONE)
{
E_BLEND_FACTOR srcRGBFact = EBF_ZERO;
E_BLEND_FACTOR dstRGBFact = EBF_ZERO;
E_BLEND_FACTOR srcAlphaFact = EBF_ZERO;
E_BLEND_FACTOR dstAlphaFact = EBF_ZERO;
E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;
u32 alphaSource = 0;
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, BlendFactor);
if (textureBlendFunc_hasAlpha(srcRGBFact) || textureBlendFunc_hasAlpha(dstRGBFact) ||
textureBlendFunc_hasAlpha(srcAlphaFact) || textureBlendFunc_hasAlpha(dstAlphaFact))
{
status = true;
}
}
return status;
}
};
//! global const identity Material

View File

@ -164,7 +164,7 @@ void CAnimatedMeshSceneNode::OnRegisterSceneNode()
video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(Materials[i].MaterialType);
if ((rnd && rnd->isTransparent()) || Materials[i].BlendOperation != video::EBO_NONE)
if ((rnd && rnd->isTransparent()) || Materials[i].isTransparent())
++transparentCount;
else
++solidCount;

View File

@ -26,7 +26,7 @@ namespace video
//! constructor
CD3D8Driver::CD3D8Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io)
: CNullDriver(io, params.WindowSize), CurrentRenderMode(ERM_NONE),
: CNullDriver(io, params.WindowSize), BridgeCalls(0), CurrentRenderMode(ERM_NONE),
ResetRenderStates(true), Transformation3DChanged(false),
D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0),
WindowId(0), SceneSourceRect(0),
@ -66,6 +66,8 @@ CD3D8Driver::~CD3D8Driver()
{
deleteMaterialRenders();
delete BridgeCalls;
// drop d3d8
if (pID3DDevice)
@ -369,6 +371,9 @@ bool CD3D8Driver::initDriver(HWND hwnd, bool pureSoftware)
Params.Stencilbuffer = false;
}
if (!BridgeCalls)
BridgeCalls = new CD3D8CallBridge(pID3DDevice);
// set default vertex shader
setVertexShader(EVT_STANDARD);
@ -608,6 +613,9 @@ bool CD3D8Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
case EVDF_COLOR_MASK:
return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0;
case EVDF_BLEND_OPERATIONS:
return true;
case EVDF_BLEND_SEPARATE:
return false;
case EVDF_TEXTURE_MATRIX:
return true;
case EVDF_TEXTURE_COMPRESSED_DXT:
@ -1533,7 +1541,7 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria
// zwrite
// if (resetAllRenderstates || lastmaterial.ZWriteEnable != material.ZWriteEnable)
{
if (material.ZWriteEnable && (AllowZWriteOnTransparent || (material.BlendOperation == EBO_NONE &&
if (material.ZWriteEnable && (AllowZWriteOnTransparent || (!material.isTransparent() &&
!MaterialRenderers[material.MaterialType].Renderer->isTransparent())))
{
pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
@ -1591,40 +1599,50 @@ void CD3D8Driver::setBasicRenderStates(const SMaterial& material, const SMateria
}
// Blend Operation
if (resetAllRenderstates || lastmaterial.BlendOperation != material.BlendOperation)
{
if (material.BlendOperation==EBO_NONE)
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
else
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
if (material.BlendOperation == EBO_NONE)
BridgeCalls->setBlend(false);
else
{
BridgeCalls->setBlend(true);
if (queryFeature(EVDF_BLEND_OPERATIONS))
{
switch (material.BlendOperation)
{
case EBO_MAX:
case EBO_MAX_FACTOR:
case EBO_MAX_ALPHA:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX);
break;
case EBO_MIN:
case EBO_MIN_FACTOR:
case EBO_MIN_ALPHA:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN);
break;
case EBO_SUBTRACT:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
break;
case EBO_REVSUBTRACT:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
break;
default:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
break;
}
if (queryFeature(EVDF_BLEND_OPERATIONS))
{
switch (material.BlendOperation)
{
case EBO_MAX:
case EBO_MAX_FACTOR:
case EBO_MAX_ALPHA:
BridgeCalls->setBlendOperation(D3DBLENDOP_MAX);
break;
case EBO_MIN:
case EBO_MIN_FACTOR:
case EBO_MIN_ALPHA:
BridgeCalls->setBlendOperation(D3DBLENDOP_MIN);
break;
case EBO_SUBTRACT:
BridgeCalls->setBlendOperation(D3DBLENDOP_SUBTRACT);
break;
case EBO_REVSUBTRACT:
BridgeCalls->setBlendOperation(D3DBLENDOP_REVSUBTRACT);
break;
default:
BridgeCalls->setBlendOperation(D3DBLENDOP_ADD);
break;
}
}
}
}
// Blend Factor
if (material.BlendFactor != 0.f)
{
E_BLEND_FACTOR srcFact = EBF_ZERO;
E_BLEND_FACTOR dstFact = EBF_ZERO;
E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;
u32 alphaSource = 0;
unpack_textureBlendFunc(srcFact, dstFact, modulo, alphaSource, material.BlendFactor);
BridgeCalls->setBlendFunc(getD3DBlend(srcFact), getD3DBlend(dstFact));
}
// Polygon offset
@ -1796,9 +1814,8 @@ void CD3D8Driver::setRenderStatesStencilFillMode(bool alpha)
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
BridgeCalls->setBlend(true);
BridgeCalls->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
}
else
{
@ -1806,7 +1823,7 @@ void CD3D8Driver::setRenderStatesStencilFillMode(bool alpha)
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
BridgeCalls->setBlend(false);
}
}
@ -1868,12 +1885,11 @@ void CD3D8Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan
if (alpha || alphaChannel)
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
BridgeCalls->setBlend(true);
BridgeCalls->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
}
else
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
BridgeCalls->setBlend(false);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
@ -2433,6 +2449,96 @@ core::dimension2du CD3D8Driver::getMaxTextureSize() const
}
u32 CD3D8Driver::getD3DBlend(E_BLEND_FACTOR factor) const
{
u32 r = 0;
switch ( factor )
{
case EBF_ZERO: r = D3DBLEND_ZERO; break;
case EBF_ONE: r = D3DBLEND_ONE; break;
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
}
return r;
}
u32 CD3D8Driver::getD3DModulate(E_MODULATE_FUNC func) const
{
u32 r = D3DTOP_MODULATE;
switch ( func )
{
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
}
return r;
}
CD3D8CallBridge* CD3D8Driver::getBridgeCalls() const
{
return BridgeCalls;
}
CD3D8CallBridge::CD3D8CallBridge(IDirect3DDevice8* p) : pID3DDevice(p),
BlendOperation(D3DBLENDOP_ADD), BlendSource(D3DBLEND_ONE), BlendDestination(D3DBLEND_ZERO), Blend(false)
{
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
void CD3D8CallBridge::setBlendOperation(DWORD mode)
{
if (BlendOperation != mode)
{
pID3DDevice->SetRenderState(D3DRS_BLENDOP, mode);
BlendOperation = mode;
}
}
void CD3D8CallBridge::setBlendFunc(DWORD source, DWORD destination)
{
if (BlendSource != source)
{
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, source);
BlendSource = source;
}
if (BlendDestination != destination)
{
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, destination);
BlendDestination = destination;
}
}
void CD3D8CallBridge::setBlend(bool enable)
{
if (Blend != enable)
{
if (enable)
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
else
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Blend = enable;
}
}
} // end namespace video
} // end namespace irr

View File

@ -25,8 +25,11 @@ namespace irr
{
namespace video
{
class CD3D8CallBridge;
class CD3D8Driver : public CNullDriver, IMaterialRendererServices
{
friend class CD3D8CallBridge;
friend class CD3D8Texture;
public:
@ -228,6 +231,16 @@ namespace video
virtual core::dimension2du getMaxTextureSize() const _IRR_OVERRIDE_;
virtual bool checkDriverReset() _IRR_OVERRIDE_ {return DriverWasReset;}
//! Get D3D blending factor.
u32 getD3DBlend(E_BLEND_FACTOR factor) const;
//! Get D3D modulate.
u32 getD3DModulate(E_MODULATE_FUNC func) const;
//! Get bridge calls.
CD3D8CallBridge* getBridgeCalls() const;
private:
// enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates.
@ -295,6 +308,8 @@ namespace video
return v;
}
CD3D8CallBridge* BridgeCalls;
E_RENDER_MODE CurrentRenderMode;
D3DPRESENT_PARAMETERS present;
@ -332,6 +347,31 @@ namespace video
SIrrlichtCreationParameters Params;
};
//! This bridge between Irlicht pseudo D3D8 calls
//! and true D3D8 calls.
class CD3D8CallBridge
{
public:
CD3D8CallBridge(IDirect3DDevice8* p);
// Blending calls.
void setBlendOperation(DWORD mode);
void setBlendFunc(DWORD source, DWORD destination);
void setBlend(bool enable);
private:
IDirect3DDevice8* pID3DDevice;
DWORD BlendOperation;
DWORD BlendSource;
DWORD BlendDestination;
bool Blend;
};
} // end namespace video
} // end namespace irr

View File

@ -12,6 +12,7 @@
#include <d3d8.h>
#include "IMaterialRenderer.h"
#include "CD3D8Driver.h"
namespace irr
{
@ -55,7 +56,7 @@ class CD3D8MaterialRenderer : public IMaterialRenderer
public:
//! Constructor
CD3D8MaterialRenderer(IDirect3DDevice8* d3ddev, video::IVideoDriver* driver)
CD3D8MaterialRenderer(IDirect3DDevice8* d3ddev, CD3D8Driver* driver)
: pID3DDevice(d3ddev), Driver(driver)
{
}
@ -63,7 +64,7 @@ public:
protected:
IDirect3DDevice8* pID3DDevice;
video::IVideoDriver* Driver;
CD3D8Driver* Driver;
};
@ -72,7 +73,7 @@ class CD3D8MaterialRenderer_SOLID : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_SOLID(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_SOLID(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -95,7 +96,7 @@ class CD3D8MaterialRenderer_ONETEXTURE_BLEND : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -113,19 +114,11 @@ public:
u32 alphaSource;
unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
else
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
}
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(Driver->getD3DBlend(srcFact), Driver->getD3DBlend(dstFact));
setTextureColorStage(pID3DDevice, 0,
D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
D3DTA_TEXTURE, CD3D8MaterialRenderer::getD3DModulate(modulate), D3DTA_DIFFUSE);
if ( alphaSource && (textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) ))
{
@ -151,7 +144,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent.
@ -163,41 +156,6 @@ public:
{
return true;
}
private:
u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
{
u32 r = 0;
switch ( factor )
{
case EBF_ZERO: r = D3DBLEND_ZERO; break;
case EBF_ONE: r = D3DBLEND_ONE; break;
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
}
return r;
}
u32 getD3DModulate ( E_MODULATE_FUNC func ) const
{
u32 r = D3DTOP_MODULATE;
switch ( func )
{
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
}
return r;
}
};
@ -206,7 +164,7 @@ class CD3D8MaterialRenderer_SOLID_2_LAYER : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -230,7 +188,7 @@ class CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -238,9 +196,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_ONE, D3DBLEND_INVSRCCOLOR);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -253,7 +210,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene management needs to know this
@ -270,7 +227,7 @@ class CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D8MaterialRende
{
public:
CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -278,9 +235,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -294,7 +250,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene managment needs to know this
@ -311,7 +267,7 @@ class CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D8MaterialRend
{
public:
CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -319,9 +275,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
@ -341,7 +296,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene managment needs to know this
@ -358,7 +313,7 @@ class CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D8Material
{
public:
CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -400,7 +355,7 @@ class CD3D8MaterialRenderer_LIGHTMAP : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_LIGHTMAP(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_LIGHTMAP(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -443,7 +398,7 @@ class CD3D8MaterialRenderer_DETAIL_MAP : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_DETAIL_MAP(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_DETAIL_MAP(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -468,7 +423,7 @@ class CD3D8MaterialRenderer_SPHERE_MAP : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_SPHERE_MAP(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_SPHERE_MAP(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -503,7 +458,7 @@ class CD3D8MaterialRenderer_REFLECTION_2_LAYER : public CD3D8MaterialRenderer
{
public:
CD3D8MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -539,7 +494,7 @@ class CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D8Materia
{
public:
CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice8* p, video::IVideoDriver* d)
CD3D8MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice8* p, CD3D8Driver* d)
: CD3D8MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -547,9 +502,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -571,7 +525,7 @@ public:
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D8);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene managment needs to know this

View File

@ -30,7 +30,7 @@ namespace
//! constructor
CD3D9Driver::CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io)
: CNullDriver(io, params.WindowSize), CurrentRenderMode(ERM_NONE),
: CNullDriver(io, params.WindowSize), BridgeCalls(0), CurrentRenderMode(ERM_NONE),
ResetRenderStates(true), Transformation3DChanged(false),
D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0),
WindowId(0), SceneSourceRect(0),
@ -88,6 +88,8 @@ CD3D9Driver::~CD3D9Driver()
}
DepthBuffers.clear();
delete BridgeCalls;
// drop d3d9
if (pID3DDevice)
@ -420,6 +422,9 @@ bool CD3D9Driver::initDriver(HWND hwnd, bool pureSoftware)
Params.Stencilbuffer = false;
}
if (!BridgeCalls)
BridgeCalls = new CD3D9CallBridge(pID3DDevice, this);
// set default vertex shader
setVertexShader(EVT_STANDARD);
@ -680,6 +685,9 @@ bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
case EVDF_POLYGON_OFFSET:
return (Caps.RasterCaps & (D3DPRASTERCAPS_DEPTHBIAS|D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS)) != 0;
case EVDF_BLEND_OPERATIONS:
return true;
case EVDF_BLEND_SEPARATE:
return (Caps.PrimitiveMiscCaps & D3DPMISCCAPS_SEPARATEALPHABLEND) != 0;
case EVDF_TEXTURE_MATRIX:
return true;
case EVDF_TEXTURE_COMPRESSED_DXT:
@ -2244,7 +2252,7 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria
// zwrite
// if (resetAllRenderstates || (lastmaterial.ZWriteEnable != material.ZWriteEnable))
{
if (material.ZWriteEnable && (AllowZWriteOnTransparent || (material.BlendOperation == EBO_NONE &&
if (material.ZWriteEnable && (AllowZWriteOnTransparent || (!material.isTransparent() &&
!MaterialRenderers[material.MaterialType].Renderer->isTransparent())))
{
pID3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
@ -2302,40 +2310,53 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria
}
// Blend Operation
if (resetAllRenderstates || lastmaterial.BlendOperation != material.BlendOperation)
{
if (material.BlendOperation==EBO_NONE)
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
else
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
if (material.BlendOperation == EBO_NONE)
BridgeCalls->setBlend(false);
else
{
BridgeCalls->setBlend(true);
if (queryFeature(EVDF_BLEND_OPERATIONS))
{
switch (material.BlendOperation)
{
case EBO_SUBTRACT:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
break;
case EBO_REVSUBTRACT:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
break;
case EBO_MIN:
case EBO_MIN_FACTOR:
case EBO_MIN_ALPHA:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN);
break;
case EBO_MAX:
case EBO_MAX_FACTOR:
case EBO_MAX_ALPHA:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MAX);
break;
default:
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
break;
}
if (queryFeature(EVDF_BLEND_OPERATIONS))
{
switch (material.BlendOperation)
{
case EBO_MAX:
case EBO_MAX_FACTOR:
case EBO_MAX_ALPHA:
BridgeCalls->setBlendOperation(D3DBLENDOP_MAX);
break;
case EBO_MIN:
case EBO_MIN_FACTOR:
case EBO_MIN_ALPHA:
BridgeCalls->setBlendOperation(D3DBLENDOP_MIN);
break;
case EBO_SUBTRACT:
BridgeCalls->setBlendOperation(D3DBLENDOP_SUBTRACT);
break;
case EBO_REVSUBTRACT:
BridgeCalls->setBlendOperation(D3DBLENDOP_REVSUBTRACT);
break;
default:
BridgeCalls->setBlendOperation(D3DBLENDOP_ADD);
break;
}
}
}
}
// Blend Factor
if (material.BlendFactor != 0.f)
{
E_BLEND_FACTOR srcRGBFact = EBF_ZERO;
E_BLEND_FACTOR dstRGBFact = EBF_ZERO;
E_BLEND_FACTOR srcAlphaFact = EBF_ZERO;
E_BLEND_FACTOR dstAlphaFact = EBF_ZERO;
E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;
u32 alphaSource = 0;
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor);
BridgeCalls->setBlendFuncSeparate(getD3DBlend(srcRGBFact), getD3DBlend(dstRGBFact),
getD3DBlend(srcAlphaFact), getD3DBlend(dstAlphaFact));
}
// Polygon offset
@ -2565,13 +2586,12 @@ void CD3D9Driver::setRenderStatesStencilFillMode(bool alpha)
pID3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
if (alpha)
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
BridgeCalls->setBlend(true);
BridgeCalls->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
}
else
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
BridgeCalls->setBlend(false);
}
}
@ -2646,12 +2666,11 @@ void CD3D9Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChan
if (alpha || alphaChannel)
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
BridgeCalls->setBlend(true);
BridgeCalls->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
}
else
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
BridgeCalls->setBlend(false);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
pID3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
@ -3601,6 +3620,46 @@ core::dimension2du CD3D9Driver::getMaxTextureSize() const
return core::dimension2du(Caps.MaxTextureWidth, Caps.MaxTextureHeight);
}
u32 CD3D9Driver::getD3DBlend(E_BLEND_FACTOR factor) const
{
u32 r = 0;
switch (factor)
{
case EBF_ZERO: r = D3DBLEND_ZERO; break;
case EBF_ONE: r = D3DBLEND_ONE; break;
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
}
return r;
}
u32 CD3D9Driver::getD3DModulate(E_MODULATE_FUNC func) const
{
u32 r = D3DTOP_MODULATE;
switch (func)
{
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
}
return r;
}
CD3D9CallBridge* CD3D9Driver::getBridgeCalls() const
{
return BridgeCalls;
}
#ifdef _IRR_COMPILE_WITH_CG_
const CGcontext& CD3D9Driver::getCgContext()
{
@ -3609,6 +3668,122 @@ const CGcontext& CD3D9Driver::getCgContext()
#endif
CD3D9CallBridge::CD3D9CallBridge(IDirect3DDevice9* p, CD3D9Driver* driver) : pID3DDevice(p),
BlendOperation(D3DBLENDOP_ADD), BlendSourceRGB(D3DBLEND_ONE), BlendDestinationRGB(D3DBLEND_ZERO),
BlendSourceAlpha(D3DBLEND_ONE), BlendDestinationAlpha(D3DBLEND_ZERO), Blend(false), BlendSeparate(false)
{
FeatureBlendSeparate = driver->queryFeature(EVDF_BLEND_SEPARATE);
pID3DDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
if (FeatureBlendSeparate)
{
pID3DDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
pID3DDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
}
}
void CD3D9CallBridge::setBlendOperation(DWORD mode)
{
if (BlendOperation != mode)
{
pID3DDevice->SetRenderState(D3DRS_BLENDOP, mode);
BlendOperation = mode;
}
}
void CD3D9CallBridge::setBlendFunc(DWORD source, DWORD destination)
{
if (BlendSourceRGB != source)
{
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, source);
BlendSourceRGB = source;
}
if (BlendDestinationRGB != destination)
{
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, destination);
BlendDestinationRGB = destination;
}
if (FeatureBlendSeparate && BlendSeparate)
{
pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
BlendSeparate = false;
}
}
void CD3D9CallBridge::setBlendFuncSeparate(DWORD sourceRGB, DWORD destinationRGB, DWORD sourceAlpha, DWORD destinationAlpha)
{
if (BlendSourceRGB != sourceRGB)
{
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, sourceRGB);
BlendSourceRGB = sourceRGB;
}
if (BlendDestinationRGB != destinationRGB)
{
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, destinationRGB);
BlendDestinationRGB = destinationRGB;
}
if (FeatureBlendSeparate)
{
if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha)
{
if (BlendSourceAlpha != sourceAlpha)
{
pID3DDevice->SetRenderState(D3DRS_SRCBLENDALPHA, sourceAlpha);
BlendSourceAlpha = sourceAlpha;
}
if (BlendDestinationAlpha != destinationAlpha)
{
pID3DDevice->SetRenderState(D3DRS_DESTBLENDALPHA, destinationAlpha);
BlendDestinationAlpha = destinationAlpha;
}
if (!BlendSeparate)
{
pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
BlendSeparate = true;
}
}
else if (BlendSeparate)
{
pID3DDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
BlendSeparate = false;
}
}
}
void CD3D9CallBridge::setBlend(bool enable)
{
if (Blend != enable)
{
if (enable)
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
else
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Blend = enable;
}
}
} // end namespace video
} // end namespace irr

View File

@ -31,6 +31,8 @@ namespace irr
{
namespace video
{
class CD3D9CallBridge;
struct SDepthSurface : public IReferenceCounted
{
SDepthSurface() : Surface(0)
@ -53,6 +55,7 @@ namespace video
{
public:
friend class CD3D9CallBridge;
friend class CD3D9Texture;
//! constructor
@ -332,6 +335,15 @@ namespace video
//! Get Irrlicht color format from D3D color format.
ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format) const;
//! Get D3D blending factor.
u32 getD3DBlend(E_BLEND_FACTOR factor) const;
//! Get D3D modulate.
u32 getD3DModulate(E_MODULATE_FUNC func) const;
//! Get bridge calls.
CD3D9CallBridge* getBridgeCalls() const;
//! Get Cg context
#ifdef _IRR_COMPILE_WITH_CG_
const CGcontext& getCgContext();
@ -427,6 +439,8 @@ namespace video
return v;
}
CD3D9CallBridge* BridgeCalls;
E_RENDER_MODE CurrentRenderMode;
D3DPRESENT_PARAMETERS present;
@ -486,6 +500,37 @@ namespace video
#endif
};
//! This bridge between Irlicht pseudo D3D8 calls
//! and true D3D8 calls.
class CD3D9CallBridge
{
public:
CD3D9CallBridge(IDirect3DDevice9* p, CD3D9Driver* driver);
// Blending calls.
void setBlendOperation(DWORD mode);
void setBlendFunc(DWORD source, DWORD destination);
void setBlendFuncSeparate(DWORD sourceRGB, DWORD destinationRGB, DWORD sourceAlpha, DWORD destinationAlpha);
void setBlend(bool enable);
private:
IDirect3DDevice9* pID3DDevice;
DWORD BlendOperation;
DWORD BlendSourceRGB;
DWORD BlendDestinationRGB;
DWORD BlendSourceAlpha;
DWORD BlendDestinationAlpha;
bool Blend;
bool BlendSeparate;
bool FeatureBlendSeparate;
};
} // end namespace video
} // end namespace irr

View File

@ -15,6 +15,7 @@
#include <d3d9.h>
#include "IMaterialRenderer.h"
#include "CD3D9Driver.h"
namespace irr
{
@ -58,7 +59,7 @@ class CD3D9MaterialRenderer : public IMaterialRenderer
public:
//! Constructor
CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver)
CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, CD3D9Driver* driver)
: pID3DDevice(d3ddev), Driver(driver)
{
}
@ -91,7 +92,7 @@ public:
protected:
IDirect3DDevice9* pID3DDevice;
video::IVideoDriver* Driver;
CD3D9Driver* Driver;
};
@ -100,7 +101,7 @@ class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -123,7 +124,7 @@ class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -135,27 +136,20 @@ public:
// material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
// resetAllRenderstates)
{
E_BLEND_FACTOR srcFact,dstFact;
E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;
E_MODULATE_FUNC modulate;
u32 alphaSource;
unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);
if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
else
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
}
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFuncSeparate(Driver->getD3DBlend(srcRGBFact), Driver->getD3DBlend(dstRGBFact),
Driver->getD3DBlend(srcAlphaFact), Driver->getD3DBlend(dstAlphaFact));
setTextureColorStage(pID3DDevice, 0,
D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
D3DTA_TEXTURE, Driver->getD3DModulate(modulate), D3DTA_DIFFUSE);
if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )
if (textureBlendFunc_hasAlpha(srcRGBFact) || textureBlendFunc_hasAlpha(dstRGBFact) ||
textureBlendFunc_hasAlpha(srcAlphaFact) || textureBlendFunc_hasAlpha(dstAlphaFact))
{
if (alphaSource==EAS_VERTEX_COLOR)
{
@ -179,7 +173,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent.
@ -191,42 +185,6 @@ public:
{
return true;
}
private:
u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
{
u32 r = 0;
switch ( factor )
{
case EBF_ZERO: r = D3DBLEND_ZERO; break;
case EBF_ONE: r = D3DBLEND_ONE; break;
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
}
return r;
}
u32 getD3DModulate ( E_MODULATE_FUNC func ) const
{
u32 r = D3DTOP_MODULATE;
switch ( func )
{
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
}
return r;
}
bool transparent;
};
@ -236,7 +194,7 @@ class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -260,7 +218,7 @@ class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -268,9 +226,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_ONE, D3DBLEND_INVSRCCOLOR);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -283,7 +240,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene management needs to know this
@ -300,7 +257,7 @@ class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRende
{
public:
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -308,9 +265,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -324,7 +280,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene managment needs to know this
@ -341,7 +297,7 @@ class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRend
{
public:
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -349,9 +305,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
@ -371,7 +326,7 @@ public:
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
{
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene managment needs to know this
@ -389,7 +344,7 @@ class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9Material
{
public:
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -431,7 +386,7 @@ class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -475,7 +430,7 @@ class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -500,7 +455,7 @@ class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -535,7 +490,7 @@ class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
{
public:
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -571,7 +526,7 @@ class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9Materia
{
public:
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, CD3D9Driver* d)
: CD3D9MaterialRenderer(p, d) {}
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
@ -579,9 +534,8 @@ public:
{
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setBlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
{
@ -603,7 +557,7 @@ public:
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9);
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
Driver->getBridgeCalls()->setBlend(false);
}
//! Returns if the material is transparent. The scene managment needs to know this

View File

@ -89,7 +89,7 @@ void CMeshSceneNode::OnRegisterSceneNode()
video::IMaterialRenderer* rnd =
driver->getMaterialRenderer(Materials[i].MaterialType);
if ((rnd && rnd->isTransparent()) || Materials[i].BlendOperation != video::EBO_NONE)
if ((rnd && rnd->isTransparent()) || Materials[i].isTransparent())
++transparentCount;
else
++solidCount;

View File

@ -76,7 +76,7 @@ void COctreeSceneNode::OnRegisterSceneNode()
const video::IMaterialRenderer* const rnd =
driver->getMaterialRenderer(Materials[i].MaterialType);
if ((rnd && rnd->isTransparent()) || Materials[i].BlendOperation != video::EBO_NONE)
if ((rnd && rnd->isTransparent()) || Materials[i].isTransparent())
++transparentCount;
else
++solidCount;

View File

@ -637,8 +637,6 @@ COpenGLDriver::~COpenGLDriver()
cgDestroyContext(CgContext);
#endif
delete BridgeCalls;
RequestedLights.clear();
deleteMaterialRenders();
@ -650,6 +648,8 @@ COpenGLDriver::~COpenGLDriver()
removeAllOcclusionQueries();
removeAllHardwareBuffers();
delete BridgeCalls;
#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_
if (DeviceType == EIDT_WIN32)
{
@ -3051,7 +3051,7 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
// zwrite
// if (resetAllRenderStates || lastmaterial.ZWriteEnable != material.ZWriteEnable)
{
if (material.ZWriteEnable && (AllowZWriteOnTransparent || (material.BlendOperation == EBO_NONE &&
if (material.ZWriteEnable && (AllowZWriteOnTransparent || (!material.isTransparent() &&
!MaterialRenderers[material.MaterialType].Renderer->isTransparent())))
{
BridgeCalls->setDepthMask(true);
@ -3095,104 +3095,124 @@ void COpenGLDriver::setBasicRenderStates(const SMaterial& material, const SMater
}
// Blend Equation
if (resetAllRenderStates|| lastmaterial.BlendOperation != material.BlendOperation)
{
if (material.BlendOperation==EBO_NONE)
BridgeCalls->setBlend(false);
else
{
BridgeCalls->setBlend(true);
if (material.BlendOperation == EBO_NONE)
BridgeCalls->setBlend(false);
else
{
BridgeCalls->setBlend(true);
#if defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op) || defined(GL_VERSION_1_4)
if (queryFeature(EVDF_BLEND_OPERATIONS))
{
switch (material.BlendOperation)
{
case EBO_SUBTRACT:
if (queryFeature(EVDF_BLEND_OPERATIONS))
{
switch (material.BlendOperation)
{
case EBO_SUBTRACT:
#if defined(GL_VERSION_1_4)
BridgeCalls->setBlendEquation(GL_FUNC_SUBTRACT);
BridgeCalls->setBlendEquation(GL_FUNC_SUBTRACT);
#elif defined(GL_EXT_blend_subtract)
BridgeCalls->setBlendEquation(GL_FUNC_SUBTRACT_EXT);
BridgeCalls->setBlendEquation(GL_FUNC_SUBTRACT_EXT);
#endif
break;
case EBO_REVSUBTRACT:
break;
case EBO_REVSUBTRACT:
#if defined(GL_VERSION_1_4)
BridgeCalls->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
BridgeCalls->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
#elif defined(GL_EXT_blend_subtract)
BridgeCalls->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT_EXT);
BridgeCalls->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT_EXT);
#endif
break;
case EBO_MIN:
break;
case EBO_MIN:
#if defined(GL_VERSION_1_4)
BridgeCalls->setBlendEquation(GL_MIN);
BridgeCalls->setBlendEquation(GL_MIN);
#elif defined(GL_EXT_blend_minmax)
BridgeCalls->setBlendEquation(GL_MIN_EXT);
BridgeCalls->setBlendEquation(GL_MIN_EXT);
#endif
break;
case EBO_MAX:
break;
case EBO_MAX:
#if defined(GL_VERSION_1_4)
BridgeCalls->setBlendEquation(GL_MAX);
BridgeCalls->setBlendEquation(GL_MAX);
#elif defined(GL_EXT_blend_minmax)
BridgeCalls->setBlendEquation(GL_MAX_EXT);
BridgeCalls->setBlendEquation(GL_MAX_EXT);
#endif
break;
case EBO_MIN_FACTOR:
break;
case EBO_MIN_FACTOR:
#if defined(GL_AMD_blend_minmax_factor)
if (FeatureAvailable[IRR_AMD_blend_minmax_factor])
BridgeCalls->setBlendEquation(GL_FACTOR_MIN_AMD);
if (FeatureAvailable[IRR_AMD_blend_minmax_factor])
BridgeCalls->setBlendEquation(GL_FACTOR_MIN_AMD);
#endif
// fallback in case of missing extension
#if defined(GL_VERSION_1_4)
#if defined(GL_AMD_blend_minmax_factor)
else
else
#endif
BridgeCalls->setBlendEquation(GL_MIN);
BridgeCalls->setBlendEquation(GL_MIN);
#endif
break;
case EBO_MAX_FACTOR:
break;
case EBO_MAX_FACTOR:
#if defined(GL_AMD_blend_minmax_factor)
if (FeatureAvailable[IRR_AMD_blend_minmax_factor])
BridgeCalls->setBlendEquation(GL_FACTOR_MAX_AMD);
if (FeatureAvailable[IRR_AMD_blend_minmax_factor])
BridgeCalls->setBlendEquation(GL_FACTOR_MAX_AMD);
#endif
// fallback in case of missing extension
#if defined(GL_VERSION_1_4)
#if defined(GL_AMD_blend_minmax_factor)
else
else
#endif
BridgeCalls->setBlendEquation(GL_MAX);
BridgeCalls->setBlendEquation(GL_MAX);
#endif
break;
case EBO_MIN_ALPHA:
break;
case EBO_MIN_ALPHA:
#if defined(GL_SGIX_blend_alpha_minmax)
if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax])
BridgeCalls->setBlendEquation(GL_ALPHA_MIN_SGIX);
// fallback in case of missing extension
else
if (FeatureAvailable[IRR_EXT_blend_minmax])
BridgeCalls->setBlendEquation(GL_MIN_EXT);
if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax])
BridgeCalls->setBlendEquation(GL_ALPHA_MIN_SGIX);
// fallback in case of missing extension
else
if (FeatureAvailable[IRR_EXT_blend_minmax])
BridgeCalls->setBlendEquation(GL_MIN_EXT);
#endif
break;
case EBO_MAX_ALPHA:
break;
case EBO_MAX_ALPHA:
#if defined(GL_SGIX_blend_alpha_minmax)
if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax])
BridgeCalls->setBlendEquation(GL_ALPHA_MAX_SGIX);
// fallback in case of missing extension
else
if (FeatureAvailable[IRR_EXT_blend_minmax])
BridgeCalls->setBlendEquation(GL_MAX_EXT);
if (FeatureAvailable[IRR_SGIX_blend_alpha_minmax])
BridgeCalls->setBlendEquation(GL_ALPHA_MAX_SGIX);
// fallback in case of missing extension
else
if (FeatureAvailable[IRR_EXT_blend_minmax])
BridgeCalls->setBlendEquation(GL_MAX_EXT);
#endif
break;
default:
break;
default:
#if defined(GL_VERSION_1_4)
BridgeCalls->setBlendEquation(GL_FUNC_ADD);
BridgeCalls->setBlendEquation(GL_FUNC_ADD);
#elif defined(GL_EXT_blend_subtract) || defined(GL_EXT_blend_minmax) || defined(GL_EXT_blend_logic_op)
BridgeCalls->setBlendEquation(GL_FUNC_ADD_EXT);
#endif
break;
}
}
BridgeCalls->setBlendEquation(GL_FUNC_ADD_EXT);
#endif
break;
}
}
#endif
}
// Blend Factor
if (material.BlendFactor != 0.f)
{
E_BLEND_FACTOR srcRGBFact = EBF_ZERO;
E_BLEND_FACTOR dstRGBFact = EBF_ZERO;
E_BLEND_FACTOR srcAlphaFact = EBF_ZERO;
E_BLEND_FACTOR dstAlphaFact = EBF_ZERO;
E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;
u32 alphaSource = 0;
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor);
if (queryFeature(EVDF_BLEND_SEPARATE))
{
BridgeCalls->setBlendFuncSeparate(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact),
getGLBlend(srcAlphaFact), getGLBlend(dstAlphaFact));
}
else
{
BridgeCalls->setBlendFunc(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact));
}
}
// Polygon Offset
@ -5045,8 +5065,10 @@ COpenGLCallBridge::COpenGLCallBridge(COpenGLDriver* driver) : Driver(driver),
BlendIndexCount = core::max_(static_cast<GLuint>(1), static_cast<GLuint>(Driver->MaxMultipleRenderTargets));
BlendEquation = new GLenum[BlendIndexCount];
BlendSource = new GLenum[BlendIndexCount];
BlendDestination = new GLenum[BlendIndexCount];
BlendSourceRGB = new GLenum[BlendIndexCount];
BlendDestinationRGB = new GLenum[BlendIndexCount];
BlendSourceAlpha = new GLenum[BlendIndexCount];
BlendDestinationAlpha = new GLenum[BlendIndexCount];
Blend = new bool[BlendIndexCount];
for (u32 i = 0; i < BlendIndexCount; ++i)
@ -5057,8 +5079,10 @@ COpenGLCallBridge::COpenGLCallBridge(COpenGLDriver* driver) : Driver(driver),
BlendEquation[i] = GL_FUNC_ADD_EXT;
#endif
BlendSource[i] = GL_ONE;
BlendDestination[i] = GL_ZERO;
BlendSourceRGB[i] = GL_ONE;
BlendDestinationRGB[i] = GL_ZERO;
BlendSourceAlpha[i] = GL_ONE;
BlendDestinationAlpha[i] = GL_ZERO;
Blend[i] = false;
}
@ -5111,8 +5135,10 @@ COpenGLCallBridge::COpenGLCallBridge(COpenGLDriver* driver) : Driver(driver),
COpenGLCallBridge::~COpenGLCallBridge()
{
delete[] BlendEquation;
delete[] BlendSource;
delete[] BlendDestination;
delete[] BlendSourceRGB;
delete[] BlendDestinationRGB;
delete[] BlendSourceAlpha;
delete[] BlendDestinationAlpha;
delete[] Blend;
}
@ -5162,29 +5188,80 @@ void COpenGLCallBridge::setBlendEquationIndexed(GLuint index, GLenum mode)
void COpenGLCallBridge::setBlendFunc(GLenum source, GLenum destination)
{
if (BlendSource[0] != source || BlendDestination[0] != destination)
if (BlendSourceRGB[0] != source || BlendDestinationRGB[0] != destination ||
BlendSourceAlpha[0] != source || BlendDestinationAlpha[0] != destination)
{
glBlendFunc(source, destination);
for (GLuint i = 0; i < BlendIndexCount; ++i)
{
BlendSource[i] = source;
BlendDestination[i] = destination;
BlendSourceRGB[i] = source;
BlendDestinationRGB[i] = destination;
BlendSourceAlpha[i] = source;
BlendDestinationAlpha[i] = destination;
}
}
}
void COpenGLCallBridge::setBlendFuncSeparate(GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha)
{
if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha)
{
if (BlendSourceRGB[0] != sourceRGB || BlendDestinationRGB[0] != destinationRGB ||
BlendSourceAlpha[0] != sourceAlpha || BlendDestinationAlpha[0] != destinationAlpha)
{
Driver->extGlBlendFuncSeparate(sourceRGB, destinationRGB, sourceAlpha, destinationAlpha);
for (GLuint i = 0; i < BlendIndexCount; ++i)
{
BlendSourceRGB[i] = sourceRGB;
BlendDestinationRGB[i] = destinationRGB;
BlendSourceAlpha[i] = sourceAlpha;
BlendDestinationAlpha[i] = destinationAlpha;
}
}
}
else
{
setBlendFunc(sourceRGB, destinationRGB);
}
}
void COpenGLCallBridge::setBlendFuncIndexed(GLuint index, GLenum source, GLenum destination)
{
if (index < BlendIndexCount && (BlendSource[index] != source || BlendDestination[index] != destination))
if (index < BlendIndexCount && (BlendSourceRGB[index] != source || BlendDestinationRGB[index] != destination ||
BlendSourceAlpha[index] != source || BlendDestinationAlpha[index] != destination))
{
Driver->extGlBlendFuncIndexed(index, source, destination);
BlendSource[index] = source;
BlendDestination[index] = destination;
BlendSourceRGB[index] = source;
BlendDestinationRGB[index] = destination;
BlendSourceAlpha[index] = source;
BlendDestinationAlpha[index] = destination;
}
}
void COpenGLCallBridge::setBlendFuncSeparateIndexed(GLuint index, GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha)
{
if (sourceRGB != sourceAlpha || destinationRGB != destinationAlpha)
{
if (index < BlendIndexCount && (BlendSourceRGB[index] != sourceRGB || BlendDestinationRGB[index] != destinationRGB ||
BlendSourceAlpha[index] != sourceAlpha || BlendDestinationAlpha[index] != destinationAlpha))
{
Driver->extGlBlendFuncSeparateIndexed(index, sourceRGB, destinationRGB, sourceAlpha, destinationAlpha);
BlendSourceRGB[index] = sourceRGB;
BlendDestinationRGB[index] = destinationRGB;
BlendSourceAlpha[index] = sourceAlpha;
BlendDestinationAlpha[index] = destinationAlpha;
}
}
else
{
setBlendFuncIndexed(index, sourceRGB, destinationRGB);
}
}
void COpenGLCallBridge::setBlend(bool enable)
{
if (Blend[0] != enable)

View File

@ -661,8 +661,12 @@ namespace video
void setBlendFunc(GLenum source, GLenum destination);
void setBlendFuncSeparate(GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha);
void setBlendFuncIndexed(GLuint index, GLenum source, GLenum destination);
void setBlendFuncSeparateIndexed(GLuint index, GLenum sourceRGB, GLenum destinationRGB, GLenum sourceAlpha, GLenum destinationAlpha);
void setBlend(bool enable);
void setBlendIndexed(GLuint index, bool enable);
@ -705,8 +709,10 @@ namespace video
bool AlphaTest;
GLenum* BlendEquation;
GLenum* BlendSource;
GLenum* BlendDestination;
GLenum* BlendSourceRGB;
GLenum* BlendDestinationRGB;
GLenum* BlendSourceAlpha;
GLenum* BlendDestinationAlpha;
bool* Blend;
GLuint BlendIndexCount;

View File

@ -100,10 +100,22 @@ public:
// material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
// resetAllRenderstates)
{
E_BLEND_FACTOR srcFact,dstFact;
E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;
E_MODULATE_FUNC modulate;
u32 alphaSource;
unpack_textureBlendFunc(srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam);
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);
Driver->getBridgeCalls()->setBlend(true);
if (Driver->queryFeature(EVDF_BLEND_SEPARATE))
{
Driver->getBridgeCalls()->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact),
Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact));
}
else
{
Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact));
}
#ifdef GL_ARB_texture_env_combine
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
@ -119,12 +131,8 @@ public:
glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, (f32) modulate );
#endif
Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcFact), Driver->getGLBlend(dstFact));
Driver->getBridgeCalls()->setAlphaTest(true);
Driver->getBridgeCalls()->setAlphaFunc(GL_GREATER, 0.f);
Driver->getBridgeCalls()->setBlend(true);
if ( textureBlendFunc_hasAlpha(srcFact) || textureBlendFunc_hasAlpha(dstFact) )
if (textureBlendFunc_hasAlpha(srcRGBFact) || textureBlendFunc_hasAlpha(dstRGBFact) ||
textureBlendFunc_hasAlpha(srcAlphaFact) || textureBlendFunc_hasAlpha(dstAlphaFact))
{
if (alphaSource==EAS_VERTEX_COLOR)
{
@ -164,16 +172,22 @@ public:
virtual void OnSetBaseMaterial(const SMaterial& material) _IRR_OVERRIDE_
{
E_BLEND_FACTOR srcFact,dstFact;
E_MODULATE_FUNC modulate;
u32 alphaSource;
unpack_textureBlendFunc(srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam);
E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;
E_MODULATE_FUNC modulate;
u32 alphaSource;
unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);
Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcFact), Driver->getGLBlend(dstFact));
Driver->getBridgeCalls()->setBlend(true);
Driver->getBridgeCalls()->setAlphaTest(true);
Driver->getBridgeCalls()->setAlphaFunc(GL_GREATER, 0.f);
Driver->getBridgeCalls()->setBlend(true);
if (Driver->queryFeature(EVDF_BLEND_SEPARATE))
{
Driver->getBridgeCalls()->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact),
Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact));
}
else
{
Driver->getBridgeCalls()->setBlendFunc(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact));
}
}
virtual void OnUnsetMaterial() _IRR_OVERRIDE_
@ -190,13 +204,11 @@ public:
#endif
Driver->getBridgeCalls()->setBlend(false);
Driver->getBridgeCalls()->setAlphaTest(false);
}
virtual void OnUnsetBaseMaterial() _IRR_OVERRIDE_
{
Driver->getBridgeCalls()->setBlend(false);
Driver->getBridgeCalls()->setAlphaTest(false);
}
//! Returns if the material is transparent.

View File

@ -1317,7 +1317,7 @@ u32 CSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDE
{
video::IMaterialRenderer* rnd =
Driver->getMaterialRenderer(node->getMaterial(i).MaterialType);
if ((rnd && rnd->isTransparent()) || node->getMaterial(i).BlendOperation != video::EBO_NONE)
if ((rnd && rnd->isTransparent()) || node->getMaterial(i).isTransparent())
{
// register as transparent node
TransparentNodeEntry e(node, camWorldPos);

View File

@ -486,7 +486,7 @@ void CBurningVideoDriver::setCurrentShader()
bool zMaterialTest = Material.org.ZBuffer != ECFN_DISABLED &&
Material.org.ZWriteEnable &&
( AllowZWriteOnTransparent || (Material.org.BlendOperation == EBO_NONE &&
( AllowZWriteOnTransparent || (!Material.org.isTransparent() &&
!MaterialRenderers[Material.org.MaterialType].Renderer->isTransparent()) );
EBurningFFShader shader = zMaterialTest ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ;