diff --git a/src/gpu/rendercontext.cpp b/src/gpu/rendercontext.cpp index 7976ca5c..50483709 100644 --- a/src/gpu/rendercontext.cpp +++ b/src/gpu/rendercontext.cpp @@ -57,6 +57,7 @@ private: TrackedState m_clear_depth; TrackedState m_alpha_func; TrackedState m_alpha_value; + TrackedState m_blend_rgb, m_blend_alpha; TrackedState m_blend_src, m_blend_dst; TrackedState m_depth_func; TrackedState m_depth_mask; @@ -166,6 +167,26 @@ float RenderContext::GetAlphaValue() return g_renderer->GetAlphaValue(); } +void RenderContext::SetBlendEquation(BlendEquation rgb, BlendEquation alpha) +{ + if (!m_data->m_blend_rgb.HasChanged()) + m_data->m_blend_rgb.TrackValue(g_renderer->GetBlendEquationRgb()); + if (!m_data->m_blend_alpha.HasChanged()) + m_data->m_blend_alpha.TrackValue(g_renderer->GetBlendEquationAlpha()); + + g_renderer->SetBlendEquation(rgb, alpha); +} + +BlendEquation RenderContext::GetBlendEquationRgb() +{ + return g_renderer->GetBlendEquationRgb(); +} + +BlendEquation RenderContext::GetBlendEquationAlpha() +{ + return g_renderer->GetBlendEquationAlpha(); +} + void RenderContext::SetBlendFunc(BlendFunc src, BlendFunc dst) { if (!m_data->m_blend_src.HasChanged()) diff --git a/src/gpu/renderer.cpp b/src/gpu/renderer.cpp index 95cee3cc..ac8dfc3c 100755 --- a/src/gpu/renderer.cpp +++ b/src/gpu/renderer.cpp @@ -61,6 +61,7 @@ private: float m_clear_depth; AlphaFunc m_alpha_func; float m_alpha_value; + BlendEquation m_blend_rgb, m_blend_alpha; BlendFunc m_blend_src, m_blend_dst; DepthFunc m_depth_func; DepthMask m_depth_mask; @@ -150,6 +151,10 @@ Renderer::Renderer(ivec2 size) m_data->m_alpha_value = -1.0f; SetAlphaFunc(AlphaFunc::Disabled, 0.0f); + m_data->m_blend_rgb = BlendEquation::Subtract; + m_data->m_blend_alpha = BlendEquation::Subtract; + SetBlendEquation(BlendEquation::Add, BlendEquation::Add); + m_data->m_blend_src = BlendFunc::Disabled; m_data->m_blend_dst = BlendFunc::Disabled; SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); @@ -408,6 +413,84 @@ float Renderer::GetAlphaValue() const return m_data->m_alpha_value; } +/* + * Blend equation + */ + +void Renderer::SetBlendEquation(BlendEquation rgb, BlendEquation alpha) +{ + if (m_data->m_blend_rgb == rgb && m_data->m_blend_alpha == alpha) + return; + +#if defined USE_D3D9 || defined _XBOX + D3DBLEND s1[2] = { D3DBLENDOP_ADD, D3DBLENDOP_ADD }; + BlendEquation s2[2] = { rgb, alpha }; + + for (int i = 0; i < 2; ++i) + { + switch (s2[i]) + { + case BlendEquation::Add: + s1[i] = D3DBLENDOP_ADD; break; + case BlendEquation::Subtract: + s1[i] = D3DBLENDOP_SUBTRACT; break; + case BlendEquation::ReverseSubtract: + s1[i] = D3DBLENDOP_REVSUBTRACT; break; + case BlendEquation::Max: + s1[i] = D3DBLENDOP_MAX; break; + case BlendEquation::Min: + s1[i] = D3DBLENDOP_MIN; break; + } + } + + m_data->m_d3d_dev->SetRenderState(D3DRS_BLENDOP, s1[0]); + m_data->m_d3d_dev->SetRenderState(D3DRS_BLENDOPALPHA, s1[1]); +#else + GLenum s1[2] = { GL_FUNC_ADD, GL_FUNC_ADD }; + BlendEquation s2[2] = { rgb, alpha }; + + for (int i = 0; i < 2; ++i) + { + switch (s2[i]) + { + case BlendEquation::Add: + s1[i] = GL_FUNC_ADD; break; + case BlendEquation::Subtract: + s1[i] = GL_FUNC_SUBTRACT; break; + case BlendEquation::ReverseSubtract: + s1[i] = GL_FUNC_REVERSE_SUBTRACT; break; + case BlendEquation::Max: +#if defined GL_MAX + s1[i] = GL_MAX; break; +#else + s1[i] = GL_MAX_EXT; break; +#endif + case BlendEquation::Min: +#if defined GL_MIN + s1[i] = GL_MIN; break; +#else + s1[i] = GL_MIN_EXT; break; +#endif + } + } + + glBlendEquationSeparate(s1[0], s1[1]); +#endif + + m_data->m_blend_rgb = rgb; + m_data->m_blend_alpha = alpha; +} + +BlendEquation Renderer::GetBlendEquationRgb() const +{ + return m_data->m_blend_rgb; +} + +BlendEquation Renderer::GetBlendEquationAlpha() const +{ + return m_data->m_blend_alpha; +} + /* * Blend function */ diff --git a/src/lol/gpu/rendercontext.h b/src/lol/gpu/rendercontext.h index 78cb4a66..7b6982fc 100644 --- a/src/lol/gpu/rendercontext.h +++ b/src/lol/gpu/rendercontext.h @@ -31,6 +31,7 @@ public: void SetClearColor(vec4 color); void SetClearDepth(float depth); void SetAlphaFunc(AlphaFunc func, float alpha); + void SetBlendEquation(BlendEquation rgb, BlendEquation alpha); void SetBlendFunc(BlendFunc src, BlendFunc dst); void SetDepthFunc(DepthFunc func); void SetDepthMask(DepthMask mask); @@ -42,6 +43,8 @@ public: float GetClearDepth(); AlphaFunc GetAlphaFunc(); float GetAlphaValue(); + BlendEquation GetBlendEquationRgb(); + BlendEquation GetBlendEquationAlpha(); BlendFunc GetBlendFuncSrc(); BlendFunc GetBlendFuncDst(); DepthFunc GetDepthFunc(); diff --git a/src/lol/gpu/renderer.h b/src/lol/gpu/renderer.h index b26db243..6e8ccda8 100755 --- a/src/lol/gpu/renderer.h +++ b/src/lol/gpu/renderer.h @@ -41,6 +41,24 @@ struct ClearMask inline operator Value() { return m_value; } }; +/* A safe enum to indicate the blend equation. */ +struct BlendEquation +{ + enum Value + { + Add, + Subtract, + ReverseSubtract, + Min, + Max, + } + m_value; + + inline BlendEquation() : m_value(Add) {} + inline BlendEquation(Value v) : m_value(v) {} + inline operator Value() { return m_value; } +}; + /* A safe enum to indicate the blending factors. */ struct BlendFunc { @@ -190,6 +208,10 @@ public: AlphaFunc GetAlphaFunc() const; float GetAlphaValue() const; + void SetBlendEquation(BlendEquation rgb, BlendEquation alpha); + BlendEquation GetBlendEquationRgb() const; + BlendEquation GetBlendEquationAlpha() const; + void SetBlendFunc(BlendFunc src, BlendFunc dst); BlendFunc GetBlendFuncSrc() const; BlendFunc GetBlendFuncDst() const; diff --git a/src/scene.cpp b/src/scene.cpp index b2e6ec92..87c2b4ed 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -282,6 +282,7 @@ void Scene::RenderTiles() // XXX: rename to Blit() rc.SetDepthFunc(DepthFunc::LessOrEqual); rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); + rc.SetBlendEquation(BlendEquation::Add, BlendEquation::Max); rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); #if defined USE_D3D9 || defined _XBOX @@ -397,6 +398,7 @@ void Scene::RenderLines(float seconds) // XXX: rename to Blit() rc.SetDepthFunc(DepthFunc::LessOrEqual); rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); + rc.SetBlendEquation(BlendEquation::Add, BlendEquation::Max); rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); int linecount = data->m_lines.Count();