forked from 0ad/0ad
Moved from terrain; contains a whole load of changes related to shadows, props and animation.
This was SVN commit r302.
This commit is contained in:
parent
5b45b032e5
commit
6f20408595
261
source/renderer/ModelRData.cpp
Executable file
261
source/renderer/ModelRData.cpp
Executable file
@ -0,0 +1,261 @@
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include "res/tex.h"
|
||||
#include "Renderer.h"
|
||||
#include "TransparencyRenderer.h"
|
||||
#include "ModelRData.h"
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
CModelRData::CModelRData(CModel* model)
|
||||
: m_Model(model), m_Vertices(0), m_Normals(0), m_Indices(0), m_VB(0), m_Flags(0)
|
||||
{
|
||||
assert(model);
|
||||
// build all data now
|
||||
Build();
|
||||
}
|
||||
|
||||
CModelRData::~CModelRData()
|
||||
{
|
||||
delete[] m_Indices;
|
||||
delete[] m_Vertices;
|
||||
delete[] m_Normals;
|
||||
if (m_VB) {
|
||||
glGenBuffersARB(1,(GLuint*) &m_VB);
|
||||
}
|
||||
}
|
||||
|
||||
void CModelRData::Build()
|
||||
{
|
||||
// build data
|
||||
BuildVertices();
|
||||
BuildIndices();
|
||||
// force a texture load on models texture
|
||||
g_Renderer.LoadTexture(m_Model->GetTexture(),GL_CLAMP_TO_EDGE);
|
||||
// setup model render flags
|
||||
if (g_Renderer.IsTextureTransparent(m_Model->GetTexture())) {
|
||||
m_Flags|=MODELRDATA_FLAG_TRANSPARENT;
|
||||
}
|
||||
}
|
||||
|
||||
void CModelRData::BuildIndices()
|
||||
{
|
||||
CModelDef* mdef=m_Model->GetModelDef();
|
||||
|
||||
// allocate indices if we haven't got any already
|
||||
if (!m_Indices) {
|
||||
m_Indices=new u16[mdef->GetNumFaces()*3];
|
||||
}
|
||||
|
||||
// build indices
|
||||
u32 indices=0;
|
||||
SModelFace* faces=mdef->GetFaces();
|
||||
for (int j=0; j<mdef->GetNumFaces(); j++) {
|
||||
SModelFace& face=faces[j];
|
||||
m_Indices[indices++]=face.m_Verts[0];
|
||||
m_Indices[indices++]=face.m_Verts[1];
|
||||
m_Indices[indices++]=face.m_Verts[2];
|
||||
}
|
||||
}
|
||||
|
||||
inline int clamp(int x,int min,int max)
|
||||
{
|
||||
if (x<min) return min;
|
||||
else if (x>max) return max;
|
||||
else return x;
|
||||
}
|
||||
|
||||
static SColor4ub ConvertColor(const RGBColor& src)
|
||||
{
|
||||
SColor4ub result;
|
||||
result.R=clamp(int(src.X*255),0,255);
|
||||
result.G=clamp(int(src.Y*255),0,255);
|
||||
result.B=clamp(int(src.Z*255),0,255);
|
||||
result.A=0xff;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CVector3D SkinPoint(const SModelVertex& vertex,const CMatrix3D* matrices)
|
||||
{
|
||||
CVector3D result(0,0,0),tmp;
|
||||
|
||||
for (u32 i=0;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
||||
const CMatrix3D& m=matrices[vertex.m_Blend.m_Bone[i]];
|
||||
m.Transform(vertex.m_Coords,tmp);
|
||||
result+=tmp*vertex.m_Blend.m_Weight[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static CVector3D SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices)
|
||||
{
|
||||
CVector3D result(0,0,0),tmp;
|
||||
|
||||
for (u32 i=0;vertex.m_Blend.m_Bone[i]!=0xff && i<SVertexBlend::SIZE;i++) {
|
||||
const CMatrix3D& m=invmatrices[vertex.m_Blend.m_Bone[i]];
|
||||
m.RotateTransposed(vertex.m_Norm,tmp);
|
||||
result+=tmp*vertex.m_Blend.m_Weight[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CModelRData::BuildVertices()
|
||||
{
|
||||
CModelDef* mdef=m_Model->GetModelDef();
|
||||
|
||||
// allocate vertices if we haven't got any already
|
||||
if (!m_Vertices) {
|
||||
m_Vertices=new SVertex[mdef->GetNumVertices()];
|
||||
m_Normals=new CVector3D[mdef->GetNumVertices()];
|
||||
}
|
||||
|
||||
// build vertices
|
||||
u32 numVertices=mdef->GetNumVertices();
|
||||
SModelVertex* vertices=mdef->GetVertices();
|
||||
if (m_Model->GetBoneMatrices()) {
|
||||
// boned model - calculate skinned vertex positions/normals
|
||||
for (uint j=0; j<numVertices; j++) {
|
||||
m_Vertices[j].m_Position=SkinPoint(vertices[j],m_Model->GetBoneMatrices());
|
||||
m_Normals[j]=SkinNormal(vertices[j],m_Model->GetInvBoneMatrices());
|
||||
}
|
||||
} else {
|
||||
// just copy regular positions, transform normals to world space
|
||||
const CMatrix3D& trans=m_Model->GetInvTransform();
|
||||
for (uint j=0; j<numVertices; j++) {
|
||||
m_Vertices[j].m_Position=vertices[j].m_Coords;
|
||||
m_Normals[j]=trans.RotateTransposed(vertices[j].m_Norm);
|
||||
}
|
||||
}
|
||||
|
||||
// now fill in UV and vertex colour data
|
||||
for (uint j=0; j<numVertices; j++) {
|
||||
m_Vertices[j].m_UVs[0]=vertices[j].m_U;
|
||||
m_Vertices[j].m_UVs[1]=1-vertices[j].m_V;
|
||||
g_Renderer.m_SHCoeffsUnits.Evaluate(m_Normals[j],m_Vertices[j].m_Color);
|
||||
}
|
||||
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
if (!m_VB) {
|
||||
glGenBuffersARB(1,(GLuint*) &m_VB);
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB);
|
||||
glBufferDataARB(GL_ARRAY_BUFFER_ARB,mdef->GetNumVertices()*sizeof(SVertex),0,mdef->GetNumBones() ? GL_DYNAMIC_DRAW_ARB : GL_STATIC_DRAW_ARB);
|
||||
}
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB);
|
||||
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB,0,mdef->GetNumVertices()*sizeof(SVertex),m_Vertices);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CModelRData::RenderStreams(u32 streamflags,bool transparentPass)
|
||||
{
|
||||
// ignore transparent passes if this is a transparent object
|
||||
if (!transparentPass && (m_Flags & MODELRDATA_FLAG_TRANSPARENT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CModelDef* mdldef=(CModelDef*) m_Model->GetModelDef();
|
||||
|
||||
if (streamflags & STREAM_UV0) g_Renderer.SetTexture(0,m_Model->GetTexture());
|
||||
|
||||
u8* base;
|
||||
if (g_Renderer.m_Caps.m_VBO) {
|
||||
glBindBufferARB(GL_ARRAY_BUFFER_ARB,m_VB);
|
||||
base=0;
|
||||
} else {
|
||||
base=(u8*) &m_Vertices[0];
|
||||
}
|
||||
|
||||
// set vertex pointers
|
||||
u32 stride=sizeof(SVertex);
|
||||
glVertexPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Position));
|
||||
if (streamflags & STREAM_COLOR) glColorPointer(3,GL_FLOAT,stride,base+offsetof(SVertex,m_Color));
|
||||
if (streamflags & STREAM_UV0) glTexCoordPointer(2,GL_FLOAT,stride,base+offsetof(SVertex,m_UVs));
|
||||
|
||||
// render the lot
|
||||
u32 numFaces=mdldef->GetNumFaces();
|
||||
// glDrawRangeElements(GL_TRIANGLES,0,mdldef->GetNumVertices(),numFaces*3,GL_UNSIGNED_SHORT,m_Indices);
|
||||
glDrawElements(GL_TRIANGLES,numFaces*3,GL_UNSIGNED_SHORT,m_Indices);
|
||||
|
||||
// bump stats
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
if (transparentPass) {
|
||||
g_Renderer.m_Stats.m_TransparentTris+=numFaces;
|
||||
} else {
|
||||
g_Renderer.m_Stats.m_ModelTris+=numFaces;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CModelRData::Update()
|
||||
{
|
||||
if (m_UpdateFlags!=0) {
|
||||
// renderdata changed : rebuild necessary portions
|
||||
if (m_UpdateFlags & RENDERDATA_UPDATE_VERTICES) {
|
||||
BuildVertices();
|
||||
}
|
||||
if (m_UpdateFlags & RENDERDATA_UPDATE_INDICES) {
|
||||
BuildIndices();
|
||||
}
|
||||
|
||||
m_UpdateFlags=0;
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::pair<int,float> IntFloatPair;
|
||||
static std::vector<IntFloatPair> IndexSorter;
|
||||
|
||||
struct SortFacesByDist {
|
||||
bool operator()(const IntFloatPair& lhs,const IntFloatPair& rhs) {
|
||||
return lhs.second>rhs.second ? true : false;
|
||||
}
|
||||
};
|
||||
|
||||
float CModelRData::BackToFrontIndexSort(CMatrix3D& objToCam)
|
||||
{
|
||||
float mindist=1.0e30f;
|
||||
CVector3D osvtx,csvtx;
|
||||
|
||||
CModelDef* mdldef=(CModelDef*) m_Model->GetModelDef();
|
||||
|
||||
SModelVertex* vtxs=mdldef->GetVertices();
|
||||
|
||||
u32 numFaces=mdldef->GetNumFaces();
|
||||
SModelFace* faces=mdldef->GetFaces();
|
||||
|
||||
IndexSorter.reserve(numFaces);
|
||||
|
||||
SModelFace* facePtr=faces;
|
||||
u32 i;
|
||||
for (i=0;i<numFaces;i++)
|
||||
{
|
||||
osvtx=vtxs[facePtr->m_Verts[0]].m_Coords;
|
||||
osvtx+=vtxs[facePtr->m_Verts[1]].m_Coords;
|
||||
osvtx+=vtxs[facePtr->m_Verts[2]].m_Coords;
|
||||
osvtx*=1.0f/3.0f;
|
||||
|
||||
csvtx=objToCam.Transform(osvtx);
|
||||
float distsqrd=SQR(csvtx.X)+SQR(csvtx.Y)+SQR(csvtx.Z);
|
||||
if (distsqrd<mindist) mindist=distsqrd;
|
||||
|
||||
IndexSorter.push_back(IntFloatPair(i,distsqrd));
|
||||
facePtr++;
|
||||
}
|
||||
|
||||
std::sort(IndexSorter.begin(),IndexSorter.end(),SortFacesByDist());
|
||||
|
||||
// now build index list
|
||||
u32 indices=0;
|
||||
for (i=0;i<numFaces;i++) {
|
||||
SModelFace& face=faces[IndexSorter[i].first];
|
||||
m_Indices[indices++]=face.m_Verts[0];
|
||||
m_Indices[indices++]=face.m_Verts[1];
|
||||
m_Indices[indices++]=face.m_Verts[2];
|
||||
}
|
||||
|
||||
// clear list for next call
|
||||
IndexSorter.clear();
|
||||
|
||||
return mindist;
|
||||
}
|
62
source/renderer/ModelRData.h
Executable file
62
source/renderer/ModelRData.h
Executable file
@ -0,0 +1,62 @@
|
||||
#ifndef _MODELRDATA_H
|
||||
#define _MODELRDATA_H
|
||||
|
||||
#include <vector>
|
||||
#include "res/res.h"
|
||||
#include "Vector3D.h"
|
||||
#include "Color.h"
|
||||
#include "RenderableObject.h"
|
||||
|
||||
#define MODELRDATA_FLAG_TRANSPARENT (1<<0)
|
||||
|
||||
class CModel;
|
||||
|
||||
class CModelRData : public CRenderData
|
||||
{
|
||||
public:
|
||||
CModelRData(CModel* model);
|
||||
~CModelRData();
|
||||
|
||||
void Update();
|
||||
void RenderStreams(u32 streamflags,bool transparentPass=false);
|
||||
|
||||
// return render flags for this model
|
||||
u32 GetFlags() const { return m_Flags; }
|
||||
|
||||
// sort indices of this object from back to front according to given
|
||||
// object to camera space transform; return sqrd distance to centre of nearest triangle
|
||||
float BackToFrontIndexSort(CMatrix3D& objToCam);
|
||||
|
||||
private:
|
||||
// build this renderdata object
|
||||
void Build();
|
||||
|
||||
void BuildVertices();
|
||||
void BuildIndices();
|
||||
|
||||
|
||||
struct SVertex {
|
||||
// vertex position
|
||||
CVector3D m_Position;
|
||||
// vertex uvs for base texture
|
||||
float m_UVs[2];
|
||||
// RGB vertex color
|
||||
RGBColor m_Color;
|
||||
};
|
||||
|
||||
// owner model
|
||||
CModel* m_Model;
|
||||
// handle to models vertex buffer
|
||||
u32 m_VB;
|
||||
// model render vertices
|
||||
SVertex* m_Vertices;
|
||||
// transformed vertex normals - required for recalculating lighting on skinned models
|
||||
CVector3D* m_Normals;
|
||||
// model render indices
|
||||
u16* m_Indices;
|
||||
// model render flags
|
||||
u32 m_Flags;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
1349
source/renderer/Renderer.cpp
Executable file
1349
source/renderer/Renderer.cpp
Executable file
File diff suppressed because it is too large
Load Diff
312
source/renderer/Renderer.h
Executable file
312
source/renderer/Renderer.h
Executable file
@ -0,0 +1,312 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Name: Renderer.h
|
||||
// Author: Rich Cross
|
||||
// Contact: rich@wildfiregames.com
|
||||
//
|
||||
// Description: OpenGL renderer class; a higher level interface
|
||||
// on top of OpenGL to handle rendering the basic visual games
|
||||
// types - terrain, models, sprites, particles etc
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
#include <vector>
|
||||
#include "res/res.h"
|
||||
#include "ogl.h"
|
||||
#include "Camera.h"
|
||||
#include "Frustum.h"
|
||||
#include "PatchRData.h"
|
||||
#include "ModelRData.h"
|
||||
#include "SHCoeffs.h"
|
||||
#include "Terrain.h"
|
||||
#include "Singleton.h"
|
||||
|
||||
// necessary declarations
|
||||
class CCamera;
|
||||
class CPatch;
|
||||
class CSprite;
|
||||
class CParticleSys;
|
||||
class COverlay;
|
||||
class CMaterial;
|
||||
class CLightEnv;
|
||||
class CTexture;
|
||||
class CTerrain;
|
||||
|
||||
|
||||
// rendering modes
|
||||
enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
|
||||
|
||||
// stream flags
|
||||
#define STREAM_POS 0x01
|
||||
#define STREAM_NORMAL 0x02
|
||||
#define STREAM_COLOR 0x04
|
||||
#define STREAM_UV0 0x08
|
||||
#define STREAM_UV1 0x10
|
||||
#define STREAM_UV2 0x20
|
||||
#define STREAM_UV3 0x40
|
||||
#define STREAM_POSTOUV0 0x80
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SVertex3D: simple 3D vertex declaration
|
||||
struct SVertex3D
|
||||
{
|
||||
float m_Position[3];
|
||||
float m_TexCoords[2];
|
||||
unsigned int m_Color;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SVertex2D: simple 2D vertex declaration
|
||||
struct SVertex2D
|
||||
{
|
||||
float m_Position[2];
|
||||
float m_TexCoords[2];
|
||||
unsigned int m_Color;
|
||||
};
|
||||
|
||||
// access to sole renderer object
|
||||
#define g_Renderer CRenderer::GetSingleton()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CRenderer: base renderer class - primary interface to the rendering engine
|
||||
class CRenderer : public Singleton<CRenderer>
|
||||
{
|
||||
public:
|
||||
// various enumerations and renderer related constants
|
||||
enum { NumAlphaMaps=14 };
|
||||
enum { MaxTextureUnits=16 };
|
||||
enum Option {
|
||||
OPT_NOVBO,
|
||||
OPT_NOPBUFFER,
|
||||
OPT_SHADOWS,
|
||||
OPT_SHADOWCOLOR
|
||||
};
|
||||
|
||||
// stats class - per frame counts of number of draw calls, poly counts etc
|
||||
struct Stats {
|
||||
// set all stats to zero
|
||||
void Reset() { memset(this,0,sizeof(*this)); }
|
||||
// add given stats to this stats
|
||||
Stats& operator+=(const Stats& rhs) {
|
||||
m_Counter++;
|
||||
m_DrawCalls+=rhs.m_DrawCalls;
|
||||
m_TerrainTris+=rhs.m_TerrainTris;
|
||||
m_ModelTris+=rhs.m_ModelTris;
|
||||
m_TransparentTris+=rhs.m_TransparentTris;
|
||||
m_BlendSplats+=rhs.m_BlendSplats;
|
||||
return *this;
|
||||
}
|
||||
// count of the number of stats added together
|
||||
u32 m_Counter;
|
||||
// number of draw calls per frame - total DrawElements + Begin/End immediate mode loops
|
||||
u32 m_DrawCalls;
|
||||
// number of terrain triangles drawn
|
||||
u32 m_TerrainTris;
|
||||
// number of (non-transparent) model triangles drawn
|
||||
u32 m_ModelTris;
|
||||
// number of transparent model triangles drawn
|
||||
u32 m_TransparentTris;
|
||||
// number of splat passes for alphamapping
|
||||
u32 m_BlendSplats;
|
||||
};
|
||||
|
||||
public:
|
||||
// constructor, destructor
|
||||
CRenderer();
|
||||
~CRenderer();
|
||||
|
||||
// open up the renderer: performs any necessary initialisation
|
||||
bool Open(int width,int height,int depth);
|
||||
// shutdown the renderer: performs any necessary cleanup
|
||||
void Close();
|
||||
|
||||
// resize renderer view
|
||||
void Resize(int width,int height);
|
||||
|
||||
// set/get boolean renderer option
|
||||
void SetOptionBool(enum Option opt,bool value);
|
||||
bool GetOptionBool(enum Option opt) const;
|
||||
// set/get color renderer option
|
||||
void SetOptionColor(enum Option opt,const RGBColor& value);
|
||||
const RGBColor& GetOptionColor(enum Option opt) const;
|
||||
|
||||
// return view width
|
||||
int GetWidth() const { return m_Width; }
|
||||
// return view height
|
||||
int GetHeight() const { return m_Height; }
|
||||
// return view aspect ratio
|
||||
float GetAspect() const { return float(m_Width)/float(m_Height); }
|
||||
|
||||
// signal frame start
|
||||
void BeginFrame();
|
||||
// force rendering of any batched objects
|
||||
void FlushFrame();
|
||||
// signal frame end : implicitly flushes batched objects
|
||||
void EndFrame();
|
||||
|
||||
// set color used to clear screen in BeginFrame()
|
||||
void SetClearColor(u32 color);
|
||||
|
||||
// return current frame counter
|
||||
int GetFrameCounter() const { return m_FrameCounter; }
|
||||
|
||||
// set camera used for subsequent rendering operations; includes viewport, projection and modelview matrices
|
||||
void SetCamera(CCamera& camera);
|
||||
|
||||
// submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond
|
||||
// the call to frame end, as must the object itself
|
||||
void Submit(CPatch* patch);
|
||||
void Submit(CModel* model);
|
||||
void Submit(CSprite* sprite);
|
||||
void Submit(CParticleSys* psys);
|
||||
void Submit(COverlay* overlay);
|
||||
|
||||
// basic primitive rendering operations in 2 and 3D; handy for debugging stuff, but also useful in
|
||||
// editor tools (eg for highlighting specific terrain patches)
|
||||
// note:
|
||||
// * all 3D vertices specified in world space
|
||||
// * primitive operations rendered immediatedly, never batched
|
||||
// * primitives rendered in current material (set via SetMaterial)
|
||||
void RenderLine(const SVertex2D* vertices);
|
||||
void RenderLineLoop(int len,const SVertex2D* vertices);
|
||||
void RenderTri(const SVertex2D* vertices);
|
||||
void RenderQuad(const SVertex2D* vertices);
|
||||
void RenderLine(const SVertex3D* vertices);
|
||||
void RenderLineLoop(int len,const SVertex3D* vertices);
|
||||
void RenderTri(const SVertex3D* vertices);
|
||||
void RenderQuad(const SVertex3D* vertices);
|
||||
|
||||
// set the current lighting environment; (note: the passed pointer is just copied to a variable within the renderer,
|
||||
// so the lightenv passed must be scoped such that it is not destructed until after the renderer is no longer rendering)
|
||||
void SetLightEnv(CLightEnv* lightenv) {
|
||||
m_LightEnv=lightenv;
|
||||
}
|
||||
|
||||
// set the mode to render subsequent terrain patches
|
||||
void SetTerrainRenderMode(ERenderMode mode) { m_TerrainRenderMode=mode; }
|
||||
// get the mode to render subsequent terrain patches
|
||||
ERenderMode GetTerrainRenderMode() const { return m_TerrainRenderMode; }
|
||||
|
||||
// set the mode to render subsequent models
|
||||
void SetModelRenderMode(ERenderMode mode) { m_ModelRenderMode=mode; }
|
||||
// get the mode to render subsequent models
|
||||
ERenderMode GetModelRenderMode() const { return m_ModelRenderMode; }
|
||||
|
||||
// try and load the given texture
|
||||
bool LoadTexture(CTexture* texture,u32 wrapflags);
|
||||
// set the given unit to reference the given texture; pass a null texture to disable texturing on any unit
|
||||
void SetTexture(int unit,CTexture* texture);
|
||||
// BindTexture: bind a GL texture object to given unit
|
||||
void BindTexture(int unit,GLuint tex);
|
||||
// query transparency of given texture
|
||||
bool IsTextureTransparent(CTexture* texture);
|
||||
|
||||
// load the default set of alphamaps; return false if any alphamap fails to load, true otherwise
|
||||
bool LoadAlphaMaps(const char* fnames[]);
|
||||
|
||||
// return stats accumulated for current frame
|
||||
const Stats& GetStats() { return m_Stats; }
|
||||
|
||||
protected:
|
||||
friend class CPatchRData;
|
||||
friend class CModelRData;
|
||||
friend class CTransparencyRenderer;
|
||||
|
||||
// recurse down given model building renderdata for it and all it's children
|
||||
void UpdateModelDataRecursive(CModel* model);
|
||||
// update renderdata of everything submitted
|
||||
void UpdateSubmittedObjectData();
|
||||
|
||||
// patch rendering stuff
|
||||
void RenderPatchSubmissions();
|
||||
void RenderPatches();
|
||||
|
||||
// model rendering stuff
|
||||
void BuildTransparentPasses(CModel* model);
|
||||
void RenderModelSubmissions();
|
||||
void RenderModelsRecursive(CModel* model,u32 streamflags);
|
||||
void RenderModelsStreams(u32 streamflags);
|
||||
void RenderModels();
|
||||
|
||||
// shadow rendering stuff
|
||||
void CreateShadowMap();
|
||||
void RenderShadowMap();
|
||||
void ApplyShadowMap();
|
||||
void CRenderer::BuildTransformation(const CVector3D& pos,const CVector3D& right,const CVector3D& up,
|
||||
const CVector3D& dir,CMatrix3D& result);
|
||||
void ConstructLightTransform(const CVector3D& pos,const CVector3D& lightdir,CMatrix3D& result);
|
||||
void CalcShadowMatrices();
|
||||
void CalcShadowBounds(CBound& bounds);
|
||||
|
||||
// RENDERER DATA:
|
||||
// view width
|
||||
int m_Width;
|
||||
// view height
|
||||
int m_Height;
|
||||
// view depth (bpp)
|
||||
int m_Depth;
|
||||
// frame counter
|
||||
int m_FrameCounter;
|
||||
// current terrain rendering mode
|
||||
ERenderMode m_TerrainRenderMode;
|
||||
// current model rendering mode
|
||||
ERenderMode m_ModelRenderMode;
|
||||
// current view camera
|
||||
CCamera m_Camera;
|
||||
// color used to clear screen in BeginFrame
|
||||
float m_ClearColor[4];
|
||||
// submitted object lists for batching
|
||||
std::vector<CPatch*> m_TerrainPatches;
|
||||
std::vector<CModel*> m_Models;
|
||||
std::vector<CSprite*> m_Sprites;
|
||||
std::vector<CParticleSys*> m_ParticleSyses;
|
||||
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;
|
||||
// handle of composite alpha map (all the alpha maps packed into one texture)
|
||||
u32 m_CompositeAlphaMap;
|
||||
// handle of shadow map
|
||||
u32 m_ShadowMap;
|
||||
// size of each side of shadow map
|
||||
u32 m_ShadowMapSize;
|
||||
// per-frame flag: has the shadow map been rendered this frame?
|
||||
bool m_ShadowRendered;
|
||||
// projection matrix of shadow casting light
|
||||
CMatrix3D m_LightProjection;
|
||||
// transformation matrix of shadow casting light
|
||||
CMatrix3D m_LightTransform;
|
||||
// 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_PBuffer;
|
||||
bool m_GenerateMipmaps;
|
||||
} m_Caps;
|
||||
// renderer options
|
||||
struct Options {
|
||||
bool m_NoVBO;
|
||||
bool m_NoPBuffer;
|
||||
bool m_Shadows;
|
||||
RGBColor m_ShadowColor;
|
||||
} m_Options;
|
||||
// build card cap bits
|
||||
void EnumCaps();
|
||||
// per-frame renderer stats
|
||||
Stats m_Stats;
|
||||
// active textures on each unit
|
||||
GLuint m_ActiveTextures[MaxTextureUnits];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
185
source/renderer/TransparencyRenderer.cpp
Executable file
185
source/renderer/TransparencyRenderer.cpp
Executable file
@ -0,0 +1,185 @@
|
||||
#include <algorithm>
|
||||
#include "Renderer.h"
|
||||
#include "TransparencyRenderer.h"
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
CTransparencyRenderer g_TransparencyRenderer;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SortObjectsByDist: sorting class used for back-to-front sort of transparent passes
|
||||
struct SortObjectsByDist {
|
||||
typedef CTransparencyRenderer::SObject SortObj;
|
||||
|
||||
bool operator()(const SortObj& lhs,const SortObj& rhs) {
|
||||
return lhs.m_Dist>rhs.m_Dist? true : false;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sort: coarsely sort submitted objects in back to front manner
|
||||
void CTransparencyRenderer::Sort()
|
||||
{
|
||||
std::sort(m_Objects.begin(),m_Objects.end(),SortObjectsByDist());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Render: render all deferred passes; call Sort before using to ensure passes
|
||||
// are drawn in correct order
|
||||
void CTransparencyRenderer::Render()
|
||||
{
|
||||
// switch on wireframe if we need it
|
||||
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
}
|
||||
|
||||
// switch on client states
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
// setup texture environment to modulate diffuse color with texture color
|
||||
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_TEXTURE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
|
||||
// just pass through texture's alpha
|
||||
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);
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER,0.975f);
|
||||
|
||||
RenderObjectsStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0);
|
||||
|
||||
glDepthMask(0);
|
||||
glAlphaFunc(GL_LEQUAL,0.975f);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
RenderObjectsStreams(STREAM_POS|STREAM_COLOR|STREAM_UV0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDepthMask(1);
|
||||
|
||||
// switch off client states
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
|
||||
// switch wireframe off again
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
} else if (g_Renderer.m_ModelRenderMode==EDGED_FACES) {
|
||||
// edged faces: need to make a second pass over the data:
|
||||
// first switch on wireframe
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
|
||||
// setup some renderstate ..
|
||||
glDepthMask(0);
|
||||
g_Renderer.SetTexture(0,0);
|
||||
glColor4f(1,1,1,0.75f);
|
||||
glLineWidth(1.0f);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// .. and some client states
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
// render each model
|
||||
RenderObjectsStreams(STREAM_POS);
|
||||
|
||||
// .. and switch off the client states
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
// .. and restore the renderstates
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(1);
|
||||
|
||||
// restore fill mode, and we're done
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
}
|
||||
}
|
||||
|
||||
void CTransparencyRenderer::Clear()
|
||||
{
|
||||
// all transparent objects rendered; release them
|
||||
m_Objects.clear();
|
||||
}
|
||||
|
||||
void CTransparencyRenderer::Add(CModel* model)
|
||||
{
|
||||
// resize array, get last object in list
|
||||
m_Objects.resize(m_Objects.size()+1);
|
||||
|
||||
SObject& obj=m_Objects.back();
|
||||
obj.m_Model=model;
|
||||
|
||||
// build transform from object to camera space
|
||||
CMatrix3D objToCam,invcam;
|
||||
g_Renderer.m_Camera.m_Orientation.GetInverse(objToCam);
|
||||
objToCam*=model->GetTransform();
|
||||
|
||||
// resort model indices from back to front, according to camera position - and store
|
||||
// the returned sqrd distance to the centre of the nearest triangle
|
||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
||||
obj.m_Dist=modeldata->BackToFrontIndexSort(objToCam);
|
||||
}
|
||||
|
||||
void CTransparencyRenderer::RenderShadows()
|
||||
{
|
||||
// coarsely sort submitted objects in back to front manner
|
||||
std::sort(m_Objects.begin(),m_Objects.end(),SortObjectsByDist());
|
||||
|
||||
// switch on client states
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDepthMask(0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
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_ARB);
|
||||
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);
|
||||
|
||||
RenderObjectsStreams(STREAM_POS|STREAM_UV0);
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDepthMask(1);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// switch off client states
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderObjectsStreams: render given streams on all objects
|
||||
void CTransparencyRenderer::RenderObjectsStreams(u32 streamflags)
|
||||
{
|
||||
for (uint i=0;i<m_Objects.size();++i) {
|
||||
CModel* model=m_Objects[i].m_Model;
|
||||
|
||||
glPushMatrix();
|
||||
glMultMatrixf(&model->GetTransform()._11);
|
||||
|
||||
CModelRData* modeldata=(CModelRData*) model->GetRenderData();
|
||||
modeldata->RenderStreams(streamflags,true);
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
39
source/renderer/TransparencyRenderer.h
Executable file
39
source/renderer/TransparencyRenderer.h
Executable file
@ -0,0 +1,39 @@
|
||||
#ifndef __TRANSPARENCYRENDERER_H
|
||||
#define __TRANSPARENCYRENDERER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
class CModel;
|
||||
|
||||
class CTransparencyRenderer
|
||||
{
|
||||
public:
|
||||
struct SObject {
|
||||
// the transparent model
|
||||
CModel* m_Model;
|
||||
// sqrd distance from camera to centre of nearest triangle
|
||||
float m_Dist;
|
||||
};
|
||||
|
||||
public:
|
||||
// add object to render in deferred transparency pass
|
||||
void Add(CModel* model);
|
||||
// render all deferred objects
|
||||
void Render();
|
||||
// render shadows from all deferred objects
|
||||
void RenderShadows();
|
||||
// coarsely sort submitted objects in back to front manner
|
||||
void Sort();
|
||||
// empty object list
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
// render given streams on all objects
|
||||
void RenderObjectsStreams(u32 streamflags);
|
||||
// list of transparent objects to render
|
||||
std::vector<SObject> m_Objects;
|
||||
};
|
||||
|
||||
extern CTransparencyRenderer g_TransparencyRenderer;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user