@@ -57,6 +57,9 @@ private: | |||
TrackedState<vec4> m_clear_color; | |||
TrackedState<float> m_clear_depth; | |||
TrackedState<bool> m_alpha_blend; | |||
TrackedState<BlendFactor> m_blend_src; | |||
TrackedState<BlendFactor> m_blend_dst; | |||
TrackedState<bool> m_alpha_test; | |||
TrackedState<bool> m_depth_test; | |||
TrackedState<bool> m_face_culling; | |||
}; | |||
@@ -73,9 +76,22 @@ RenderContext::RenderContext() | |||
RenderContext::~RenderContext() | |||
{ | |||
if (m_data->m_clear_color.HasChanged()) | |||
g_renderer->SetClearColor(m_data->m_clear_color.GetValue()); | |||
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_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_test.HasChanged()) | |||
g_renderer->SetDepthTest(m_data->m_depth_test.GetValue()); | |||
@@ -109,6 +125,24 @@ void RenderContext::SetAlphaBlend(bool set) | |||
g_renderer->SetAlphaBlend(set); | |||
} | |||
void RenderContext::SetBlendFunc(BlendFactor src, BlendFactor dst) | |||
{ | |||
if (!m_data->m_blend_src.HasChanged()) | |||
m_data->m_blend_src.TrackValue(g_renderer->GetBlendFuncSrc()); | |||
if (!m_data->m_blend_dst.HasChanged()) | |||
m_data->m_blend_dst.TrackValue(g_renderer->GetBlendFuncDst()); | |||
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::SetDepthTest(bool set) | |||
{ | |||
if (!m_data->m_depth_test.HasChanged()) | |||
@@ -49,7 +49,8 @@ class RendererData | |||
private: | |||
vec4 m_clear_color; | |||
float m_clear_depth; | |||
bool m_blend, m_depth_test, m_face_culling; | |||
BlendFactor m_blend_src, m_blend_dst; | |||
bool m_alpha_blend, m_alpha_test, m_depth_test, m_face_culling; | |||
}; | |||
/* | |||
@@ -80,9 +81,16 @@ Renderer::Renderer() | |||
m_data->m_clear_depth = -1.f; | |||
SetClearDepth(1.f); | |||
m_data->m_blend = false; | |||
m_data->m_alpha_blend = false; | |||
SetAlphaBlend(true); | |||
m_data->m_alpha_test = true; | |||
SetAlphaTest(false); | |||
m_data->m_blend_src = BlendFactor::Zero; | |||
m_data->m_blend_dst = BlendFactor::Zero; | |||
SetBlendFunc(BlendFactor::SrcAlpha, BlendFactor::OneMinusSrcAlpha); | |||
m_data->m_depth_test = false; | |||
SetDepthTest(true); | |||
@@ -152,13 +160,11 @@ float Renderer::GetClearDepth() const | |||
void Renderer::SetAlphaBlend(bool set) | |||
{ | |||
if (m_data->m_blend == set) | |||
if (m_data->m_alpha_blend == set) | |||
return; | |||
#if defined USE_D3D9 || defined _XBOX | |||
# define STR0(x) #x | |||
# define STR(x) STR0(x) | |||
# pragma message(__FILE__ "(" STR(__LINE__) "): warning: Renderer::SetAlphaBlend() not implemented") | |||
m_data->m_d3d_dev->SetRenderState(D3DRS_ALPHABLENDENABLE, set ? 1 : 0); | |||
#else | |||
if (set) | |||
glEnable(GL_BLEND); | |||
@@ -166,12 +172,149 @@ void Renderer::SetAlphaBlend(bool set) | |||
glDisable(GL_BLEND); | |||
#endif | |||
m_data->m_blend = set; | |||
m_data->m_alpha_blend = set; | |||
} | |||
bool Renderer::GetAlphaBlend() const | |||
{ | |||
return m_data->m_blend; | |||
return m_data->m_alpha_blend; | |||
} | |||
/* | |||
* Blend function | |||
*/ | |||
void Renderer::SetBlendFunc(BlendFactor src, BlendFactor dst) | |||
{ | |||
if (m_data->m_blend_src == src && m_data->m_blend_dst == dst) | |||
return; | |||
#if defined USE_D3D9 || defined _XBOX | |||
enum D3DBLEND s1[2] = { D3DBLEND_ONE, D3DBLEND_ZERO }; | |||
BlendFactor s2[2] = { src, dst }; | |||
for (int i = 0; i < 2; ++i) | |||
{ | |||
switch (s2[i]) | |||
{ | |||
case BlendFactor::Zero: | |||
s1[i] = D3DBLEND_ZERO; break; | |||
case BlendFactor::One: | |||
s1[i] = D3DBLEND_ONE; break; | |||
case BlendFactor::SrcColor: | |||
s1[i] = D3DBLEND_SRCCOLOR; break; | |||
case BlendFactor::OneMinusSrcColor: | |||
s1[i] = D3DBLEND_INVSRCCOLOR; break; | |||
case BlendFactor::DstColor: | |||
s1[i] = D3DBLEND_DESTCOLOR; break; | |||
case BlendFactor::OneMinusDstColor: | |||
s1[i] = D3DBLEND_INVDESTCOLOR; break; | |||
case BlendFactor::SrcAlpha: | |||
s1[i] = D3DBLEND_SRCALPHA; break; | |||
case BlendFactor::OneMinusSrcAlpha: | |||
s1[i] = D3DBLEND_INVSRCALPHA; break; | |||
case BlendFactor::DstAlpha: | |||
s1[i] = D3DBLEND_DESTALPHA; break; | |||
case BlendFactor::OneMinusDstAlpha: | |||
s1[i] = D3DBLEND_INVDESTALPHA; break; | |||
/* FiXME: these can be supported using D3DPBLENDCAPS_BLENDFACTOR */ | |||
case BlendFactor::ConstantColor: | |||
assert(0, "BlendFactor::ConstantColor not supported"); | |||
break; | |||
case BlendFactor::OneMinusConstantColor: | |||
assert(0, "BlendFactor::OneMinusConstantColor not supported"); | |||
break; | |||
case BlendFactor::ConstantAlpha: | |||
assert(0, "BlendFactor::ConstantAlpha not supported"); | |||
break; | |||
case BlendFactor::OneMinusConstantAlpha: | |||
assert(0, "BlendFactor::OneMinusConstantAlpha not supported"); | |||
break; | |||
} | |||
} | |||
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 }; | |||
BlendFactor s2[2] = { src, dst }; | |||
for (int i = 0; i < 2; ++i) | |||
{ | |||
switch (s2[i]) | |||
{ | |||
case BlendFactor::Zero: | |||
s1[i] = GL_ZERO; break; | |||
case BlendFactor::One: | |||
s1[i] = GL_ONE; break; | |||
case BlendFactor::SrcColor: | |||
s1[i] = GL_SRC_COLOR; break; | |||
case BlendFactor::OneMinusSrcColor: | |||
s1[i] = GL_ONE_MINUS_SRC_COLOR; break; | |||
case BlendFactor::DstColor: | |||
s1[i] = GL_DST_COLOR; break; | |||
case BlendFactor::OneMinusDstColor: | |||
s1[i] = GL_ONE_MINUS_DST_COLOR; break; | |||
case BlendFactor::SrcAlpha: | |||
s1[i] = GL_SRC_ALPHA; break; | |||
case BlendFactor::OneMinusSrcAlpha: | |||
s1[i] = GL_ONE_MINUS_SRC_ALPHA; break; | |||
case BlendFactor::DstAlpha: | |||
s1[i] = GL_DST_ALPHA; break; | |||
case BlendFactor::OneMinusDstAlpha: | |||
s1[i] = GL_ONE_MINUS_DST_ALPHA; break; | |||
case BlendFactor::ConstantColor: | |||
s1[i] = GL_CONSTANT_COLOR; break; | |||
case BlendFactor::OneMinusConstantColor: | |||
s1[i] = GL_ONE_MINUS_CONSTANT_COLOR; break; | |||
case BlendFactor::ConstantAlpha: | |||
s1[i] = GL_CONSTANT_ALPHA; break; | |||
case BlendFactor::OneMinusConstantAlpha: | |||
s1[i] = GL_ONE_MINUS_CONSTANT_ALPHA; break; | |||
} | |||
} | |||
glBlendFunc(s1[0], s1[1]); | |||
#endif | |||
m_data->m_blend_src = src; | |||
m_data->m_blend_dst = dst; | |||
} | |||
BlendFactor Renderer::GetBlendFuncSrc() const | |||
{ | |||
return m_data->m_blend_src; | |||
} | |||
BlendFactor 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; | |||
} | |||
/* | |||
@@ -127,9 +127,6 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) | |||
return; | |||
#if defined _XBOX || defined USE_D3D9 | |||
g_d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1); | |||
g_d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | |||
g_d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |||
if (FAILED(g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW))) | |||
Abort(); | |||
switch (type) | |||
@@ -163,7 +160,6 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count) | |||
#else | |||
/* FIXME: this has nothing to do here! */ | |||
glFrontFace(GL_CCW); | |||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
switch (type) | |||
{ | |||
@@ -194,9 +190,6 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, | |||
return; | |||
#if defined _XBOX || defined USE_D3D9 | |||
g_d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 1); | |||
g_d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | |||
g_d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |||
if (FAILED(g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW))) | |||
Abort(); | |||
switch (type) | |||
@@ -233,7 +226,6 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase, | |||
#else | |||
/* FIXME: this has nothing to do here! */ | |||
glFrontFace(GL_CCW); | |||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
switch (type) | |||
{ | |||
@@ -30,6 +30,8 @@ public: | |||
void SetClearColor(vec4 color); | |||
void SetClearDepth(float depth); | |||
void SetAlphaBlend(bool set); | |||
void SetBlendFunc(BlendFactor src, BlendFactor dst); | |||
void SetAlphaTest(bool set); | |||
void SetDepthTest(bool set); | |||
void SetFaceCulling(bool set); | |||
@@ -21,6 +21,33 @@ namespace lol | |||
class RendererData; | |||
/* A safe enum to indicate the blending factors. */ | |||
struct BlendFactor | |||
{ | |||
enum Value | |||
{ | |||
Zero, | |||
One, | |||
SrcColor, | |||
OneMinusSrcColor, | |||
DstColor, | |||
OneMinusDstColor, | |||
SrcAlpha, | |||
OneMinusSrcAlpha, | |||
DstAlpha, | |||
OneMinusDstAlpha, | |||
ConstantColor, | |||
OneMinusConstantColor, | |||
ConstantAlpha, | |||
OneMinusConstantAlpha, | |||
} | |||
m_value; | |||
inline BlendFactor() : m_value(Zero) {} | |||
inline BlendFactor(Value v) : m_value(v) {} | |||
inline operator Value() { return m_value; } | |||
}; | |||
class Renderer | |||
{ | |||
private: | |||
@@ -40,6 +67,13 @@ public: | |||
void SetAlphaBlend(bool set); | |||
bool GetAlphaBlend() const; | |||
void SetBlendFunc(BlendFactor src, BlendFactor dst); | |||
BlendFactor GetBlendFuncSrc() const; | |||
BlendFactor GetBlendFuncDst() const; | |||
void SetAlphaTest(bool set); | |||
bool GetAlphaTest() const; | |||
void SetDepthTest(bool set); | |||
bool GetDepthTest() const; | |||
@@ -194,6 +194,7 @@ void Scene::Render() // XXX: rename to Blit() | |||
RenderContext rc; | |||
rc.SetDepthTest(true); | |||
rc.SetAlphaBlend(true); | |||
rc.SetBlendFunc(BlendFactor::SrcAlpha, BlendFactor::OneMinusSrcAlpha); | |||
#if defined USE_D3D9 || defined _XBOX | |||
#else | |||
@@ -202,7 +203,6 @@ void Scene::Render() // XXX: rename to Blit() | |||
glEnable(GL_ALPHA_TEST); | |||
glAlphaFunc(GL_GEQUAL, 0.01f); | |||
#endif | |||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |||
#endif | |||
/* Early test if nothing needs to be rendered */ | |||