diff --git a/source/graphics/ParticleEngine.cpp b/source/graphics/ParticleEngine.cpp index c36c80a0d3..dbe8c771ab 100644 --- a/source/graphics/ParticleEngine.cpp +++ b/source/graphics/ParticleEngine.cpp @@ -9,7 +9,7 @@ #include "precompiled.h" #include "ParticleEngine.h" #include "ogl.h" -#include "renderer.h" +#include "Renderer.h" CParticleEngine *CParticleEngine::m_pInstance = 0; CParticleEngine::CParticleEngine(void) @@ -59,7 +59,7 @@ CParticleEngine *CParticleEngine::GetInstance(void) } void CParticleEngine::DeleteInstance() -{ +{ if (m_pInstance) delete m_pInstance; m_pInstance = 0; @@ -158,7 +158,7 @@ void CParticleEngine::updateEmitters() { // store a pointer to the next node tEmitterNode *pTemp = temp->next; - + // check for the head if(!temp->prev) m_pHead = pTemp; @@ -166,7 +166,7 @@ void CParticleEngine::updateEmitters() // forward the previous's pointer temp->prev->next = pTemp; - // if there is any next one, + // if there is any next one, if(pTemp) // fix the backwards pointer pTemp->prev = temp->prev; @@ -214,7 +214,7 @@ void CParticleEngine::destroyAllEmitters(bool fade) { // store a pointer to the next node tEmitterNode *pTemp = temp->next; - + // check for the head if(!temp->prev) m_pHead = pTemp; @@ -222,7 +222,7 @@ void CParticleEngine::destroyAllEmitters(bool fade) // forward the previous's pointer temp->prev->next = pTemp; - // if there is any next one, + // if there is any next one, if(pTemp) // fix the backwards pointer pTemp->prev = temp->prev; diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index cc34b80050..281802dfa1 100755 --- a/source/renderer/Renderer.cpp +++ b/source/renderer/Renderer.cpp @@ -252,6 +252,7 @@ CRenderer::CRenderer() // Must query card capabilities before creating renderers that depend // on card capabilities. EnumCaps(); + m->shadow->SetUseDepthTexture(true); m_VertexShader = new RenderPathVertexShader; if (!m_VertexShader->Init()) @@ -301,6 +302,7 @@ CRenderer::CRenderer() m_Models.ModSolidColor = RenderModifierPtr(new SolidColorRenderModifier); m_Models.ModTransparent = RenderModifierPtr(new TransparentRenderModifier); m_Models.ModTransparentShadow = RenderModifierPtr(new TransparentShadowRenderModifier); + m_Models.ModTransparentDepthShadow = RenderModifierPtr(new TransparentDepthShadowModifier); CEmitter *pEmitter = new CDefaultEmitter(1000, -1); CParticleEngine::GetInstance()->addEmitter(pEmitter); @@ -343,6 +345,7 @@ void CRenderer::EnumCaps() m_Caps.m_TextureBorderClamp=false; m_Caps.m_GenerateMipmaps=false; m_Caps.m_VertexShader=false; + m_Caps.m_DepthTextureShadows = false; // now start querying extensions if (!m_Options.m_NoVBO) { @@ -361,6 +364,9 @@ void CRenderer::EnumCaps() if (oglHaveExtension("GL_ARB_vertex_shader")) m_Caps.m_VertexShader=true; } + if (0 == oglHaveExtensions(0, "GL_ARB_shadow", "GL_ARB_depth_texture", 0)) { + m_Caps.m_DepthTextureShadows = true; + } } @@ -591,8 +597,6 @@ void CRenderer::BeginFrame() } // init per frame stuff - m_ShadowRendered=false; - m->shadow->SetupFrame(m_CullCamera, m_LightEnv->m_SunDir); } @@ -612,7 +616,6 @@ void CRenderer::RenderShadowMap() m->shadow->BeginRender(); - // TODO HACK fold this into ShadowMap glColor4fv(m_Options.m_ShadowColor); glDisable(GL_CULL_FACE); @@ -627,37 +630,24 @@ void CRenderer::RenderShadowMap() m_Models.NormalInstancing->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS); if (m_Models.PlayerInstancing) m_Models.PlayerInstancing->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS); - m_Models.TranspFF->Render(m_Models.ModTransparentShadow, MODELFLAG_CASTSHADOWS); + + RenderModifierPtr transparentShadows = m_Models.ModTransparentShadow; + + if (m->shadow->GetUseDepthTexture()) + transparentShadows = m_Models.ModTransparentDepthShadow; + + m_Models.TranspFF->Render(transparentShadows, MODELFLAG_CASTSHADOWS); if (m_Models.TranspHWLit) - m_Models.TranspHWLit->Render(m_Models.ModTransparentShadow, MODELFLAG_CASTSHADOWS); - m_Models.TranspSortAll->Render(m_Models.ModTransparentShadow, MODELFLAG_CASTSHADOWS); + m_Models.TranspHWLit->Render(transparentShadows, MODELFLAG_CASTSHADOWS); + m_Models.TranspSortAll->Render(transparentShadows, MODELFLAG_CASTSHADOWS); glEnable(GL_CULL_FACE); - glColor3f(1.0f,1.0f,1.0f); + glColor3f(1.0, 1.0, 1.0); m->shadow->EndRender(); } -//TODO: Fold into TerrainRenderer -void CRenderer::ApplyShadowMap() -{ - PROFILE( "applying shadows" ); - - const CMatrix3D& texturematrix = m->shadow->GetTextureMatrix(); - GLuint shadowmap = m->shadow->GetTexture(); - - glMatrixMode(GL_TEXTURE); - glLoadMatrixf(&texturematrix._11); - glMatrixMode(GL_MODELVIEW); - - m->terrainRenderer->ApplyShadowMap(shadowmap); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); -} - void CRenderer::RenderPatches() { PROFILE(" render patches "); @@ -670,7 +660,7 @@ void CRenderer::RenderPatches() // render all the patches, including blend pass MICROLOG(L"render patch submissions"); - m->terrainRenderer->RenderTerrain(); + m->terrainRenderer->RenderTerrain(m_Options.m_Shadows ? m->shadow : 0, m_Options.m_ShadowColor); if (m_TerrainRenderMode==WIREFRAME) { // switch wireframe off again @@ -804,16 +794,15 @@ void CRenderer::FlushFrame() m->terrainRenderer->PrepareForRendering(); PROFILE_END("prepare terrain"); - if (!m_ShadowRendered) { - if (m_Options.m_Shadows) { - MICROLOG(L"render shadows"); - RenderShadowMap(); - } - // clear buffers - glClearColor(m_ClearColor[0],m_ClearColor[1],m_ClearColor[2],m_ClearColor[3]); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (m_Options.m_Shadows) { + MICROLOG(L"render shadows"); + RenderShadowMap(); } + // clear buffers + glClearColor(m_ClearColor[0],m_ClearColor[1],m_ClearColor[2],m_ClearColor[3]); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + oglCheck(); // render submitted patches and models @@ -825,13 +814,6 @@ void CRenderer::FlushFrame() RenderModels(); oglCheck(); - if (m_Options.m_Shadows && !m_ShadowRendered) { - MICROLOG(L"apply shadows"); - ApplyShadowMap(); - oglCheck(); - } - m_ShadowRendered=true; - // call on the transparency renderer to render all the transparent stuff MICROLOG(L"render transparent"); RenderTransparentModels(); @@ -1284,10 +1266,26 @@ void CRenderer::JSI_SetRenderPath(JSContext* ctx, jsval newval) SetRenderPath(GetRenderPathByName(name)); } +jsval CRenderer::JSI_GetUseDepthTexture(JSContext*) +{ + return ToJSVal(m->shadow->GetUseDepthTexture()); +} + +void CRenderer::JSI_SetUseDepthTexture(JSContext* ctx, jsval newval) +{ + bool depthTexture; + + if (!ToPrimitive(ctx, newval, depthTexture)) + return; + + m->shadow->SetUseDepthTexture(depthTexture); +} + void CRenderer::ScriptingInit() { AddProperty(L"fastPlayerColor", &CRenderer::JSI_GetFastPlayerColor, &CRenderer::JSI_SetFastPlayerColor); AddProperty(L"renderpath", &CRenderer::JSI_GetRenderPath, &CRenderer::JSI_SetRenderPath); + AddProperty(L"useDepthTexture", &CRenderer::JSI_GetUseDepthTexture, &CRenderer::JSI_SetUseDepthTexture); AddProperty(L"sortAllTransparent", &CRenderer::m_SortAllTransparent); AddProperty(L"fastNormals", &CRenderer::m_FastNormals); AddProperty(L"displayFrustum", &CRenderer::m_DisplayFrustum); diff --git a/source/renderer/Renderer.h b/source/renderer/Renderer.h index df73a7be5d..a151d22944 100755 --- a/source/renderer/Renderer.h +++ b/source/renderer/Renderer.h @@ -140,6 +140,14 @@ public: RenderPath m_RenderPath; } m_Options; + struct Caps { + bool m_VBO; + bool m_TextureBorderClamp; + bool m_GenerateMipmaps; + bool m_VertexShader; + bool m_DepthTextureShadows; + }; + public: // constructor, destructor CRenderer(); @@ -280,6 +288,13 @@ public: */ void SetFastPlayerColor(bool fast); + /** + * GetCapabilities: Return which OpenGL capabilities are available and enabled. + * + * @return capabilities structure + */ + const Caps& GetCapabilities() const { return m_Caps; } + protected: friend struct CRendererInternals; friend class CVertexBuffer; @@ -298,6 +313,8 @@ protected: void JSI_SetFastPlayerColor(JSContext* ctx, jsval newval); jsval JSI_GetRenderPath(JSContext*); void JSI_SetRenderPath(JSContext* ctx, jsval newval); + jsval JSI_GetUseDepthTexture(JSContext*); + void JSI_SetUseDepthTexture(JSContext* ctx, jsval newval); static void ScriptingInit(); // patch rendering stuff @@ -309,7 +326,6 @@ protected: // shadow rendering stuff void RenderShadowMap(); - void ApplyShadowMap(); // debugging void DisplayFrustum(); @@ -358,19 +374,12 @@ protected: CSHCoeffs m_SHCoeffsTerrain; // ogl_tex handle of composite alpha map (all the alpha maps packed into one texture) Handle m_hCompositeAlphaMap; - // per-frame flag: has the shadow map been rendered this frame? - bool m_ShadowRendered; // coordinates of each (untransformed) alpha map within the packed texture struct { float u0,u1,v0,v1; } m_AlphaMapCoords[NumAlphaMaps]; // card capabilities - struct Caps { - bool m_VBO; - bool m_TextureBorderClamp; - bool m_GenerateMipmaps; - bool m_VertexShader; - } m_Caps; + Caps m_Caps; // build card cap bits void EnumCaps(); // per-frame renderer stats @@ -439,6 +448,7 @@ protected: RenderModifierPtr ModSolidColor; RenderModifierPtr ModTransparent; RenderModifierPtr ModTransparentShadow; + RenderModifierPtr ModTransparentDepthShadow; } m_Models; }; diff --git a/source/renderer/ShadowMap.cpp b/source/renderer/ShadowMap.cpp index e4fce797b4..9c3f1721e0 100644 --- a/source/renderer/ShadowMap.cpp +++ b/source/renderer/ShadowMap.cpp @@ -11,6 +11,7 @@ #include "precompiled.h" #include "ogl.h" +#include "CLogger.h" #include "graphics/LightEnv.h" @@ -21,6 +22,8 @@ #include "renderer/Renderer.h" #include "renderer/ShadowMap.h" +#define LOG_CATEGORY "graphics" + /////////////////////////////////////////////////////////////////////////////////////////////////// // ShadowMap implementation @@ -30,6 +33,8 @@ */ struct ShadowMapInternals { + // whether we're using depth texture or luminance map + bool UseDepthTexture; // handle of shadow map GLuint Texture; // width, height of shadow map @@ -61,6 +66,9 @@ ShadowMap::ShadowMap() { m = new ShadowMapInternals; m->Texture = 0; + m->Width = 0; + m->Height = 0; + m->UseDepthTexture = false; } @@ -203,21 +211,36 @@ void ShadowMapInternals::CreateTexture() Height = g_Renderer.GetHeight(); Height = RoundUpToPowerOf2(Height); + LOG(NORMAL, LOG_CATEGORY, "Creating shadow texture (size %ix%i) (format = %s)", + Width, Height, UseDepthTexture ? "DEPTH_COMPONENT" : "LUMINANCE"); + // create texture object glGenTextures(1, &Texture); g_Renderer.BindTexture(0, Texture); u32 size = Width*Height; - u32* buf=new u32[size]; - for (uint i=0;iCalcShadowMatrices(); // clear buffers - glClearColor(1,1,1,0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (m->UseDepthTexture) + { + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glColorMask(0,0,0,0); + } + else + { + glClearColor(1,1,1,0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } // setup viewport glViewport(0, 0, renderWidth, renderHeight); @@ -264,6 +295,11 @@ void ShadowMap::EndRender() g_Renderer.BindTexture(0, m->Texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, g_Renderer.GetWidth(), g_Renderer.GetHeight()); + if (m->UseDepthTexture) + { + glColorMask(1,1,1,1); + } + // restore matrix stack glPopMatrix(); glMatrixMode(GL_PROJECTION); @@ -285,6 +321,38 @@ const CMatrix3D& ShadowMap::GetTextureMatrix() } +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Using depth textures vs. a simple luminance map +bool ShadowMap::GetUseDepthTexture() +{ + return m->UseDepthTexture; +} + +void ShadowMap::SetUseDepthTexture(bool depthTexture) +{ + if (depthTexture) + { + if (!g_Renderer.GetCapabilities().m_DepthTextureShadows) + { + LOG(WARNING, LOG_CATEGORY, "Depth textures are not supported by your graphics card/driver. Fallback to luminance map (no self-shadowing)!"); + depthTexture = false; + } + } + + if (depthTexture != m->UseDepthTexture) + { + if (m->Texture) + { + glDeleteTextures(1, &m->Texture); + m->Texture = 0; + } + m->Width = m->Height = 0; + + m->UseDepthTexture = depthTexture; + } +} + + ////////////////////////////////////////////////////////////////////////////// // RenderDebugDisplay: debug visualizations // - blue: objects in shadow @@ -363,6 +431,11 @@ void ShadowMap::RenderDebugDisplay() glDisable(GL_DEPTH_TEST); g_Renderer.BindTexture(0, m->Texture); + if (m->UseDepthTexture) + { + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } glColor3f(1.0, 1.0, 1.0); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0); diff --git a/source/renderer/ShadowMap.h b/source/renderer/ShadowMap.h index 811da6425d..0983ef01f3 100644 --- a/source/renderer/ShadowMap.h +++ b/source/renderer/ShadowMap.h @@ -25,7 +25,9 @@ struct ShadowMapInternals; * The class will automatically generate a texture the first time the shadow map is rendered into. * The texture will not be resized afterwards. * - * @todo use depth textures for self-shadowing + * Can use a simple luminance map to store shadows (no self-shadowing possible) or + * depth textures (with self-shadowing). Default is to use a luminance map, use SetUseDepthTexture + * to override the default. */ class ShadowMap { @@ -33,6 +35,28 @@ public: ShadowMap(); ~ShadowMap(); + /** + * GetUseDepthTexture: Return whether rendering uses a depth texture (instead of + * a luminance texture). + * + * Note that this value may be changed automatically based on OpenGL capabilities. + * It is guarantueed that it stays constant after SetupFrame until the end of the + * frame or the next call to SetUseDepthTexture. + * + * @return whether shadow rendering uses depth textures + */ + bool GetUseDepthTexture(); + + /** + * SetUseDepthTexture: Set whether shadowing should use depth textures. + * Note that even passing @c true for depthTexture does not actually guarantuee that + * depth textures will be used (mostly due to OpenGL capabilities). See the comment + * for GetUseDepthTexture. + * + * @param depthTexture whether shadow rendering should use depth textures + */ + void SetUseDepthTexture(bool depthTexture); + /** * SetupFrame: Configure light space for the given camera and light direction, * create the shadow texture if necessary, etc. diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index cc8dc7df97..5764b0ed16 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -24,6 +24,7 @@ #include "renderer/PatchRData.h" #include "renderer/Renderer.h" +#include "renderer/ShadowMap.h" #include "renderer/TerrainRenderer.h" #include "renderer/WaterManager.h" @@ -56,6 +57,9 @@ struct TerrainRendererInternals * @todo Merge this list with CPatchRData list */ std::vector visiblePatches; + + // Helper functions + void ApplyShadowMap(ShadowMap* shadow, const RGBAColor& shadowColor); }; @@ -124,7 +128,7 @@ bool TerrainRenderer::HaveSubmissions() /////////////////////////////////////////////////////////////////// // Full-featured terrain rendering with blending and everything -void TerrainRenderer::RenderTerrain() +void TerrainRenderer::RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowColor) { debug_assert(m->phase == Phase_Render); @@ -157,7 +161,7 @@ void TerrainRenderer::RenderTerrain() CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData(); patchdata->RenderBase(); } - + // render blends // switch on the composite alpha map texture (void)ogl_tex_bind(g_Renderer.m_hCompositeAlphaMap, 1); @@ -197,7 +201,7 @@ void TerrainRenderer::RenderTerrain() pglClientActiveTextureARB(GL_TEXTURE1); glDisableClientState(GL_TEXTURE_COORD_ARRAY); g_Renderer.BindTexture(1,0); - + pglClientActiveTextureARB(GL_TEXTURE0); pglActiveTextureARB(GL_TEXTURE0); @@ -205,6 +209,12 @@ void TerrainRenderer::RenderTerrain() glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); + + // Now render shadows as a second pass + if (shadow) + { + m->ApplyShadowMap(shadow, shadowColor); + } } @@ -368,35 +378,71 @@ void TerrainRenderer::RenderWater() /////////////////////////////////////////////////////////////////// -// -void TerrainRenderer::ApplyShadowMap(GLuint shadowmaphandle) +// ApplyShadowMap: add luminance map shadows after rendering the +// actual terrain +void TerrainRendererInternals::ApplyShadowMap(ShadowMap* shadow, const RGBAColor& shadowColor) { - debug_assert(m->phase == Phase_Render); + debug_assert(phase == Phase_Render); - g_Renderer.BindTexture(0, shadowmaphandle); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); + const CMatrix3D& texturematrix = shadow->GetTextureMatrix(); + GLuint shadowmap = shadow->GetTexture(); - glColor3f(1,1,1); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf(&texturematrix._11); + glMatrixMode(GL_MODELVIEW); + + g_Renderer.BindTexture(0, shadowmap); + if (shadow->GetUseDepthTexture()) + { + glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_GREATER); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); + + glColor4fv(shadowColor); + glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + } + else + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); + + glColor3f(1,1,1); + glBlendFunc(GL_DST_COLOR,GL_ZERO); + } glEnable(GL_BLEND); - glBlendFunc(GL_DST_COLOR,GL_ZERO); + glDepthMask(0); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - for (uint i = 0; i < m->visiblePatches.size(); ++i) + for (uint i = 0; i < visiblePatches.size(); ++i) { - CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData(); + CPatchRData* patchdata = (CPatchRData*)visiblePatches[i]->GetRenderData(); patchdata->RenderStreams(STREAM_POS|STREAM_POSTOUV0); } + glDepthMask(1); glDisable(GL_BLEND); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } diff --git a/source/renderer/TerrainRenderer.h b/source/renderer/TerrainRenderer.h index c9caed4ca1..25288b35ab 100644 --- a/source/renderer/TerrainRenderer.h +++ b/source/renderer/TerrainRenderer.h @@ -13,6 +13,7 @@ #define TERRAINRENDERER_H class CPatch; +class ShadowMap; class WaterManager; struct TerrainRendererInternals; @@ -69,8 +70,11 @@ public: * * preconditions : PrepareForRendering must have been called this * frame before calling RenderTerrain. + * + * @param shadow a prepared shadow map, in case rendering with shadows is enabled + * @param shadowColor color of shadows */ - void RenderTerrain(); + void RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowColor); /** * RenderPatches: Render all patches un-textured as polygons. @@ -97,14 +101,6 @@ public: */ void RenderWater(); - /** - * ApplyShadowMap: transition measure during refactoring - * - * @todo fix this - * @deprecated - */ - void ApplyShadowMap(GLuint handle); - private: TerrainRendererInternals* m; }; diff --git a/source/renderer/TransparencyRenderer.cpp b/source/renderer/TransparencyRenderer.cpp index 847e1ab1bc..e10a1d389d 100755 --- a/source/renderer/TransparencyRenderer.cpp +++ b/source/renderer/TransparencyRenderer.cpp @@ -659,3 +659,53 @@ void TransparentShadowRenderModifier::PrepareModel(uint UNUSED(pass), CModel* UN { // No per-model setup necessary } + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// TransparentDepthShadowModifier implementation + +TransparentDepthShadowModifier::TransparentDepthShadowModifier() +{ +} + +TransparentDepthShadowModifier::~TransparentDepthShadowModifier() +{ +} + +u32 TransparentDepthShadowModifier::BeginPass(uint pass) +{ + debug_assert(pass == 0); + + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.4); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); + + // Set the proper LOD bias + glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias); + + return STREAM_POS|STREAM_UV0; +} + +bool TransparentDepthShadowModifier::EndPass(uint UNUSED(pass)) +{ + glDisable(GL_ALPHA_TEST); + + return true; +} + +void TransparentDepthShadowModifier::PrepareTexture(uint UNUSED(pass), CTexture* texture) +{ + g_Renderer.SetTexture(0, texture); +} + +void TransparentDepthShadowModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(model)) +{ + // No per-model setup necessary +} diff --git a/source/renderer/TransparencyRenderer.h b/source/renderer/TransparencyRenderer.h index 24fca33693..f3a80cd2f1 100755 --- a/source/renderer/TransparencyRenderer.h +++ b/source/renderer/TransparencyRenderer.h @@ -24,7 +24,7 @@ struct PolygonSortModelRendererInternals; /** * Class PolygonSortModelRenderer: Render animated models using only * OpenGL fixed function, sorting polygons from back to front. - * + * * This ModelVertexRenderer should only be used with SortModelRenderer. * However, SortModelRenderer can be used with other ModelVertexRenderers * than this one. @@ -55,12 +55,12 @@ struct SortModelRendererInternals; /** * Class SortModelRenderer: Render models back-to-front from the * camera's point of view. - * + * * This is less efficient than batched model renderers, but * necessary for transparent models. - * + * * TransparencyRenderer can be used with any ModelVertexRenderer. - * + * * Use this renderer together with TransparentRenderModifier and * TransparentShadowRenderModifier to achieve transparency. */ @@ -69,7 +69,7 @@ class SortModelRenderer : public ModelRenderer public: SortModelRenderer(ModelVertexRendererPtr vertexrenderer); ~SortModelRenderer(); - + // Transparency renderer implementation void Submit(CModel* model); void PrepareModels(); @@ -101,8 +101,8 @@ public: }; /** - * Class TransparentShadowRenderModifier: Use for shadow rendering of - * transparent models. + * Class TransparentShadowRenderModifier: Use to render shadow data for + * transparent models into a luminance map. */ class TransparentShadowRenderModifier : public RenderModifier { @@ -117,4 +117,22 @@ public: void PrepareModel(uint pass, CModel* model); }; +/** + * Class TransparentDepthShadowModifier: Use to render shadow data for + * transparent models into a depth texture: Writes into the depth buffer, + * color data is undefined. + */ +class TransparentDepthShadowModifier : public RenderModifier +{ +public: + TransparentDepthShadowModifier(); + ~TransparentDepthShadowModifier(); + + // Implementation + u32 BeginPass(uint pass); + bool EndPass(uint pass); + void PrepareTexture(uint pass, CTexture* texture); + void PrepareModel(uint pass, CModel* model); +}; + #endif