Add ARB_vertex_shader specific functions to glext_funcs.h
Add an "instancing" model renderer to improve rendering of non-transparent, unanimated models. This renderer is used when the vertexshader path is rendering path is used. This was SVN commit r3052.
This commit is contained in:
parent
998622ff54
commit
875cb3bca1
10
binaries/data/mods/official/shaders/instancing.vs
Normal file
10
binaries/data/mods/official/shaders/instancing.vs
Normal file
@ -0,0 +1,10 @@
|
||||
vec4 InstancingPosition(vec4 position);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 worldPos = InstancingPosition(gl_Vertex);
|
||||
|
||||
gl_FrontColor = gl_BackColor = gl_Color;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * worldPos;
|
||||
}
|
9
binaries/data/mods/official/shaders/instancing.xml
Normal file
9
binaries/data/mods/official/shaders/instancing.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
|
||||
|
||||
<Program>
|
||||
<Shaders>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing_base.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/shlight.vs</Shader>
|
||||
</Shaders>
|
||||
</Program>
|
29
binaries/data/mods/official/shaders/instancing_base.vs
Normal file
29
binaries/data/mods/official/shaders/instancing_base.vs
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
// 3x4 part of the model-to-world matrix
|
||||
attribute vec4 Instancing1;
|
||||
attribute vec4 Instancing2;
|
||||
attribute vec4 Instancing3;
|
||||
|
||||
// Calculate a normal that has been transformed for instancing
|
||||
vec3 InstancingNormal(vec3 normal)
|
||||
{
|
||||
vec3 tmp;
|
||||
|
||||
tmp.x = dot(vec3(Instancing1), normal);
|
||||
tmp.y = dot(vec3(Instancing2), normal);
|
||||
tmp.z = dot(vec3(Instancing3), normal);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Calculate position, transformed for instancing
|
||||
vec4 InstancingPosition(vec4 position)
|
||||
{
|
||||
vec3 tmp;
|
||||
|
||||
tmp.x = dot(Instancing1, position);
|
||||
tmp.y = dot(Instancing2, position);
|
||||
tmp.z = dot(Instancing3, position);
|
||||
|
||||
return vec4(tmp, 1.0);
|
||||
}
|
14
binaries/data/mods/official/shaders/instancing_light.vs
Normal file
14
binaries/data/mods/official/shaders/instancing_light.vs
Normal file
@ -0,0 +1,14 @@
|
||||
vec3 lighting(vec3 normal);
|
||||
|
||||
vec3 InstancingNormal(vec3 normal);
|
||||
vec4 InstancingPosition(vec4 position);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 normal = InstancingNormal(gl_Normal);
|
||||
vec4 worldPos = InstancingPosition(gl_Vertex);
|
||||
|
||||
gl_FrontColor = gl_BackColor = vec4(lighting(normal),1.0) * gl_Color;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * worldPos;
|
||||
}
|
9
binaries/data/mods/official/shaders/instancing_light.xml
Normal file
9
binaries/data/mods/official/shaders/instancing_light.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
|
||||
|
||||
<Program>
|
||||
<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>
|
||||
</Shaders>
|
||||
</Program>
|
@ -268,7 +268,6 @@ void CGameView::CameraLock(float x, float y, float z, bool smooth)
|
||||
|
||||
void CGameView::SubmitModelRecursive(CModel* model)
|
||||
{
|
||||
model->ValidatePosition();
|
||||
g_Renderer.Submit(model);
|
||||
|
||||
const std::vector<CModel::Prop>& props=model->GetProps();
|
||||
|
@ -102,6 +102,53 @@ FUNC2(void, glGetUniformfvARB, glGetUniformfv, "2.0", (GLhandleARB programObj, G
|
||||
FUNC2(void, glGetUniformivARB, glGetUniformiv, "2.0", (GLhandleARB programObj, GLint location, GLint *params))
|
||||
FUNC2(void, glGetShaderSourceARB, glGetShaderSource, "2.0", (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source))
|
||||
|
||||
// GL_ARB_vertex_shader
|
||||
FUNC2(void, glVertexAttrib1fARB, glVertexAttrib1f, "2.0", (GLuint index, GLfloat v0))
|
||||
FUNC2(void, glVertexAttrib1sARB, glVertexAttrib1s, "2.0", (GLuint index, GLshort v0))
|
||||
FUNC2(void, glVertexAttrib1dARB, glVertexAttrib1d, "2.0", (GLuint index, GLdouble v0))
|
||||
FUNC2(void, glVertexAttrib2fARB, glVertexAttrib2f, "2.0", (GLuint index, GLfloat v0, GLfloat v1))
|
||||
FUNC2(void, glVertexAttrib2sARB, glVertexAttrib2s, "2.0", (GLuint index, GLshort v0, GLshort v1))
|
||||
FUNC2(void, glVertexAttrib2dARB, glVertexAttrib2d, "2.0", (GLuint index, GLdouble v0, GLdouble v1))
|
||||
FUNC2(void, glVertexAttrib3fARB, glVertexAttrib3f, "2.0", (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2))
|
||||
FUNC2(void, glVertexAttrib3sARB, glVertexAttrib3s, "2.0", (GLuint index, GLshort v0, GLshort v1, GLshort v2))
|
||||
FUNC2(void, glVertexAttrib3dARB, glVertexAttrib3d, "2.0", (GLuint index, GLdouble v0, GLdouble v1, GLdouble v2))
|
||||
FUNC2(void, glVertexAttrib4fARB, glVertexAttrib4f, "2.0", (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3))
|
||||
FUNC2(void, glVertexAttrib4sARB, glVertexAttrib4s, "2.0", (GLuint index, GLshort v0, GLshort v1, GLshort v2, GLshort v3))
|
||||
FUNC2(void, glVertexAttrib4dARB, glVertexAttrib4d, "2.0", (GLuint index, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3))
|
||||
FUNC2(void, glVertexAttrib4NubARB, glVertexAttrib4Nub, "2.0", (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w))
|
||||
FUNC2(void, glVertexAttrib1fvARB, glVertexAttrib1fv, "2.0", (GLuint index, const GLfloat *v))
|
||||
FUNC2(void, glVertexAttrib1svARB, glVertexAttrib1sv, "2.0", (GLuint index, const GLshort *v))
|
||||
FUNC2(void, glVertexAttrib1dvARB, glVertexAttrib1dv, "2.0", (GLuint index, const GLdouble *v))
|
||||
FUNC2(void, glVertexAttrib2fvARB, glVertexAttrib2fv, "2.0", (GLuint index, const GLfloat *v))
|
||||
FUNC2(void, glVertexAttrib2svARB, glVertexAttrib2sv, "2.0", (GLuint index, const GLshort *v))
|
||||
FUNC2(void, glVertexAttrib2dvARB, glVertexAttrib2dv, "2.0", (GLuint index, const GLdouble *v))
|
||||
FUNC2(void, glVertexAttrib3fvARB, glVertexAttrib3fv, "2.0", (GLuint index, const GLfloat *v))
|
||||
FUNC2(void, glVertexAttrib3svARB, glVertexAttrib3sv, "2.0", (GLuint index, const GLshort *v))
|
||||
FUNC2(void, glVertexAttrib3dvARB, glVertexAttrib3dv, "2.0", (GLuint index, const GLdouble *v))
|
||||
FUNC2(void, glVertexAttrib4fvARB, glVertexAttrib4fv, "2.0", (GLuint index, const GLfloat *v))
|
||||
FUNC2(void, glVertexAttrib4svARB, glVertexAttrib4sv, "2.0", (GLuint index, const GLshort *v))
|
||||
FUNC2(void, glVertexAttrib4dvARB, glVertexAttrib4dv, "2.0", (GLuint index, const GLdouble *v))
|
||||
FUNC2(void, glVertexAttrib4ivARB, glVertexAttrib4iv, "2.0", (GLuint index, const GLint *v))
|
||||
FUNC2(void, glVertexAttrib4bvARB, glVertexAttrib4bv, "2.0", (GLuint index, const GLbyte *v))
|
||||
FUNC2(void, glVertexAttrib4ubvARB, glVertexAttrib4ubv, "2.0", (GLuint index, const GLubyte *v))
|
||||
FUNC2(void, glVertexAttrib4usvARB, glVertexAttrib4usv, "2.0", (GLuint index, const GLushort *v))
|
||||
FUNC2(void, glVertexAttrib4uivARB, glVertexAttrib4uiv, "2.0", (GLuint index, const GLuint *v))
|
||||
FUNC2(void, glVertexAttrib4NbvARB, glVertexAttrib4Nbv, "2.0", (GLuint index, const GLbyte *v))
|
||||
FUNC2(void, glVertexAttrib4NsvARB, glVertexAttrib4Nsv, "2.0", (GLuint index, const GLshort *v))
|
||||
FUNC2(void, glVertexAttrib4NivARB, glVertexAttrib4Niv, "2.0", (GLuint index, const GLint *v))
|
||||
FUNC2(void, glVertexAttrib4NubvARB, glVertexAttrib4Nubv, "2.0", (GLuint index, const GLubyte *v))
|
||||
FUNC2(void, glVertexAttrib4NusvARB, glVertexAttrib4Nusv, "2.0", (GLuint index, const GLushort *v))
|
||||
FUNC2(void, glVertexAttrib4NuivARB, glVertexAttrib4Nuiv, "2.0", (GLuint index, const GLuint *v))
|
||||
FUNC2(void, glVertexAttribPointerARB, glVertexAttribPointer, "2.0", (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer))
|
||||
FUNC2(void, glEnableVertexAttribArrayARB, glEnableVertexAttribArray, "2.0", (GLuint index))
|
||||
FUNC2(void, glDisableVertexAttribArrayARB, glDisableVertexAttribArray, "2.0", (GLuint index))
|
||||
FUNC2(void, glBindAttribLocationARB, glBindAttribLocation, "2.0", (GLhandleARB programObj, GLuint index, const char *name))
|
||||
FUNC2(void, glGetActiveAttribARB, glGetActiveAttrib, "2.0", (GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, int *size, GLenum *type, char *name))
|
||||
FUNC2(GLint, glGetAttribLocationARB, glGetAttribLocation, "2.0", (GLhandleARB programObj, const char *name))
|
||||
FUNC2(void, glGetVertexAttribdvARB, glGetVertexAttribdv, "2.0", (GLuint index, GLenum pname, GLdouble *params))
|
||||
FUNC2(void, glGetVertexAttribfvARB, glGetVertexAttribfv, "2.0", (GLuint index, GLenum pname, GLfloat *params))
|
||||
FUNC2(void, glGetVertexAttribivARB, glGetVertexAttribiv, "2.0", (GLuint index, GLenum pname, GLint *params))
|
||||
FUNC2(void, glGetVertexAttribPointervARB, glGetVertexAttribPointerv, "2.0", (GLuint index, GLenum pname, void **pointer))
|
||||
|
||||
#if OS_WIN
|
||||
// WGL_EXT_swap_control
|
||||
|
@ -445,3 +445,12 @@ GLint ogl_program_get_uniform_location(Handle h, const char* name)
|
||||
|
||||
return glGetUniformLocationARB(p->id, name);
|
||||
}
|
||||
|
||||
|
||||
// Query vertex attribute information
|
||||
GLint ogl_program_get_attrib_location(Handle h, const char* name)
|
||||
{
|
||||
H_DEREF(h, Ogl_Program, p);
|
||||
|
||||
return glGetAttribLocationARB(p->id, name);
|
||||
}
|
||||
|
@ -47,4 +47,7 @@ int ogl_program_use(Handle h);
|
||||
// Query uniform information
|
||||
GLint ogl_program_get_uniform_location(Handle h, const char* name);
|
||||
|
||||
// Query vertex attribute information
|
||||
GLint ogl_program_get_attrib_location(Handle h, const char* name);
|
||||
|
||||
#endif // OGL_SHADER_H__
|
||||
|
@ -17,8 +17,8 @@
|
||||
struct HWLightingModelRendererInternals;
|
||||
|
||||
/**
|
||||
* Class HWLightingModelRenderer: Render animated models using only
|
||||
* OpenGL fixed function.
|
||||
* Class HWLightingModelRenderer: Render animated models using vertex
|
||||
* shaders for lighting.
|
||||
*
|
||||
* Use the RenderModifier to enable normal model rendering as well
|
||||
* as player colour rendering using this model renderer.
|
||||
|
264
source/renderer/InstancingModelRenderer.cpp
Normal file
264
source/renderer/InstancingModelRenderer.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : InstancingModelRenderer.cpp
|
||||
* Project : Pyrogenesis
|
||||
* Description : Implementation of InstancingModelRenderer
|
||||
*
|
||||
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "ogl.h"
|
||||
#include "lib/res/graphics/ogl_shader.h"
|
||||
#include "Vector3D.h"
|
||||
#include "Vector4D.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "graphics/ModelDef.h"
|
||||
|
||||
#include "renderer/InstancingModelRenderer.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/RenderPathVertexShader.h"
|
||||
#include "renderer/SHCoeffs.h"
|
||||
#include "renderer/VertexArray.h"
|
||||
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// InstancingModelRenderer implementation
|
||||
|
||||
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; }
|
||||
};
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
struct InstancingModelRendererInternals
|
||||
{
|
||||
/// Currently used RenderModifier
|
||||
RenderModifierPtr modifier;
|
||||
|
||||
/// Current rendering pass
|
||||
uint pass;
|
||||
|
||||
/// Streamflags required in this pass
|
||||
uint streamflags;
|
||||
|
||||
/// Previously prepared modeldef
|
||||
IModelDef* imodeldef;
|
||||
};
|
||||
|
||||
|
||||
// Construction and Destruction
|
||||
InstancingModelRenderer::InstancingModelRenderer()
|
||||
{
|
||||
m = new InstancingModelRendererInternals;
|
||||
}
|
||||
|
||||
InstancingModelRenderer::~InstancingModelRenderer()
|
||||
{
|
||||
delete m;
|
||||
}
|
||||
|
||||
|
||||
// Check hardware support
|
||||
bool InstancingModelRenderer::IsAvailable()
|
||||
{
|
||||
return g_Renderer.m_VertexShader != 0;
|
||||
}
|
||||
|
||||
|
||||
// Render submitted models.
|
||||
void InstancingModelRenderer::Render(RenderModifierPtr modifier, u32 flags)
|
||||
{
|
||||
if (!HaveSubmissions())
|
||||
return;
|
||||
|
||||
// Save for later
|
||||
m->modifier = modifier;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
m->pass = 0;
|
||||
do
|
||||
{
|
||||
m->streamflags = modifier->BeginPass(m->pass);
|
||||
|
||||
if (m->streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (m->streamflags & STREAM_COLOR)
|
||||
{
|
||||
const RGBColor* coeffs = g_Renderer.m_SHCoeffsUnits.GetCoefficients();
|
||||
int idx;
|
||||
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_InstancingLight);
|
||||
idx = g_Renderer.m_VertexShader->m_InstancingLight_SHCoefficients;
|
||||
glUniform3fvARB(idx, 9, (float*)coeffs);
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_Instancing);
|
||||
}
|
||||
|
||||
RenderAllModels(flags);
|
||||
|
||||
if (m->streamflags & STREAM_UV0) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (m->streamflags & STREAM_COLOR) glDisableClientState(GL_NORMAL_ARRAY);
|
||||
|
||||
glUseProgramObjectARB(0);
|
||||
|
||||
} while(!modifier->EndPass(m->pass++));
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
// Build modeldef data if necessary - we have no per-CModel data
|
||||
void* InstancingModelRenderer::CreateModelData(CModel* model)
|
||||
{
|
||||
CModelDefPtr mdef = model->GetModelDef();
|
||||
IModelDef* imodeldef = (IModelDef*)mdef->GetRenderData(m);
|
||||
|
||||
debug_assert(!model->GetBoneMatrices());
|
||||
|
||||
if (!imodeldef)
|
||||
{
|
||||
imodeldef = new IModelDef(mdef);
|
||||
mdef->SetRenderData(m, imodeldef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InstancingModelRenderer::UpdateModelData(CModel* model, void* data, u32 updateflags)
|
||||
{
|
||||
// We have no per-CModel data
|
||||
}
|
||||
|
||||
|
||||
void InstancingModelRenderer::DestroyModelData(CModel* model, void* data)
|
||||
{
|
||||
// We have no per-CModel data, and per-CModelDef data is deleted by the CModelDef
|
||||
}
|
||||
|
||||
|
||||
// Prepare UV coordinates for this modeldef
|
||||
void InstancingModelRenderer::PrepareModelDef(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 (m->streamflags & STREAM_COLOR)
|
||||
{
|
||||
glNormalPointer(GL_FLOAT, stride, base + m->imodeldef->m_Normal.offset);
|
||||
}
|
||||
if (m->streamflags & STREAM_UV0)
|
||||
{
|
||||
glTexCoordPointer(2, GL_FLOAT, stride, base + m->imodeldef->m_UV.offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Call the modifier to prepare the given texture
|
||||
void InstancingModelRenderer::PrepareTexture(CTexture* texture)
|
||||
{
|
||||
m->modifier->PrepareTexture(m->pass, texture);
|
||||
}
|
||||
|
||||
|
||||
// Render one model
|
||||
void InstancingModelRenderer::RenderModel(CModel* model, void* data)
|
||||
{
|
||||
m->modifier->PrepareModel(m->pass, model);
|
||||
|
||||
CModelDefPtr mdldef = model->GetModelDef();
|
||||
const CMatrix3D& mat = model->GetTransform();
|
||||
RenderPathVertexShader* rpvs = g_Renderer.m_VertexShader;
|
||||
|
||||
if (m->streamflags & STREAM_COLOR)
|
||||
{
|
||||
CColor sc = model->GetShadingColor();
|
||||
glColor3f(sc.r, sc.g, sc.b);
|
||||
|
||||
glVertexAttrib4fARB(rpvs->m_InstancingLight_Instancing1, mat._11, mat._12, mat._13, mat._14);
|
||||
glVertexAttrib4fARB(rpvs->m_InstancingLight_Instancing2, mat._21, mat._22, mat._23, mat._24);
|
||||
glVertexAttrib4fARB(rpvs->m_InstancingLight_Instancing3, mat._31, mat._32, mat._33, mat._34);
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttrib4fARB(rpvs->m_Instancing_Instancing1, mat._11, mat._12, mat._13, mat._14);
|
||||
glVertexAttrib4fARB(rpvs->m_Instancing_Instancing2, mat._21, mat._22, mat._23, mat._24);
|
||||
glVertexAttrib4fARB(rpvs->m_Instancing_Instancing3, mat._31, mat._32, mat._33, mat._34);
|
||||
}
|
||||
|
||||
// render the lot
|
||||
size_t numFaces = mdldef->GetNumFaces();
|
||||
glDrawRangeElementsEXT(GL_TRIANGLES, 0, mdldef->GetNumVertices(),
|
||||
numFaces*3, GL_UNSIGNED_SHORT, m->imodeldef->m_Indices);
|
||||
|
||||
// bump stats
|
||||
g_Renderer.m_Stats.m_DrawCalls++;
|
||||
g_Renderer.m_Stats.m_ModelTris += numFaces;
|
||||
}
|
||||
|
75
source/renderer/InstancingModelRenderer.h
Normal file
75
source/renderer/InstancingModelRenderer.h
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* =========================================================================
|
||||
* File : InstancingModelRenderer.h
|
||||
* Project : Pyrogenesis
|
||||
* Description : Special BatchModelRenderer that only works for non-animated
|
||||
* : models, but performs all transformation in a vertex shader.
|
||||
*
|
||||
* @author Nicolai Hähnle <nicolai@wildfiregames.com>
|
||||
* =========================================================================
|
||||
*/
|
||||
|
||||
#ifndef INSTANCINGMODELRENDERER_H
|
||||
#define INSTANCINGMODELRENDERER_H
|
||||
|
||||
#include "renderer/ModelRenderer.h"
|
||||
|
||||
struct InstancingModelRendererInternals;
|
||||
|
||||
/**
|
||||
* Class InstancingModelRenderer: Render non-animated (but potentially
|
||||
* moving models) using vertex shaders.
|
||||
*
|
||||
* Use the RenderModifier to enable normal model rendering as well
|
||||
* as player colour rendering using this model renderer.
|
||||
*
|
||||
* @note You should verify hardware capabilities using IsAvailable
|
||||
* before creating this model renderer.
|
||||
*/
|
||||
class InstancingModelRenderer : public BatchModelRenderer
|
||||
{
|
||||
public:
|
||||
InstancingModelRenderer();
|
||||
~InstancingModelRenderer();
|
||||
|
||||
/**
|
||||
* Render: Render submitted models using the given RenderModifier
|
||||
* for fragment stages.
|
||||
*
|
||||
* preconditions : PrepareModels must be called before Render.
|
||||
*
|
||||
* @param modifier The RenderModifier that specifies the fragment stage.
|
||||
* @param flags If flags is 0, all submitted models are rendered.
|
||||
* If flags is non-zero, only models that contain flags in their
|
||||
* CModel::GetFlags() are rendered.
|
||||
*/
|
||||
void Render(RenderModifierPtr modifier, u32 flags);
|
||||
|
||||
/**
|
||||
* IsAvailable: Determines whether this model renderer can be used
|
||||
* given the OpenGL implementation specific limits.
|
||||
*
|
||||
* @note Do not attempt to construct a InstancingModelRenderer object
|
||||
* when IsAvailable returns false.
|
||||
*
|
||||
* @return true if the OpenGL implementation can support this
|
||||
* model renderer.
|
||||
*/
|
||||
static bool IsAvailable();
|
||||
|
||||
protected:
|
||||
// Implementations
|
||||
void* CreateModelData(CModel* model);
|
||||
void UpdateModelData(CModel* model, void* data, u32 updateflags);
|
||||
void DestroyModelData(CModel* model, void* data);
|
||||
|
||||
void PrepareModelDef(CModelDefPtr def);
|
||||
void PrepareTexture(CTexture* texture);
|
||||
void RenderModel(CModel* model, void* data);
|
||||
|
||||
private:
|
||||
InstancingModelRendererInternals* m;
|
||||
};
|
||||
|
||||
|
||||
#endif // INSTANCINGMODELRENDERER_H
|
@ -74,6 +74,22 @@ static void SkinNormal(const SModelVertex& vertex, const CMatrix3D* invtranspmat
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ModelRenderer implementation
|
||||
|
||||
// Helper function to copy object-space position and normal vectors into arrays.
|
||||
void ModelRenderer::CopyPositionAndNormals(
|
||||
CModelDefPtr mdef,
|
||||
VertexArrayIterator<CVector3D> Position,
|
||||
VertexArrayIterator<CVector3D> Normal)
|
||||
{
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
SModelVertex* vertices = mdef->GetVertices();
|
||||
|
||||
for(size_t j = 0; j < numVertices; ++j)
|
||||
{
|
||||
Position[j] = vertices[j].m_Coords;
|
||||
Normal[j] = vertices[j].m_Norm;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to transform position and normal vectors into world-space.
|
||||
void ModelRenderer::BuildPositionAndNormals(
|
||||
CModel* model,
|
||||
|
@ -143,6 +143,23 @@ public:
|
||||
*/
|
||||
virtual void Render(RenderModifierPtr modifier, u32 flags) = 0;
|
||||
|
||||
/**
|
||||
* CopyPositionAndNormals: Copy unanimated object-space vertices and
|
||||
* normals into the given vertex array.
|
||||
*
|
||||
* @param mdef The underlying CModelDef that contains mesh data.
|
||||
* @param Position Points to the array that will receive
|
||||
* position vectors. The array behind the iterator
|
||||
* must be large enough to hold model->GetModelDef()->GetNumVertices()
|
||||
* vertices.
|
||||
* @param Normal Points to the array that will receive normal vectors.
|
||||
* The array behind the iterator must be as large as the Position array.
|
||||
*/
|
||||
static void CopyPositionAndNormals(
|
||||
CModelDefPtr mdef,
|
||||
VertexArrayIterator<CVector3D> Position,
|
||||
VertexArrayIterator<CVector3D> Normal);
|
||||
|
||||
/**
|
||||
* BuildPositionAndNormals: Build animated vertices and normals,
|
||||
* transformed into world space.
|
||||
|
@ -13,12 +13,27 @@ RenderPathVertexShader::RenderPathVertexShader()
|
||||
{
|
||||
m_ModelLight = 0;
|
||||
m_ModelLight_SHCoefficients = -1;
|
||||
|
||||
m_InstancingLight = 0;
|
||||
m_InstancingLight_SHCoefficients = -1;
|
||||
m_InstancingLight_Instancing1 = -1;
|
||||
m_InstancingLight_Instancing2 = -1;
|
||||
m_InstancingLight_Instancing3 = -1;
|
||||
|
||||
m_Instancing = 0;
|
||||
m_Instancing_Instancing1 = -1;
|
||||
m_Instancing_Instancing2 = -1;
|
||||
m_Instancing_Instancing3 = -1;
|
||||
}
|
||||
|
||||
RenderPathVertexShader::~RenderPathVertexShader()
|
||||
{
|
||||
if (m_ModelLight)
|
||||
ogl_program_free(m_ModelLight);
|
||||
if (m_InstancingLight)
|
||||
ogl_program_free(m_InstancingLight);
|
||||
if (m_Instancing)
|
||||
ogl_program_free(m_Instancing);
|
||||
}
|
||||
|
||||
// Initialize this render path.
|
||||
@ -36,6 +51,20 @@ bool RenderPathVertexShader::Init()
|
||||
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;
|
||||
}
|
||||
|
||||
@ -45,4 +74,20 @@ bool RenderPathVertexShader::Init()
|
||||
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_InstancingLight_Instancing1 = ogl_program_get_attrib_location(
|
||||
m_InstancingLight, "Instancing1");
|
||||
m_InstancingLight_Instancing2 = ogl_program_get_attrib_location(
|
||||
m_InstancingLight, "Instancing2");
|
||||
m_InstancingLight_Instancing3 = ogl_program_get_attrib_location(
|
||||
m_InstancingLight, "Instancing3");
|
||||
|
||||
m_Instancing_Instancing1 = ogl_program_get_attrib_location(
|
||||
m_Instancing, "Instancing1");
|
||||
m_Instancing_Instancing2 = ogl_program_get_attrib_location(
|
||||
m_Instancing, "Instancing2");
|
||||
m_Instancing_Instancing3 = ogl_program_get_attrib_location(
|
||||
m_Instancing, "Instancing3");
|
||||
}
|
||||
|
@ -16,6 +16,17 @@ public:
|
||||
public:
|
||||
Handle m_ModelLight;
|
||||
GLint m_ModelLight_SHCoefficients;
|
||||
|
||||
Handle m_InstancingLight;
|
||||
GLint m_InstancingLight_SHCoefficients;
|
||||
GLint m_InstancingLight_Instancing1; // matrix rows
|
||||
GLint m_InstancingLight_Instancing2;
|
||||
GLint m_InstancingLight_Instancing3;
|
||||
|
||||
Handle m_Instancing;
|
||||
GLint m_Instancing_Instancing1; // matrix rows
|
||||
GLint m_Instancing_Instancing2;
|
||||
GLint m_Instancing_Instancing3;
|
||||
};
|
||||
|
||||
#endif // __RENDERPATHVERTEXSHADER_H__
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
#include "renderer/FixedFunctionModelRenderer.h"
|
||||
#include "renderer/HWLightingModelRenderer.h"
|
||||
#include "renderer/InstancingModelRenderer.h"
|
||||
#include "renderer/ModelRenderer.h"
|
||||
#include "renderer/PlayerRenderer.h"
|
||||
#include "renderer/RenderModifiers.h"
|
||||
@ -108,6 +109,16 @@ CRenderer::CRenderer()
|
||||
m_Models.PlayerHWLit = NULL;
|
||||
m_Models.TransparentHWLit = NULL;
|
||||
}
|
||||
if (InstancingModelRenderer::IsAvailable())
|
||||
{
|
||||
m_Models.NormalInstancing = new InstancingModelRenderer;
|
||||
m_Models.PlayerInstancing = new InstancingModelRenderer;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Models.NormalInstancing = NULL;
|
||||
m_Models.PlayerInstancing = NULL;
|
||||
}
|
||||
m_Models.Transparency = new TransparencyRenderer;
|
||||
|
||||
m_Models.ModWireframe = RenderModifierPtr(new WireframeRenderModifier);
|
||||
@ -148,6 +159,8 @@ CRenderer::~CRenderer()
|
||||
delete m_Models.NormalHWLit;
|
||||
delete m_Models.PlayerHWLit;
|
||||
delete m_Models.TransparentHWLit;
|
||||
delete m_Models.NormalInstancing;
|
||||
delete m_Models.PlayerInstancing;
|
||||
delete m_Models.Transparency;
|
||||
|
||||
// general
|
||||
@ -788,6 +801,10 @@ void CRenderer::RenderShadowMap()
|
||||
m_Models.NormalHWLit->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
if (m_Models.PlayerHWLit)
|
||||
m_Models.PlayerHWLit->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
m_Models.TransparentFF->Render(m_Models.ModTransparentShadow, MODELFLAG_CASTSHADOWS);
|
||||
if (m_Models.TransparentHWLit)
|
||||
m_Models.TransparentHWLit->Render(m_Models.ModTransparentShadow, MODELFLAG_CASTSHADOWS);
|
||||
@ -1017,7 +1034,7 @@ void CRenderer::RenderWater()
|
||||
}
|
||||
}
|
||||
|
||||
glColor4f(m_WaterColor.r*losMod, m_WaterColor.g*losMod, m_WaterColor.b*losMod, alpha);
|
||||
glColor4f(m_WaterColor.r*losMod, m_WaterColor.g*losMod, m_WaterColor.b*losMod, alpha);
|
||||
glMultiTexCoord2fARB(GL_TEXTURE0, vertX/16.0f, vertZ/16.0f);
|
||||
glVertex3f(vertX, m_WaterHeight, vertZ);
|
||||
}
|
||||
@ -1050,6 +1067,10 @@ void CRenderer::RenderModels()
|
||||
m_Models.NormalHWLit->Render(m_Models.ModPlain, 0);
|
||||
if (m_Models.PlayerHWLit)
|
||||
m_Models.PlayerHWLit->Render(m_Models.ModPlayer, 0);
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->Render(m_Models.ModPlain, 0);
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->Render(m_Models.ModPlayer, 0);
|
||||
|
||||
if (m_ModelRenderMode==WIREFRAME) {
|
||||
// switch wireframe off again
|
||||
@ -1061,6 +1082,10 @@ void CRenderer::RenderModels()
|
||||
m_Models.NormalHWLit->Render(m_Models.ModWireframe, 0);
|
||||
if (m_Models.PlayerHWLit)
|
||||
m_Models.PlayerHWLit->Render(m_Models.ModWireframe, 0);
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->Render(m_Models.ModWireframe, 0);
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->Render(m_Models.ModWireframe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1111,6 +1136,10 @@ void CRenderer::FlushFrame()
|
||||
m_Models.PlayerHWLit->PrepareModels();
|
||||
if (m_Models.TransparentHWLit)
|
||||
m_Models.TransparentHWLit->PrepareModels();
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->PrepareModels();
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->PrepareModels();
|
||||
m_Models.Transparency->PrepareModels();
|
||||
PROFILE_END("prepare models");
|
||||
|
||||
@ -1169,6 +1198,10 @@ void CRenderer::FlushFrame()
|
||||
m_Models.PlayerHWLit->EndFrame();
|
||||
if (m_Models.TransparentHWLit)
|
||||
m_Models.TransparentHWLit->EndFrame();
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->EndFrame();
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->EndFrame();
|
||||
m_Models.Transparency->EndFrame();
|
||||
}
|
||||
|
||||
@ -1225,17 +1258,30 @@ void CRenderer::Submit(CModel* model)
|
||||
{
|
||||
if (model->GetFlags() & MODELFLAG_CASTSHADOWS) {
|
||||
PROFILE( "updating shadow bounds" );
|
||||
m_ShadowBound+=model->GetBounds();
|
||||
m_ShadowBound += model->GetBounds();
|
||||
}
|
||||
|
||||
// Tricky: The call to GetBounds() above can invalidate the position
|
||||
model->ValidatePosition();
|
||||
|
||||
bool canUseInstancing = false;
|
||||
|
||||
if (model->GetModelDef()->GetNumBones() == 0)
|
||||
canUseInstancing = true;
|
||||
|
||||
if (model->GetMaterial().IsPlayer())
|
||||
{
|
||||
if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
m_Models.PlayerHWLit->Submit(model);
|
||||
{
|
||||
if (canUseInstancing && m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->Submit(model);
|
||||
else
|
||||
m_Models.PlayerHWLit->Submit(model);
|
||||
}
|
||||
else
|
||||
m_Models.PlayerFF->Submit(model);
|
||||
}
|
||||
else if(model->GetMaterial().UsesAlpha())
|
||||
else if (model->GetMaterial().UsesAlpha())
|
||||
{
|
||||
if (m_SortAllTransparent)
|
||||
m_Models.Transparency->Submit(model);
|
||||
@ -1247,7 +1293,12 @@ void CRenderer::Submit(CModel* model)
|
||||
else
|
||||
{
|
||||
if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
m_Models.NormalHWLit->Submit(model);
|
||||
{
|
||||
if (canUseInstancing && m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->Submit(model);
|
||||
else
|
||||
m_Models.NormalHWLit->Submit(model);
|
||||
}
|
||||
else
|
||||
m_Models.NormalFF->Submit(model);
|
||||
}
|
||||
|
@ -295,6 +295,7 @@ protected:
|
||||
friend class TransparencyRenderer;
|
||||
friend class RenderPathVertexShader;
|
||||
friend class HWLightingModelRenderer;
|
||||
friend class InstancingModelRenderer;
|
||||
|
||||
// scripting
|
||||
jsval JSI_GetFastPlayerColor(JSContext*);
|
||||
@ -416,6 +417,8 @@ protected:
|
||||
ModelRenderer* NormalHWLit;
|
||||
ModelRenderer* PlayerHWLit;
|
||||
ModelRenderer* TransparentHWLit;
|
||||
ModelRenderer* NormalInstancing;
|
||||
ModelRenderer* PlayerInstancing;
|
||||
ModelRenderer* Transparency;
|
||||
|
||||
RenderModifierPtr ModWireframe;
|
||||
|
Loading…
Reference in New Issue
Block a user