Rewritten shadow mapping implementation
parent
9679546988
commit
e6a2fc9671
|
@ -99,12 +99,22 @@ struct DeviceConfig
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \enum TextureUnit
|
||||
* \brief Texture unit values for binding textures
|
||||
*
|
||||
* These enums should be used for indexing textures instead of raw integers.
|
||||
*/
|
||||
enum TextureUnit
|
||||
{
|
||||
TEXTURE_PRIMARY = 0,
|
||||
TEXTURE_SECONDARY = 1,
|
||||
TEXTURE_SHADOW = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* \enum TransformType
|
||||
* \brief Type of transformation in rendering pipeline
|
||||
*
|
||||
* These correspond to DirectX's three transformation matrices.
|
||||
*/
|
||||
enum TransformType
|
||||
{
|
||||
|
@ -128,6 +138,7 @@ enum RenderState
|
|||
RENDER_STATE_ALPHA_TEST,
|
||||
RENDER_STATE_CULLING,
|
||||
RENDER_STATE_DEPTH_BIAS,
|
||||
RENDER_STATE_SHADOW_MAPPING,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -3486,6 +3486,7 @@ void CEngine::RenderShadowMap()
|
|||
|
||||
m_device->SetTexture(0, 0);
|
||||
m_device->SetTexture(1, 0);
|
||||
m_device->SetTexture(2, 0);
|
||||
|
||||
// render objects into shadow map
|
||||
for (int objRank = 0; objRank < static_cast<int>(m_objects.size()); objRank++)
|
||||
|
@ -3552,173 +3553,17 @@ void CEngine::UseShadowMapping(bool enable)
|
|||
if (!m_shadowMapping) return;
|
||||
if (m_shadowMap.id == 0) return;
|
||||
|
||||
// all devices that are not OpenGL 1.4
|
||||
if (m_device->GetName() != "OpenGL 1.4")
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
m_device->SetShadowColor(m_shadowColor);
|
||||
|
||||
m_device->SetTextureEnabled(2, true);
|
||||
m_device->SetTexture(2, m_shadowMap);
|
||||
m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
|
||||
m_device->SetTexture(TEXTURE_SHADOW, m_shadowMap.id);
|
||||
m_device->SetRenderState(RENDER_STATE_SHADOW_MAPPING, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_device->SetTexture(2, 0);
|
||||
m_device->SetTextureEnabled(2, false);
|
||||
}
|
||||
}
|
||||
// special case for OpenGL 1.4 device
|
||||
else
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
m_device->SetShadowColor(m_shadowColor);
|
||||
|
||||
if (m_qualityShadows)
|
||||
{
|
||||
// Texture Unit 2
|
||||
m_device->SetTextureEnabled(2, true);
|
||||
m_device->SetTexture(2, m_shadowMap);
|
||||
m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
|
||||
|
||||
Math::Matrix identity;
|
||||
identity.LoadIdentity();
|
||||
m_device->SetTransform(TRANSFORM_WORLD, identity);
|
||||
|
||||
float shadowBias = m_shadowColor;
|
||||
float shadowUnbias = 1.0f - shadowBias;
|
||||
|
||||
TextureStageParams params;
|
||||
params.colorOperation = TEX_MIX_OPER_MODULATE;
|
||||
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
|
||||
params.colorArg2 = TEX_MIX_ARG_FACTOR;
|
||||
params.colorOperation = TEX_MIX_OPER_DEFAULT;
|
||||
params.factor = Color(shadowBias, shadowBias, shadowBias, 1.0f);
|
||||
params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
|
||||
m_device->SetTextureStageParams(2, params);
|
||||
|
||||
TextureGenerationParams genParams;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
genParams.coords[i].mode = TEX_GEN_EYE_LINEAR;
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
genParams.coords[i].plane[j] = (i == j ? 1.0f : 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
m_device->SetTextureCoordGeneration(2, genParams);
|
||||
|
||||
// Texture Unit 3
|
||||
m_device->SetTextureEnabled(3, true);
|
||||
m_device->SetTexture(3, m_shadowMap);
|
||||
|
||||
params.LoadDefault();
|
||||
params.colorOperation = TEX_MIX_OPER_ADD;
|
||||
params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
|
||||
params.colorArg2 = TEX_MIX_ARG_FACTOR;
|
||||
params.alphaOperation = TEX_MIX_OPER_DEFAULT;
|
||||
params.factor = Color(shadowUnbias, shadowUnbias, shadowUnbias, 0.0f);
|
||||
params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
|
||||
m_device->SetTextureStageParams(3, params);
|
||||
|
||||
// Texture Unit 4
|
||||
m_device->SetTextureEnabled(4, true);
|
||||
m_device->SetTexture(4, m_shadowMap);
|
||||
|
||||
params.LoadDefault();
|
||||
params.colorOperation = TEX_MIX_OPER_MODULATE;
|
||||
params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
|
||||
params.colorArg2 = TEX_MIX_ARG_SRC_COLOR;
|
||||
params.alphaOperation = TEX_MIX_OPER_DEFAULT;
|
||||
params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
|
||||
m_device->SetTextureStageParams(4, params);
|
||||
|
||||
// Texture Unit 5
|
||||
m_device->SetTextureEnabled(5, true);
|
||||
m_device->SetTexture(5, m_shadowMap);
|
||||
|
||||
params.LoadDefault();
|
||||
params.colorOperation = TEX_MIX_OPER_MODULATE;
|
||||
params.colorArg1 = TEX_MIX_ARG_COMPUTED_COLOR;
|
||||
params.colorArg2 = TEX_MIX_ARG_TEXTURE_0;
|
||||
params.alphaOperation = TEX_MIX_OPER_DEFAULT;
|
||||
params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
|
||||
m_device->SetTextureStageParams(5, params);
|
||||
}
|
||||
else // Simpler shadows
|
||||
{
|
||||
// Texture Unit 2
|
||||
m_device->SetTextureEnabled(2, true);
|
||||
m_device->SetTexture(2, m_shadowMap);
|
||||
m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat);
|
||||
|
||||
Math::Matrix identity;
|
||||
identity.LoadIdentity();
|
||||
m_device->SetTransform(TRANSFORM_WORLD, identity);
|
||||
|
||||
TextureStageParams params;
|
||||
params.colorOperation = TEX_MIX_OPER_MODULATE;
|
||||
params.wrapS = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
params.wrapT = TEX_WRAP_CLAMP_TO_BORDER;
|
||||
m_device->SetTextureStageParams(2, params);
|
||||
|
||||
TextureGenerationParams genParams;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
genParams.coords[i].mode = TEX_GEN_EYE_LINEAR;
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
genParams.coords[i].plane[j] = (i == j ? 1.0f : 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
m_device->SetTextureCoordGeneration(2, genParams);
|
||||
}
|
||||
}
|
||||
// disable shadows
|
||||
else
|
||||
{
|
||||
Math::Matrix identity;
|
||||
identity.LoadIdentity();
|
||||
|
||||
m_device->SetTexture(2, 0);
|
||||
m_device->SetTextureEnabled(2, false);
|
||||
m_device->SetTransform(TRANSFORM_SHADOW, identity);
|
||||
|
||||
TextureGenerationParams params;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
params.coords[i].mode = TEX_GEN_NONE;
|
||||
|
||||
m_device->SetTextureCoordGeneration(2, params);
|
||||
|
||||
if (m_qualityShadows)
|
||||
{
|
||||
m_device->SetTexture(3, 0);
|
||||
m_device->SetTextureEnabled(3, false);
|
||||
|
||||
m_device->SetTexture(4, 0);
|
||||
m_device->SetTextureEnabled(4, false);
|
||||
|
||||
m_device->SetTexture(5, 0);
|
||||
m_device->SetTextureEnabled(5, false);
|
||||
}
|
||||
}
|
||||
m_device->SetRenderState(RENDER_STATE_SHADOW_MAPPING, false);
|
||||
m_device->SetTexture(TEXTURE_SHADOW, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -602,6 +602,9 @@ void CGL21Device::BeginScene()
|
|||
|
||||
void CGL21Device::EndScene()
|
||||
{
|
||||
#ifdef DEV_BUILD
|
||||
CheckGLErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGL21Device::Clear()
|
||||
|
@ -1852,6 +1855,12 @@ void CGL21Device::SetRenderState(RenderState state, bool enabled)
|
|||
|
||||
return;
|
||||
}
|
||||
else if (state == RENDER_STATE_SHADOW_MAPPING)
|
||||
{
|
||||
SetTextureEnabled(TEXTURE_SHADOW, enabled);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum flag = 0;
|
||||
|
||||
|
|
|
@ -608,6 +608,9 @@ void CGL33Device::BeginScene()
|
|||
|
||||
void CGL33Device::EndScene()
|
||||
{
|
||||
#ifdef DEV_BUILD
|
||||
CheckGLErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGL33Device::Clear()
|
||||
|
@ -2105,6 +2108,12 @@ void CGL33Device::SetRenderState(RenderState state, bool enabled)
|
|||
|
||||
return;
|
||||
}
|
||||
else if (state == RENDER_STATE_SHADOW_MAPPING)
|
||||
{
|
||||
SetTextureEnabled(TEXTURE_SHADOW, enabled);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum flag = 0;
|
||||
|
||||
|
|
|
@ -193,11 +193,6 @@ bool CGLDevice::Create()
|
|||
GetLogger()->Info("OpenGL %s\n", version);
|
||||
GetLogger()->Info("%s\n", renderer);
|
||||
|
||||
// Detect multitexture support
|
||||
m_multitextureAvailable = glewIsSupported("GL_ARB_multitexture GL_ARB_texture_env_combine");
|
||||
if (!m_multitextureAvailable)
|
||||
GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n");
|
||||
|
||||
// Detect Shadow mapping support
|
||||
if (glVersion >= 14) // Core depth texture+shadow, OpenGL 1.4+
|
||||
{
|
||||
|
@ -215,10 +210,6 @@ bool CGLDevice::Create()
|
|||
GetLogger()->Info("Shadow mapping not available\n");
|
||||
}
|
||||
|
||||
m_shadowAmbientSupported = glewIsSupported("GL_ARB_shadow_ambient");
|
||||
if (m_shadowAmbientSupported)
|
||||
GetLogger()->Info("Shadow ambient supported\n");
|
||||
|
||||
// Detect support of anisotropic filtering
|
||||
m_anisotropyAvailable = glewIsSupported("GL_EXT_texture_filter_anisotropic");
|
||||
if(m_anisotropyAvailable)
|
||||
|
@ -309,6 +300,23 @@ bool CGLDevice::Create()
|
|||
m_currentTextures = std::vector<Texture> (maxTextures, Texture());
|
||||
m_texturesEnabled = std::vector<bool> (maxTextures, false);
|
||||
m_textureStageParams = std::vector<TextureStageParams>(maxTextures, TextureStageParams());
|
||||
m_remap = std::vector<int> (maxTextures, 0);
|
||||
|
||||
// default mapping
|
||||
for (int i = 0; i < maxTextures; i++)
|
||||
m_remap[i] = i;
|
||||
|
||||
// special remapping for quality shadows
|
||||
if (maxTextures >= 4)
|
||||
{
|
||||
m_remap[0] = 2;
|
||||
m_remap[1] = 3;
|
||||
m_remap[2] = 0;
|
||||
m_remap[3] = 1;
|
||||
|
||||
m_shadowQuality = true;
|
||||
GetLogger()->Debug("Using quality shadows\n");
|
||||
}
|
||||
|
||||
// create default framebuffer object
|
||||
FramebufferParams framebufferParams;
|
||||
|
@ -387,6 +395,9 @@ void CGLDevice::BeginScene()
|
|||
|
||||
void CGLDevice::EndScene()
|
||||
{
|
||||
#ifdef DEV_BUILD
|
||||
CheckGLErrors();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGLDevice::Clear()
|
||||
|
@ -426,13 +437,11 @@ void CGLDevice::SetTransform(TransformType type, const Math::Matrix &matrix)
|
|||
}
|
||||
else if (type == TRANSFORM_SHADOW)
|
||||
{
|
||||
if (!m_multitextureAvailable)
|
||||
return;
|
||||
m_shadowMatrix = matrix;
|
||||
|
||||
Math::Matrix temp = matrix;
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[2]);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(temp.Array());
|
||||
glLoadMatrixf(m_shadowMatrix.Array());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -650,8 +659,7 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par
|
|||
result.originalSize = result.size;
|
||||
|
||||
// Use & enable 1st texture stage
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
|
@ -839,8 +847,7 @@ Texture CGLDevice::CreateDepthTexture(int width, int height, int depth)
|
|||
result.size.y = height;
|
||||
|
||||
// Use & enable 1st texture stage
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
|
||||
glGenTextures(1, &result.id);
|
||||
glBindTexture(GL_TEXTURE_2D, result.id);
|
||||
|
@ -886,11 +893,6 @@ Texture CGLDevice::CreateDepthTexture(int width, int height, int depth)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
|
||||
}
|
||||
|
||||
if (m_shadowAmbientSupported)
|
||||
{
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 0.5f);
|
||||
}
|
||||
|
||||
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
@ -950,14 +952,10 @@ void CGLDevice::SetTexture(int index, const Texture &texture)
|
|||
|
||||
m_currentTextures[index] = texture; // remember the new value
|
||||
|
||||
if (!m_multitextureAvailable && index != 0)
|
||||
return;
|
||||
|
||||
if (same)
|
||||
return; // nothing to do
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[index]);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
|
||||
|
@ -974,11 +972,7 @@ void CGLDevice::SetTexture(int index, unsigned int textureId)
|
|||
|
||||
m_currentTextures[index].id = textureId;
|
||||
|
||||
if (!m_multitextureAvailable && index != 0)
|
||||
return;
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[index]);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
|
||||
|
@ -997,11 +991,7 @@ void CGLDevice::SetTextureEnabled(int index, bool enabled)
|
|||
if (same)
|
||||
return; // nothing to do
|
||||
|
||||
if (!m_multitextureAvailable && index != 0)
|
||||
return;
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[index]);
|
||||
|
||||
if (enabled)
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
@ -1025,11 +1015,7 @@ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams ¶m
|
|||
|
||||
void CGLDevice::SetTextureCoordGeneration(int index, TextureGenerationParams ¶ms)
|
||||
{
|
||||
if (!m_multitextureAvailable && index != 0)
|
||||
return;
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[index]);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
|
@ -1071,17 +1057,13 @@ void CGLDevice::UpdateTextureParams(int index)
|
|||
{
|
||||
assert(index >= 0 && index < static_cast<int>(m_currentTextures.size()));
|
||||
|
||||
if (!m_multitextureAvailable && index != 0)
|
||||
return;
|
||||
|
||||
// Don't actually do anything if texture not set
|
||||
if (! m_currentTextures[index].Valid())
|
||||
return;
|
||||
|
||||
const TextureStageParams ¶ms = m_textureStageParams[index];
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[index]);
|
||||
|
||||
if (params.wrapS == TEX_WRAP_CLAMP)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
|
@ -1099,10 +1081,6 @@ void CGLDevice::UpdateTextureParams(int index)
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
else assert(false);
|
||||
|
||||
// Texture env setting is silly without multitexturing
|
||||
if (!m_multitextureAvailable)
|
||||
return;
|
||||
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, params.factor.Array());
|
||||
|
||||
// To save some trouble
|
||||
|
@ -1240,6 +1218,129 @@ after_tex_color:
|
|||
after_tex_operations: ;
|
||||
}
|
||||
|
||||
void CGLDevice::EnableShadows()
|
||||
{
|
||||
// already enabled
|
||||
if (m_shadowMapping) return;
|
||||
|
||||
// shadow map unit
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[2]);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(m_shadowMatrix.Array());
|
||||
|
||||
// enable texture coordinate generation
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
glEnable(GL_TEXTURE_GEN_Q);
|
||||
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
||||
|
||||
float plane1[] = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||
float plane2[] = { 0.0f, 1.0f, 0.0f, 0.0f };
|
||||
float plane3[] = { 0.0f, 0.0f, 1.0f, 0.0f };
|
||||
float plane4[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
glTexGenfv(GL_S, GL_EYE_PLANE, plane1);
|
||||
glTexGenfv(GL_T, GL_EYE_PLANE, plane2);
|
||||
glTexGenfv(GL_R, GL_EYE_PLANE, plane3);
|
||||
glTexGenfv(GL_Q, GL_EYE_PLANE, plane4);
|
||||
|
||||
// simple shadows
|
||||
if (!m_shadowQuality)
|
||||
{
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
// quality shadows
|
||||
else
|
||||
{
|
||||
// texture environment settings
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
float half[] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, half);
|
||||
|
||||
// color = 0.5 * (1.0 - shadow)
|
||||
// = 0.5 for shadow = 0.0
|
||||
// = 0.0 for shadow = 1.0
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
|
||||
// alpha = previous
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
|
||||
|
||||
// combine unit
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[3]);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
int color = 0xFFFFFFFF;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &color);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// texture enviromnent settings
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
|
||||
// color = (1.0 - previous) * primary color
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
|
||||
|
||||
// alpha = primary color
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
|
||||
}
|
||||
|
||||
m_shadowMapping = true;
|
||||
}
|
||||
|
||||
void CGLDevice::DisableShadows()
|
||||
{
|
||||
// already disabled
|
||||
if (!m_shadowMapping) return;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[2]);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
glDisable(GL_TEXTURE_GEN_Q);
|
||||
|
||||
// quality shadows
|
||||
if (m_shadowQuality)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[3]);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
m_shadowMapping = false;
|
||||
}
|
||||
|
||||
void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wrapT)
|
||||
{
|
||||
assert(index >= 0 && index < static_cast<int>( m_currentTextures.size() ));
|
||||
|
@ -1252,11 +1353,7 @@ void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wr
|
|||
if (! m_currentTextures[index].Valid())
|
||||
return;
|
||||
|
||||
if (!m_multitextureAvailable && index != 0)
|
||||
return;
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[index]);
|
||||
|
||||
if (wrapS == TEX_WRAP_CLAMP)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
|
@ -1286,9 +1383,7 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int ve
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, sizeof(Vertex), reinterpret_cast<GLfloat*>(&vs[0].normal));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<GLfloat*>(&vs[0].texCoord));
|
||||
|
||||
|
@ -1312,18 +1407,13 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, in
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].normal));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord2));
|
||||
}
|
||||
|
||||
glColor4fv(color.Array());
|
||||
|
||||
|
@ -1332,12 +1422,11 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, in
|
|||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1
|
||||
if (m_multitextureAvailable)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount)
|
||||
{
|
||||
|
@ -1366,9 +1455,7 @@ void CGLDevice::DrawPrimitives(PrimitiveType type, const Vertex *vertices,
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, sizeof(Vertex), reinterpret_cast<GLfloat*>(&vs[0].normal));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast<GLfloat*>(&vs[0].texCoord));
|
||||
|
||||
|
@ -1402,18 +1489,13 @@ void CGLDevice::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].normal));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast<GLfloat*>(&vs[0].texCoord2));
|
||||
}
|
||||
|
||||
glColor4fv(color.Array());
|
||||
|
||||
|
@ -1432,12 +1514,10 @@ void CGLDevice::DrawPrimitives(PrimitiveType type, const VertexTex2 *vertices,
|
|||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1
|
||||
if (m_multitextureAvailable)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
void CGLDevice::DrawPrimitives(PrimitiveType type, const VertexCol *vertices,
|
||||
int first[], int count[], int drawCount)
|
||||
|
@ -1729,9 +1809,7 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId)
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, normal));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), static_cast<char*>(nullptr) + offsetof(Vertex, texCoord));
|
||||
}
|
||||
|
@ -1743,19 +1821,14 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId)
|
|||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, normal));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, texCoord));
|
||||
|
||||
if (m_multitextureAvailable)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE1);
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[1]);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast<char*>(nullptr) + offsetof(VertexTex2, texCoord2));
|
||||
}
|
||||
}
|
||||
else if ((*it).second.vertexType == VERTEX_TYPE_COL)
|
||||
{
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -1779,12 +1852,10 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId)
|
|||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1
|
||||
if (m_multitextureAvailable)
|
||||
{
|
||||
glClientActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glClientActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
}
|
||||
else if ((*it).second.vertexType == VERTEX_TYPE_COL)
|
||||
{
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -1934,6 +2005,15 @@ void CGLDevice::SetRenderState(RenderState state, bool enabled)
|
|||
|
||||
return;
|
||||
}
|
||||
else if (state == RENDER_STATE_SHADOW_MAPPING)
|
||||
{
|
||||
if (enabled)
|
||||
EnableShadows();
|
||||
else
|
||||
DisableShadows();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum flag = 0;
|
||||
|
||||
|
@ -2036,8 +2116,7 @@ void CGLDevice::CopyFramebufferToTexture(Texture& texture, int xOffset, int yOff
|
|||
if (texture.id == 0) return;
|
||||
|
||||
// Use & enable 1st texture stage
|
||||
if (m_multitextureAvailable)
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glActiveTexture(GL_TEXTURE0 + m_remap[0]);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height);
|
||||
|
|
|
@ -204,6 +204,11 @@ private:
|
|||
//! Updates the texture params for given texture stage
|
||||
void UpdateTextureParams(int index);
|
||||
|
||||
//! Enables shadows
|
||||
void EnableShadows();
|
||||
//! Disables shadows
|
||||
void DisableShadows();
|
||||
|
||||
private:
|
||||
//! Current config
|
||||
DeviceConfig m_config;
|
||||
|
@ -218,6 +223,8 @@ private:
|
|||
Math::Matrix m_projectionMat;
|
||||
//! Combined world-view-projection matrix
|
||||
Math::Matrix m_combinedMatrix;
|
||||
//! Current shadow matrix
|
||||
Math::Matrix m_shadowMatrix;
|
||||
//! true means that combined matrix is outdated
|
||||
bool m_combinedMatrixOutdated = true;
|
||||
|
||||
|
@ -237,6 +244,8 @@ private:
|
|||
std::vector<bool> m_texturesEnabled;
|
||||
//! Current texture params
|
||||
std::vector<TextureStageParams> m_textureStageParams;
|
||||
//! Texture unit remap
|
||||
std::vector<int> m_remap;
|
||||
|
||||
//! Set of all created textures
|
||||
std::set<Texture> m_allTextures;
|
||||
|
@ -264,10 +273,6 @@ private:
|
|||
//! Detected capabilities
|
||||
//! Depth texture support
|
||||
ShadowMappingSupport m_shadowMappingSupport = SMS_NONE;
|
||||
//! Shadow ambient support
|
||||
bool m_shadowAmbientSupported = false;
|
||||
//! Whether to use multitexturing
|
||||
bool m_multitextureAvailable = false;
|
||||
//! Whether to use VBOs or display lists
|
||||
bool m_vboAvailable = false;
|
||||
//! Whether anisotropic filtering is available
|
||||
|
@ -288,6 +293,11 @@ private:
|
|||
std::map<unsigned int, VboObjectInfo> m_vboObjects;
|
||||
//! Last ID of VBO object
|
||||
unsigned int m_lastVboId = 0;
|
||||
|
||||
//! true means shadow mapping is enabled
|
||||
bool m_shadowMapping = false;
|
||||
//! true means that quality shadows are enabled
|
||||
bool m_shadowQuality = true;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue