Shadow rendering can use depth textures, as a preparation for

self-shadowing and shadows on models in general.
Usage of depth textures can be toggled using
?renderer.useDepthTexture = true/false in the JavaScript console.

This was SVN commit r3495.
This commit is contained in:
prefect 2006-02-11 18:04:32 +00:00
parent 58da2342c2
commit 9f055eddb0
9 changed files with 315 additions and 100 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;
};

View File

@ -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;i<size;i++) buf[i]=0x00ffffff;
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width,Height,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
delete[] buf;
if (UseDepthTexture)
{
float* buf = new float[size];
for(uint i = 0; i < size; i++) buf[i] = 1.0;
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, Width, Height, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, buf);
delete[] buf;
}
else
{
u32* buf=new u32[size];
for (uint i=0;i<size;i++) buf[i]=0x00ffffff;
glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE8,Width,Height,0,GL_RGBA,GL_UNSIGNED_BYTE,buf);
delete[] buf;
}
// set texture parameters
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
@ -235,8 +258,16 @@ void ShadowMap::BeginRender()
m->CalcShadowMatrices();
// 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);

View File

@ -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.

View File

@ -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<CPatch*> 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);
}

View File

@ -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;
};

View File

@ -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
}

View File

@ -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