Commit 9bad8de6 authored by nadro's avatar nadro

- 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
parent 6058c276
--------------------------
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.
......
......@@ -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,
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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)
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:
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)
{
if (material.BlendOperation==EBO_NONE)
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
else
{
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
E_BLEND_FACTOR srcFact = EBF_ZERO;
E_BLEND_FACTOR dstFact = EBF_ZERO;
E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;
u32 alphaSource = 0;
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;
}
}
}
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
......
......@@ -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
......
This diff is collapsed.
This diff is collapsed.
......@@ -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
......
This diff is collapsed.
......@@ -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;
......
......@@ -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;
......
This diff is collapsed.
......@@ -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;
......
......@@ -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.
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment