From 5b763a28bb7d9e8f04ad247fb26e3b3ba9d1a6e2 Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Fri, 29 Mar 2013 22:58:50 -0700 Subject: [PATCH] Added blend factor/color blend modes support. --- include/bgfx.h | 7 ++++++- src/bgfx.cpp | 4 ++-- src/bgfx_p.h | 7 +++++-- src/glimports.h | 1 + src/renderer_d3d11.cpp | 38 +++++++++++++++++++++++--------------- src/renderer_d3d9.cpp | 34 ++++++++++++++++++++++------------ src/renderer_gl.cpp | 42 ++++++++++++++++++++++++++++++------------ 7 files changed, 89 insertions(+), 44 deletions(-) diff --git a/include/bgfx.h b/include/bgfx.h index 0e6dd58b..b694c115 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -37,6 +37,8 @@ #define BGFX_STATE_BLEND_DST_COLOR UINT64_C(0x0000000000009000) #define BGFX_STATE_BLEND_INV_DST_COLOR UINT64_C(0x000000000000a000) #define BGFX_STATE_BLEND_SRC_ALPHA_SAT UINT64_C(0x000000000000b000) +#define BGFX_STATE_BLEND_FACTOR UINT64_C(0x000000000000c000) +#define BGFX_STATE_BLEND_INV_FACTOR UINT64_C(0x000000000000d000) #define BGFX_STATE_BLEND_SHIFT 12 #define BGFX_STATE_BLEND_MASK UINT64_C(0x000000000ffff000) @@ -724,10 +726,13 @@ namespace bgfx /// BGFX_STATE_MSAA - Enable MSAA. /// BGFX_STATE_PT_[LINES/POINTS] - Primitive type. /// + /// @param _rgba Sets blend factor used by BGFX_STATE_BLEND_FACTOR and + /// BGFX_STATE_BLEND_INV_FACTOR blend modes. + /// /// NOTE: /// Use BGFX_STATE_ALPHA_REF, BGFX_STATE_BLEND_FUNC and /// BGFX_STATE_BLEND_FUNC macros to setup more complex states. - void setState(uint64_t _state); + void setState(uint64_t _state, uint32_t _rgba = UINT32_MAX); /// Set stencil test state. /// diff --git a/src/bgfx.cpp b/src/bgfx.cpp index d46914d1..a65039cf 100755 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -1299,10 +1299,10 @@ namespace bgfx s_ctx.setViewTransformMask(_viewMask, _view, _proj, _other); } - void setState(uint64_t _state) + void setState(uint64_t _state, uint32_t _rgba) { BGFX_CHECK_MAIN_THREAD(); - s_ctx.m_submit->setState(_state); + s_ctx.m_submit->setState(_state, _rgba); } void setStencil(uint32_t _fstencil, uint32_t _bstencil) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 2d3ffee5..5e4a080c 100755 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -855,11 +855,12 @@ namespace bgfx m_constBegin = m_constEnd; m_flags = BGFX_STATE_DEFAULT; m_stencil = packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT); + m_rgba = UINT32_MAX; m_matrix = 0; m_startIndex = 0; m_numIndices = UINT32_MAX; m_startVertex = 0; - m_numVertices = UINT32_C(0xffffffff); + m_numVertices = UINT32_MAX; m_instanceDataOffset = 0; m_instanceDataStride = 0; m_numInstances = 1; @@ -878,6 +879,7 @@ namespace bgfx uint64_t m_flags; uint64_t m_stencil; + uint32_t m_rgba; uint32_t m_constBegin; uint32_t m_constEnd; uint32_t m_matrix; @@ -984,11 +986,12 @@ namespace bgfx } } - void setState(uint64_t _state) + void setState(uint64_t _state, uint32_t _rgba) { uint8_t blend = ( (_state&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT)&0xff; m_key.m_trans = "\x0\x1\x1\x2\x2\x1\x2\x1\x2\x1\x1\x1\x1\x1\x1\x1\x1"[( (blend)&0xf) + (!!blend)]; m_state.m_flags = _state; + m_state.m_rgba = _rgba; } void setStencil(uint32_t _fstencil, uint32_t _bstencil) diff --git a/src/glimports.h b/src/glimports.h index 8361e3ad..22514143 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -135,6 +135,7 @@ GL_IMPORT(true, PFNGLSTENCILOPSEPARATEPROC, glStencilOpSeparate); GL_IMPORT(true, PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); GL_IMPORT(true, PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); +GL_IMPORT(true, PFNGLBLENDCOLORPROC, glBlendColor); #if BGFX_CONFIG_DEBUG_GREMEDY GL_IMPORT(true, PFNGLSTRINGMARKERGREMEDYPROC, glStringMarkerGREMEDY); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 3c2959e2..dfc66d97 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -19,18 +19,20 @@ namespace bgfx static const D3D11_BLEND s_blendFactor[][2] = { - { (D3D11_BLEND)0, (D3D11_BLEND)0 }, // ignored - { D3D11_BLEND_ZERO, D3D11_BLEND_ZERO }, - { D3D11_BLEND_ONE, D3D11_BLEND_ONE }, - { D3D11_BLEND_SRC_COLOR, D3D11_BLEND_SRC_ALPHA }, - { D3D11_BLEND_INV_SRC_COLOR, D3D11_BLEND_INV_SRC_ALPHA }, - { D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_SRC_ALPHA }, - { D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA }, - { D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA }, - { D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_INV_DEST_ALPHA }, - { D3D11_BLEND_DEST_COLOR, D3D11_BLEND_DEST_ALPHA }, - { D3D11_BLEND_INV_DEST_COLOR, D3D11_BLEND_INV_DEST_ALPHA }, - { D3D11_BLEND_SRC_ALPHA_SAT, D3D11_BLEND_ONE }, + { (D3D11_BLEND)0, (D3D11_BLEND)0 }, // ignored + { D3D11_BLEND_ZERO, D3D11_BLEND_ZERO }, + { D3D11_BLEND_ONE, D3D11_BLEND_ONE }, + { D3D11_BLEND_SRC_COLOR, D3D11_BLEND_SRC_ALPHA }, + { D3D11_BLEND_INV_SRC_COLOR, D3D11_BLEND_INV_SRC_ALPHA }, + { D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_SRC_ALPHA }, + { D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA }, + { D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_DEST_ALPHA }, + { D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_INV_DEST_ALPHA }, + { D3D11_BLEND_DEST_COLOR, D3D11_BLEND_DEST_ALPHA }, + { D3D11_BLEND_INV_DEST_COLOR, D3D11_BLEND_INV_DEST_ALPHA }, + { D3D11_BLEND_SRC_ALPHA_SAT, D3D11_BLEND_ONE }, + { D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_BLEND_FACTOR }, + { D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR }, }; static const D3D11_COMPARISON_FUNC s_depthFunc[] = @@ -642,7 +644,7 @@ namespace bgfx m_deviceCtx->IASetInputLayout(layout); } - void setBlendState(uint64_t _state) + void setBlendState(uint64_t _state, uint32_t _rgba = UINT32_MAX) { _state &= BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE; @@ -675,7 +677,13 @@ namespace bgfx m_blendStateCache.add(_state, bs); } - m_deviceCtx->OMSetBlendState(bs, NULL, 0xffffffff); + float blendFactor[4]; + blendFactor[0] = (_rgba>>24)/255.0f; + blendFactor[1] = ( (_rgba>>16)&0xff)/255.0f; + blendFactor[2] = ( (_rgba>>8)&0xff)/255.0f; + blendFactor[3] = (_rgba&0xff)/255.0f; + + m_deviceCtx->OMSetBlendState(bs, blendFactor, 0xffffffff); } void setDepthStencilState(uint64_t _state, uint64_t _stencil = 0) @@ -2192,7 +2200,7 @@ namespace bgfx { if ( (BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags) { - s_renderCtx.setBlendState(newFlags); + s_renderCtx.setBlendState(newFlags, state.m_rgba); } if ( (BGFX_STATE_CULL_MASK) & changedFlags) diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 5e547afb..aa376221 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -37,18 +37,20 @@ namespace bgfx static const D3DBLEND s_blendFactor[][2] = { - { (D3DBLEND)0, (D3DBLEND)0 }, // ignored - { D3DBLEND_ZERO, D3DBLEND_ZERO }, - { D3DBLEND_ONE, D3DBLEND_ONE }, - { D3DBLEND_SRCCOLOR, D3DBLEND_SRCCOLOR }, - { D3DBLEND_INVSRCCOLOR, D3DBLEND_INVSRCCOLOR }, - { D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA }, - { D3DBLEND_INVSRCALPHA, D3DBLEND_INVSRCALPHA }, - { D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA }, - { D3DBLEND_INVDESTALPHA, D3DBLEND_INVDESTALPHA }, - { D3DBLEND_DESTCOLOR, D3DBLEND_DESTCOLOR }, - { D3DBLEND_INVDESTCOLOR, D3DBLEND_INVDESTCOLOR }, - { D3DBLEND_SRCALPHASAT, D3DBLEND_ONE }, + { (D3DBLEND)0, (D3DBLEND)0 }, // ignored + { D3DBLEND_ZERO, D3DBLEND_ZERO }, + { D3DBLEND_ONE, D3DBLEND_ONE }, + { D3DBLEND_SRCCOLOR, D3DBLEND_SRCCOLOR }, + { D3DBLEND_INVSRCCOLOR, D3DBLEND_INVSRCCOLOR }, + { D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA }, + { D3DBLEND_INVSRCALPHA, D3DBLEND_INVSRCALPHA }, + { D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA }, + { D3DBLEND_INVDESTALPHA, D3DBLEND_INVDESTALPHA }, + { D3DBLEND_DESTCOLOR, D3DBLEND_DESTCOLOR }, + { D3DBLEND_INVDESTCOLOR, D3DBLEND_INVDESTCOLOR }, + { D3DBLEND_SRCALPHASAT, D3DBLEND_ONE }, + { D3DBLEND_BLENDFACTOR, D3DBLEND_BLENDFACTOR }, + { D3DBLEND_INVBLENDFACTOR, D3DBLEND_INVBLENDFACTOR }, }; static const D3DCMPFUNC s_depthFunc[] = @@ -2165,6 +2167,7 @@ namespace bgfx uint8_t view = 0xff; RenderTargetHandle rt = BGFX_INVALID_HANDLE; float alphaRef = 0.0f; + uint32_t blendFactor = 0; D3DPRIMITIVETYPE primType = D3DPT_TRIANGLELIST; uint32_t primNumVerts = 3; @@ -2395,6 +2398,13 @@ namespace bgfx DX_CHECK(device->SetRenderState(D3DRS_DESTBLEND, s_blendFactor[dst][1]) ); // DX_CHECK(device->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_SRCALPHA) ); // DX_CHECK(device->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA) ); + + if (0 != (blend&(BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_FACTOR) ) ) + && blendFactor != state.m_rgba) + { + blendFactor = state.m_rgba; + DX_CHECK(device->SetRenderState(D3DRS_BLENDFACTOR, blendFactor) ); + } } } diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 7fcd3e5a..cb1426be 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -59,6 +59,7 @@ namespace bgfx NVX_gpu_memory_info, OES_rgb8_rgba8, EXT_texture_storage, + EXT_blend_color, Count }; @@ -113,6 +114,7 @@ namespace bgfx { "GL_NVX_gpu_memory_info", false, true }, { "GL_OES_rgb8_rgba8", false, true }, { "GL_EXT_texture_storage", false, true }, + { "GL_EXT_blend_color", BGFX_CONFIG_RENDERER_OPENGL >= 31, true }, }; #if BGFX_CONFIG_RENDERER_OPENGLES3 @@ -556,18 +558,20 @@ namespace bgfx static const GLenum s_blendFactor[][2] = { - { 0, 0 }, // ignored - { GL_ZERO, GL_ZERO }, - { GL_ONE, GL_ONE }, - { GL_SRC_COLOR, GL_SRC_COLOR }, - { GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR }, - { GL_SRC_ALPHA, GL_SRC_ALPHA }, - { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, - { GL_DST_ALPHA, GL_DST_ALPHA }, - { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }, - { GL_DST_COLOR, GL_DST_COLOR }, - { GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_DST_COLOR }, - { GL_SRC_ALPHA_SATURATE, GL_ONE }, + { 0, 0 }, // ignored + { GL_ZERO, GL_ZERO }, + { GL_ONE, GL_ONE }, + { GL_SRC_COLOR, GL_SRC_COLOR }, + { GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR }, + { GL_SRC_ALPHA, GL_SRC_ALPHA }, + { GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, + { GL_DST_ALPHA, GL_DST_ALPHA }, + { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }, + { GL_DST_COLOR, GL_DST_COLOR }, + { GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_DST_COLOR }, + { GL_SRC_ALPHA_SATURATE, GL_ONE }, + { GL_CONSTANT_COLOR, GL_CONSTANT_COLOR }, + { GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR }, }; static const GLenum s_depthFunc[] = @@ -2454,6 +2458,7 @@ namespace bgfx RenderTargetHandle rt = BGFX_INVALID_HANDLE; int32_t height = m_render->m_resolution.m_height; float alphaRef = 0.0f; + uint32_t blendFactor = 0; GLenum primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : GL_TRIANGLES; uint32_t primNumVerts = 3; uint32_t baseVertex = 0; @@ -2647,6 +2652,19 @@ namespace bgfx uint32_t dst = (blend>>4)&0xf; GL_CHECK(glEnable(GL_BLEND) ); GL_CHECK(glBlendFunc(s_blendFactor[src][0], s_blendFactor[dst][1]) ); + + if (0 != (blend&(BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_FACTOR, BGFX_STATE_BLEND_FACTOR) ) ) + && blendFactor != state.m_rgba) + { + blendFactor = state.m_rgba; + + GLclampf rr = (blendFactor>>24)/255.0f; + GLclampf gg = ( (blendFactor>>16)&0xff)/255.0f; + GLclampf bb = ( (blendFactor>>8)&0xff)/255.0f; + GLclampf aa = (blendFactor&0xff)/255.0f; + + GL_CHECK(glBlendColor(rr, gg, bb, aa) ); + } } else {