Added blend equation support.

This commit is contained in:
bkaradzic 2013-06-17 22:11:45 -07:00
parent 1f4539ec7c
commit 87dfe979a5
5 changed files with 107 additions and 23 deletions

View file

@ -40,7 +40,14 @@
#define BGFX_STATE_BLEND_FACTOR UINT64_C(0x000000000000c000) #define BGFX_STATE_BLEND_FACTOR UINT64_C(0x000000000000c000)
#define BGFX_STATE_BLEND_INV_FACTOR UINT64_C(0x000000000000d000) #define BGFX_STATE_BLEND_INV_FACTOR UINT64_C(0x000000000000d000)
#define BGFX_STATE_BLEND_SHIFT 12 #define BGFX_STATE_BLEND_SHIFT 12
#define BGFX_STATE_BLEND_MASK UINT64_C(0x000000000ffff000) #define BGFX_STATE_BLEND_MASK UINT64_C(0x00000000000ff000)
#define BGFX_STATE_BLEND_EQUATION_SUB UINT64_C(0x0000000000100000)
#define BGFX_STATE_BLEND_EQUATION_REVSUB UINT64_C(0x0000000000200000)
#define BGFX_STATE_BLEND_EQUATION_MIN UINT64_C(0x0000000000300000)
#define BGFX_STATE_BLEND_EQUATION_MAX UINT64_C(0x0000000000400000)
#define BGFX_STATE_BLEND_EQUATION_SHIFT 20
#define BGFX_STATE_BLEND_EQUATION_MASK UINT64_C(0x0000000000700000)
#define BGFX_STATE_CULL_CW UINT64_C(0x0000000010000000) #define BGFX_STATE_CULL_CW UINT64_C(0x0000000010000000)
#define BGFX_STATE_CULL_CCW UINT64_C(0x0000000020000000) #define BGFX_STATE_CULL_CCW UINT64_C(0x0000000020000000)
@ -80,6 +87,14 @@
#define BGFX_STATE_POINT_SIZE(_size) ( (uint64_t(_size)<<BGFX_STATE_POINT_SIZE_SHIFT)&BGFX_STATE_POINT_SIZE_MASK) #define BGFX_STATE_POINT_SIZE(_size) ( (uint64_t(_size)<<BGFX_STATE_POINT_SIZE_SHIFT)&BGFX_STATE_POINT_SIZE_MASK)
#define BGFX_STATE_BLEND_FUNC(_src, _dst) ( uint64_t(_src)|( uint64_t(_dst)<<4) ) #define BGFX_STATE_BLEND_FUNC(_src, _dst) ( uint64_t(_src)|( uint64_t(_dst)<<4) )
#define BGFX_STATE_BLEND_ADD (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE ) )
#define BGFX_STATE_BLEND_ALPHA (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_COLOR) )
#define BGFX_STATE_BLEND_DARKEN (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE ) | BGFX_STATE_BLEND_EQUATION_MIN)
#define BGFX_STATE_BLEND_LIGHTEN (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE ) | BGFX_STATE_BLEND_EQUATION_MAX)
#define BGFX_STATE_BLEND_MULTIPLY (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_ZERO ) )
#define BGFX_STATE_BLEND_SCREEN (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_INV_SRC_COLOR) )
#define BGFX_STATE_BLEND_LINEAR_BURN (BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_DST_COLOR, BGFX_STATE_BLEND_INV_DST_COLOR) | BGFX_STATE_BLEND_EQUATION_SUB)
/// ///
#define BGFX_STENCIL_FUNC_REF_SHIFT 0 #define BGFX_STENCIL_FUNC_REF_SHIFT 0
#define BGFX_STENCIL_FUNC_REF_MASK UINT32_C(0x000000ff) #define BGFX_STENCIL_FUNC_REF_MASK UINT32_C(0x000000ff)
@ -788,7 +803,8 @@ namespace bgfx
/// BGFX_STATE_ALPHA_WRITE - Enable alpha write. /// BGFX_STATE_ALPHA_WRITE - Enable alpha write.
/// BGFX_STATE_DEPTH_WRITE - Enable depth write. /// BGFX_STATE_DEPTH_WRITE - Enable depth write.
/// BGFX_STATE_DEPTH_TEST_* - Depth test function. /// BGFX_STATE_DEPTH_TEST_* - Depth test function.
/// BGFX_STATE_BLEND_* - See NOTE: BGFX_STATE_BLEND_FUNC. /// BGFX_STATE_BLEND_* - See NOTE 1: BGFX_STATE_BLEND_FUNC.
/// BGFX_STATE_BLEND_EQUATION_* - See NOTE 2.
/// BGFX_STATE_CULL_* - Backface culling mode. /// BGFX_STATE_CULL_* - Backface culling mode.
/// BGFX_STATE_RGB_WRITE - Enable RGB write. /// BGFX_STATE_RGB_WRITE - Enable RGB write.
/// BGFX_STATE_SRGBWRITE - Enable sRGB write. /// BGFX_STATE_SRGBWRITE - Enable sRGB write.
@ -799,8 +815,10 @@ namespace bgfx
/// BGFX_STATE_BLEND_INV_FACTOR blend modes. /// BGFX_STATE_BLEND_INV_FACTOR blend modes.
/// ///
/// NOTE: /// NOTE:
/// Use BGFX_STATE_ALPHA_REF, BGFX_STATE_POINT_SIZE and /// 1. Use BGFX_STATE_ALPHA_REF, BGFX_STATE_POINT_SIZE and
/// BGFX_STATE_BLEND_FUNC macros to setup more complex states. /// BGFX_STATE_BLEND_FUNC macros to setup more complex states.
/// 2. BGFX_STATE_BLEND_EQUATION_ADD is set when no other blend
/// equation is specified.
/// ///
void setState(uint64_t _state, uint32_t _rgba = UINT32_MAX); void setState(uint64_t _state, uint32_t _rgba = UINT32_MAX);

