diff --git a/src/gpu/rendercontext.cpp b/src/gpu/rendercontext.cpp index 288ed2d7..56823b1e 100644 --- a/src/gpu/rendercontext.cpp +++ b/src/gpu/rendercontext.cpp @@ -55,12 +55,16 @@ private: Scene *m_scene; TrackedState m_clear_color; + TrackedState m_clear_depth; - TrackedState m_alpha_blend; - TrackedState m_blend_src; - TrackedState m_blend_dst; - TrackedState m_alpha_test; + + TrackedState m_alpha_func; + TrackedState m_alpha_value; + + TrackedState m_blend_src, m_blend_dst; + TrackedState m_depth_func; + TrackedState m_face_culling; }; @@ -82,16 +86,14 @@ RenderContext::~RenderContext() if (m_data->m_clear_depth.HasChanged()) g_renderer->SetClearDepth(m_data->m_clear_depth.GetValue()); - if (m_data->m_alpha_blend.HasChanged()) - g_renderer->SetAlphaBlend(m_data->m_alpha_blend.GetValue()); + if (m_data->m_alpha_func.HasChanged()) + g_renderer->SetAlphaFunc(m_data->m_alpha_func.GetValue(), + m_data->m_alpha_value.GetValue()); if (m_data->m_blend_src.HasChanged()) g_renderer->SetBlendFunc(m_data->m_blend_src.GetValue(), m_data->m_blend_dst.GetValue()); - if (m_data->m_alpha_test.HasChanged()) - g_renderer->SetAlphaTest(m_data->m_alpha_test.GetValue()); - if (m_data->m_depth_func.HasChanged()) g_renderer->SetDepthFunc(m_data->m_depth_func.GetValue()); @@ -117,12 +119,14 @@ void RenderContext::SetClearDepth(float depth) g_renderer->SetClearDepth(depth); } -void RenderContext::SetAlphaBlend(bool set) +void RenderContext::SetAlphaFunc(AlphaFunc func, float alpha) { - if (!m_data->m_alpha_blend.HasChanged()) - m_data->m_alpha_blend.TrackValue(g_renderer->GetAlphaBlend()); + if (!m_data->m_alpha_func.HasChanged()) + m_data->m_alpha_func.TrackValue(g_renderer->GetAlphaFunc()); + if (!m_data->m_alpha_value.HasChanged()) + m_data->m_alpha_value.TrackValue(g_renderer->GetAlphaValue()); - g_renderer->SetAlphaBlend(set); + g_renderer->SetAlphaFunc(func, alpha); } void RenderContext::SetBlendFunc(BlendFunc src, BlendFunc dst) @@ -135,14 +139,6 @@ void RenderContext::SetBlendFunc(BlendFunc src, BlendFunc dst) g_renderer->SetBlendFunc(src, dst); } -void RenderContext::SetAlphaTest(bool set) -{ - if (!m_data->m_alpha_test.HasChanged()) - m_data->m_alpha_test.TrackValue(g_renderer->GetAlphaTest()); - - g_renderer->SetAlphaTest(set); -} - void RenderContext::SetDepthFunc(DepthFunc func) { if (!m_data->m_depth_func.HasChanged()) diff --git a/src/gpu/renderer.cpp b/src/gpu/renderer.cpp index bcc7898a..d5f93d5d 100644 --- a/src/gpu/renderer.cpp +++ b/src/gpu/renderer.cpp @@ -55,10 +55,11 @@ class RendererData private: vec4 m_clear_color; float m_clear_depth; + AlphaFunc m_alpha_func; + float m_alpha_value; BlendFunc m_blend_src, m_blend_dst; DepthFunc m_depth_func; CullMode m_face_culling; - bool m_alpha_blend, m_alpha_test; #if defined USE_D3D9 IDirect3DDevice9 *m_d3d_dev; @@ -96,14 +97,12 @@ Renderer::Renderer() m_data->m_clear_depth = -1.f; SetClearDepth(1.f); - m_data->m_alpha_blend = false; - SetAlphaBlend(true); + m_data->m_alpha_func = AlphaFunc::Never; + m_data->m_alpha_value = -1.0f; + SetAlphaFunc(AlphaFunc::Disabled, 0.0f); - m_data->m_alpha_test = true; - SetAlphaTest(false); - - m_data->m_blend_src = BlendFunc::Zero; - m_data->m_blend_dst = BlendFunc::Zero; + m_data->m_blend_src = BlendFunc::Disabled; + m_data->m_blend_dst = BlendFunc::Disabled; SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); m_data->m_depth_func = DepthFunc::Disabled; @@ -170,29 +169,96 @@ float Renderer::GetClearDepth() const } /* - * Alpha blending + * Alpha testing */ -void Renderer::SetAlphaBlend(bool set) +void Renderer::SetAlphaFunc(AlphaFunc func, float alpha) { - if (m_data->m_alpha_blend == set) + if (m_data->m_alpha_func == func && m_data->m_alpha_value == alpha) return; #if defined USE_D3D9 || defined _XBOX - m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, set ? 1 : 0); + switch (func) + { + case AlphaFunc::Disabled: + break; /* Nothing to do */ + case AlphaFunc::Never: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NEVER); + break; + case AlphaFunc::Less: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESS); + break; + case AlphaFunc::Equal: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_EQUAL); + break; + case AlphaFunc::LessOrEqual: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_LESSEQUAL); + break; + case AlphaFunc::Greater: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); + break; + case AlphaFunc::NotEqual: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_NOTEQUAL); + break; + case AlphaFunc::GreaterOrEqual: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); + break; + case AlphaFunc::Always: + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); + break; + } + + if (func == AlphaFunc::Disabled) + { + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + } + else + { + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHAREF, + (DWORD)(alpha * 255.999f)); + } #else - if (set) - glEnable(GL_BLEND); + switch (func) + { + case AlphaFunc::Disabled: + break; /* Nothing to do */ + case AlphaFunc::Never: + glAlphaFunc(GL_NEVER, alpha); break; + case AlphaFunc::Less: + glAlphaFunc(GL_LESS, alpha); break; + case AlphaFunc::Equal: + glAlphaFunc(GL_EQUAL, alpha); break; + case AlphaFunc::LessOrEqual: + glAlphaFunc(GL_LEQUAL, alpha); break; + case AlphaFunc::Greater: + glAlphaFunc(GL_GREATER, alpha); break; + case AlphaFunc::NotEqual: + glAlphaFunc(GL_NOTEQUAL, alpha); break; + case AlphaFunc::GreaterOrEqual: + glAlphaFunc(GL_GEQUAL, alpha); break; + case AlphaFunc::Always: + glAlphaFunc(GL_ALWAYS, alpha); break; + } + + if (func == AlphaFunc::Disabled) + glDisable(GL_ALPHA_TEST); else - glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); #endif - m_data->m_alpha_blend = set; + m_data->m_alpha_func = func; + m_data->m_alpha_value = alpha; +} + +AlphaFunc Renderer::GetAlphaFunc() const +{ + return m_data->m_alpha_func; } -bool Renderer::GetAlphaBlend() const +float Renderer::GetAlphaValue() const { - return m_data->m_alpha_blend; + return m_data->m_alpha_value; } /* @@ -212,6 +278,8 @@ void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst) { switch (s2[i]) { + case BlendFunc::Disabled: + break; /* Nothing to do */ case BlendFunc::Zero: s1[i] = D3DBLEND_ZERO; break; case BlendFunc::One: @@ -248,8 +316,16 @@ void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst) } } - m_data->m_d3d_dev->SetRenderState(D3DRS_SRCBLEND, s1[0]); - m_data->m_d3d_dev->SetRenderState(D3DRS_DESTBLEND, s1[1]); + if (src == BlendFunc::Disabled) + { + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, 0); + } + else + { + m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, 1); + m_data->m_d3d_dev->SetRenderState(D3DRS_SRCBLEND, s1[0]); + m_data->m_d3d_dev->SetRenderState(D3DRS_DESTBLEND, s1[1]); + } #else GLenum s1[2] = { GL_ONE, GL_ZERO }; BlendFunc s2[2] = { src, dst }; @@ -258,6 +334,8 @@ void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst) { switch (s2[i]) { + case BlendFunc::Disabled: + break; /* Nothing to do */ case BlendFunc::Zero: s1[i] = GL_ZERO; break; case BlendFunc::One: @@ -289,7 +367,15 @@ void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst) } } - glBlendFunc(s1[0], s1[1]); + if (src == BlendFunc::Disabled) + { + glDisable(GL_BLEND); + } + else + { + glEnable(GL_BLEND); + glBlendFunc(s1[0], s1[1]); + } #endif m_data->m_blend_src = src; @@ -306,32 +392,6 @@ BlendFunc Renderer::GetBlendFuncDst() const return m_data->m_blend_dst; } -/* - * Alpha testing - */ - -void Renderer::SetAlphaTest(bool set) -{ - if (m_data->m_alpha_test == set) - return; - -#if defined USE_D3D9 || defined _XBOX - m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHATESTENABLE, set ? 1 : 0); -#else - if (set) - glEnable(GL_ALPHA_TEST); - else - glDisable(GL_ALPHA_TEST); -#endif - - m_data->m_alpha_test = set; -} - -bool Renderer::GetAlphaTest() const -{ - return m_data->m_alpha_test; -} - /* * Depth test */ @@ -443,10 +503,12 @@ void Renderer::SetFaceCulling(CullMode mode) break; case CullMode::Clockwise: glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); glFrontFace(GL_CW); break; case CullMode::CounterClockwise: glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); glFrontFace(GL_CCW); break; } diff --git a/src/lol/gpu/rendercontext.h b/src/lol/gpu/rendercontext.h index aac83065..92e14d0f 100644 --- a/src/lol/gpu/rendercontext.h +++ b/src/lol/gpu/rendercontext.h @@ -29,9 +29,8 @@ public: void SetClearColor(vec4 color); void SetClearDepth(float depth); - void SetAlphaBlend(bool set); + void SetAlphaFunc(AlphaFunc func, float alpha); void SetBlendFunc(BlendFunc src, BlendFunc dst); - void SetAlphaTest(bool set); void SetDepthFunc(DepthFunc func); void SetFaceCulling(CullMode mode); diff --git a/src/lol/gpu/renderer.h b/src/lol/gpu/renderer.h index d6920429..91b29b2b 100644 --- a/src/lol/gpu/renderer.h +++ b/src/lol/gpu/renderer.h @@ -26,6 +26,7 @@ struct BlendFunc { enum Value { + Disabled, Zero, One, SrcColor, @@ -86,6 +87,28 @@ struct DepthFunc inline operator Value() { return m_value; } }; +/* A safe enum to indicate the alpha test mode. */ +struct AlphaFunc +{ + enum Value + { + Disabled, + Never, + Less, + Equal, + LessOrEqual, + Greater, + NotEqual, + GreaterOrEqual, + Always, + } + m_value; + + inline AlphaFunc() : m_value(Disabled) {} + inline AlphaFunc(Value v) : m_value(v) {} + inline operator Value() { return m_value; } +}; + class Renderer { private: @@ -102,16 +125,14 @@ public: void SetClearDepth(float depth); float GetClearDepth() const; - void SetAlphaBlend(bool set); - bool GetAlphaBlend() const; + void SetAlphaFunc(AlphaFunc func, float alpha); + AlphaFunc GetAlphaFunc() const; + float GetAlphaValue() const; void SetBlendFunc(BlendFunc src, BlendFunc dst); BlendFunc GetBlendFuncSrc() const; BlendFunc GetBlendFuncDst() const; - void SetAlphaTest(bool set); - bool GetAlphaTest() const; - void SetDepthFunc(DepthFunc func); DepthFunc GetDepthFunc() const; diff --git a/src/scene.cpp b/src/scene.cpp index e819807e..671bc537 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -193,16 +193,8 @@ void Scene::Render() // XXX: rename to Blit() { RenderContext rc; rc.SetDepthFunc(DepthFunc::LessOrEqual); - rc.SetAlphaBlend(true); rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); - -#if defined USE_D3D9 || defined _XBOX -#else -#if defined HAVE_GL_2X && !defined __APPLE__ - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GEQUAL, 0.01f); -#endif -#endif + rc.SetAlphaFunc(AlphaFunc::GreaterOrEqual, 0.01f); /* Early test if nothing needs to be rendered */ if (data->m_tiles.Count()) @@ -344,14 +336,6 @@ void Scene::Render() // XXX: rename to Blit() data->m_lines.Empty(); delete vb; } - -#if defined USE_D3D9 || defined _XBOX - /* TODO */ -#else -# if defined HAVE_GL_2X && !defined __APPLE__ - glDisable(GL_ALPHA_TEST); -# endif -#endif } } /* namespace lol */