| @@ -57,6 +57,7 @@ private: | |||||
| TrackedState<float> m_clear_depth; | TrackedState<float> m_clear_depth; | ||||
| TrackedState<AlphaFunc> m_alpha_func; | TrackedState<AlphaFunc> m_alpha_func; | ||||
| TrackedState<float> m_alpha_value; | TrackedState<float> m_alpha_value; | ||||
| TrackedState<BlendEquation> m_blend_rgb, m_blend_alpha; | |||||
| TrackedState<BlendFunc> m_blend_src, m_blend_dst; | TrackedState<BlendFunc> m_blend_src, m_blend_dst; | ||||
| TrackedState<DepthFunc> m_depth_func; | TrackedState<DepthFunc> m_depth_func; | ||||
| TrackedState<DepthMask> m_depth_mask; | TrackedState<DepthMask> m_depth_mask; | ||||
| @@ -166,6 +167,26 @@ float RenderContext::GetAlphaValue() | |||||
| return g_renderer->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) | void RenderContext::SetBlendFunc(BlendFunc src, BlendFunc dst) | ||||
| { | { | ||||
| if (!m_data->m_blend_src.HasChanged()) | if (!m_data->m_blend_src.HasChanged()) | ||||
| @@ -61,6 +61,7 @@ private: | |||||
| float m_clear_depth; | float m_clear_depth; | ||||
| AlphaFunc m_alpha_func; | AlphaFunc m_alpha_func; | ||||
| float m_alpha_value; | float m_alpha_value; | ||||
| BlendEquation m_blend_rgb, m_blend_alpha; | |||||
| BlendFunc m_blend_src, m_blend_dst; | BlendFunc m_blend_src, m_blend_dst; | ||||
| DepthFunc m_depth_func; | DepthFunc m_depth_func; | ||||
| DepthMask m_depth_mask; | DepthMask m_depth_mask; | ||||
| @@ -150,6 +151,10 @@ Renderer::Renderer(ivec2 size) | |||||
| m_data->m_alpha_value = -1.0f; | m_data->m_alpha_value = -1.0f; | ||||
| SetAlphaFunc(AlphaFunc::Disabled, 0.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_src = BlendFunc::Disabled; | ||||
| m_data->m_blend_dst = BlendFunc::Disabled; | m_data->m_blend_dst = BlendFunc::Disabled; | ||||
| SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); | SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); | ||||
| @@ -408,6 +413,84 @@ float Renderer::GetAlphaValue() const | |||||
| return m_data->m_alpha_value; | 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 | * Blend function | ||||
| */ | */ | ||||
| @@ -31,6 +31,7 @@ public: | |||||
| void SetClearColor(vec4 color); | void SetClearColor(vec4 color); | ||||
| void SetClearDepth(float depth); | void SetClearDepth(float depth); | ||||
| void SetAlphaFunc(AlphaFunc func, float alpha); | void SetAlphaFunc(AlphaFunc func, float alpha); | ||||
| void SetBlendEquation(BlendEquation rgb, BlendEquation alpha); | |||||
| void SetBlendFunc(BlendFunc src, BlendFunc dst); | void SetBlendFunc(BlendFunc src, BlendFunc dst); | ||||
| void SetDepthFunc(DepthFunc func); | void SetDepthFunc(DepthFunc func); | ||||
| void SetDepthMask(DepthMask mask); | void SetDepthMask(DepthMask mask); | ||||
| @@ -42,6 +43,8 @@ public: | |||||
| float GetClearDepth(); | float GetClearDepth(); | ||||
| AlphaFunc GetAlphaFunc(); | AlphaFunc GetAlphaFunc(); | ||||
| float GetAlphaValue(); | float GetAlphaValue(); | ||||
| BlendEquation GetBlendEquationRgb(); | |||||
| BlendEquation GetBlendEquationAlpha(); | |||||
| BlendFunc GetBlendFuncSrc(); | BlendFunc GetBlendFuncSrc(); | ||||
| BlendFunc GetBlendFuncDst(); | BlendFunc GetBlendFuncDst(); | ||||
| DepthFunc GetDepthFunc(); | DepthFunc GetDepthFunc(); | ||||
| @@ -41,6 +41,24 @@ struct ClearMask | |||||
| inline operator Value() { return m_value; } | 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. */ | /* A safe enum to indicate the blending factors. */ | ||||
| struct BlendFunc | struct BlendFunc | ||||
| { | { | ||||
| @@ -190,6 +208,10 @@ public: | |||||
| AlphaFunc GetAlphaFunc() const; | AlphaFunc GetAlphaFunc() const; | ||||
| float GetAlphaValue() const; | float GetAlphaValue() const; | ||||
| void SetBlendEquation(BlendEquation rgb, BlendEquation alpha); | |||||
| BlendEquation GetBlendEquationRgb() const; | |||||
| BlendEquation GetBlendEquationAlpha() const; | |||||
| void SetBlendFunc(BlendFunc src, BlendFunc dst); | void SetBlendFunc(BlendFunc src, BlendFunc dst); | ||||
| BlendFunc GetBlendFuncSrc() const; | BlendFunc GetBlendFuncSrc() const; | ||||
| BlendFunc GetBlendFuncDst() const; | BlendFunc GetBlendFuncDst() const; | ||||
| @@ -282,6 +282,7 @@ void Scene::RenderTiles() // XXX: rename to Blit() | |||||
| rc.SetDepthFunc(DepthFunc::LessOrEqual); | rc.SetDepthFunc(DepthFunc::LessOrEqual); | ||||
| rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); | rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); | ||||
| rc.SetBlendEquation(BlendEquation::Add, BlendEquation::Max); | |||||
| rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); | rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); | ||||
| #if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
| @@ -397,6 +398,7 @@ void Scene::RenderLines(float seconds) // XXX: rename to Blit() | |||||
| rc.SetDepthFunc(DepthFunc::LessOrEqual); | rc.SetDepthFunc(DepthFunc::LessOrEqual); | ||||
| rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); | rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); | ||||
| rc.SetBlendEquation(BlendEquation::Add, BlendEquation::Max); | |||||
| rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); | rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); | ||||
| int linecount = data->m_lines.Count(); | int linecount = data->m_lines.Count(); | ||||