From e6a2fc967149a6bb6096e5208f4d7d52fc0e200c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kapu=C5=9Bci=C5=84ski?= Date: Mon, 7 Mar 2016 18:33:19 +0100 Subject: [PATCH] Rewritten shadow mapping implementation --- src/graphics/core/device.h | 15 +- src/graphics/engine/engine.cpp | 171 +--------------- src/graphics/opengl/gl21device.cpp | 9 + src/graphics/opengl/gl33device.cpp | 9 + src/graphics/opengl/gldevice.cpp | 307 ++++++++++++++++++----------- src/graphics/opengl/gldevice.h | 18 +- 6 files changed, 246 insertions(+), 283 deletions(-) diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 0b3ff01f..2636d2e8 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -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, }; /** diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index ab5ec640..c6296d5f 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -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(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) { - 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); - } - else - { - m_device->SetTexture(2, 0); - m_device->SetTextureEnabled(2, false); - } + m_device->SetShadowColor(m_shadowColor); + m_device->SetTransform(TRANSFORM_SHADOW, m_shadowTextureMat); + m_device->SetTexture(TEXTURE_SHADOW, m_shadowMap.id); + m_device->SetRenderState(RENDER_STATE_SHADOW_MAPPING, true); } - // 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); } } diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp index f7d2ec7b..fc58105e 100644 --- a/src/graphics/opengl/gl21device.cpp +++ b/src/graphics/opengl/gl21device.cpp @@ -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; diff --git a/src/graphics/opengl/gl33device.cpp b/src/graphics/opengl/gl33device.cpp index ba6cf93b..b3b576b6 100644 --- a/src/graphics/opengl/gl33device.cpp +++ b/src/graphics/opengl/gl33device.cpp @@ -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; diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 3161b623..fb826ff3 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -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 (maxTextures, Texture()); m_texturesEnabled = std::vector (maxTextures, false); m_textureStageParams = std::vector(maxTextures, TextureStageParams()); + m_remap = std::vector (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); @@ -967,18 +965,14 @@ void CGLDevice::SetTexture(int index, const Texture &texture) void CGLDevice::SetTexture(int index, unsigned int textureId) { - assert(index >= 0 && index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast(m_currentTextures.size())); if (m_currentTextures[index].id == textureId) return; // nothing to do 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); @@ -988,7 +982,7 @@ void CGLDevice::SetTexture(int index, unsigned int textureId) void CGLDevice::SetTextureEnabled(int index, bool enabled) { - assert(index >= 0 && index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast(m_currentTextures.size())); bool same = m_texturesEnabled[index] == enabled; @@ -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); @@ -1015,7 +1005,7 @@ void CGLDevice::SetTextureEnabled(int index, bool enabled) The settings are remembered, even if texturing is disabled at the moment. */ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams ¶ms) { - assert(index >= 0 && index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast(m_currentTextures.size())); // Remember the settings m_textureStageParams[index] = params; @@ -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++) { @@ -1069,10 +1055,7 @@ void CGLDevice::SetTextureCoordGeneration(int index, TextureGenerationParams &pa void CGLDevice::UpdateTextureParams(int index) { - assert(index >= 0 && index < static_cast( m_currentTextures.size() )); - - if (!m_multitextureAvailable && index != 0) - return; + assert(index >= 0 && index < static_cast(m_currentTextures.size())); // Don't actually do anything if texture not set if (! m_currentTextures[index].Valid()) @@ -1080,8 +1063,7 @@ void CGLDevice::UpdateTextureParams(int index) 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( 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(&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(&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(&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(&vs[0].texCoord)); - if (m_multitextureAvailable) - { - glClientActiveTexture(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord2)); - } + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord2)); glColor4fv(color.Array()); @@ -1332,11 +1422,10 @@ 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); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } + + 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(&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(&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(&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(&vs[0].texCoord)); - if (m_multitextureAvailable) - { - glClientActiveTexture(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord2)); - } + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord2)); glColor4fv(color.Array()); @@ -1432,11 +1514,9 @@ 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); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } + + glClientActiveTexture(GL_TEXTURE0 + m_remap[0]); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void CGLDevice::DrawPrimitives(PrimitiveType type, const VertexCol *vertices, @@ -1729,9 +1809,7 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast(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(nullptr) + offsetof(Vertex, texCoord)); } @@ -1743,18 +1821,13 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(VertexTex2), static_cast(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(nullptr) + offsetof(VertexTex2, texCoord)); - if (m_multitextureAvailable) - { - glClientActiveTexture(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord2)); - } + glClientActiveTexture(GL_TEXTURE0 + m_remap[1]); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord2)); } else if ((*it).second.vertexType == VERTEX_TYPE_COL) { @@ -1779,11 +1852,9 @@ 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); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } + + glClientActiveTexture(GL_TEXTURE0 + m_remap[0]); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } else if ((*it).second.vertexType == VERTEX_TYPE_COL) { @@ -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); diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index a76c1267..a81d6207 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -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 m_texturesEnabled; //! Current texture params std::vector m_textureStageParams; + //! Texture unit remap + std::vector m_remap; //! Set of all created textures std::set 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 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; };