Browse Source

gpu: add full support for alpha test in GL and D3D.

legacy
Sam Hocevar sam 11 years ago
parent
commit
a75e07d329
5 changed files with 154 additions and 92 deletions
  1. +17
    -21
      src/gpu/rendercontext.cpp
  2. +109
    -47
      src/gpu/renderer.cpp
  3. +1
    -2
      src/lol/gpu/rendercontext.h
  4. +26
    -5
      src/lol/gpu/renderer.h
  5. +1
    -17
      src/scene.cpp

+ 17
- 21
src/gpu/rendercontext.cpp View File

@@ -55,12 +55,16 @@ private:
Scene *m_scene; Scene *m_scene;


TrackedState<vec4> m_clear_color; TrackedState<vec4> m_clear_color;

TrackedState<float> m_clear_depth; TrackedState<float> m_clear_depth;
TrackedState<bool> m_alpha_blend;
TrackedState<BlendFunc> m_blend_src;
TrackedState<BlendFunc> m_blend_dst;
TrackedState<bool> m_alpha_test;

TrackedState<AlphaFunc> m_alpha_func;
TrackedState<float> m_alpha_value;

TrackedState<BlendFunc> m_blend_src, m_blend_dst;

TrackedState<DepthFunc> m_depth_func; TrackedState<DepthFunc> m_depth_func;

TrackedState<CullMode> m_face_culling; TrackedState<CullMode> m_face_culling;
}; };


