- Terrain self-shadows (only noticeable with a low angle of sun)
- explicitly split ambient and diffuse - add renderer.shadowZBias to bias depths in the depth texture and avoid flickering artifacts caused by Z fighting - cantabrian_generated uses new light values so that shadows aren't pitch black This was SVN commit r3508.
This commit is contained in:
parent
10d84599e9
commit
7dee30e24c
BIN
binaries/data/mods/official/maps/scenarios/cantabrian_generated.xml
(Stored with Git LFS)
BIN
binaries/data/mods/official/maps/scenarios/cantabrian_generated.xml
(Stored with Git LFS)
Binary file not shown.
11
binaries/data/mods/official/shaders/globallight.vs
Normal file
11
binaries/data/mods/official/shaders/globallight.vs
Normal file
@ -0,0 +1,11 @@
|
||||
uniform vec3 ambient;
|
||||
uniform vec3 sunDir;
|
||||
uniform vec3 sunColor;
|
||||
|
||||
vec3 lighting(vec3 normal)
|
||||
{
|
||||
vec3 color = ambient;
|
||||
float d = max(0.0, -dot(normal, sunDir));
|
||||
color += d * sunColor;
|
||||
return color;
|
||||
}
|
@ -4,6 +4,6 @@
|
||||
<Shaders>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing_light.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing_base.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/shlight.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/globallight.vs</Shader>
|
||||
</Shaders>
|
||||
</Program>
|
||||
|
@ -3,6 +3,6 @@
|
||||
<Program>
|
||||
<Shaders>
|
||||
<Shader type="VERTEX_SHADER">shaders/model_light.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/shlight.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/globallight.vs</Shader>
|
||||
</Shaders>
|
||||
</Program>
|
||||
|
@ -1,16 +0,0 @@
|
||||
uniform vec3 SHCoefficients[9];
|
||||
|
||||
vec3 lighting(vec3 normal)
|
||||
{
|
||||
vec3 color = SHCoefficients[0];
|
||||
vec3 normalsq = normal*normal;
|
||||
color += SHCoefficients[1]*normal.x;
|
||||
color += SHCoefficients[2]*normal.y;
|
||||
color += SHCoefficients[3]*normal.z;
|
||||
color += SHCoefficients[4]*(normal.x*normal.z);
|
||||
color += SHCoefficients[5]*(normal.z*normal.y);
|
||||
color += SHCoefficients[6]*(normal.y*normal.x);
|
||||
color += SHCoefficients[7]*(3.0*normalsq.z-1.0);
|
||||
color += SHCoefficients[8]*(normalsq.x-normalsq.y);
|
||||
return color;
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
#include "Vector4D.h"
|
||||
#include "lib/types.h"
|
||||
|
||||
// simple defines for 3 and 4 component floating point colors - just map to
|
||||
// simple defines for 3 and 4 component floating point colors - just map to
|
||||
// corresponding vector types
|
||||
typedef CVector3D RGBColor;
|
||||
typedef CVector4D RGBAColor;
|
||||
@ -33,6 +33,9 @@ struct SColor4ub
|
||||
u8 G;
|
||||
u8 B;
|
||||
u8 A;
|
||||
|
||||
SColor4ub() { }
|
||||
SColor4ub(u8 _r, u8 _g, u8 _b, u8 _a) : R(_r), G(_g), B(_b), A(_a) { }
|
||||
};
|
||||
|
||||
extern u32 (*ConvertRGBColorTo4ub)(const RGBColor& src);
|
||||
|
@ -4,8 +4,8 @@
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
// Description: class describing current lighting environment -
|
||||
// at the minute, this is only sunlight and ambient light
|
||||
// Description: class describing current lighting environment -
|
||||
// at the minute, this is only sunlight and ambient light
|
||||
// parameters; will be extended to handle dynamic lights at some
|
||||
// later date
|
||||
//
|
||||
@ -25,7 +25,7 @@ class CMainFrame;
|
||||
class CLightSettingsDlg;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CLightEnv: description of a lighting environment - contains all the
|
||||
// CLightEnv: description of a lighting environment - contains all the
|
||||
// necessary parameters for representation of the lighting within a scenario
|
||||
class CLightEnv
|
||||
{
|
||||
@ -67,6 +67,58 @@ public:
|
||||
CalculateSunDirection();
|
||||
}
|
||||
|
||||
/**
|
||||
* EvaluateTerrain: Calculate brightness of a point of the terrain with the given normal
|
||||
* vector.
|
||||
* The resulting color contains both ambient and diffuse light.
|
||||
*
|
||||
* @param normal normal vector (must have length 1)
|
||||
* @param color resulting color
|
||||
*/
|
||||
void EvaluateTerrain(const CVector3D& normal, RGBColor& color) const
|
||||
{
|
||||
float dot = -normal.Dot(m_SunDir);
|
||||
|
||||
color = m_TerrainAmbientColor;
|
||||
if (dot > 0)
|
||||
color += m_SunColor * dot;
|
||||
}
|
||||
|
||||
/**
|
||||
* EvaluateUnit: Calculate brightness of a point of a unit with the given normal
|
||||
* vector.
|
||||
* The resulting color contains both ambient and diffuse light.
|
||||
*
|
||||
* @param normal normal vector (must have length 1)
|
||||
* @param color resulting color
|
||||
*/
|
||||
void EvaluateUnit(const CVector3D& normal, RGBColor& color) const
|
||||
{
|
||||
float dot = -normal.Dot(m_SunDir);
|
||||
|
||||
color = m_UnitsAmbientColor;
|
||||
if (dot > 0)
|
||||
color += m_SunColor * dot;
|
||||
}
|
||||
|
||||
/**
|
||||
* EvaluateDirect: Like EvaluateTerrain and EvaluateUnit, but return only the direct
|
||||
* sunlight term without ambient.
|
||||
*
|
||||
* @param normal normal vector (must have length 1)
|
||||
* @param color resulting color
|
||||
*/
|
||||
void EvaluateDirect(const CVector3D& normal, RGBColor& color) const
|
||||
{
|
||||
float dot = -normal.Dot(m_SunDir);
|
||||
|
||||
if (dot > 0)
|
||||
color = m_SunColor * dot;
|
||||
else
|
||||
color = CVector3D(0,0,0);
|
||||
}
|
||||
|
||||
private:
|
||||
void CalculateSunDirection()
|
||||
{
|
||||
m_SunDir.Y=-float(sin(m_Elevation));
|
||||
|
@ -53,8 +53,8 @@ bool CTerrain::Initialize(u32 size,const u16* data)
|
||||
// store terrain size
|
||||
m_MapSize=(size*PATCH_SIZE)+1;
|
||||
m_MapSizePatches=size;
|
||||
WaterManager *WaterMgr = g_Renderer.GetWaterManager();
|
||||
WaterMgr->InitWave();
|
||||
//WaterManager *WaterMgr = g_Renderer.GetWaterManager();
|
||||
//WaterMgr->InitWave();
|
||||
// allocate data for new terrain
|
||||
m_Heightmap=new u16[m_MapSize*m_MapSize];
|
||||
m_Patches=new CPatch[m_MapSizePatches*m_MapSizePatches];
|
||||
@ -94,12 +94,12 @@ void CTerrain::CalcPosition(i32 i, i32 j, CVector3D& pos) const
|
||||
void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal) const
|
||||
{
|
||||
CVector3D left, right, up, down;
|
||||
|
||||
|
||||
left.Clear();
|
||||
right.Clear();
|
||||
up.Clear();
|
||||
down.Clear();
|
||||
|
||||
|
||||
// get position of vertex where normal is being evaluated
|
||||
CVector3D basepos;
|
||||
CalcPosition(i,j,basepos);
|
||||
@ -128,7 +128,7 @@ void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal) const
|
||||
CVector3D n0 = up.Cross(left);
|
||||
CVector3D n1 = left.Cross(down);
|
||||
CVector3D n2 = down.Cross(right);
|
||||
CVector3D n3 = right.Cross(up);
|
||||
CVector3D n3 = right.Cross(up);
|
||||
|
||||
normal = n0 + n1 + n2 + n3;
|
||||
float nlen=normal.GetLength();
|
||||
@ -137,18 +137,18 @@ void CTerrain::CalcNormal(u32 i, u32 j, CVector3D& normal) const
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetPatch: return the patch at (x,z) in patch space, or null if the patch is
|
||||
// GetPatch: return the patch at (x,z) in patch space, or null if the patch is
|
||||
// out of bounds
|
||||
CPatch* CTerrain::GetPatch(i32 x, i32 z) const
|
||||
{
|
||||
if (x<0 || x>=i32(m_MapSizePatches)) return 0;
|
||||
if (z<0 || z>=i32(m_MapSizePatches)) return 0;
|
||||
return &m_Patches[(z*m_MapSizePatches)+x];
|
||||
return &m_Patches[(z*m_MapSizePatches)+x];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GetPatch: return the tile at (x,z) in tile space, or null if the tile is out
|
||||
// GetPatch: return the tile at (x,z) in tile space, or null if the tile is out
|
||||
// of bounds
|
||||
CMiniPatch* CTerrain::GetTile(i32 x, i32 z) const
|
||||
{
|
||||
@ -160,7 +160,7 @@ CMiniPatch* CTerrain::GetTile(i32 x, i32 z) const
|
||||
}
|
||||
|
||||
float CTerrain::getVertexGroundLevel(int x, int z) const
|
||||
{
|
||||
{
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
@ -266,7 +266,7 @@ void CTerrain::Resize(u32 size)
|
||||
for (u32 i=0;i<newMapSize-m_MapSize;i++) {
|
||||
*dst++=*(src-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -286,7 +286,7 @@ void CTerrain::Resize(u32 size)
|
||||
// copy over texture data from existing tiles, if possible
|
||||
if (i<m_MapSizePatches && j<m_MapSizePatches) {
|
||||
memcpy2(newPatches[j*size+i].m_MiniPatches,m_Patches[j*m_MapSizePatches+i].m_MiniPatches,sizeof(CMiniPatch)*PATCH_SIZE*PATCH_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j<m_MapSizePatches && size>m_MapSizePatches) {
|
||||
@ -303,7 +303,7 @@ void CTerrain::Resize(u32 size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (size>m_MapSizePatches) {
|
||||
// copy over the last tile from each column
|
||||
CPatch* srcpatch=&newPatches[(m_MapSizePatches-1)*size];
|
||||
@ -351,7 +351,7 @@ void CTerrain::InitialisePatches()
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SetHeightMap: set up a new heightmap from 16-bit source data;
|
||||
// SetHeightMap: set up a new heightmap from 16-bit source data;
|
||||
// assumes heightmap matches current terrain size
|
||||
void CTerrain::SetHeightMap(u16* heightmap)
|
||||
{
|
||||
@ -370,15 +370,15 @@ void CTerrain::SetHeightMap(u16* heightmap)
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// FlattenArea: flatten out an area of terrain (specified in world space
|
||||
// FlattenArea: flatten out an area of terrain (specified in world space
|
||||
// coords); return the average height of the flattened area
|
||||
float CTerrain::FlattenArea(float x0,float x1,float z0,float z1)
|
||||
{
|
||||
u32 tx0=u32(clamp(int(float(x0/CELL_SIZE)),0,int(m_MapSize)));
|
||||
u32 tx1=u32(clamp(int(float(x1/CELL_SIZE)+1.0f),0,int(m_MapSize)));
|
||||
u32 tz0=u32(clamp(int(float(z0/CELL_SIZE)),0,int(m_MapSize)));
|
||||
u32 tz1=u32(clamp(int(float(z1/CELL_SIZE)+1.0f),0,int(m_MapSize)));
|
||||
|
||||
u32 tx0=u32(clamp(int(float(x0/CELL_SIZE)),0,int(m_MapSize)));
|
||||
u32 tx1=u32(clamp(int(float(x1/CELL_SIZE)+1.0f),0,int(m_MapSize)));
|
||||
u32 tz0=u32(clamp(int(float(z0/CELL_SIZE)),0,int(m_MapSize)));
|
||||
u32 tz1=u32(clamp(int(float(z1/CELL_SIZE)+1.0f),0,int(m_MapSize)));
|
||||
|
||||
u32 count=0;
|
||||
u32 y=0;
|
||||
for (u32 x=tx0;x<=tx1;x++) {
|
||||
|
@ -114,7 +114,7 @@ static int SetVideoMode(int w, int h, int bpp, bool fullscreen)
|
||||
// (Note that atexit hooks are guarantueed to be called in reverse order of their registration.)
|
||||
atexit(SDL_Quit);
|
||||
// End work around.
|
||||
|
||||
|
||||
glViewport(0, 0, w, h);
|
||||
|
||||
#ifndef NO_GUI
|
||||
@ -255,7 +255,7 @@ void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
|
||||
#ifndef NO_GUI
|
||||
CStrW i18n_description = I18n::translate(pending_task);
|
||||
JSString* js_desc = StringConvert::wstring_to_jsstring(g_ScriptingHost.getContext(), i18n_description);
|
||||
g_ScriptingHost.SetGlobal("g_Progress", INT_TO_JSVAL(percent));
|
||||
g_ScriptingHost.SetGlobal("g_Progress", INT_TO_JSVAL(percent));
|
||||
g_ScriptingHost.SetGlobal("g_LoadDescription", STRING_TO_JSVAL(js_desc));
|
||||
g_GUI.SendEventToAll("progress");
|
||||
#endif
|
||||
@ -331,7 +331,7 @@ void Render()
|
||||
PROFILE_END( "render selection" );
|
||||
|
||||
PROFILE_START( "render building placement cursor" );
|
||||
if( g_BuildingPlacer.m_active )
|
||||
if( g_BuildingPlacer.m_active )
|
||||
{
|
||||
//glEnable( GL_DEPTH_TEST );
|
||||
g_BuildingPlacer.render();
|
||||
@ -339,7 +339,7 @@ void Render()
|
||||
}
|
||||
PROFILE_END( "render building placement cursor" );
|
||||
|
||||
|
||||
|
||||
PROFILE_START( "render health bars" );
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
@ -493,7 +493,7 @@ static void InitScripting()
|
||||
CScriptEvent::ScriptingInit();
|
||||
CJSProgressTimer::ScriptingInit();
|
||||
CProjectile::ScriptingInit();
|
||||
|
||||
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_GOTO", CEntityListener::NOTIFY_GOTO );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_RUN", CEntityListener::NOTIFY_RUN );
|
||||
g_ScriptingHost.DefineConstant( "NOTIFY_FOLLOW", CEntityListener::NOTIFY_FOLLOW );
|
||||
@ -605,7 +605,7 @@ static void InitInput()
|
||||
|
||||
in_add_handler(CProfileViewer::InputThunk);
|
||||
|
||||
in_add_handler(hotkeyInputHandler);
|
||||
in_add_handler(hotkeyInputHandler);
|
||||
|
||||
in_add_handler(GlobalsInputHandler);
|
||||
}
|
||||
@ -666,7 +666,7 @@ static void InitRenderer()
|
||||
g_LightEnv.m_SunColor=RGBColor(1,1,1);
|
||||
g_LightEnv.SetRotation(DEGTORAD(270));
|
||||
g_LightEnv.SetElevation(DEGTORAD(45));
|
||||
g_LightEnv.m_TerrainAmbientColor=RGBColor(0,0,0);
|
||||
g_LightEnv.m_TerrainAmbientColor=RGBColor(0.4f,0.4f,0.4f);
|
||||
g_LightEnv.m_UnitsAmbientColor=RGBColor(0.4f,0.4f,0.4f);
|
||||
g_Renderer.SetLightEnv(&g_LightEnv);
|
||||
|
||||
@ -843,7 +843,7 @@ void Init(int argc, char* argv[], uint flags)
|
||||
|
||||
// Query CPU capabilities, possibly set some CPU-dependent flags
|
||||
cpu_init();
|
||||
|
||||
|
||||
// Do this as soon as possible, because it chdirs
|
||||
// and will mess up the error reporting if anything
|
||||
// crashes before the working directory is set.
|
||||
@ -1032,7 +1032,7 @@ void Init(int argc, char* argv[], uint flags)
|
||||
// Code copied mostly from atlas/GameInterface/Handlers/Map.cpp -
|
||||
// maybe should be refactored to avoid duplication
|
||||
g_GameAttributes.m_MapFile = g_AutostartMap+".pmp";
|
||||
for (int i=1; i<8; ++i)
|
||||
for (int i=1; i<8; ++i)
|
||||
g_GameAttributes.GetSlot(i)->AssignLocal();
|
||||
g_GameAttributes.m_LOSSetting = 2;
|
||||
g_Game = new CGame();
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "graphics/ModelDef.h"
|
||||
|
||||
@ -25,7 +26,6 @@
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/RenderPathVertexShader.h"
|
||||
#include "renderer/SHCoeffs.h"
|
||||
#include "renderer/VertexArray.h"
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ struct HWLModelDef : public CModelDefRPrivate
|
||||
{
|
||||
/// Indices are the same for all models, so share them
|
||||
u16* m_Indices;
|
||||
|
||||
|
||||
|
||||
HWLModelDef(CModelDefPtr mdef);
|
||||
~HWLModelDef() { delete[] m_Indices; }
|
||||
@ -57,14 +57,14 @@ struct HWLModel
|
||||
{
|
||||
/// Dynamic per-CModel vertex array
|
||||
VertexArray m_Array;
|
||||
|
||||
|
||||
/// Position and normals are recalculated on CPU every frame
|
||||
VertexArray::Attribute m_Position;
|
||||
VertexArray::Attribute m_Normal;
|
||||
|
||||
|
||||
/// UV is stored per-CModel in order to avoid space wastage due to alignment
|
||||
VertexArray::Attribute m_UV;
|
||||
|
||||
|
||||
HWLModel() : m_Array(true) { }
|
||||
};
|
||||
|
||||
@ -73,7 +73,7 @@ struct HWLightingModelRendererInternals
|
||||
{
|
||||
/// Currently used RenderModifier
|
||||
RenderModifierPtr modifier;
|
||||
|
||||
|
||||
/// Previously prepared modeldef
|
||||
HWLModelDef* hwlmodeldef;
|
||||
};
|
||||
@ -125,13 +125,13 @@ void* HWLightingModelRenderer::CreateModelData(CModel* model)
|
||||
hwlmodel->m_Normal.type = GL_FLOAT;
|
||||
hwlmodel->m_Normal.elems = 3;
|
||||
hwlmodel->m_Array.AddAttribute(&hwlmodel->m_Normal);
|
||||
|
||||
|
||||
hwlmodel->m_Array.SetNumVertices(mdef->GetNumVertices());
|
||||
hwlmodel->m_Array.Layout();
|
||||
|
||||
// Fill in static UV coordinates
|
||||
VertexArrayIterator<float[2]> UVit = hwlmodel->m_UV.GetIterator<float[2]>();
|
||||
|
||||
|
||||
ModelRenderer::BuildUV(mdef, UVit);
|
||||
|
||||
return hwlmodel;
|
||||
@ -142,17 +142,17 @@ void* HWLightingModelRenderer::CreateModelData(CModel* model)
|
||||
void HWLightingModelRenderer::UpdateModelData(CModel* model, void* data, u32 updateflags)
|
||||
{
|
||||
HWLModel* hwlmodel = (HWLModel*)data;
|
||||
|
||||
|
||||
if (updateflags & RENDERDATA_UPDATE_VERTICES)
|
||||
{
|
||||
CModelDefPtr mdef = model->GetModelDef();
|
||||
|
||||
|
||||
// build vertices
|
||||
VertexArrayIterator<CVector3D> Position = hwlmodel->m_Position.GetIterator<CVector3D>();
|
||||
VertexArrayIterator<CVector3D> Normal = hwlmodel->m_Normal.GetIterator<CVector3D>();
|
||||
|
||||
|
||||
ModelRenderer::BuildPositionAndNormals(model, Position, Normal);
|
||||
|
||||
|
||||
// upload everything to vertex buffer
|
||||
hwlmodel->m_Array.Upload();
|
||||
}
|
||||
@ -164,7 +164,7 @@ void HWLightingModelRenderer::UpdateModelData(CModel* model, void* data, u32 upd
|
||||
void HWLightingModelRenderer::DestroyModelData(CModel* UNUSED(model), void* data)
|
||||
{
|
||||
HWLModel* hwlmodel = (HWLModel*)data;
|
||||
|
||||
|
||||
delete hwlmodel;
|
||||
}
|
||||
|
||||
@ -173,16 +173,20 @@ void HWLightingModelRenderer::DestroyModelData(CModel* UNUSED(model), void* data
|
||||
void HWLightingModelRenderer::BeginPass(uint streamflags)
|
||||
{
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
const RGBColor* coeffs = g_Renderer.m_SHCoeffsUnits.GetCoefficients();
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
int idx;
|
||||
|
||||
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_ModelLight);
|
||||
idx = g_Renderer.m_VertexShader->m_ModelLight_SHCoefficients;
|
||||
pglUniform3fvARB(idx, 9, (float*)coeffs);
|
||||
idx = g_Renderer.m_VertexShader->m_ModelLight_Ambient;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_UnitsAmbientColor.X);
|
||||
idx = g_Renderer.m_VertexShader->m_ModelLight_SunDir;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_SunDir.X);
|
||||
idx = g_Renderer.m_VertexShader->m_ModelLight_SunColor;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_SunColor.X);
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
@ -199,7 +203,7 @@ void HWLightingModelRenderer::EndPass(uint streamflags)
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
@ -208,7 +212,7 @@ void HWLightingModelRenderer::EndPass(uint streamflags)
|
||||
void HWLightingModelRenderer::PrepareModelDef(uint UNUSED(streamflags), CModelDefPtr def)
|
||||
{
|
||||
m->hwlmodeldef = (HWLModelDef*)def->GetRenderData(m);
|
||||
|
||||
|
||||
debug_assert(m->hwlmodeldef);
|
||||
}
|
||||
|
||||
@ -218,16 +222,16 @@ void HWLightingModelRenderer::RenderModel(uint streamflags, CModel* model, void*
|
||||
{
|
||||
CModelDefPtr mdldef = model->GetModelDef();
|
||||
HWLModel* hwlmodel = (HWLModel*)data;
|
||||
|
||||
|
||||
u8* base = hwlmodel->m_Array.Bind();
|
||||
GLsizei stride = (GLsizei)hwlmodel->m_Array.GetStride();
|
||||
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, stride, base + hwlmodel->m_Position.offset);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
CColor sc = model->GetShadingColor();
|
||||
glColor3f(sc.r, sc.g, sc.b);
|
||||
|
||||
|
||||
glNormalPointer(GL_FLOAT, stride, base + hwlmodel->m_Normal.offset);
|
||||
}
|
||||
if (streamflags & STREAM_UV0)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "graphics/ModelDef.h"
|
||||
|
||||
@ -25,7 +26,6 @@
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/RenderPathVertexShader.h"
|
||||
#include "renderer/SHCoeffs.h"
|
||||
#include "renderer/VertexArray.h"
|
||||
|
||||
|
||||
@ -39,15 +39,15 @@ struct IModelDef : public CModelDefRPrivate
|
||||
{
|
||||
/// Static per-CModel vertex array
|
||||
VertexArray m_Array;
|
||||
|
||||
|
||||
/// Position, normals and UV are all static
|
||||
VertexArray::Attribute m_Position;
|
||||
VertexArray::Attribute m_Normal;
|
||||
VertexArray::Attribute m_UV;
|
||||
|
||||
|
||||
/// Indices are the same for all models, so share them
|
||||
u16* m_Indices;
|
||||
|
||||
|
||||
|
||||
IModelDef(CModelDefPtr mdef);
|
||||
~IModelDef() { delete[] m_Indices; }
|
||||
@ -58,32 +58,32 @@ IModelDef::IModelDef(CModelDefPtr mdef)
|
||||
: m_Array(false)
|
||||
{
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
|
||||
|
||||
m_Position.type = GL_FLOAT;
|
||||
m_Position.elems = 3;
|
||||
m_Array.AddAttribute(&m_Position);
|
||||
|
||||
|
||||
m_Normal.type = GL_FLOAT;
|
||||
m_Normal.elems = 3;
|
||||
m_Array.AddAttribute(&m_Normal);
|
||||
|
||||
|
||||
m_UV.type = GL_FLOAT;
|
||||
m_UV.elems = 2;
|
||||
m_Array.AddAttribute(&m_UV);
|
||||
|
||||
|
||||
m_Array.SetNumVertices(numVertices);
|
||||
m_Array.Layout();
|
||||
|
||||
VertexArrayIterator<CVector3D> Position = m_Position.GetIterator<CVector3D>();
|
||||
VertexArrayIterator<CVector3D> Normal = m_Normal.GetIterator<CVector3D>();
|
||||
VertexArrayIterator<float[2]> UVit = m_UV.GetIterator<float[2]>();
|
||||
|
||||
|
||||
ModelRenderer::CopyPositionAndNormals(mdef, Position, Normal);
|
||||
ModelRenderer::BuildUV(mdef, UVit);
|
||||
|
||||
|
||||
m_Array.Upload();
|
||||
m_Array.FreeBackingStore();
|
||||
|
||||
|
||||
m_Indices = new u16[mdef->GetNumFaces()*3];
|
||||
ModelRenderer::BuildIndices(mdef, m_Indices);
|
||||
}
|
||||
@ -93,7 +93,7 @@ struct InstancingModelRendererInternals
|
||||
{
|
||||
/// Currently used RenderModifier
|
||||
RenderModifierPtr modifier;
|
||||
|
||||
|
||||
/// Previously prepared modeldef
|
||||
IModelDef* imodeldef;
|
||||
};
|
||||
@ -126,13 +126,13 @@ void* InstancingModelRenderer::CreateModelData(CModel* model)
|
||||
IModelDef* imodeldef = (IModelDef*)mdef->GetRenderData(m);
|
||||
|
||||
debug_assert(!model->GetBoneMatrices());
|
||||
|
||||
|
||||
if (!imodeldef)
|
||||
{
|
||||
imodeldef = new IModelDef(mdef);
|
||||
mdef->SetRenderData(m, imodeldef);
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -153,16 +153,20 @@ void InstancingModelRenderer::DestroyModelData(CModel* UNUSED(model), void* UNUS
|
||||
void InstancingModelRenderer::BeginPass(uint streamflags)
|
||||
{
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
const RGBColor* coeffs = g_Renderer.m_SHCoeffsUnits.GetCoefficients();
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
int idx;
|
||||
|
||||
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_InstancingLight);
|
||||
idx = g_Renderer.m_VertexShader->m_InstancingLight_SHCoefficients;
|
||||
pglUniform3fvARB(idx, 9, (float*)coeffs);
|
||||
idx = g_Renderer.m_VertexShader->m_InstancingLight_Ambient;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_UnitsAmbientColor.X);
|
||||
idx = g_Renderer.m_VertexShader->m_InstancingLight_SunDir;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_SunDir.X);
|
||||
idx = g_Renderer.m_VertexShader->m_InstancingLight_SunColor;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_SunColor.X);
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
@ -187,12 +191,12 @@ void InstancingModelRenderer::EndPass(uint streamflags)
|
||||
void InstancingModelRenderer::PrepareModelDef(uint streamflags, CModelDefPtr def)
|
||||
{
|
||||
m->imodeldef = (IModelDef*)def->GetRenderData(m);
|
||||
|
||||
|
||||
debug_assert(m->imodeldef);
|
||||
|
||||
u8* base = m->imodeldef->m_Array.Bind();
|
||||
GLsizei stride = (GLsizei)m->imodeldef->m_Array.GetStride();
|
||||
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, stride, base + m->imodeldef->m_Position.offset);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
@ -211,12 +215,12 @@ void InstancingModelRenderer::RenderModel(uint streamflags, CModel* model, void*
|
||||
CModelDefPtr mdldef = model->GetModelDef();
|
||||
const CMatrix3D& mat = model->GetTransform();
|
||||
RenderPathVertexShader* rpvs = g_Renderer.m_VertexShader;
|
||||
|
||||
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
CColor sc = model->GetShadingColor();
|
||||
glColor3f(sc.r, sc.g, sc.b);
|
||||
|
||||
|
||||
pglVertexAttrib4fARB(rpvs->m_InstancingLight_Instancing1, mat._11, mat._12, mat._13, mat._14);
|
||||
pglVertexAttrib4fARB(rpvs->m_InstancingLight_Instancing2, mat._21, mat._22, mat._23, mat._24);
|
||||
pglVertexAttrib4fARB(rpvs->m_InstancingLight_Instancing3, mat._31, mat._32, mat._33, mat._34);
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ps/Profile.h"
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "graphics/ModelDef.h"
|
||||
|
||||
@ -25,7 +26,6 @@
|
||||
#include "renderer/ModelVertexRenderer.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/SHCoeffs.h"
|
||||
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
@ -84,7 +84,7 @@ void ModelRenderer::CopyPositionAndNormals(
|
||||
{
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
SModelVertex* vertices = mdef->GetVertices();
|
||||
|
||||
|
||||
for(size_t j = 0; j < numVertices; ++j)
|
||||
{
|
||||
Position[j] = vertices[j].m_Coords;
|
||||
@ -101,14 +101,14 @@ void ModelRenderer::BuildPositionAndNormals(
|
||||
CModelDefPtr mdef = model->GetModelDef();
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
SModelVertex* vertices=mdef->GetVertices();
|
||||
|
||||
|
||||
const CMatrix3D* bonematrices = model->GetBoneMatrices();
|
||||
if (bonematrices)
|
||||
{
|
||||
// boned model - calculate skinned vertex positions/normals
|
||||
PROFILE( "skinning bones" );
|
||||
const CMatrix3D* invtranspbonematrices;
|
||||
|
||||
|
||||
// Analytic geometry tells us that normal vectors need to be
|
||||
// multiplied by the inverse of the transpose. However, calculating
|
||||
// the inverse is slow, and analytic geometry also tells us that
|
||||
@ -123,7 +123,7 @@ void ModelRenderer::BuildPositionAndNormals(
|
||||
invtranspbonematrices = bonematrices;
|
||||
else
|
||||
invtranspbonematrices = model->GetInvTranspBoneMatrices();
|
||||
|
||||
|
||||
for (size_t j=0; j<numVertices; j++)
|
||||
{
|
||||
SkinPoint(vertices[j],bonematrices,Position[j]);
|
||||
@ -152,17 +152,19 @@ void ModelRenderer::BuildColor4ub(
|
||||
VertexArrayIterator<SColor4ub> Color)
|
||||
{
|
||||
PROFILE( "lighting vertices" );
|
||||
|
||||
|
||||
CModelDefPtr mdef = model->GetModelDef();
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
CSHCoeffs& shcoeffs = g_Renderer.m_SHCoeffsUnits;
|
||||
CColor sc = model->GetShadingColor();
|
||||
RGBColor shadingcolor(sc.r, sc.g, sc.b);
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
CColor shadingColor = model->GetShadingColor();
|
||||
RGBColor tempcolor;
|
||||
|
||||
|
||||
for (uint j=0; j<numVertices; j++)
|
||||
{
|
||||
shcoeffs.Evaluate(Normal[j], tempcolor, shadingcolor);
|
||||
lightEnv.EvaluateUnit(Normal[j], tempcolor);
|
||||
tempcolor.X *= shadingColor.r;
|
||||
tempcolor.Y *= shadingColor.g;
|
||||
tempcolor.Z *= shadingColor.b;
|
||||
*(u32*)&Color[j] = ConvertRGBColorTo4ub(tempcolor);
|
||||
}
|
||||
}
|
||||
@ -175,7 +177,7 @@ void ModelRenderer::BuildUV(
|
||||
{
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
SModelVertex* vertices = mdef->GetVertices();
|
||||
|
||||
|
||||
for (uint j=0; j < numVertices; ++j, ++UV)
|
||||
{
|
||||
(*UV)[0] = vertices[j].m_U;
|
||||
@ -191,7 +193,7 @@ void ModelRenderer::BuildIndices(
|
||||
{
|
||||
u32 idxidx = 0;
|
||||
SModelFace* faces = mdef->GetFaces();
|
||||
|
||||
|
||||
for (size_t j = 0; j < mdef->GetNumFaces(); ++j) {
|
||||
SModelFace& face=faces[j];
|
||||
Indices[idxidx++]=face.m_Verts[0];
|
||||
@ -210,7 +212,7 @@ void ModelRenderer::BuildIndices(
|
||||
enum BMRPhase {
|
||||
/// Currently allow calls to Submit and PrepareModels
|
||||
BMRSubmit,
|
||||
|
||||
|
||||
/// Allow calls to rendering and EndFrame
|
||||
BMRRender
|
||||
};
|
||||
@ -224,13 +226,13 @@ struct BMRModelData : public CModelRData
|
||||
BMRModelData(BatchModelRendererInternals* bmri, CModel* model)
|
||||
: CModelRData(bmri, model), m_BMRI(bmri), m_Data(0), m_Next(0) { }
|
||||
virtual ~BMRModelData();
|
||||
|
||||
|
||||
/// Back-link to "our" modelrenderer
|
||||
BatchModelRendererInternals* m_BMRI;
|
||||
|
||||
|
||||
/// Private data created by derived class' CreateModelData
|
||||
void* m_Data;
|
||||
|
||||
|
||||
/// Next model in the per-ModelDefTracker-slot linked list.
|
||||
BMRModelData* m_Next;
|
||||
};
|
||||
@ -238,7 +240,7 @@ struct BMRModelData : public CModelRData
|
||||
|
||||
/**
|
||||
* Class BMRModelDefTracker: Per-CModelDef data used by the BatchModelRenderer.
|
||||
*
|
||||
*
|
||||
* Note that classes that derive from BatchModelRenderer should use
|
||||
* their own per-CModelDef data if necessary.
|
||||
*/
|
||||
@ -255,7 +257,7 @@ struct BMRModelDefTracker : public CModelDefRPrivate
|
||||
|
||||
/// Number of slots used in m_ModelSlots
|
||||
uint m_Slots;
|
||||
|
||||
|
||||
/// Each slot contains a linked list of model data objects, up to m_Slots-1
|
||||
// At the end of the frame, m_Slots is reset to 0, but m_ModelSlots stays
|
||||
// the same size (we assume the same number of slots is going to be used
|
||||
@ -267,32 +269,32 @@ struct BMRModelDefTracker : public CModelDefRPrivate
|
||||
|
||||
/**
|
||||
* Struct BatchModelRendererInternals: Internal data of the BatchModelRenderer
|
||||
*
|
||||
* Separated into the source file to increase implementation hiding (and to
|
||||
*
|
||||
* Separated into the source file to increase implementation hiding (and to
|
||||
* avoid some causes of recompiles).
|
||||
*/
|
||||
struct BatchModelRendererInternals
|
||||
{
|
||||
BatchModelRendererInternals(BatchModelRenderer* r) : m_Renderer(r) { }
|
||||
|
||||
|
||||
/// Back-link to "our" renderer
|
||||
BatchModelRenderer* m_Renderer;
|
||||
|
||||
|
||||
/// ModelVertexRenderer used for vertex transformations
|
||||
ModelVertexRendererPtr vertexRenderer;
|
||||
|
||||
|
||||
/// Track the current "phase" of the frame (only for debugging purposes)
|
||||
BMRPhase phase;
|
||||
|
||||
|
||||
/// Linked list of ModelDefTrackers that have submitted models
|
||||
BMRModelDefTracker* submissions;
|
||||
|
||||
|
||||
/// Helper functions
|
||||
void ThunkDestroyModelData(CModel* model, void* data)
|
||||
{
|
||||
vertexRenderer->DestroyModelData(model, data);
|
||||
}
|
||||
|
||||
|
||||
void RenderAllModels(RenderModifierPtr modifier, u32 filterflags, uint pass, uint streamflags);
|
||||
};
|
||||
|
||||
@ -320,19 +322,19 @@ BatchModelRenderer::~BatchModelRenderer()
|
||||
void BatchModelRenderer::Submit(CModel* model)
|
||||
{
|
||||
debug_assert(m->phase == BMRSubmit);
|
||||
|
||||
|
||||
CModelDefPtr mdef = model->GetModelDef();
|
||||
BMRModelDefTracker* mdeftracker = (BMRModelDefTracker*)mdef->GetRenderData(m);
|
||||
CModelRData* rdata = (CModelRData*)model->GetRenderData();
|
||||
BMRModelData* bmrdata = 0;
|
||||
|
||||
|
||||
// Ensure model def data and model data exist
|
||||
if (!mdeftracker)
|
||||
{
|
||||
mdeftracker = new BMRModelDefTracker(mdef);
|
||||
mdef->SetRenderData(m, mdeftracker);
|
||||
}
|
||||
|
||||
|
||||
if (rdata && rdata->GetKey() == m)
|
||||
{
|
||||
bmrdata = (BMRModelData*)rdata;
|
||||
@ -357,15 +359,15 @@ void BatchModelRenderer::Submit(CModel* model)
|
||||
// Add the bmrdata to the modeldef list
|
||||
Handle htex = model->GetTexture()->GetHandle();
|
||||
uint idx;
|
||||
|
||||
|
||||
for(idx = 0; idx < mdeftracker->m_Slots; ++idx)
|
||||
{
|
||||
BMRModelData* in = mdeftracker->m_ModelSlots[idx];
|
||||
|
||||
|
||||
if (in->GetModel()->GetTexture()->GetHandle() == htex)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (idx >= mdeftracker->m_Slots)
|
||||
{
|
||||
++mdeftracker->m_Slots;
|
||||
@ -386,7 +388,7 @@ void BatchModelRenderer::Submit(CModel* model)
|
||||
void BatchModelRenderer::PrepareModels()
|
||||
{
|
||||
debug_assert(m->phase == BMRSubmit);
|
||||
|
||||
|
||||
for(BMRModelDefTracker* mdeftracker = m->submissions; mdeftracker; mdeftracker = mdeftracker->m_Next)
|
||||
{
|
||||
for(uint idx = 0; idx < mdeftracker->m_Slots; ++idx)
|
||||
@ -394,9 +396,9 @@ void BatchModelRenderer::PrepareModels()
|
||||
for(BMRModelData* bmrdata = mdeftracker->m_ModelSlots[idx]; bmrdata; bmrdata = bmrdata->m_Next)
|
||||
{
|
||||
CModel* model = bmrdata->GetModel();
|
||||
|
||||
|
||||
debug_assert(model->GetRenderData() == bmrdata);
|
||||
|
||||
|
||||
m->vertexRenderer->UpdateModelData(
|
||||
model, bmrdata->m_Data,
|
||||
bmrdata->m_UpdateFlags);
|
||||
@ -404,7 +406,7 @@ void BatchModelRenderer::PrepareModels()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m->phase = BMRRender;
|
||||
}
|
||||
|
||||
@ -413,7 +415,7 @@ void BatchModelRenderer::PrepareModels()
|
||||
void BatchModelRenderer::EndFrame()
|
||||
{
|
||||
static uint mostslots = 1;
|
||||
|
||||
|
||||
for(BMRModelDefTracker* mdeftracker = m->submissions; mdeftracker; mdeftracker = mdeftracker->m_Next)
|
||||
{
|
||||
if (mdeftracker->m_Slots > mostslots)
|
||||
@ -424,7 +426,7 @@ void BatchModelRenderer::EndFrame()
|
||||
mdeftracker->m_Slots = 0;
|
||||
}
|
||||
m->submissions = 0;
|
||||
|
||||
|
||||
m->phase = BMRSubmit;
|
||||
}
|
||||
|
||||
@ -440,18 +442,18 @@ bool BatchModelRenderer::HaveSubmissions()
|
||||
void BatchModelRenderer::Render(RenderModifierPtr modifier, u32 flags)
|
||||
{
|
||||
debug_assert(m->phase == BMRRender);
|
||||
|
||||
|
||||
if (!HaveSubmissions())
|
||||
return;
|
||||
|
||||
|
||||
uint pass = 0;
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
uint streamflags = modifier->BeginPass(pass);
|
||||
|
||||
|
||||
m->vertexRenderer->BeginPass(streamflags);
|
||||
|
||||
|
||||
m->RenderAllModels(modifier, flags, pass, streamflags);
|
||||
|
||||
m->vertexRenderer->EndPass(streamflags);
|
||||
@ -467,7 +469,7 @@ void BatchModelRendererInternals::RenderAllModels(
|
||||
for(BMRModelDefTracker* mdeftracker = submissions; mdeftracker; mdeftracker = mdeftracker->m_Next)
|
||||
{
|
||||
vertexRenderer->PrepareModelDef(streamflags, mdeftracker->m_ModelDef.lock());
|
||||
|
||||
|
||||
for(uint idx = 0; idx < mdeftracker->m_Slots; ++idx)
|
||||
{
|
||||
BMRModelData* bmrdata = mdeftracker->m_ModelSlots[idx];
|
||||
@ -477,12 +479,12 @@ void BatchModelRendererInternals::RenderAllModels(
|
||||
for(; bmrdata; bmrdata = bmrdata->m_Next)
|
||||
{
|
||||
CModel* model = bmrdata->GetModel();
|
||||
|
||||
|
||||
debug_assert(bmrdata->GetKey() == this);
|
||||
|
||||
|
||||
if (filterflags && !(model->GetFlags()&filterflags))
|
||||
continue;
|
||||
|
||||
|
||||
modifier->PrepareModel(pass, model);
|
||||
vertexRenderer->RenderModel(streamflags, model, bmrdata->m_Data);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "boost/shared_ptr.hpp"
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/MeshManager.h"
|
||||
#include "graphics/RenderableObject.h"
|
||||
#include "renderer/VertexArray.h"
|
||||
@ -29,10 +30,10 @@ class CModel;
|
||||
|
||||
|
||||
/**
|
||||
* Class CModelRData: Render data that is maintained per CModel.
|
||||
* Class CModelRData: Render data that is maintained per CModel.
|
||||
* ModelRenderer implementations may derive from this class to store
|
||||
* per-CModel data.
|
||||
*
|
||||
*
|
||||
* The main purpose of this class over CRenderData is to track which
|
||||
* ModelRenderer the render data belongs to (via the key that is passed
|
||||
* to the constructor). When a model changes the renderer it uses
|
||||
@ -60,11 +61,11 @@ public:
|
||||
* @return The model pointer that was passed to the constructor.
|
||||
*/
|
||||
CModel* GetModel() const { return m_Model; }
|
||||
|
||||
|
||||
private:
|
||||
/// The key for model renderer identification
|
||||
const void* m_Key;
|
||||
|
||||
|
||||
/// The model this object was created for
|
||||
CModel* m_Model;
|
||||
};
|
||||
@ -72,25 +73,25 @@ private:
|
||||
|
||||
/**
|
||||
* Class ModelRenderer: Abstract base class for all model renders.
|
||||
*
|
||||
*
|
||||
* A ModelRenderer manages a per-frame list of models.
|
||||
*
|
||||
*
|
||||
* It is supposed to be derived in order to create new ways in which
|
||||
* the per-frame list of models can be managed (for batching, for
|
||||
* transparent rendering, etc.) or potentially for rarely used special
|
||||
* effects.
|
||||
*
|
||||
*
|
||||
* A typical ModelRenderer will delegate vertex transformation/setup
|
||||
* to a ModelVertexRenderer.
|
||||
* It will delegate fragment stage setup to a RenderModifier.
|
||||
*
|
||||
*
|
||||
* For most purposes, you should use a BatchModelRenderer with
|
||||
* specialized ModelVertexRenderer and RenderModifier implementations.
|
||||
*
|
||||
*
|
||||
* It is suggested that a derived class implement the provided generic
|
||||
* Render function, however in some cases it may be necessary to supply
|
||||
* a Render function with a different prototype.
|
||||
*
|
||||
*
|
||||
* ModelRenderer also contains a number of static helper functions
|
||||
* for building vertex arrays.
|
||||
*/
|
||||
@ -99,7 +100,7 @@ class ModelRenderer
|
||||
public:
|
||||
ModelRenderer() { }
|
||||
virtual ~ModelRenderer() { }
|
||||
|
||||
|
||||
/**
|
||||
* Submit: Submit a model for rendering this frame.
|
||||
*
|
||||
@ -111,7 +112,7 @@ public:
|
||||
* submitted this frame.
|
||||
*/
|
||||
virtual void Submit(CModel* model) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* PrepareModels: Calculate renderer data for all previously
|
||||
* submitted models.
|
||||
@ -120,25 +121,25 @@ public:
|
||||
* for this frame have been submitted.
|
||||
*/
|
||||
virtual void PrepareModels() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* EndFrame: Remove all models from the list of submitted
|
||||
* models.
|
||||
*/
|
||||
virtual void EndFrame() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* HaveSubmissions: Return whether any models have been submitted this frame.
|
||||
*
|
||||
* @return true if models have been submitted, false otherwise.
|
||||
*/
|
||||
virtual bool HaveSubmissions() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Render: Render submitted models, using the given RenderModifier to setup
|
||||
* the fragment stage.
|
||||
*
|
||||
* @note It is suggested that derived model renderers implement and use
|
||||
* @note It is suggested that derived model renderers implement and use
|
||||
* this Render functions. However, a highly specialized model renderer
|
||||
* may need to "disable" this function and provide its own Render function
|
||||
* with a different prototype.
|
||||
@ -152,7 +153,7 @@ public:
|
||||
* CModel::GetFlags() are rendered.
|
||||
*/
|
||||
virtual void Render(RenderModifierPtr modifier, u32 flags) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
||||
* normals into the given vertex array.
|
||||
@ -169,9 +170,9 @@ public:
|
||||
CModelDefPtr mdef,
|
||||
VertexArrayIterator<CVector3D> Position,
|
||||
VertexArrayIterator<CVector3D> Normal);
|
||||
|
||||
|
||||
/**
|
||||
* BuildPositionAndNormals: Build animated vertices and normals,
|
||||
* BuildPositionAndNormals: Build animated vertices and normals,
|
||||
* transformed into world space.
|
||||
*
|
||||
* @param model The model that is to be transformed.
|
||||
@ -187,7 +188,7 @@ public:
|
||||
CModel* model,
|
||||
VertexArrayIterator<CVector3D> Position,
|
||||
VertexArrayIterator<CVector3D> Normal);
|
||||
|
||||
|
||||
/**
|
||||
* BuildColor4ub: Build lighting colors for the given model,
|
||||
* based on previously calculated world space normals.
|
||||
@ -203,7 +204,7 @@ public:
|
||||
CModel* model,
|
||||
VertexArrayIterator<CVector3D> Normal,
|
||||
VertexArrayIterator<SColor4ub> Color);
|
||||
|
||||
|
||||
/**
|
||||
* BuildUV: Copy UV coordinates into the given vertex array.
|
||||
*
|
||||
@ -220,7 +221,7 @@ public:
|
||||
* BuildIndices: Create the indices array for the given CModelDef.
|
||||
*
|
||||
* @param mdef The model definition object.
|
||||
* @param Indices The index array, must be able to hold
|
||||
* @param Indices The index array, must be able to hold
|
||||
* mdef->GetNumFaces()*3 elements.
|
||||
*/
|
||||
static void BuildIndices(
|
||||
@ -235,14 +236,14 @@ struct BatchModelRendererInternals;
|
||||
* Class BatchModelRenderer: Model renderer that sorts submitted models
|
||||
* by CModelDef and texture for batching, and uses a ModelVertexRenderer
|
||||
* (e.g. FixedFunctionModelRenderer) to manage model vertices.
|
||||
*
|
||||
*
|
||||
* @note Deriving from this class is highly discouraged. Specialize
|
||||
* using ModelVertexRendererPtr and RenderModifier instead.
|
||||
*/
|
||||
class BatchModelRenderer : public ModelRenderer
|
||||
{
|
||||
friend struct BatchModelRendererInternals;
|
||||
|
||||
|
||||
public:
|
||||
BatchModelRenderer(ModelVertexRendererPtr vertexrender);
|
||||
virtual ~BatchModelRenderer();
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include "Pyrogenesis.h"
|
||||
#include "lib/res/graphics/ogl_tex.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "Renderer.h"
|
||||
#include "renderer/PatchRData.h"
|
||||
#include "AlphaMapCalculator.h"
|
||||
@ -31,7 +32,7 @@ const int BlendOffsets[8][2] = {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData constructor
|
||||
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_VBBase(0), m_VBBlends(0), m_Vertices(0), m_LightingColors(0)
|
||||
CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_VBBase(0), m_VBBlends(0), m_Vertices(0)
|
||||
{
|
||||
debug_assert(patch);
|
||||
Build();
|
||||
@ -39,11 +40,10 @@ CPatchRData::CPatchRData(CPatch* patch) : m_Patch(patch), m_VBBase(0), m_VBBlend
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// CPatchRData destructor
|
||||
CPatchRData::~CPatchRData()
|
||||
CPatchRData::~CPatchRData()
|
||||
{
|
||||
// delete copy of vertex data
|
||||
delete[] m_Vertices;
|
||||
delete[] m_LightingColors;
|
||||
// release vertex buffer chunks
|
||||
if (m_VBBase) g_VBMan.Release(m_VBBase);
|
||||
if (m_VBBlends) g_VBMan.Release(m_VBBlends);
|
||||
@ -104,7 +104,7 @@ void CPatchRData::BuildBlends()
|
||||
|
||||
// build list of textures of higher priority than current tile that are used by neighbouring tiles
|
||||
std::vector<STex> neighbourTextures;
|
||||
for (int m=-1;m<=1;m++) {
|
||||
for (int m=-1;m<=1;m++) {
|
||||
for (int k=-1;k<=1;k++) {
|
||||
CMiniPatch* nmp=terrain->GetTile(gx+k,gz+m);
|
||||
if (nmp && nmp->Tex1 != mp->Tex1) {
|
||||
@ -127,13 +127,13 @@ void CPatchRData::BuildBlends()
|
||||
uint count=(uint)neighbourTextures.size();
|
||||
for (uint k=0;k<count;++k) {
|
||||
|
||||
// now build the grid of blends dependent on whether the tile adjacent to the current tile
|
||||
// now build the grid of blends dependent on whether the tile adjacent to the current tile
|
||||
// uses the current neighbour texture
|
||||
BlendShape8 shape;
|
||||
for (int m=0;m<8;m++) {
|
||||
int ox=gx+BlendOffsets[m][1];
|
||||
int oz=gz+BlendOffsets[m][0];
|
||||
|
||||
|
||||
// get texture on adjacent tile
|
||||
Handle atex=GetTerrainTileTexture(terrain,ox,oz);
|
||||
// fill 0/1 into shape array
|
||||
@ -155,18 +155,18 @@ void CPatchRData::BuildBlends()
|
||||
float t=u0;
|
||||
u0=u1;
|
||||
u1=t;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (alphamapflags & BLENDMAP_FLIPV) {
|
||||
// flip v
|
||||
float t=v0;
|
||||
v0=v1;
|
||||
v1=t;
|
||||
}
|
||||
}
|
||||
|
||||
int base=0;
|
||||
if (alphamapflags & BLENDMAP_ROTATE90) {
|
||||
// rotate 1
|
||||
// rotate 1
|
||||
base=1;
|
||||
} else if (alphamapflags & BLENDMAP_ROTATE180) {
|
||||
// rotate 2
|
||||
@ -196,7 +196,7 @@ void CPatchRData::BuildBlends()
|
||||
dst.m_UVs[1]=j*0.125f;
|
||||
dst.m_AlphaUVs[0]=vtx[0].m_AlphaUVs[0];
|
||||
dst.m_AlphaUVs[1]=vtx[0].m_AlphaUVs[1];
|
||||
dst.m_Color=vtx0.m_Color;
|
||||
dst.m_LOSColor=vtx0.m_LOSColor;
|
||||
dst.m_Position=vtx0.m_Position;
|
||||
m_BlendVertices.push_back(dst);
|
||||
m_BlendVertexIndices.push_back((j*vsize)+i);
|
||||
@ -206,7 +206,7 @@ void CPatchRData::BuildBlends()
|
||||
dst.m_UVs[1]=j*0.125f;
|
||||
dst.m_AlphaUVs[0]=vtx[1].m_AlphaUVs[0];
|
||||
dst.m_AlphaUVs[1]=vtx[1].m_AlphaUVs[1];
|
||||
dst.m_Color=vtx1.m_Color;
|
||||
dst.m_LOSColor=vtx1.m_LOSColor;
|
||||
dst.m_Position=vtx1.m_Position;
|
||||
m_BlendVertices.push_back(dst);
|
||||
m_BlendVertexIndices.push_back((j*vsize)+i+1);
|
||||
@ -216,7 +216,7 @@ void CPatchRData::BuildBlends()
|
||||
dst.m_UVs[1]=(j+1)*0.125f;
|
||||
dst.m_AlphaUVs[0]=vtx[2].m_AlphaUVs[0];
|
||||
dst.m_AlphaUVs[1]=vtx[2].m_AlphaUVs[1];
|
||||
dst.m_Color=vtx2.m_Color;
|
||||
dst.m_LOSColor=vtx2.m_LOSColor;
|
||||
dst.m_Position=vtx2.m_Position;
|
||||
m_BlendVertices.push_back(dst);
|
||||
m_BlendVertexIndices.push_back(((j+1)*vsize)+i+1);
|
||||
@ -226,7 +226,7 @@ void CPatchRData::BuildBlends()
|
||||
dst.m_UVs[1]=(j+1)*0.125f;
|
||||
dst.m_AlphaUVs[0]=vtx[3].m_AlphaUVs[0];
|
||||
dst.m_AlphaUVs[1]=vtx[3].m_AlphaUVs[1];
|
||||
dst.m_Color=vtx3.m_Color;
|
||||
dst.m_LOSColor=vtx3.m_LOSColor;
|
||||
dst.m_Position=vtx3.m_Position;
|
||||
m_BlendVertices.push_back(dst);
|
||||
m_BlendVertexIndices.push_back(((j+1)*vsize)+i);
|
||||
@ -247,7 +247,7 @@ void CPatchRData::BuildBlends()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// build vertex data
|
||||
if (m_VBBlends) {
|
||||
// release existing vertex buffer chunk
|
||||
@ -257,21 +257,21 @@ void CPatchRData::BuildBlends()
|
||||
if (m_BlendVertices.size()) {
|
||||
m_VBBlends=g_VBMan.Allocate(sizeof(SBlendVertex),m_BlendVertices.size(),true);
|
||||
m_VBBlends->m_Owner->UpdateChunkVertices(m_VBBlends,&m_BlendVertices[0]);
|
||||
|
||||
|
||||
// now build outgoing splats
|
||||
m_BlendSplats.resize(splatTextures.size());
|
||||
int splatCount=0;
|
||||
|
||||
|
||||
debug_assert(m_VBBlends->m_Index < 65536);
|
||||
unsigned short base = (unsigned short)m_VBBlends->m_Index;
|
||||
std::set<Handle>::iterator iter=splatTextures.begin();
|
||||
for (;iter!=splatTextures.end();++iter) {
|
||||
Handle tex=*iter;
|
||||
|
||||
|
||||
SSplat& splat=m_BlendSplats[splatCount];
|
||||
splat.m_IndexStart=(u32)m_BlendIndices.size();
|
||||
splat.m_Texture=tex;
|
||||
|
||||
|
||||
for (uint k=0;k<(uint)splats.size();k++) {
|
||||
if (splats[k].m_Texture==tex) {
|
||||
m_BlendIndices.push_back(splats[k].m_Indices[0]+base);
|
||||
@ -314,7 +314,7 @@ void CPatchRData::BuildIndices()
|
||||
|
||||
// now build base splats from interior textures
|
||||
m_Splats.resize(textures.size());
|
||||
// build indices for base splats
|
||||
// build indices for base splats
|
||||
u32 base=(u32)m_VBBase->m_Index;
|
||||
for (uint i=0;i<(uint)m_Splats.size();i++) {
|
||||
Handle h=textures[i];
|
||||
@ -322,7 +322,7 @@ void CPatchRData::BuildIndices()
|
||||
SSplat& splat=m_Splats[i];
|
||||
splat.m_Texture=h;
|
||||
splat.m_IndexStart=(u32)m_Indices.size();
|
||||
|
||||
|
||||
for (int j=0;j<PATCH_SIZE;j++) {
|
||||
for (int i=0;i<PATCH_SIZE;i++) {
|
||||
if (texgrid[j][i]==h){
|
||||
@ -335,7 +335,7 @@ void CPatchRData::BuildIndices()
|
||||
}
|
||||
splat.m_IndexCount=(u32)m_Indices.size()-splat.m_IndexStart;
|
||||
}
|
||||
|
||||
|
||||
// build indices for the shadow map pass
|
||||
for (int j=0;j<PATCH_SIZE;j++) {
|
||||
for (int i=0;i<PATCH_SIZE;i++) {
|
||||
@ -356,19 +356,19 @@ void CPatchRData::BuildVertices()
|
||||
|
||||
// number of vertices in each direction in each patch
|
||||
int vsize=PATCH_SIZE+1;
|
||||
|
||||
|
||||
if (!m_Vertices) {
|
||||
m_Vertices=new SBaseVertex[vsize*vsize];
|
||||
m_LightingColors=new RGBColor[vsize*vsize];
|
||||
}
|
||||
SBaseVertex* vertices=m_Vertices;
|
||||
|
||||
|
||||
|
||||
|
||||
// get index of this patch
|
||||
u32 px=m_Patch->m_X;
|
||||
u32 pz=m_Patch->m_Z;
|
||||
|
||||
|
||||
CTerrain* terrain=m_Patch->m_Parent;
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
|
||||
// build vertices
|
||||
for (int j=0;j<vsize;j++) {
|
||||
@ -378,18 +378,22 @@ void CPatchRData::BuildVertices()
|
||||
int v=(j*vsize)+i;
|
||||
|
||||
// calculate vertex data
|
||||
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
|
||||
*(uint32_t*)&vertices[v].m_Color = 0; // will be set to the proper value in Update()
|
||||
terrain->CalcPosition(ix,iz,vertices[v].m_Position);
|
||||
*(uint32_t*)&vertices[v].m_LOSColor = 0; // will be set to the proper value in Update()
|
||||
vertices[v].m_UVs[0]=i*0.125f;
|
||||
vertices[v].m_UVs[1]=1 - j*0.125f;
|
||||
|
||||
// calculate lighting into the separate m_LightingColors array, which will
|
||||
// be used to set the vertex colors in Update()
|
||||
|
||||
// Calculate diffuse lighting for this vertex
|
||||
// Ambient is added by the lighting pass (since ambient is the same
|
||||
// for all vertices, it need not be stored in the vertex structure)
|
||||
terrain->CalcNormal(ix,iz,normal);
|
||||
g_Renderer.m_SHCoeffsTerrain.Evaluate(normal, m_LightingColors[v]);
|
||||
|
||||
RGBColor diffuse;
|
||||
lightEnv.EvaluateDirect(normal, diffuse);
|
||||
*(u32*)&vertices[v].m_DiffuseColor = ConvertRGBColorTo4ub(diffuse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// upload to vertex buffer
|
||||
if (!m_VBBase) {
|
||||
m_VBBase=g_VBMan.Allocate(sizeof(SBaseVertex),vsize*vsize,true);
|
||||
@ -418,7 +422,7 @@ void CPatchRData::Update()
|
||||
}
|
||||
|
||||
// Update vertex colors, which are affected by LOS
|
||||
|
||||
|
||||
u32 px=m_Patch->m_X;
|
||||
u32 pz=m_Patch->m_Z;
|
||||
|
||||
@ -436,7 +440,7 @@ void CPatchRData::Update()
|
||||
|
||||
const int DX[] = {1,1,0,0};
|
||||
const int DZ[] = {0,1,1,0};
|
||||
float losMod = 1.0f;
|
||||
SColor4ub losMod(255, 255, 255, 255);
|
||||
|
||||
for(int k=0; k<4; k++)
|
||||
{
|
||||
@ -446,17 +450,14 @@ void CPatchRData::Update()
|
||||
if(tx >= 0 && tz >= 0 && tx <= mapSize-2 && tz <= mapSize-2)
|
||||
{
|
||||
ELOSStatus s = losMgr->GetStatus(tx, tz, g_Game->GetLocalPlayer());
|
||||
if(s==LOS_EXPLORED && losMod > 0.7f)
|
||||
losMod = 0.7f;
|
||||
else if(s==LOS_UNEXPLORED && losMod > 0.0f)
|
||||
losMod = 0.0f;
|
||||
if(s==LOS_EXPLORED && losMod.R > 178)
|
||||
losMod = SColor4ub(178, 178, 178, 255);
|
||||
else if(s==LOS_UNEXPLORED && losMod.R > 0)
|
||||
losMod = SColor4ub(0, 0, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
RGBColor c = m_LightingColors[v];
|
||||
c *= losMod;
|
||||
|
||||
*(uint32_t*)&m_Vertices[v].m_Color = ConvertRGBColorTo4ub(c);
|
||||
m_Vertices[v].m_LOSColor = losMod;
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,9 +465,9 @@ void CPatchRData::Update()
|
||||
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);
|
||||
|
||||
// update blend colors by copying them from vertex colors
|
||||
for(uint i=0; i<m_BlendVertices.size(); i++)
|
||||
for(uint i=0; i<m_BlendVertices.size(); i++)
|
||||
{
|
||||
m_BlendVertices[i].m_Color = m_Vertices[m_BlendVertexIndices[i]].m_Color;
|
||||
m_BlendVertices[i].m_LOSColor = m_Vertices[m_BlendVertexIndices[i]].m_LOSColor;
|
||||
}
|
||||
|
||||
// upload blend vertices into their vertex buffer too
|
||||
@ -476,7 +477,7 @@ void CPatchRData::Update()
|
||||
}
|
||||
}
|
||||
|
||||
void CPatchRData::RenderBase()
|
||||
void CPatchRData::RenderBase(bool losColor)
|
||||
{
|
||||
debug_assert(m_UpdateFlags==0);
|
||||
|
||||
@ -485,9 +486,9 @@ void CPatchRData::RenderBase()
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBaseVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,&base->m_Position[0]);
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,&base->m_Color);
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,losColor ? &base->m_LOSColor : &base->m_DiffuseColor);
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,&base->m_UVs[0]);
|
||||
|
||||
|
||||
// render each splat
|
||||
for (uint i=0;i<(uint)m_Splats.size();i++) {
|
||||
SSplat& splat=m_Splats[i];
|
||||
@ -499,7 +500,7 @@ void CPatchRData::RenderBase()
|
||||
}
|
||||
}
|
||||
|
||||
void CPatchRData::RenderStreams(u32 streamflags)
|
||||
void CPatchRData::RenderStreams(u32 streamflags, bool losColor)
|
||||
{
|
||||
debug_assert(m_UpdateFlags==0);
|
||||
|
||||
@ -513,7 +514,11 @@ void CPatchRData::RenderStreams(u32 streamflags)
|
||||
} else if (streamflags & STREAM_POSTOUV0) {
|
||||
glTexCoordPointer(3, GL_FLOAT, stride, &base->m_Position);
|
||||
}
|
||||
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,losColor ? &base->m_LOSColor : &base->m_DiffuseColor);
|
||||
}
|
||||
|
||||
// render all base splats at once
|
||||
glDrawElements(GL_QUADS,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]);
|
||||
|
||||
@ -534,8 +539,8 @@ void CPatchRData::RenderBlends()
|
||||
// setup data pointers
|
||||
u32 stride=sizeof(SBlendVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_Position));
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_Color));
|
||||
|
||||
glColorPointer(4,GL_UNSIGNED_BYTE,stride,base+offsetof(SBlendVertex,m_LOSColor));
|
||||
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SBlendVertex,m_UVs[0]));
|
||||
|
||||
|
@ -19,14 +19,14 @@ public:
|
||||
~CPatchRData();
|
||||
|
||||
void Update();
|
||||
void RenderBase();
|
||||
void RenderBase(bool losColor);
|
||||
void RenderBlends();
|
||||
void RenderOutline();
|
||||
void RenderStreams(u32 streamflags);
|
||||
void RenderStreams(u32 streamflags, bool losColor);
|
||||
|
||||
private:
|
||||
struct SSplat {
|
||||
SSplat() : m_Texture(0), m_IndexCount(0) {}
|
||||
SSplat() : m_Texture(0), m_IndexCount(0) {}
|
||||
|
||||
// handle of texture to apply during splat
|
||||
Handle m_Texture;
|
||||
@ -39,22 +39,24 @@ private:
|
||||
struct SBaseVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex color
|
||||
SColor4ub m_Color;
|
||||
// diffuse color from sunlight
|
||||
SColor4ub m_DiffuseColor;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
};
|
||||
// color modulation from LOS
|
||||
SColor4ub m_LOSColor;
|
||||
};
|
||||
|
||||
struct SBlendVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex color
|
||||
SColor4ub m_Color;
|
||||
// color modulation from LOS
|
||||
SColor4ub m_LOSColor;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
// vertex uvs for alpha texture
|
||||
float m_AlphaUVs[2];
|
||||
};
|
||||
};
|
||||
|
||||
struct STex {
|
||||
bool operator==(const STex& rhs) const { return m_Handle==rhs.m_Handle; }
|
||||
@ -62,7 +64,7 @@ private:
|
||||
Handle m_Handle;
|
||||
int m_Priority;
|
||||
};
|
||||
|
||||
|
||||
// build this renderdata object
|
||||
void Build();
|
||||
|
||||
@ -82,11 +84,6 @@ private:
|
||||
// patch render vertices
|
||||
SBaseVertex* m_Vertices;
|
||||
|
||||
// precomputed lighting colors at each vertex; these are the multiplied by a LOS modifier
|
||||
// (black for shroud of darkness, half-darkened for fog of war), to compute the colors in
|
||||
// m_Vertices, which are passed to the graphics card
|
||||
RGBColor* m_LightingColors;
|
||||
|
||||
// indices into base vertices for the base splats
|
||||
std::vector<unsigned short> m_Indices;
|
||||
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
* are required by the fragment stages (see STREAM_XYZ constants).
|
||||
*/
|
||||
virtual u32 BeginPass(uint pass) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* EndPass: Cleanup OpenGL state after the given pass. This function
|
||||
* may indicate that additional passes are needed.
|
||||
@ -58,7 +58,7 @@ public:
|
||||
* increased pass number.
|
||||
*/
|
||||
virtual bool EndPass(uint pass) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* PrepareTexture: Called before rendering models that use the given
|
||||
* texture.
|
||||
@ -69,10 +69,10 @@ public:
|
||||
* @param texture The texture used by subsequent models
|
||||
*/
|
||||
virtual void PrepareTexture(uint pass, CTexture* texture) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* PrepareModel: Called before rendering the given model.
|
||||
*
|
||||
*
|
||||
* Default behaviour does nothing.
|
||||
*
|
||||
* @param pass The current pass number (pass == 0 is the first pass)
|
||||
@ -91,7 +91,6 @@ class RenderModifierRenderer : public ModelRenderer
|
||||
public:
|
||||
RenderModifierRenderer() { }
|
||||
virtual ~RenderModifierRenderer();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -12,10 +12,14 @@
|
||||
RenderPathVertexShader::RenderPathVertexShader()
|
||||
{
|
||||
m_ModelLight = 0;
|
||||
m_ModelLight_SHCoefficients = -1;
|
||||
m_ModelLight_Ambient = -1;
|
||||
m_ModelLight_SunDir = -1;
|
||||
m_ModelLight_SunColor = -1;
|
||||
|
||||
m_InstancingLight = 0;
|
||||
m_InstancingLight_SHCoefficients = -1;
|
||||
m_InstancingLight_Ambient = -1;
|
||||
m_InstancingLight_SunDir = -1;
|
||||
m_InstancingLight_SunColor = -1;
|
||||
m_InstancingLight_Instancing1 = -1;
|
||||
m_InstancingLight_Instancing2 = -1;
|
||||
m_InstancingLight_Instancing3 = -1;
|
||||
@ -50,21 +54,21 @@ bool RenderPathVertexShader::Init()
|
||||
LOG(WARNING, LOG_CATEGORY, "Failed to load shaders/model_light.xml: %i\n", (int)m_ModelLight);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_InstancingLight = ogl_program_load("shaders/instancing_light.xml");
|
||||
if (m_InstancingLight < 0)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Failed to load shaders/instancing_light.xml: %i\n", (int)m_InstancingLight);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
m_Instancing = ogl_program_load("shaders/instancing.xml");
|
||||
if (m_Instancing < 0)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Failed to load shaders/instancing.xml: %i\n", (int)m_Instancing);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -73,10 +77,16 @@ bool RenderPathVertexShader::Init()
|
||||
// the uniform locations might have changed under us.
|
||||
void RenderPathVertexShader::BeginFrame()
|
||||
{
|
||||
m_ModelLight_SHCoefficients = ogl_program_get_uniform_location(m_ModelLight, "SHCoefficients");
|
||||
|
||||
m_InstancingLight_SHCoefficients = ogl_program_get_uniform_location(
|
||||
m_InstancingLight, "SHCoefficients");
|
||||
m_ModelLight_Ambient = ogl_program_get_uniform_location(m_ModelLight, "ambient");
|
||||
m_ModelLight_SunDir = ogl_program_get_uniform_location(m_ModelLight, "sunDir");
|
||||
m_ModelLight_SunColor = ogl_program_get_uniform_location(m_ModelLight, "sunColor");
|
||||
|
||||
m_InstancingLight_Ambient = ogl_program_get_uniform_location(
|
||||
m_InstancingLight, "ambient");
|
||||
m_InstancingLight_SunDir = ogl_program_get_uniform_location(
|
||||
m_InstancingLight, "sunDir");
|
||||
m_InstancingLight_SunColor = ogl_program_get_uniform_location(
|
||||
m_InstancingLight, "sunColor");
|
||||
m_InstancingLight_Instancing1 = ogl_program_get_attrib_location(
|
||||
m_InstancingLight, "Instancing1");
|
||||
m_InstancingLight_Instancing2 = ogl_program_get_attrib_location(
|
||||
|
@ -6,7 +6,7 @@ class RenderPathVertexShader
|
||||
public:
|
||||
RenderPathVertexShader();
|
||||
~RenderPathVertexShader();
|
||||
|
||||
|
||||
// Initialize this render path.
|
||||
bool Init();
|
||||
|
||||
@ -15,10 +15,14 @@ public:
|
||||
|
||||
public:
|
||||
Handle m_ModelLight;
|
||||
GLint m_ModelLight_SHCoefficients;
|
||||
|
||||
GLint m_ModelLight_Ambient;
|
||||
GLint m_ModelLight_SunDir;
|
||||
GLint m_ModelLight_SunColor;
|
||||
|
||||
Handle m_InstancingLight;
|
||||
GLint m_InstancingLight_SHCoefficients;
|
||||
GLint m_InstancingLight_Ambient;
|
||||
GLint m_InstancingLight_SunDir;
|
||||
GLint m_InstancingLight_SunColor;
|
||||
GLint m_InstancingLight_Instancing1; // matrix rows
|
||||
GLint m_InstancingLight_Instancing2;
|
||||
GLint m_InstancingLight_Instancing3;
|
||||
|
@ -304,6 +304,8 @@ CRenderer::CRenderer()
|
||||
m_Models.ModTransparentShadow = RenderModifierPtr(new TransparentShadowRenderModifier);
|
||||
m_Models.ModTransparentDepthShadow = RenderModifierPtr(new TransparentDepthShadowModifier);
|
||||
|
||||
m_ShadowZBias = 0.001;
|
||||
|
||||
CEmitter *pEmitter = new CDefaultEmitter(1000, -1);
|
||||
CParticleEngine::GetInstance()->addEmitter(pEmitter);
|
||||
|
||||
@ -584,18 +586,6 @@ void CRenderer::BeginFrame()
|
||||
// zero out all the per-frame stats
|
||||
m_Stats.Reset();
|
||||
|
||||
// calculate coefficients for terrain and unit lighting
|
||||
m_SHCoeffsUnits.Clear();
|
||||
m_SHCoeffsTerrain.Clear();
|
||||
|
||||
if (m_LightEnv) {
|
||||
m_SHCoeffsUnits.AddDirectionalLight(m_LightEnv->m_SunDir, m_LightEnv->m_SunColor);
|
||||
m_SHCoeffsTerrain.AddDirectionalLight(m_LightEnv->m_SunDir, m_LightEnv->m_SunColor);
|
||||
|
||||
m_SHCoeffsUnits.AddAmbientLight(m_LightEnv->m_UnitsAmbientColor);
|
||||
m_SHCoeffsTerrain.AddAmbientLight(m_LightEnv->m_TerrainAmbientColor);
|
||||
}
|
||||
|
||||
// init per frame stuff
|
||||
m->shadow->SetupFrame(m_CullCamera, m_LightEnv->m_SunDir);
|
||||
}
|
||||
@ -618,6 +608,22 @@ void CRenderer::RenderShadowMap()
|
||||
|
||||
glColor4fv(m_Options.m_ShadowColor);
|
||||
|
||||
// Figure out transparent rendering strategy
|
||||
RenderModifierPtr transparentShadows = m_Models.ModTransparentShadow;
|
||||
|
||||
if (m->shadow->GetUseDepthTexture())
|
||||
transparentShadows = m_Models.ModTransparentDepthShadow;
|
||||
|
||||
// Render all closed models (i.e. models where rendering back faces will produce
|
||||
// the correct result)
|
||||
glCullFace(GL_FRONT);
|
||||
|
||||
if (m->shadow->GetUseDepthTexture())
|
||||
m->terrainRenderer->RenderPatches();
|
||||
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
// Render models that aren't closed
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_Models.NormalFF->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
@ -631,10 +637,6 @@ void CRenderer::RenderShadowMap()
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->Render(m_Models.ModSolidColor, 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)
|
||||
@ -660,7 +662,7 @@ void CRenderer::RenderPatches()
|
||||
|
||||
// render all the patches, including blend pass
|
||||
MICROLOG(L"render patch submissions");
|
||||
m->terrainRenderer->RenderTerrain(m_Options.m_Shadows ? m->shadow : 0, m_Options.m_ShadowColor);
|
||||
m->terrainRenderer->RenderTerrain(m_Options.m_Shadows ? m->shadow : 0);
|
||||
|
||||
if (m_TerrainRenderMode==WIREFRAME) {
|
||||
// switch wireframe off again
|
||||
@ -1290,6 +1292,7 @@ void CRenderer::ScriptingInit()
|
||||
AddProperty(L"sortAllTransparent", &CRenderer::m_SortAllTransparent);
|
||||
AddProperty(L"fastNormals", &CRenderer::m_FastNormals);
|
||||
AddProperty(L"displayFrustum", &CRenderer::m_DisplayFrustum);
|
||||
AddProperty(L"shadowZBias", &CRenderer::m_ShadowZBias);
|
||||
|
||||
CJSObject<CRenderer>::ScriptingInit("Renderer");
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "ogl.h"
|
||||
#include "Camera.h"
|
||||
#include "Frustum.h"
|
||||
#include "SHCoeffs.h"
|
||||
#include "Terrain.h"
|
||||
#include "Singleton.h"
|
||||
#include "Overlay.h"
|
||||
@ -368,10 +367,6 @@ protected:
|
||||
std::vector<COverlay*> m_Overlays;
|
||||
// current lighting setup
|
||||
CLightEnv* m_LightEnv;
|
||||
// current spherical harmonic coefficients (for unit lighting), derived from lightenv
|
||||
CSHCoeffs m_SHCoeffsUnits;
|
||||
// current spherical harmonic coefficients (for terrain lighting), derived from lightenv
|
||||
CSHCoeffs m_SHCoeffsTerrain;
|
||||
// ogl_tex handle of composite alpha map (all the alpha maps packed into one texture)
|
||||
Handle m_hCompositeAlphaMap;
|
||||
// coordinates of each (untransformed) alpha map within the packed texture
|
||||
@ -450,6 +445,16 @@ protected:
|
||||
RenderModifierPtr ModTransparentShadow;
|
||||
RenderModifierPtr ModTransparentDepthShadow;
|
||||
} m_Models;
|
||||
|
||||
public:
|
||||
/**
|
||||
* m_ShadowZBias: Z bias used when rendering shadows into a depth texture.
|
||||
* This can be used to control shadowing artifacts.
|
||||
*
|
||||
* Can be accessed via JS as renderer.shadowZBias
|
||||
* ShadowMap uses this for matrix calculation.
|
||||
*/
|
||||
float m_ShadowZBias;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,85 +0,0 @@
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
// Name: SHCoeffs.h
|
||||
// Last Update: 25/11/03
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@0ad.wildfiregames.com
|
||||
//
|
||||
// Description: implementation of 9 component spherical harmonic
|
||||
// lighting
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "SHCoeffs.h"
|
||||
#include "MathUtil.h"
|
||||
|
||||
CSHCoeffs::CSHCoeffs()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CSHCoeffs::Clear()
|
||||
{
|
||||
for (int i=0;i<9;i++) {
|
||||
_data[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CSHCoeffs::AddAmbientLight(const RGBColor& color)
|
||||
{
|
||||
_data[0]+=color;
|
||||
}
|
||||
|
||||
void CSHCoeffs::AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor)
|
||||
{
|
||||
CVector3D dirToLight(-lightDir.X,-lightDir.Y,-lightDir.Z);
|
||||
|
||||
const float normalisation = PI*16/17;
|
||||
const float c1 = SQR(0.282095f) * normalisation * 1.0f;
|
||||
const float c2 = SQR(0.488603f) * normalisation * (2.0f/3.0f);
|
||||
const float c3 = SQR(1.092548f) * normalisation * (1.0f/4.0f);
|
||||
const float c4 = SQR(0.315392f) * normalisation * (1.0f/4.0f);
|
||||
const float c5 = SQR(0.546274f) * normalisation * (1.0f/4.0f);
|
||||
|
||||
_data[0]+=lightColor*c1;
|
||||
_data[1]+=lightColor*c2*dirToLight.X;
|
||||
_data[2]+=lightColor*c2*dirToLight.Y;
|
||||
_data[3]+=lightColor*c2*dirToLight.Z;
|
||||
_data[4]+=lightColor*c3*dirToLight.X*dirToLight.Z;
|
||||
_data[5]+=lightColor*c3*dirToLight.Z*dirToLight.Y;
|
||||
_data[6]+=lightColor*c3*dirToLight.Y*dirToLight.X;
|
||||
_data[7]+=lightColor*c4*(3.0f*SQR(dirToLight.Z)-1.0f);
|
||||
_data[8]+=lightColor*c5*(SQR(dirToLight.X)-SQR(dirToLight.Y));
|
||||
}
|
||||
|
||||
void CSHCoeffs::Evaluate(const CVector3D& normal,RGBColor& color,RGBColor mod) const
|
||||
{
|
||||
#if 1
|
||||
float c4=normal.X*normal.Z;
|
||||
float c5=normal.Z*normal.Y;
|
||||
float c6=normal.Y*normal.X;
|
||||
float c7=(3*SQR(normal.Z)-1.0f);
|
||||
float c8=(SQR(normal.X)-SQR(normal.Y));
|
||||
|
||||
#define DO(C) \
|
||||
color.C = mod.C * (\
|
||||
_data[0].C \
|
||||
+ _data[1].C*normal.X \
|
||||
+ _data[2].C*normal.Y \
|
||||
+ _data[3].C*normal.Z \
|
||||
+ _data[4].C*c4 \
|
||||
+ _data[5].C*c5 \
|
||||
+ _data[6].C*c6 \
|
||||
+ _data[7].C*c7 \
|
||||
+ _data[8].C*c8)
|
||||
DO(X);
|
||||
DO(Y);
|
||||
DO(Z);
|
||||
#undef DO
|
||||
|
||||
#else
|
||||
// debug aid: output quantised normal
|
||||
color=RGBColor((normal.X+1)*0.5,(normal.Y+1)*0.5,(normal.Z+1)*0.5);
|
||||
#endif
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//----------------------------------------------------------------
|
||||
//
|
||||
// Name: SHCoeffs.h
|
||||
// Last Update: 25/11/03
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@0ad.wildfiregames.com
|
||||
//
|
||||
// Description: implementation of 9 component spherical harmonic
|
||||
// lighting
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#ifndef __SHCOEFFS_H
|
||||
#define __SHCOEFFS_H
|
||||
|
||||
#include "Color.h"
|
||||
|
||||
class CSHCoeffs
|
||||
{
|
||||
public:
|
||||
CSHCoeffs();
|
||||
|
||||
void Clear();
|
||||
|
||||
void AddAmbientLight(const RGBColor& color);
|
||||
void AddDirectionalLight(const CVector3D& lightDir,const RGBColor& lightColor);
|
||||
|
||||
void Evaluate(const CVector3D& normal, RGBColor& color, RGBColor mod=RGBColor(1,1,1)) const;
|
||||
|
||||
const RGBColor* GetCoefficients() const { return _data; }
|
||||
|
||||
private:
|
||||
RGBColor _data[9];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -174,26 +174,31 @@ void ShadowMapInternals::CalcShadowMatrices()
|
||||
LightProjection._22 = scale.Y;
|
||||
LightProjection._24 = shift.Y * scale.Y;
|
||||
LightProjection._33 = scale.Z;
|
||||
LightProjection._34 = shift.Z * scale.Z;
|
||||
LightProjection._34 = shift.Z * scale.Z + renderer.m_ShadowZBias;
|
||||
LightProjection._44 = 1.0;
|
||||
|
||||
|
||||
// Calculate texture matrix by creating the clip space to texture coordinate matrix
|
||||
// and then concatenating all matrices that have been calculated so far
|
||||
CMatrix3D clipToTex;
|
||||
float texscalex = 0.5 * (float)renderer.GetWidth() / (float)Width;
|
||||
float texscaley = 0.5 * (float)renderer.GetHeight() / (float)Height;
|
||||
CMatrix3D lightToTex;
|
||||
float texscalex = (float)renderer.GetWidth() / (float)Width;
|
||||
float texscaley = (float)renderer.GetHeight() / (float)Height;
|
||||
float texscalez = 1.0;
|
||||
|
||||
clipToTex.SetZero();
|
||||
clipToTex._11 = texscalex;
|
||||
clipToTex._14 = texscalex;
|
||||
clipToTex._22 = texscaley;
|
||||
clipToTex._24 = texscaley;
|
||||
clipToTex._33 = 0.5; // translate -1..1 clip space Z values to tex Z values
|
||||
clipToTex._34 = 0.5;
|
||||
clipToTex._44 = 1.0;
|
||||
texscalex = texscalex / (ShadowBound[1].X - ShadowBound[0].X);
|
||||
texscaley = texscaley / (ShadowBound[1].Y - ShadowBound[0].Y);
|
||||
texscalez = texscalez / (ShadowBound[1].Z - ShadowBound[0].Z);
|
||||
|
||||
TextureMatrix = clipToTex * LightProjection * LightTransform;
|
||||
lightToTex.SetZero();
|
||||
lightToTex._11 = texscalex;
|
||||
lightToTex._14 = -ShadowBound[0].X * texscalex;
|
||||
lightToTex._22 = texscaley;
|
||||
lightToTex._24 = -ShadowBound[0].Y * texscaley;
|
||||
lightToTex._33 = texscalez;
|
||||
lightToTex._34 = -ShadowBound[0].Z * texscalez;
|
||||
lightToTex._44 = 1.0;
|
||||
|
||||
TextureMatrix = lightToTex * LightTransform;
|
||||
}
|
||||
|
||||
|
||||
@ -224,7 +229,7 @@ void ShadowMapInternals::CreateTexture()
|
||||
{
|
||||
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,
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, Width, Height, 0,
|
||||
GL_DEPTH_COMPONENT, GL_FLOAT, buf);
|
||||
delete[] buf;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "graphics/Camera.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Patch.h"
|
||||
#include "graphics/Terrain.h"
|
||||
|
||||
@ -57,9 +58,6 @@ struct TerrainRendererInternals
|
||||
* @todo Merge this list with CPatchRData list
|
||||
*/
|
||||
std::vector<CPatch*> visiblePatches;
|
||||
|
||||
// Helper functions
|
||||
void ApplyShadowMap(ShadowMap* shadow, const RGBAColor& shadowColor);
|
||||
};
|
||||
|
||||
|
||||
@ -128,7 +126,7 @@ bool TerrainRenderer::HaveSubmissions()
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Full-featured terrain rendering with blending and everything
|
||||
void TerrainRenderer::RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowColor)
|
||||
void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
|
||||
{
|
||||
debug_assert(m->phase == Phase_Render);
|
||||
|
||||
@ -137,7 +135,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowCo
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// render everything
|
||||
// render everything fullbright
|
||||
// set up texture environment for base pass
|
||||
MICROLOG(L"base splat textures");
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
@ -159,7 +157,7 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowCo
|
||||
for(uint i = 0; i < m->visiblePatches.size(); ++i)
|
||||
{
|
||||
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
|
||||
patchdata->RenderBase();
|
||||
patchdata->RenderBase(true); // with LOS color
|
||||
}
|
||||
|
||||
// render blends
|
||||
@ -194,27 +192,87 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowCo
|
||||
patchdata->RenderBlends();
|
||||
}
|
||||
|
||||
// restore OpenGL state
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// Disable second texcoord array
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// Now apply lighting
|
||||
// Light color is Ambient + ShadowTerm * Diffuse
|
||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0); // Diffuse * Shadow
|
||||
if (shadow)
|
||||
glBindTexture(GL_TEXTURE_2D, shadow->GetTexture());
|
||||
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_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_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE1); // + Ambient
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
|
||||
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_SOURCE1_RGB_ARB, GL_CONSTANT);
|
||||
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_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &lightEnv.m_TerrainAmbientColor.X);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
const CMatrix3D& texturematrix = shadow->GetTextureMatrix();
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(&texturematrix._11);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
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_LEQUAL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
for (uint i = 0; i < m->visiblePatches.size(); ++i)
|
||||
{
|
||||
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
|
||||
patchdata->RenderStreams(STREAM_POS|STREAM_COLOR|STREAM_POSTOUV0, false);
|
||||
}
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
// restore OpenGL state
|
||||
g_Renderer.BindTexture(1,0);
|
||||
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
// switch off all client states
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
// Now render shadows as a second pass
|
||||
if (shadow)
|
||||
{
|
||||
m->ApplyShadowMap(shadow, shadowColor);
|
||||
}
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
@ -228,7 +286,7 @@ void TerrainRenderer::RenderPatches()
|
||||
for(uint i = 0; i < m->visiblePatches.size(); ++i)
|
||||
{
|
||||
CPatchRData* patchdata = (CPatchRData*)m->visiblePatches[i]->GetRenderData();
|
||||
patchdata->RenderStreams(STREAM_POS);
|
||||
patchdata->RenderStreams(STREAM_POS, true);
|
||||
}
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
@ -376,73 +434,3 @@ void TerrainRenderer::RenderWater()
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// ApplyShadowMap: add luminance map shadows after rendering the
|
||||
// actual terrain
|
||||
void TerrainRendererInternals::ApplyShadowMap(ShadowMap* shadow, const RGBAColor& shadowColor)
|
||||
{
|
||||
debug_assert(phase == Phase_Render);
|
||||
|
||||
const CMatrix3D& texturematrix = shadow->GetTextureMatrix();
|
||||
GLuint shadowmap = shadow->GetTexture();
|
||||
|
||||
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);
|
||||
glDepthMask(0);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
for (uint i = 0; i < visiblePatches.size(); ++i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
* @param shadow a prepared shadow map, in case rendering with shadows is enabled
|
||||
* @param shadowColor color of shadows
|
||||
*/
|
||||
void RenderTerrain(ShadowMap* shadow, const RGBAColor& shadowColor);
|
||||
void RenderTerrain(ShadowMap* shadow);
|
||||
|
||||
/**
|
||||
* RenderPatches: Render all patches un-textured as polygons.
|
||||
|
Loading…
Reference in New Issue
Block a user