View file

@ -57,6 +57,15 @@ namespace bgfx
{ D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR }, { D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR },
}; };
static const D3D11_BLEND_OP s_blendEquation[] =
{
D3D11_BLEND_OP_ADD,
D3D11_BLEND_OP_SUBTRACT,
D3D11_BLEND_OP_REV_SUBTRACT,
D3D11_BLEND_OP_MIN,
D3D11_BLEND_OP_MAX,
};
static const D3D11_COMPARISON_FUNC s_depthFunc[] = static const D3D11_COMPARISON_FUNC s_depthFunc[] =
{ {
D3D11_COMPARISON_LESS, // ignored D3D11_COMPARISON_LESS, // ignored
@ -795,7 +804,7 @@ namespace bgfx
void setBlendState(uint64_t _state, uint32_t _rgba = UINT32_MAX) void setBlendState(uint64_t _state, uint32_t _rgba = UINT32_MAX)
{ {
_state &= BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE; _state &= BGFX_STATE_BLEND_MASK|BGFX_STATE_BLEND_EQUATION_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE;
ID3D11BlendState* bs = m_blendStateCache.find(_state); ID3D11BlendState* bs = m_blendStateCache.find(_state);
if (NULL == bs) if (NULL == bs)
@ -806,6 +815,7 @@ namespace bgfx
drt.BlendEnable = !!(BGFX_STATE_BLEND_MASK & _state); drt.BlendEnable = !!(BGFX_STATE_BLEND_MASK & _state);
uint32_t blend = (_state&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT; uint32_t blend = (_state&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT;
uint32_t equation = (_state&BGFX_STATE_BLEND_EQUATION_MASK)>>BGFX_STATE_BLEND_EQUATION_SHIFT;
uint32_t src = blend&0xf; uint32_t src = blend&0xf;
uint32_t dst = (blend>>4)&0xf; uint32_t dst = (blend>>4)&0xf;
uint32_t writeMask = (_state&BGFX_STATE_ALPHA_WRITE) ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0; uint32_t writeMask = (_state&BGFX_STATE_ALPHA_WRITE) ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0;
@ -813,11 +823,11 @@ namespace bgfx
drt.SrcBlend = s_blendFactor[src][0]; drt.SrcBlend = s_blendFactor[src][0];
drt.DestBlend = s_blendFactor[dst][0]; drt.DestBlend = s_blendFactor[dst][0];
drt.BlendOp = D3D11_BLEND_OP_ADD; drt.BlendOp = s_blendEquation[equation];
drt.SrcBlendAlpha = s_blendFactor[src][1]; drt.SrcBlendAlpha = s_blendFactor[src][1];
drt.DestBlendAlpha = s_blendFactor[dst][1]; drt.DestBlendAlpha = s_blendFactor[dst][1];
drt.BlendOpAlpha = D3D11_BLEND_OP_ADD; drt.BlendOpAlpha = s_blendEquation[equation];
drt.RenderTargetWriteMask = writeMask; drt.RenderTargetWriteMask = writeMask;
@ -2385,11 +2395,20 @@ namespace bgfx
s_renderCtx.setDepthStencilState(newFlags, newStencil); s_renderCtx.setDepthStencilState(newFlags, newStencil);
} }
if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE if ( (0
|BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK | BGFX_STATE_CULL_MASK
|BGFX_STATE_POINT_SIZE_MASK|BGFX_STATE_SRGBWRITE|BGFX_STATE_MSAA) & changedFlags) | BGFX_STATE_ALPHA_MASK
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_ALPHA_REF_MASK
| BGFX_STATE_PT_MASK
| BGFX_STATE_POINT_SIZE_MASK
| BGFX_STATE_SRGBWRITE
| BGFX_STATE_MSAA
) & changedFlags)
{ {
if ( (BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags) if ( (BGFX_STATE_BLEND_MASK|BGFX_STATE_BLEND_EQUATION_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags)
{ {
s_renderCtx.setBlendState(newFlags, state.m_rgba); s_renderCtx.setBlendState(newFlags, state.m_rgba);
} }

View file

@ -62,6 +62,15 @@ namespace bgfx
{ D3DBLEND_INVBLENDFACTOR, D3DBLEND_INVBLENDFACTOR, true }, { D3DBLEND_INVBLENDFACTOR, D3DBLEND_INVBLENDFACTOR, true },
}; };
static const D3DBLENDOP s_blendEquation[] =
{
D3DBLENDOP_ADD,
D3DBLENDOP_SUBTRACT,
D3DBLENDOP_REVSUBTRACT,
D3DBLENDOP_MIN,
D3DBLENDOP_MAX,
};
static const D3DCMPFUNC s_depthFunc[] = static const D3DCMPFUNC s_depthFunc[] =
{ {
(D3DCMPFUNC)0, // ignored (D3DCMPFUNC)0, // ignored
@ -2361,10 +2370,20 @@ namespace bgfx
} }
} }
if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK if ( (0
|BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE|BGFX_STATE_BLEND_MASK | BGFX_STATE_CULL_MASK
|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK|BGFX_STATE_POINT_SIZE_MASK | BGFX_STATE_DEPTH_WRITE
|BGFX_STATE_SRGBWRITE|BGFX_STATE_MSAA) & changedFlags) | BGFX_STATE_DEPTH_TEST_MASK
| BGFX_STATE_ALPHA_MASK
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_ALPHA_REF_MASK
| BGFX_STATE_PT_MASK
| BGFX_STATE_POINT_SIZE_MASK
| BGFX_STATE_SRGBWRITE
| BGFX_STATE_MSAA
) & changedFlags)
{ {
if (BGFX_STATE_CULL_MASK & changedFlags) if (BGFX_STATE_CULL_MASK & changedFlags)
{ {
@ -2418,7 +2437,7 @@ namespace bgfx
DX_CHECK(device->SetRenderState(D3DRS_COLORWRITEENABLE, writeEnable) ); DX_CHECK(device->SetRenderState(D3DRS_COLORWRITEENABLE, writeEnable) );
} }
if (BGFX_STATE_BLEND_MASK & changedFlags) if ( (BGFX_STATE_BLEND_MASK|BGFX_STATE_BLEND_EQUATION_MASK) & changedFlags)
{ {
bool alphaBlendEnabled = !!(BGFX_STATE_BLEND_MASK & newFlags); bool alphaBlendEnabled = !!(BGFX_STATE_BLEND_MASK & newFlags);
DX_CHECK(device->SetRenderState(D3DRS_ALPHABLENDENABLE, alphaBlendEnabled) ); DX_CHECK(device->SetRenderState(D3DRS_ALPHABLENDENABLE, alphaBlendEnabled) );
@ -2427,11 +2446,13 @@ namespace bgfx
if (alphaBlendEnabled) if (alphaBlendEnabled)
{ {
uint32_t blend = (newFlags&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT; uint32_t blend = (newFlags&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT;
uint32_t equation = (newFlags&BGFX_STATE_BLEND_EQUATION_MASK)>>BGFX_STATE_BLEND_EQUATION_SHIFT;
uint32_t src = blend&0xf; uint32_t src = blend&0xf;
uint32_t dst = (blend>>4)&0xf; uint32_t dst = (blend>>4)&0xf;
DX_CHECK(device->SetRenderState(D3DRS_SRCBLEND, s_blendFactor[src].m_src) ); DX_CHECK(device->SetRenderState(D3DRS_SRCBLEND, s_blendFactor[src].m_src) );
DX_CHECK(device->SetRenderState(D3DRS_DESTBLEND, s_blendFactor[dst].m_dst) ); DX_CHECK(device->SetRenderState(D3DRS_DESTBLEND, s_blendFactor[dst].m_dst) );
DX_CHECK(device->SetRenderState(D3DRS_BLENDOP, s_blendEquation[equation]) );
// DX_CHECK(device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_SRCALPHA) ); // DX_CHECK(device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_SRCALPHA) );
// DX_CHECK(device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA) ); // DX_CHECK(device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA) );

View file

@ -62,6 +62,8 @@ namespace bgfx
OES_rgb8_rgba8, OES_rgb8_rgba8,
EXT_texture_storage, EXT_texture_storage,
EXT_blend_color, EXT_blend_color,
EXT_blend_subtract,
EXT_blend_minmax,
ARB_debug_output, ARB_debug_output,
Count Count
@ -118,6 +120,8 @@ namespace bgfx
{ "GL_OES_rgb8_rgba8", false, true }, { "GL_OES_rgb8_rgba8", false, true },
{ "GL_EXT_texture_storage", false, true }, { "GL_EXT_texture_storage", false, true },
{ "GL_EXT_blend_color", BGFX_CONFIG_RENDERER_OPENGL >= 31, true }, { "GL_EXT_blend_color", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
{ "GL_EXT_blend_subtract", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
{ "GL_EXT_blend_minmax", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
{ "GL_ARB_debug_output", BGFX_CONFIG_RENDERER_OPENGL >= 43, true }, { "GL_ARB_debug_output", BGFX_CONFIG_RENDERER_OPENGL >= 43, true },
}; };
@ -709,6 +713,15 @@ namespace bgfx
{ GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, true }, { GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, true },
}; };
static const GLenum s_blendEquation[] =
{
GL_FUNC_ADD,
GL_FUNC_SUBTRACT,
GL_FUNC_REVERSE_SUBTRACT,
GL_MIN,
GL_MAX,
};
static const GLenum s_depthFunc[] = static const GLenum s_depthFunc[] =
{ {
0, // ignored 0, // ignored
@ -2762,10 +2775,19 @@ namespace bgfx
} }
} }
if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK if ( (0
|BGFX_STATE_ALPHA_MASK|BGFX_STATE_RGB_WRITE|BGFX_STATE_BLEND_MASK | BGFX_STATE_CULL_MASK
|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK|BGFX_STATE_POINT_SIZE_MASK | BGFX_STATE_DEPTH_WRITE
|BGFX_STATE_MSAA) & changedFlags) | BGFX_STATE_DEPTH_TEST_MASK
| BGFX_STATE_ALPHA_MASK
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_ALPHA_REF_MASK
| BGFX_STATE_PT_MASK
| BGFX_STATE_POINT_SIZE_MASK
| BGFX_STATE_MSAA
) & changedFlags)
{ {
if (BGFX_STATE_CULL_MASK & changedFlags) if (BGFX_STATE_CULL_MASK & changedFlags)
{ {
@ -2838,15 +2860,17 @@ namespace bgfx
GL_CHECK(glColorMask(rgb, rgb, rgb, alpha) ); GL_CHECK(glColorMask(rgb, rgb, rgb, alpha) );
} }
if (BGFX_STATE_BLEND_MASK & changedFlags) if ( (BGFX_STATE_BLEND_MASK|BGFX_STATE_BLEND_EQUATION_MASK) & changedFlags)
{ {
if (BGFX_STATE_BLEND_MASK & newFlags) if (BGFX_STATE_BLEND_MASK & newFlags)
{ {
uint32_t blend = (newFlags&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT; uint32_t blend = (newFlags&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT;
uint32_t equation = (newFlags&BGFX_STATE_BLEND_EQUATION_MASK)>>BGFX_STATE_BLEND_EQUATION_SHIFT;
uint32_t src = blend&0xf; uint32_t src = blend&0xf;
uint32_t dst = (blend>>4)&0xf; uint32_t dst = (blend>>4)&0xf;
GL_CHECK(glEnable(GL_BLEND) ); GL_CHECK(glEnable(GL_BLEND) );
GL_CHECK(glBlendFunc(s_blendFactor[src].m_src, s_blendFactor[dst].m_dst) ); GL_CHECK(glBlendFunc(s_blendFactor[src].m_src, s_blendFactor[dst].m_dst) );
GL_CHECK(glBlendEquation(s_blendEquation[equation]) );
if ( (s_blendFactor[src].m_factor || s_blendFactor[dst].m_factor) if ( (s_blendFactor[src].m_factor || s_blendFactor[dst].m_factor)
&& blendFactor != state.m_rgba) && blendFactor != state.m_rgba)

View file

@ -80,6 +80,8 @@
# define GL_R32F GL_R32F_EXT # define GL_R32F GL_R32F_EXT
# define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT # define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT
# define GL_SAMPLER_3D GL_SAMPLER_3D_OES # define GL_SAMPLER_3D GL_SAMPLER_3D_OES
# define GL_MIN GL_MIN_EXT
# define GL_MAX GL_MAX_EXT
# elif BGFX_CONFIG_RENDERER_OPENGLES3 # elif BGFX_CONFIG_RENDERER_OPENGLES3
# include <GLES3/gl3platform.h> # include <GLES3/gl3platform.h>
# include <GLES3/gl3.h> # include <GLES3/gl3.h>
@ -256,7 +258,7 @@ namespace bgfx
# define _GREMEDY_SETMARKER(_string) glStringMarkerGREMEDY(0, _string) # define _GREMEDY_SETMARKER(_string) glStringMarkerGREMEDY(0, _string)
# define _GREMEDY_FRAMETERMINATOR() glFrameTerminatorGREMEDY() # define _GREMEDY_FRAMETERMINATOR() glFrameTerminatorGREMEDY()
#else #else
# define _GREMEDY_SETMARKER(_string) do {} while(0) # define _GREMEDY_SETMARKER(_string) do { BX_UNUSED(_string); } while(0)
# define _GREMEDY_FRAMETERMINATOR() do {} while(0) # define _GREMEDY_FRAMETERMINATOR() do {} while(0)
#endif // BGFX_CONFIG_DEBUG_GREMEDY #endif // BGFX_CONFIG_DEBUG_GREMEDY