@@ -82,16 +86,14 @@ RenderContext::~RenderContext()
if (m_data->m_clear_depth.HasChanged()) if (m_data->m_clear_depth.HasChanged())
g_renderer->SetClearDepth(m_data->m_clear_depth.GetValue()); 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()) if (m_data->m_blend_src.HasChanged())
g_renderer->SetBlendFunc(m_data->m_blend_src.GetValue(), g_renderer->SetBlendFunc(m_data->m_blend_src.GetValue(),
m_data->m_blend_dst.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()) if (m_data->m_depth_func.HasChanged())
g_renderer->SetDepthFunc(m_data->m_depth_func.GetValue()); g_renderer->SetDepthFunc(m_data->m_depth_func.GetValue());


@@ -117,12 +119,14 @@ void RenderContext::SetClearDepth(float depth)
g_renderer->SetClearDepth(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) void RenderContext::SetBlendFunc(BlendFunc src, BlendFunc dst)
@@ -135,14 +139,6 @@ void RenderContext::SetBlendFunc(BlendFunc src, BlendFunc dst)
g_renderer->SetBlendFunc(src, 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) void RenderContext::SetDepthFunc(DepthFunc func)
{ {
if (!m_data->m_depth_func.HasChanged()) if (!m_data->m_depth_func.HasChanged())


+ 109
- 47
src/gpu/renderer.cpp View File

@@ -55,10 +55,11 @@ class RendererData
private: private:
vec4 m_clear_color; vec4 m_clear_color;
float m_clear_depth; float m_clear_depth;
AlphaFunc m_alpha_func;
float m_alpha_value;
BlendFunc m_blend_src, m_blend_dst; BlendFunc m_blend_src, m_blend_dst;
DepthFunc m_depth_func; DepthFunc m_depth_func;
CullMode m_face_culling; CullMode m_face_culling;
bool m_alpha_blend, m_alpha_test;


#if defined USE_D3D9 #if defined USE_D3D9
IDirect3DDevice9 *m_d3d_dev; IDirect3DDevice9 *m_d3d_dev;
@@ -96,14 +97,12 @@ Renderer::Renderer()
m_data->m_clear_depth = -1.f; m_data->m_clear_depth = -1.f;
SetClearDepth(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); SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);


m_data->m_depth_func = DepthFunc::Disabled; 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; return;


#if defined USE_D3D9 || defined _XBOX #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 #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 else
glDisable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
#endif #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]) switch (s2[i])
{ {
case BlendFunc::Disabled:
break; /* Nothing to do */
case BlendFunc::Zero: case BlendFunc::Zero:
s1[i] = D3DBLEND_ZERO; break; s1[i] = D3DBLEND_ZERO; break;
case BlendFunc::One: 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 #else
GLenum s1[2] = { GL_ONE, GL_ZERO }; GLenum s1[2] = { GL_ONE, GL_ZERO };
BlendFunc s2[2] = { src, dst }; BlendFunc s2[2] = { src, dst };
@@ -258,6 +334,8 @@ void Renderer::SetBlendFunc(BlendFunc src, BlendFunc dst)
{ {
switch (s2[i]) switch (s2[i])
{ {
case BlendFunc::Disabled:
break; /* Nothing to do */
case BlendFunc::Zero: case BlendFunc::Zero:
s1[i] = GL_ZERO; break; s1[i] = GL_ZERO; break;
case BlendFunc::One: 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 #endif


m_data->m_blend_src = src; m_data->m_blend_src = src;
@@ -306,32 +392,6 @@ BlendFunc Renderer::GetBlendFuncDst() const
return m_data->m_blend_dst; 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 * Depth test
*/ */
@@ -443,10 +503,12 @@ void Renderer::SetFaceCulling(CullMode mode)
break; break;
case CullMode::Clockwise: case CullMode::Clockwise:
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW); glFrontFace(GL_CW);
break; break;
case CullMode::CounterClockwise: case CullMode::CounterClockwise:
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
break; break;
} }


+ 1
- 2
src/lol/gpu/rendercontext.h View File

@@ -29,9 +29,8 @@ public:


void SetClearColor(vec4 color); void SetClearColor(vec4 color);
void SetClearDepth(float depth); void SetClearDepth(float depth);
void SetAlphaBlend(bool set);
void SetAlphaFunc(AlphaFunc func, float alpha);
void SetBlendFunc(BlendFunc src, BlendFunc dst); void SetBlendFunc(BlendFunc src, BlendFunc dst);
void SetAlphaTest(bool set);
void SetDepthFunc(DepthFunc func); void SetDepthFunc(DepthFunc func);
void SetFaceCulling(CullMode mode); void SetFaceCulling(CullMode mode);




+ 26
- 5
src/lol/gpu/renderer.h View File

@@ -26,6 +26,7 @@ struct BlendFunc
{ {
enum Value enum Value
{ {
Disabled,
Zero, Zero,
One, One,
SrcColor, SrcColor,
@@ -86,6 +87,28 @@ struct DepthFunc
inline operator Value() { return m_value; } 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 class Renderer
{ {
private: private:
@@ -102,16 +125,14 @@ public:
void SetClearDepth(float depth); void SetClearDepth(float depth);
float GetClearDepth() const; 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); void SetBlendFunc(BlendFunc src, BlendFunc dst);
BlendFunc GetBlendFuncSrc() const; BlendFunc GetBlendFuncSrc() const;
BlendFunc GetBlendFuncDst() const; BlendFunc GetBlendFuncDst() const;


void SetAlphaTest(bool set);
bool GetAlphaTest() const;

void SetDepthFunc(DepthFunc func); void SetDepthFunc(DepthFunc func);
DepthFunc GetDepthFunc() const; DepthFunc GetDepthFunc() const;




+ 1
- 17
src/scene.cpp View File

@@ -193,16 +193,8 @@ void Scene::Render() // XXX: rename to Blit()
{ {
RenderContext rc; RenderContext rc;
rc.SetDepthFunc(DepthFunc::LessOrEqual); rc.SetDepthFunc(DepthFunc::LessOrEqual);
rc.SetAlphaBlend(true);
rc.SetBlendFunc(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha); 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 */ /* Early test if nothing needs to be rendered */
if (data->m_tiles.Count()) if (data->m_tiles.Count())
@@ -344,14 +336,6 @@ void Scene::Render() // XXX: rename to Blit()
data->m_lines.Empty(); data->m_lines.Empty();
delete vb; 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 */ } /* namespace lol */


Loading…
Cancel
Save