Переглянути джерело

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

legacy
Sam Hocevar sam 11 роки тому
джерело
коміт
a75e07d329
5 змінених файлів з 154 додано та 92 видалено
  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 Переглянути файл

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

TrackedState<vec4> m_clear_color;

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<CullMode> 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())


+ 109
- 47
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;
}


+ 1
- 2
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);



+ 26
- 5
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;



+ 1
- 17
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 */


Завантаження…
Відмінити
Зберегти