#Models receive shadows now, including self-shadows.
This is a huge patch, including: * add a LitRenderModifier abstract base class for RenderModifiers with shadow+light * add LitRenderModifiers for all types of models * add STREAM_TEXGENTOUV1 to request generation of shadow map texcoords for models * create facilities to pass the texture matrix from the RenderModifier (fragment stage) to the ModelRenderer (vertex stage) * split ambient and diffuse terms of lighting until further down in the pipeline; this is necessary since shadowed regions receive only ambient light * small improvement in how RenderPathVertexShader scales to a greater number of vertex shaders This was SVN commit r3690.
This commit is contained in:
parent
0bd5778536
commit
e2bbd9a654
17
binaries/data/mods/official/shaders/instancing_lightp.vs
Normal file
17
binaries/data/mods/official/shaders/instancing_lightp.vs
Normal file
@ -0,0 +1,17 @@
|
||||
vec3 lighting(vec3 normal);
|
||||
|
||||
vec3 InstancingNormal(vec3 normal);
|
||||
vec4 InstancingPosition(vec4 position);
|
||||
|
||||
vec4 postouv1(vec4 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 normal = InstancingNormal(gl_Normal);
|
||||
vec4 worldPos = InstancingPosition(gl_Vertex);
|
||||
|
||||
gl_FrontColor = vec4(lighting(normal),1.0) * gl_Color;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1] = postouv1(worldPos);
|
||||
gl_Position = gl_ModelViewProjectionMatrix * worldPos;
|
||||
}
|
10
binaries/data/mods/official/shaders/instancing_lightp.xml
Normal file
10
binaries/data/mods/official/shaders/instancing_lightp.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
|
||||
|
||||
<Program>
|
||||
<Shaders>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing_lightp.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing_base.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/globallight.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/postouv1.vs</Shader>
|
||||
</Shaders>
|
||||
</Program>
|
12
binaries/data/mods/official/shaders/instancingp.vs
Normal file
12
binaries/data/mods/official/shaders/instancingp.vs
Normal file
@ -0,0 +1,12 @@
|
||||
vec4 InstancingPosition(vec4 position);
|
||||
vec4 postouv1(vec4 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 worldPos = InstancingPosition(gl_Vertex);
|
||||
|
||||
gl_FrontColor = gl_Color;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1] = postouv1(worldPos);
|
||||
gl_Position = gl_ModelViewProjectionMatrix * worldPos;
|
||||
}
|
9
binaries/data/mods/official/shaders/instancingp.xml
Normal file
9
binaries/data/mods/official/shaders/instancingp.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
|
||||
|
||||
<Program>
|
||||
<Shaders>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancingp.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/instancing_base.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/postouv1.vs</Shader>
|
||||
</Shaders>
|
||||
</Program>
|
10
binaries/data/mods/official/shaders/model_lightp.vs
Normal file
10
binaries/data/mods/official/shaders/model_lightp.vs
Normal file
@ -0,0 +1,10 @@
|
||||
vec3 lighting(vec3 normal);
|
||||
vec4 postouv1(vec4 pos);
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FrontColor = vec4(lighting(gl_Normal),1.0) * gl_Color;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1] = postouv1(gl_Vertex);
|
||||
gl_Position = ftransform();
|
||||
}
|
9
binaries/data/mods/official/shaders/model_lightp.xml
Normal file
9
binaries/data/mods/official/shaders/model_lightp.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
|
||||
|
||||
<Program>
|
||||
<Shaders>
|
||||
<Shader type="VERTEX_SHADER">shaders/model_lightp.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/globallight.vs</Shader>
|
||||
<Shader type="VERTEX_SHADER">shaders/postouv1.vs</Shader>
|
||||
</Shaders>
|
||||
</Program>
|
14
binaries/data/mods/official/shaders/postouv1.vs
Normal file
14
binaries/data/mods/official/shaders/postouv1.vs
Normal file
@ -0,0 +1,14 @@
|
||||
uniform vec4 TextureMatrix1;
|
||||
uniform vec4 TextureMatrix2;
|
||||
uniform vec4 TextureMatrix3;
|
||||
|
||||
vec4 postouv1(vec4 pos)
|
||||
{
|
||||
vec3 tmp;
|
||||
|
||||
tmp.x = dot(TextureMatrix1, pos);
|
||||
tmp.y = dot(TextureMatrix2, pos);
|
||||
tmp.z = dot(TextureMatrix3, pos);
|
||||
|
||||
return vec4(tmp, 1.0);
|
||||
}
|
@ -92,14 +92,18 @@ struct FixedFunctionModelRendererInternals
|
||||
|
||||
/// Previously prepared modeldef
|
||||
FFModelDef* ffmodeldef;
|
||||
|
||||
/// If true, primary color will only contain the diffuse term
|
||||
bool colorIsDiffuseOnly;
|
||||
};
|
||||
|
||||
|
||||
// Construction and Destruction
|
||||
FixedFunctionModelRenderer::FixedFunctionModelRenderer()
|
||||
FixedFunctionModelRenderer::FixedFunctionModelRenderer(bool colorIsDiffuseOnly)
|
||||
{
|
||||
m = new FixedFunctionModelRendererInternals;
|
||||
m->ffmodeldef = 0;
|
||||
m->colorIsDiffuseOnly = colorIsDiffuseOnly;
|
||||
}
|
||||
|
||||
FixedFunctionModelRenderer::~FixedFunctionModelRenderer()
|
||||
@ -159,7 +163,7 @@ void FixedFunctionModelRenderer::UpdateModelData(CModel* model, void* data, u32
|
||||
|
||||
VertexArrayIterator<SColor4ub> Color = ffmodel->m_Color.GetIterator<SColor4ub>();
|
||||
|
||||
ModelRenderer::BuildColor4ub(model, Normal, Color);
|
||||
ModelRenderer::BuildColor4ub(model, Normal, Color, m->colorIsDiffuseOnly);
|
||||
|
||||
// upload everything to vertex buffer
|
||||
ffmodel->m_Array.Upload();
|
||||
@ -178,12 +182,28 @@ void FixedFunctionModelRenderer::DestroyModelData(CModel* UNUSED(model), void* d
|
||||
|
||||
|
||||
// Setup one rendering pass
|
||||
void FixedFunctionModelRenderer::BeginPass(uint streamflags)
|
||||
void FixedFunctionModelRenderer::BeginPass(uint streamflags, const CMatrix3D* texturematrix)
|
||||
{
|
||||
debug_assert(streamflags == streamflags & (STREAM_POS|STREAM_UV0|STREAM_COLOR|STREAM_TEXGENTOUV1));
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR) glEnableClientState(GL_COLOR_ARRAY);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf(&texturematrix->_11);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -192,6 +212,20 @@ void FixedFunctionModelRenderer::EndPass(uint streamflags)
|
||||
{
|
||||
if (streamflags & STREAM_UV0) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR) glDisableClientState(GL_COLOR_ARRAY);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
@ -226,6 +260,14 @@ void FixedFunctionModelRenderer::RenderModel(uint streamflags, CModel* model, vo
|
||||
glVertexPointer(3, GL_FLOAT, stride, base + ffmodel->m_Position.offset);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
glColorPointer(3, ffmodel->m_Color.type, stride, base + ffmodel->m_Color.offset);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglClientActiveTextureARB(GL_TEXTURE1);
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
glTexCoordPointer(3, GL_FLOAT, stride, base + ffmodel->m_Position.offset);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
// render the lot
|
||||
size_t numFaces = mdldef->GetNumFaces();
|
||||
|
@ -23,7 +23,13 @@ struct FixedFunctionModelRendererInternals;
|
||||
class FixedFunctionModelRenderer : public ModelVertexRenderer
|
||||
{
|
||||
public:
|
||||
FixedFunctionModelRenderer();
|
||||
/**
|
||||
* FixedFunctionModelRenderer: Constructor.
|
||||
*
|
||||
* @param colorIsDiffuseOnly if true, the primary color sent to the fragment stage
|
||||
* contains only the diffuse term, and not the ambient
|
||||
*/
|
||||
FixedFunctionModelRenderer(bool colorIsDiffuseOnly);
|
||||
~FixedFunctionModelRenderer();
|
||||
|
||||
// Implementations
|
||||
@ -31,7 +37,7 @@ public:
|
||||
void UpdateModelData(CModel* model, void* data, u32 updateflags);
|
||||
void DestroyModelData(CModel* model, void* data);
|
||||
|
||||
void BeginPass(uint streamflags);
|
||||
void BeginPass(uint streamflags, const CMatrix3D* texturematrix);
|
||||
void EndPass(uint streamflags);
|
||||
void PrepareModelDef(uint streamflags, CModelDefPtr def);
|
||||
void RenderModel(uint streamflags, CModel* model, void* data);
|
||||
|
@ -76,14 +76,18 @@ struct HWLightingModelRendererInternals
|
||||
|
||||
/// Previously prepared modeldef
|
||||
HWLModelDef* hwlmodeldef;
|
||||
|
||||
/// If true, primary color will only contain the diffuse term
|
||||
bool colorIsDiffuseOnly;
|
||||
};
|
||||
|
||||
|
||||
// Construction and Destruction
|
||||
HWLightingModelRenderer::HWLightingModelRenderer()
|
||||
HWLightingModelRenderer::HWLightingModelRenderer(bool colorIsDiffuseOnly)
|
||||
{
|
||||
m = new HWLightingModelRendererInternals;
|
||||
m->hwlmodeldef = 0;
|
||||
m->colorIsDiffuseOnly = colorIsDiffuseOnly;
|
||||
}
|
||||
|
||||
HWLightingModelRenderer::~HWLightingModelRenderer()
|
||||
@ -170,26 +174,76 @@ void HWLightingModelRenderer::DestroyModelData(CModel* UNUSED(model), void* data
|
||||
|
||||
|
||||
// Setup one rendering pass
|
||||
void HWLightingModelRenderer::BeginPass(uint streamflags)
|
||||
void HWLightingModelRenderer::BeginPass(uint streamflags, const CMatrix3D* texturematrix)
|
||||
{
|
||||
debug_assert(streamflags == (streamflags & (STREAM_POS|STREAM_UV0|STREAM_COLOR|STREAM_TEXGENTOUV1)));
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
RenderPathVertexShader* rpvs = g_Renderer.m_VertexShader;
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
int idx;
|
||||
VS_GlobalLight* lightConfig;
|
||||
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_ModelLight);
|
||||
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.GetSunDir().X);
|
||||
idx = g_Renderer.m_VertexShader->m_ModelLight_SunColor;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_SunColor.X);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
ogl_program_use(rpvs->m_ModelLightP);
|
||||
lightConfig = &rpvs->m_ModelLightP_Light;
|
||||
|
||||
rpvs->m_ModelLightP_PosToUV1.SetMatrix(*texturematrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
ogl_program_use(rpvs->m_ModelLight);
|
||||
lightConfig = &rpvs->m_ModelLight_Light;
|
||||
}
|
||||
|
||||
if (m->colorIsDiffuseOnly)
|
||||
lightConfig->SetAmbient(RGBColor(0,0,0));
|
||||
else
|
||||
lightConfig->SetAmbient(lightEnv.m_UnitsAmbientColor);
|
||||
lightConfig->SetSunDir(lightEnv.GetSunDir());
|
||||
lightConfig->SetSunColor(lightEnv.m_SunColor);
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
|
||||
float tmp[4];
|
||||
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
||||
tmp[0] = texturematrix->_11;
|
||||
tmp[1] = texturematrix->_12;
|
||||
tmp[2] = texturematrix->_13;
|
||||
tmp[3] = texturematrix->_14;
|
||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, tmp);
|
||||
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
||||
tmp[0] = texturematrix->_21;
|
||||
tmp[1] = texturematrix->_22;
|
||||
tmp[2] = texturematrix->_23;
|
||||
tmp[3] = texturematrix->_24;
|
||||
glTexGenfv(GL_T, GL_OBJECT_PLANE, tmp);
|
||||
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
||||
tmp[0] = texturematrix->_31;
|
||||
tmp[1] = texturematrix->_32;
|
||||
tmp[2] = texturematrix->_33;
|
||||
tmp[3] = texturematrix->_34;
|
||||
glTexGenfv(GL_R, GL_OBJECT_PLANE, tmp);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -203,6 +257,19 @@ void HWLightingModelRenderer::EndPass(uint streamflags)
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
@ -26,7 +26,13 @@ struct HWLightingModelRendererInternals;
|
||||
class HWLightingModelRenderer : public ModelVertexRenderer
|
||||
{
|
||||
public:
|
||||
HWLightingModelRenderer();
|
||||
/**
|
||||
* HWLightingModelRenderer: Constructor.
|
||||
*
|
||||
* @param colorIsDiffuseOnly if true, the primary color sent to the fragment stage
|
||||
* contains only the diffuse term, and not the ambient
|
||||
*/
|
||||
HWLightingModelRenderer(bool colorIsDiffuseOnly);
|
||||
~HWLightingModelRenderer();
|
||||
|
||||
// Implementations
|
||||
@ -34,7 +40,7 @@ public:
|
||||
void UpdateModelData(CModel* model, void* data, u32 updateflags);
|
||||
void DestroyModelData(CModel* model, void* data);
|
||||
|
||||
void BeginPass(uint streamflags);
|
||||
void BeginPass(uint streamflags, const CMatrix3D* texturematrix);
|
||||
void EndPass(uint streamflags);
|
||||
void PrepareModelDef(uint streamflags, CModelDefPtr def);
|
||||
void RenderModel(uint streamflags, CModel* model, void* data);
|
||||
|
@ -96,14 +96,21 @@ struct InstancingModelRendererInternals
|
||||
|
||||
/// Previously prepared modeldef
|
||||
IModelDef* imodeldef;
|
||||
|
||||
/// If true, primary color will only contain the diffuse term
|
||||
bool colorIsDiffuseOnly;
|
||||
|
||||
/// After BeginPass, this points to the instancing matrix interface
|
||||
VS_Instancing* instancingConfig;
|
||||
};
|
||||
|
||||
|
||||
// Construction and Destruction
|
||||
InstancingModelRenderer::InstancingModelRenderer()
|
||||
InstancingModelRenderer::InstancingModelRenderer(bool colorIsDiffuseOnly)
|
||||
{
|
||||
m = new InstancingModelRendererInternals;
|
||||
m->imodeldef = 0;
|
||||
m->colorIsDiffuseOnly = colorIsDiffuseOnly;
|
||||
}
|
||||
|
||||
InstancingModelRenderer::~InstancingModelRenderer()
|
||||
@ -150,29 +157,58 @@ void InstancingModelRenderer::DestroyModelData(CModel* UNUSED(model), void* UNUS
|
||||
|
||||
|
||||
// Setup one rendering pass.
|
||||
void InstancingModelRenderer::BeginPass(uint streamflags)
|
||||
void InstancingModelRenderer::BeginPass(uint streamflags, const CMatrix3D* texturematrix)
|
||||
{
|
||||
debug_assert(streamflags == (streamflags & (STREAM_POS|STREAM_UV0|STREAM_COLOR|STREAM_TEXGENTOUV1)));
|
||||
|
||||
RenderPathVertexShader* rpvs = g_Renderer.m_VertexShader;
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
if (streamflags & STREAM_COLOR)
|
||||
{
|
||||
const CLightEnv& lightEnv = g_Renderer.GetLightEnv();
|
||||
int idx;
|
||||
VS_GlobalLight* lightConfig;
|
||||
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_InstancingLight);
|
||||
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.GetSunDir().X);
|
||||
idx = g_Renderer.m_VertexShader->m_InstancingLight_SunColor;
|
||||
pglUniform3fvARB(idx, 1, &lightEnv.m_SunColor.X);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
ogl_program_use(rpvs->m_InstancingLightP);
|
||||
lightConfig = &rpvs->m_InstancingLightP_Light;
|
||||
m->instancingConfig = &rpvs->m_InstancingLightP_Instancing;
|
||||
|
||||
rpvs->m_InstancingLightP_PosToUV1.SetMatrix(*texturematrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
ogl_program_use(rpvs->m_InstancingLight);
|
||||
lightConfig = &rpvs->m_InstancingLight_Light;
|
||||
m->instancingConfig = &rpvs->m_InstancingLight_Instancing;
|
||||
}
|
||||
|
||||
if (m->colorIsDiffuseOnly)
|
||||
lightConfig->SetAmbient(RGBColor(0,0,0));
|
||||
else
|
||||
lightConfig->SetAmbient(lightEnv.m_UnitsAmbientColor);
|
||||
lightConfig->SetSunDir(lightEnv.GetSunDir());
|
||||
lightConfig->SetSunColor(lightEnv.m_SunColor);
|
||||
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
ogl_program_use(g_Renderer.m_VertexShader->m_Instancing);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
{
|
||||
ogl_program_use(rpvs->m_InstancingP);
|
||||
m->instancingConfig = &rpvs->m_InstancingP_Instancing;
|
||||
|
||||
rpvs->m_InstancingP_PosToUV1.SetMatrix(*texturematrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
ogl_program_use(rpvs->m_Instancing);
|
||||
m->instancingConfig = &rpvs->m_Instancing_Instancing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,23 +250,14 @@ 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
pglVertexAttrib4fARB(rpvs->m_Instancing_Instancing1, mat._11, mat._12, mat._13, mat._14);
|
||||
pglVertexAttrib4fARB(rpvs->m_Instancing_Instancing2, mat._21, mat._22, mat._23, mat._24);
|
||||
pglVertexAttrib4fARB(rpvs->m_Instancing_Instancing3, mat._31, mat._32, mat._33, mat._34);
|
||||
}
|
||||
m->instancingConfig->SetMatrix(mat);
|
||||
|
||||
// render the lot
|
||||
size_t numFaces = mdldef->GetNumFaces();
|
||||
|
@ -26,7 +26,13 @@ struct InstancingModelRendererInternals;
|
||||
class InstancingModelRenderer : public ModelVertexRenderer
|
||||
{
|
||||
public:
|
||||
InstancingModelRenderer();
|
||||
/**
|
||||
* InstancingModelRenderer: Constructor.
|
||||
*
|
||||
* @param colorIsDiffuseOnly if true, the primary color sent to the fragment stage
|
||||
* contains only the diffuse term, and not the ambient
|
||||
*/
|
||||
InstancingModelRenderer(bool colorIsDiffuseOnly);
|
||||
~InstancingModelRenderer();
|
||||
|
||||
// Implementations
|
||||
@ -34,7 +40,7 @@ public:
|
||||
void UpdateModelData(CModel* model, void* data, u32 updateflags);
|
||||
void DestroyModelData(CModel* model, void* data);
|
||||
|
||||
void BeginPass(uint streamflags);
|
||||
void BeginPass(uint streamflags, const CMatrix3D* texturematrix);
|
||||
void EndPass(uint streamflags);
|
||||
void PrepareModelDef(uint streamflags, CModelDefPtr def);
|
||||
void RenderModel(uint streamflags, CModel* model, void* data);
|
||||
|
@ -149,7 +149,8 @@ void ModelRenderer::BuildPositionAndNormals(
|
||||
void ModelRenderer::BuildColor4ub(
|
||||
CModel* model,
|
||||
VertexArrayIterator<CVector3D> Normal,
|
||||
VertexArrayIterator<SColor4ub> Color)
|
||||
VertexArrayIterator<SColor4ub> Color,
|
||||
bool onlyDiffuse)
|
||||
{
|
||||
PROFILE( "lighting vertices" );
|
||||
|
||||
@ -159,6 +160,19 @@ void ModelRenderer::BuildColor4ub(
|
||||
CColor shadingColor = model->GetShadingColor();
|
||||
RGBColor tempcolor;
|
||||
|
||||
if (onlyDiffuse)
|
||||
{
|
||||
for (uint j=0; j<numVertices; j++)
|
||||
{
|
||||
lightEnv.EvaluateDirect(Normal[j], tempcolor);
|
||||
tempcolor.X *= shadingColor.r;
|
||||
tempcolor.Y *= shadingColor.g;
|
||||
tempcolor.Z *= shadingColor.b;
|
||||
*(u32*)&Color[j] = ConvertRGBColorTo4ub(tempcolor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint j=0; j<numVertices; j++)
|
||||
{
|
||||
lightEnv.EvaluateUnit(Normal[j], tempcolor);
|
||||
@ -167,6 +181,7 @@ void ModelRenderer::BuildColor4ub(
|
||||
tempcolor.Z *= shadingColor.b;
|
||||
*(u32*)&Color[j] = ConvertRGBColorTo4ub(tempcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -451,8 +466,12 @@ void BatchModelRenderer::Render(RenderModifierPtr modifier, u32 flags)
|
||||
do
|
||||
{
|
||||
uint streamflags = modifier->BeginPass(pass);
|
||||
const CMatrix3D* texturematrix = 0;
|
||||
|
||||
m->vertexRenderer->BeginPass(streamflags);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
texturematrix = modifier->GetTexGenMatrix(pass);
|
||||
|
||||
m->vertexRenderer->BeginPass(streamflags, texturematrix);
|
||||
|
||||
m->RenderAllModels(modifier, flags, pass, streamflags);
|
||||
|
||||
|
@ -23,6 +23,9 @@
|
||||
class RenderModifier;
|
||||
typedef boost::shared_ptr<RenderModifier> RenderModifierPtr;
|
||||
|
||||
class LitRenderModifier;
|
||||
typedef boost::shared_ptr<LitRenderModifier> LitRenderModifierPtr;
|
||||
|
||||
class ModelVertexRenderer;
|
||||
typedef boost::shared_ptr<ModelVertexRenderer> ModelVertexRendererPtr;
|
||||
|
||||
@ -199,11 +202,14 @@ public:
|
||||
* @param Color Points to the array that will receive the lit vertex color.
|
||||
* The array behind the iterator must large enough to hold
|
||||
* model->GetModelDef()->GetNumVertices() vertices.
|
||||
* @param onlyDiffuse if true, color will only contain the diffuse term (instead
|
||||
* of both ambient and diffuse)
|
||||
*/
|
||||
static void BuildColor4ub(
|
||||
CModel* model,
|
||||
VertexArrayIterator<CVector3D> Normal,
|
||||
VertexArrayIterator<SColor4ub> Color);
|
||||
VertexArrayIterator<SColor4ub> Color,
|
||||
bool onlyDiffuse);
|
||||
|
||||
/**
|
||||
* BuildUV: Copy UV coordinates into the given vertex array.
|
||||
|
@ -105,8 +105,11 @@ public:
|
||||
* is matched by a corresponding call to EndPass.
|
||||
*
|
||||
* @param streamflags Vertex streams required by the fragment stage.
|
||||
* @param texturematrix if texgen is requested in streamflags, this points to the
|
||||
* texture matrix that must be used to transform vertex positions into texture
|
||||
* coordinates
|
||||
*/
|
||||
virtual void BeginPass(uint streamflags) = 0;
|
||||
virtual void BeginPass(uint streamflags, const CMatrix3D* texturematrix) = 0;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/PlayerRenderer.h"
|
||||
#include "renderer/ShadowMap.h"
|
||||
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Model.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
@ -41,7 +44,7 @@ u32 FastPlayerColorRender::BeginPass(uint pass)
|
||||
{
|
||||
debug_assert(pass == 0);
|
||||
|
||||
// Nice player color uses a single pass with three texture environments
|
||||
// Fast player color uses a single pass with three texture environments
|
||||
// Note: This uses ARB_texture_env_crossbar (which is checked in GameSetup)
|
||||
//
|
||||
// We calculate: Result = Color*Texture*(PlayerColor*(1-Texture.a) + 1.0*Texture.a)
|
||||
@ -242,3 +245,160 @@ void SlowPlayerColorRender::PrepareModel(uint pass, CModel* model)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LitPlayerColorRender
|
||||
|
||||
LitPlayerColorRender::LitPlayerColorRender()
|
||||
{
|
||||
}
|
||||
|
||||
LitPlayerColorRender::~LitPlayerColorRender()
|
||||
{
|
||||
}
|
||||
|
||||
u32 LitPlayerColorRender::BeginPass(uint pass)
|
||||
{
|
||||
debug_assert(GetShadowMap() && GetShadowMap()->GetUseDepthTexture());
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
// First pass: Lay down the material color
|
||||
// We calculate:
|
||||
// Material = Texture*(PlayerColor*(1.0-Texture.a) + 1.0*Texture.a))
|
||||
// = (1 - ((1 - PlayerColor) * (1 - Texture.a)))*Texture
|
||||
|
||||
// Incoming Color holds the player color
|
||||
// Texture 0 holds the model's texture
|
||||
|
||||
// TexEnv #0
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
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_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
// Don't care about alpha; set it to something harmless
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
// TexEnv #1
|
||||
pglActiveTextureARB(GL_TEXTURE0+1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->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_ONE_MINUS_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
|
||||
|
||||
// Don't care about alpha; set it to something harmless
|
||||
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_TEXTURE0);
|
||||
|
||||
return STREAM_POS|STREAM_UV0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second pass: Multiply with lighting
|
||||
//
|
||||
// We calculate:
|
||||
// Lighting = Ambient + Diffuse * Shadow
|
||||
// and modulate with frame buffer contents
|
||||
//
|
||||
// Incoming color is diffuse
|
||||
// Texture 1 is the shadow map
|
||||
|
||||
// TexEnv #0
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->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_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1);
|
||||
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);
|
||||
|
||||
// TexEnv #1
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->GetTexture());
|
||||
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);
|
||||
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &GetLightEnv()->m_UnitsAmbientColor.X);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
// Blending, Z settings
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
|
||||
glDepthMask(0);
|
||||
|
||||
return STREAM_POS|STREAM_COLOR|STREAM_TEXGENTOUV1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LitPlayerColorRender::EndPass(uint pass)
|
||||
{
|
||||
if (pass == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore state
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const CMatrix3D* LitPlayerColorRender::GetTexGenMatrix(uint UNUSED(pass))
|
||||
{
|
||||
return &GetShadowMap()->GetTextureMatrix();
|
||||
}
|
||||
|
||||
void LitPlayerColorRender::PrepareTexture(uint pass, CTexture* texture)
|
||||
{
|
||||
if (pass == 0)
|
||||
g_Renderer.SetTexture(0, texture);
|
||||
}
|
||||
|
||||
void LitPlayerColorRender::PrepareModel(uint pass, CModel* model)
|
||||
{
|
||||
if (pass == 0)
|
||||
{
|
||||
// Get the player color
|
||||
SMaterialColor colour = model->GetMaterial().GetPlayerColor();
|
||||
|
||||
// Send the player color
|
||||
glColor3f(colour.r, colour.g, colour.b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -67,4 +67,27 @@ public:
|
||||
void PrepareModel(uint pass, CModel* model);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class LitPlayerColorRender: Render models fully textured and lit including shadows
|
||||
* and player color.
|
||||
*
|
||||
* @note Only use a LitPlayerColorRenderer instance when depth texture based shadows
|
||||
* are supported by the OpenGL implementation (as verified by CRenderer::m_Caps::m_DepthTextureShadows).
|
||||
*/
|
||||
class LitPlayerColorRender : public LitRenderModifier
|
||||
{
|
||||
public:
|
||||
LitPlayerColorRender();
|
||||
~LitPlayerColorRender();
|
||||
|
||||
// Implementation
|
||||
u32 BeginPass(uint pass);
|
||||
bool EndPass(uint pass);
|
||||
const CMatrix3D* GetTexGenMatrix(uint pass);
|
||||
void PrepareTexture(uint pass, CTexture* texture);
|
||||
void PrepareModel(uint pass, CModel* model);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -14,13 +14,17 @@
|
||||
#include "Vector3D.h"
|
||||
#include "Vector4D.h"
|
||||
|
||||
#include "maths/Matrix3D.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include "graphics/Color.h"
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Model.h"
|
||||
|
||||
#include "renderer/RenderModifiers.h"
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/ShadowMap.h"
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
@ -29,11 +33,42 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RenderModifier implementation
|
||||
|
||||
const CMatrix3D* RenderModifier::GetTexGenMatrix(uint UNUSED(pass))
|
||||
{
|
||||
debug_warn("GetTexGenMatrix not implemented by a derived RenderModifier");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RenderModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(model))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LitRenderModifier implementation
|
||||
|
||||
LitRenderModifier::LitRenderModifier()
|
||||
: m_Shadow(0), m_LightEnv(0)
|
||||
{
|
||||
}
|
||||
|
||||
LitRenderModifier::~LitRenderModifier()
|
||||
{
|
||||
}
|
||||
|
||||
// Set the shadow map for subsequent rendering
|
||||
void LitRenderModifier::SetShadowMap(const ShadowMap* shadow)
|
||||
{
|
||||
m_Shadow = shadow;
|
||||
}
|
||||
|
||||
// Set the light environment for subsequent rendering
|
||||
void LitRenderModifier::SetLightEnv(const CLightEnv* lightenv)
|
||||
{
|
||||
m_LightEnv = lightenv;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PlainRenderModifier implementation
|
||||
|
||||
@ -86,10 +121,90 @@ void PlainRenderModifier::PrepareTexture(uint UNUSED(pass), CTexture* texture)
|
||||
g_Renderer.SetTexture(0, texture);
|
||||
}
|
||||
|
||||
void PlainRenderModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(model))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PlainLitRenderModifier implementation
|
||||
|
||||
PlainLitRenderModifier::PlainLitRenderModifier()
|
||||
{
|
||||
}
|
||||
|
||||
PlainLitRenderModifier::~PlainLitRenderModifier()
|
||||
{
|
||||
}
|
||||
|
||||
u32 PlainLitRenderModifier::BeginPass(uint pass)
|
||||
{
|
||||
debug_assert(pass == 0);
|
||||
debug_assert(GetShadowMap() && GetShadowMap()->GetUseDepthTexture());
|
||||
|
||||
// Ambient + Diffuse * Shadow
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
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_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1);
|
||||
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);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->GetTexture());
|
||||
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);
|
||||
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &GetLightEnv()->m_UnitsAmbientColor.X);
|
||||
|
||||
// Incoming color is ambient + diffuse light
|
||||
pglActiveTextureARB(GL_TEXTURE2);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->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_TEXTURE0);
|
||||
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_TEXTURE0);
|
||||
|
||||
return STREAM_POS|STREAM_COLOR|STREAM_UV0|STREAM_TEXGENTOUV1;
|
||||
}
|
||||
|
||||
const CMatrix3D* PlainLitRenderModifier::GetTexGenMatrix(uint UNUSED(pass))
|
||||
{
|
||||
return &GetShadowMap()->GetTextureMatrix();
|
||||
}
|
||||
|
||||
bool PlainLitRenderModifier::EndPass(uint UNUSED(pass))
|
||||
{
|
||||
g_Renderer.BindTexture(1, 0);
|
||||
g_Renderer.BindTexture(2, 0);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
pglClientActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlainLitRenderModifier::PrepareTexture(uint UNUSED(pass), CTexture* texture)
|
||||
{
|
||||
g_Renderer.SetTexture(0, texture);
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WireframeRenderModifier implementation
|
||||
|
@ -16,9 +16,11 @@
|
||||
#include "ModelRenderer.h"
|
||||
|
||||
|
||||
class CLightEnv;
|
||||
class CMatrix3D;
|
||||
class CModel;
|
||||
class CTexture;
|
||||
|
||||
class ShadowMap;
|
||||
|
||||
/**
|
||||
* Class RenderModifier: Some ModelRenderer implementations provide vertex
|
||||
@ -45,6 +47,19 @@ public:
|
||||
*/
|
||||
virtual u32 BeginPass(uint pass) = 0;
|
||||
|
||||
/**
|
||||
* GetTexGenMatrix: If BeginPass returns STREAM_TEXGENTOUVx, the caller must
|
||||
* call this function to query the texture matrix that will be used to transform
|
||||
* vertex positions into texture coordinates.
|
||||
*
|
||||
* Default implementation raises a runtime error.
|
||||
*
|
||||
* @param pass the current pass number (pass == 0 is the first pass)
|
||||
*
|
||||
* @return a pointer to the texture matrix for the given pass
|
||||
*/
|
||||
virtual const CMatrix3D* GetTexGenMatrix(uint pass);
|
||||
|
||||
/**
|
||||
* EndPass: Cleanup OpenGL state after the given pass. This function
|
||||
* may indicate that additional passes are needed.
|
||||
@ -82,6 +97,45 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class LitRenderModifier: Abstract base class for RenderModifiers that apply
|
||||
* a shadow map.
|
||||
* LitRenderModifiers expect the diffuse brightness in the primary color (instead of ambient + diffuse).
|
||||
*/
|
||||
class LitRenderModifier : public RenderModifier
|
||||
{
|
||||
public:
|
||||
LitRenderModifier();
|
||||
~LitRenderModifier();
|
||||
|
||||
/**
|
||||
* SetShadowMap: Set the shadow map that will be used for rendering.
|
||||
* Must be called by the user of the RenderModifier.
|
||||
*
|
||||
* The shadow map must be non-null and use depth texturing, or subsequent rendering
|
||||
* using this RenderModifier will fail.
|
||||
*
|
||||
* @param shadow the shadow map
|
||||
*/
|
||||
void SetShadowMap(const ShadowMap* shadow);
|
||||
|
||||
/**
|
||||
* SetLightEnv: Set the light environment that will be used for rendering.
|
||||
* Must be called by the user of the RenderModifier.
|
||||
*
|
||||
* @param lightenv the light environment (must be non-null)
|
||||
*/
|
||||
void SetLightEnv(const CLightEnv* lightenv);
|
||||
|
||||
const ShadowMap* GetShadowMap() const { return m_Shadow; }
|
||||
const CLightEnv* GetLightEnv() const { return m_LightEnv; }
|
||||
|
||||
private:
|
||||
const ShadowMap* m_Shadow;
|
||||
const CLightEnv* m_LightEnv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class RenderModifierRenderer: Interface to a model renderer that can render
|
||||
* its models via a RenderModifier that sets up fragment stages.
|
||||
@ -108,9 +162,28 @@ public:
|
||||
u32 BeginPass(uint pass);
|
||||
bool EndPass(uint pass);
|
||||
void PrepareTexture(uint pass, CTexture* texture);
|
||||
void PrepareModel(uint pass, CModel* model);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class PlainLitRenderModifier: Use an opaque color texture for a lit object that is shadowed
|
||||
* using a depth texture.
|
||||
* Expects the diffuse brightness in the primary color.
|
||||
*/
|
||||
class PlainLitRenderModifier : public LitRenderModifier
|
||||
{
|
||||
public:
|
||||
PlainLitRenderModifier();
|
||||
~PlainLitRenderModifier();
|
||||
|
||||
// Implementation
|
||||
u32 BeginPass(uint pass);
|
||||
const CMatrix3D* GetTexGenMatrix(uint pass);
|
||||
bool EndPass(uint pass);
|
||||
void PrepareTexture(uint pass, CTexture* texture);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class WireframeRenderModifier: RenderModifier that renders wireframe models.
|
||||
*/
|
||||
|
@ -8,32 +8,44 @@
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
void VS_GlobalLight::Init(Handle shader)
|
||||
{
|
||||
m_Ambient = ogl_program_get_uniform_location(shader, "ambient");
|
||||
m_SunDir = ogl_program_get_uniform_location(shader, "sunDir");
|
||||
m_SunColor = ogl_program_get_uniform_location(shader, "sunColor");
|
||||
}
|
||||
|
||||
void VS_Instancing::Init(Handle shader)
|
||||
{
|
||||
m_Instancing1 = ogl_program_get_attrib_location(shader, "Instancing1");
|
||||
m_Instancing2 = ogl_program_get_attrib_location(shader, "Instancing2");
|
||||
m_Instancing3 = ogl_program_get_attrib_location(shader, "Instancing3");
|
||||
}
|
||||
|
||||
void VS_PosToUV1::Init(Handle shader)
|
||||
{
|
||||
m_TextureMatrix1 = ogl_program_get_uniform_location(shader, "TextureMatrix1");
|
||||
debug_assert(m_TextureMatrix1 >= 0);
|
||||
m_TextureMatrix2 = ogl_program_get_uniform_location(shader, "TextureMatrix2");
|
||||
debug_assert(m_TextureMatrix2 >= 0);
|
||||
m_TextureMatrix3 = ogl_program_get_uniform_location(shader, "TextureMatrix3");
|
||||
debug_assert(m_TextureMatrix3 >= 0);
|
||||
}
|
||||
|
||||
RenderPathVertexShader::RenderPathVertexShader()
|
||||
{
|
||||
m_ModelLight = 0;
|
||||
m_ModelLight_Ambient = -1;
|
||||
m_ModelLight_SunDir = -1;
|
||||
m_ModelLight_SunColor = -1;
|
||||
|
||||
m_ModelLightP = 0;
|
||||
m_InstancingLight = 0;
|
||||
m_InstancingLight_Ambient = -1;
|
||||
m_InstancingLight_SunDir = -1;
|
||||
m_InstancingLight_SunColor = -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_ModelLightP)
|
||||
ogl_program_free(m_ModelLightP);
|
||||
if (m_InstancingLight)
|
||||
ogl_program_free(m_InstancingLight);
|
||||
if (m_Instancing)
|
||||
@ -55,6 +67,13 @@ bool RenderPathVertexShader::Init()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ModelLightP = ogl_program_load("shaders/model_lightp.xml");
|
||||
if (m_ModelLightP < 0)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Failed to load shaders/model_lightp.xml: %i\n", (int)m_ModelLightP);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_InstancingLight = ogl_program_load("shaders/instancing_light.xml");
|
||||
if (m_InstancingLight < 0)
|
||||
{
|
||||
@ -62,6 +81,13 @@ bool RenderPathVertexShader::Init()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_InstancingLightP = ogl_program_load("shaders/instancing_lightp.xml");
|
||||
if (m_InstancingLightP < 0)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Failed to load shaders/instancing_lightp.xml: %i\n", (int)m_InstancingLightP);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Instancing = ogl_program_load("shaders/instancing.xml");
|
||||
if (m_Instancing < 0)
|
||||
{
|
||||
@ -69,6 +95,13 @@ bool RenderPathVertexShader::Init()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_InstancingP = ogl_program_load("shaders/instancingp.xml");
|
||||
if (m_InstancingP < 0)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Failed to load shaders/instancingp.xml: %i\n", (int)m_InstancingP);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -77,27 +110,20 @@ bool RenderPathVertexShader::Init()
|
||||
// the uniform locations might have changed under us.
|
||||
void RenderPathVertexShader::BeginFrame()
|
||||
{
|
||||
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_ModelLight_Light.Init(m_ModelLight);
|
||||
|
||||
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(
|
||||
m_InstancingLight, "Instancing2");
|
||||
m_InstancingLight_Instancing3 = ogl_program_get_attrib_location(
|
||||
m_InstancingLight, "Instancing3");
|
||||
m_ModelLightP_Light.Init(m_ModelLightP);
|
||||
m_ModelLightP_PosToUV1.Init(m_ModelLightP);
|
||||
|
||||
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");
|
||||
m_InstancingLight_Light.Init(m_InstancingLight);
|
||||
m_InstancingLight_Instancing.Init(m_InstancingLight);
|
||||
|
||||
m_InstancingLightP_Light.Init(m_InstancingLightP);
|
||||
m_InstancingLightP_Instancing.Init(m_InstancingLightP);
|
||||
m_InstancingLightP_PosToUV1.Init(m_InstancingLightP);
|
||||
|
||||
m_Instancing_Instancing.Init(m_Instancing);
|
||||
|
||||
m_InstancingP_Instancing.Init(m_InstancingP);
|
||||
m_InstancingP_PosToUV1.Init(m_InstancingP);
|
||||
}
|
||||
|
@ -1,6 +1,81 @@
|
||||
#ifndef __RENDERPATHVERTEXSHADER_H__
|
||||
#define __RENDERPATHVERTEXSHADER_H__
|
||||
|
||||
#include "graphics/LightEnv.h"
|
||||
|
||||
// Interface for globallight.vs
|
||||
struct VS_GlobalLight
|
||||
{
|
||||
public:
|
||||
void Init(Handle shader);
|
||||
|
||||
void SetFromLightEnv(const CLightEnv& lightenv, bool units) const
|
||||
{
|
||||
SetAmbient(units ? lightenv.m_UnitsAmbientColor : lightenv.m_TerrainAmbientColor);
|
||||
SetSunDir(lightenv.GetSunDir());
|
||||
SetSunColor(lightenv.m_SunColor);
|
||||
}
|
||||
|
||||
void SetAmbient(const RGBColor& color) const
|
||||
{
|
||||
pglUniform3fvARB(m_Ambient, 1, &color.X);
|
||||
}
|
||||
|
||||
void SetSunDir(const CVector3D& sundir) const
|
||||
{
|
||||
pglUniform3fvARB(m_SunDir, 1, &sundir.X);
|
||||
}
|
||||
|
||||
void SetSunColor(const RGBColor& color) const
|
||||
{
|
||||
pglUniform3fvARB(m_SunColor, 1, &color.X);
|
||||
}
|
||||
|
||||
private:
|
||||
GLint m_Ambient;
|
||||
GLint m_SunDir;
|
||||
GLint m_SunColor;
|
||||
};
|
||||
|
||||
// Interface for instancing_base.vs
|
||||
struct VS_Instancing
|
||||
{
|
||||
public:
|
||||
void Init(Handle shader);
|
||||
|
||||
void SetMatrix(const CMatrix3D& mat) const
|
||||
{
|
||||
pglVertexAttrib4fARB(m_Instancing1, mat._11, mat._12, mat._13, mat._14);
|
||||
pglVertexAttrib4fARB(m_Instancing2, mat._21, mat._22, mat._23, mat._24);
|
||||
pglVertexAttrib4fARB(m_Instancing3, mat._31, mat._32, mat._33, mat._34);
|
||||
}
|
||||
|
||||
private:
|
||||
GLint m_Instancing1;
|
||||
GLint m_Instancing2;
|
||||
GLint m_Instancing3;
|
||||
};
|
||||
|
||||
|
||||
// Interface for postouv1.vs
|
||||
struct VS_PosToUV1
|
||||
{
|
||||
public:
|
||||
void Init(Handle shader);
|
||||
|
||||
void SetMatrix(const CMatrix3D& mat) const
|
||||
{
|
||||
pglUniform4fARB(m_TextureMatrix1, mat._11, mat._12, mat._13, mat._14);
|
||||
pglUniform4fARB(m_TextureMatrix2, mat._21, mat._22, mat._23, mat._24);
|
||||
pglUniform4fARB(m_TextureMatrix3, mat._31, mat._32, mat._33, mat._34);
|
||||
}
|
||||
|
||||
private:
|
||||
GLint m_TextureMatrix1;
|
||||
GLint m_TextureMatrix2;
|
||||
GLint m_TextureMatrix3;
|
||||
};
|
||||
|
||||
class RenderPathVertexShader
|
||||
{
|
||||
public:
|
||||
@ -15,22 +90,27 @@ public:
|
||||
|
||||
public:
|
||||
Handle m_ModelLight;
|
||||
GLint m_ModelLight_Ambient;
|
||||
GLint m_ModelLight_SunDir;
|
||||
GLint m_ModelLight_SunColor;
|
||||
VS_GlobalLight m_ModelLight_Light;
|
||||
|
||||
Handle m_ModelLightP;
|
||||
VS_GlobalLight m_ModelLightP_Light;
|
||||
VS_PosToUV1 m_ModelLightP_PosToUV1;
|
||||
|
||||
Handle m_InstancingLight;
|
||||
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;
|
||||
VS_GlobalLight m_InstancingLight_Light;
|
||||
VS_Instancing m_InstancingLight_Instancing;
|
||||
|
||||
Handle m_InstancingLightP;
|
||||
VS_GlobalLight m_InstancingLightP_Light;
|
||||
VS_Instancing m_InstancingLightP_Instancing;
|
||||
VS_PosToUV1 m_InstancingLightP_PosToUV1;
|
||||
|
||||
Handle m_Instancing;
|
||||
GLint m_Instancing_Instancing1; // matrix rows
|
||||
GLint m_Instancing_Instancing2;
|
||||
GLint m_Instancing_Instancing3;
|
||||
VS_Instancing m_Instancing_Instancing;
|
||||
|
||||
Handle m_InstancingP;
|
||||
VS_Instancing m_InstancingP_Instancing;
|
||||
VS_PosToUV1 m_InstancingP_PosToUV1;
|
||||
};
|
||||
|
||||
#endif // __RENDERPATHVERTEXSHADER_H__
|
||||
|
@ -185,6 +185,13 @@ AbstractProfileTable* CRendererStatsTable::GetChild(uint UNUSED(row))
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// CRenderer implementation
|
||||
|
||||
enum {
|
||||
AmbientDiffuse = 0,
|
||||
OnlyDiffuse,
|
||||
|
||||
NumVertexTypes
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct CRendererInternals: Truly hide data that is supposed to be hidden
|
||||
* in this structure so it won't even appear in header files.
|
||||
@ -203,6 +210,55 @@ struct CRendererInternals
|
||||
/// Shadow map
|
||||
ShadowMap* shadow;
|
||||
|
||||
/// Various model renderers
|
||||
struct Models {
|
||||
// The following model renderers are aliases for the appropriate real_*
|
||||
// model renderers (depending on hardware availability and current settings)
|
||||
// and must be used for actual model submission and rendering
|
||||
ModelRenderer* Normal;
|
||||
ModelRenderer* NormalInstancing;
|
||||
ModelRenderer* Player;
|
||||
ModelRenderer* PlayerInstancing;
|
||||
ModelRenderer* Transp;
|
||||
|
||||
// "Palette" of available ModelRenderers. Do not use these directly for
|
||||
// rendering and submission; use the aliases above instead.
|
||||
ModelRenderer* pal_NormalFF[NumVertexTypes];
|
||||
ModelRenderer* pal_PlayerFF[NumVertexTypes];
|
||||
ModelRenderer* pal_NormalHWLit[NumVertexTypes];
|
||||
ModelRenderer* pal_PlayerHWLit[NumVertexTypes];
|
||||
ModelRenderer* pal_NormalInstancing[NumVertexTypes];
|
||||
ModelRenderer* pal_PlayerInstancing[NumVertexTypes];
|
||||
ModelRenderer* pal_TranspFF[NumVertexTypes];
|
||||
ModelRenderer* pal_TranspHWLit[NumVertexTypes];
|
||||
ModelRenderer* pal_TranspSortAll;
|
||||
|
||||
ModelVertexRendererPtr VertexFF[NumVertexTypes];
|
||||
ModelVertexRendererPtr VertexHWLit[NumVertexTypes];
|
||||
ModelVertexRendererPtr VertexInstancing[NumVertexTypes];
|
||||
ModelVertexRendererPtr VertexPolygonSort;
|
||||
|
||||
// generic RenderModifiers that are supposed to be used directly
|
||||
RenderModifierPtr ModWireframe;
|
||||
RenderModifierPtr ModSolidColor;
|
||||
RenderModifierPtr ModTransparentShadow;
|
||||
RenderModifierPtr ModTransparentDepthShadow;
|
||||
|
||||
// RenderModifiers that are selected from the palette below
|
||||
RenderModifierPtr ModNormal;
|
||||
RenderModifierPtr ModPlayer;
|
||||
RenderModifierPtr ModTransparent;
|
||||
|
||||
// Palette of available RenderModifiers
|
||||
RenderModifierPtr ModPlain;
|
||||
LitRenderModifierPtr ModPlainLit;
|
||||
RenderModifierPtr ModPlayerUnlit;
|
||||
LitRenderModifierPtr ModPlayerLit;
|
||||
RenderModifierPtr ModTransparentUnlit;
|
||||
LitRenderModifierPtr ModTransparentLit;
|
||||
} Model;
|
||||
|
||||
|
||||
CRendererInternals()
|
||||
: profileTable(g_Renderer.m_Stats)
|
||||
{
|
||||
@ -263,47 +319,61 @@ CRenderer::CRenderer()
|
||||
}
|
||||
|
||||
// model rendering
|
||||
m_Models.VertexFF = ModelVertexRendererPtr(new FixedFunctionModelRenderer);
|
||||
m->Model.VertexFF[AmbientDiffuse] = ModelVertexRendererPtr(new FixedFunctionModelRenderer(false));
|
||||
m->Model.VertexFF[OnlyDiffuse] = ModelVertexRendererPtr(new FixedFunctionModelRenderer(true));
|
||||
if (HWLightingModelRenderer::IsAvailable())
|
||||
m_Models.VertexHWLit = ModelVertexRendererPtr(new HWLightingModelRenderer);
|
||||
{
|
||||
m->Model.VertexHWLit[AmbientDiffuse] = ModelVertexRendererPtr(new HWLightingModelRenderer(false));
|
||||
m->Model.VertexHWLit[OnlyDiffuse] = ModelVertexRendererPtr(new HWLightingModelRenderer(true));
|
||||
}
|
||||
if (InstancingModelRenderer::IsAvailable())
|
||||
m_Models.VertexInstancing = ModelVertexRendererPtr(new InstancingModelRenderer);
|
||||
m_Models.VertexPolygonSort = ModelVertexRendererPtr(new PolygonSortModelRenderer);
|
||||
|
||||
m_Models.NormalFF = new BatchModelRenderer(m_Models.VertexFF);
|
||||
m_Models.PlayerFF = new BatchModelRenderer(m_Models.VertexFF);
|
||||
m_Models.TranspFF = new SortModelRenderer(m_Models.VertexFF);
|
||||
if (m_Models.VertexHWLit)
|
||||
{
|
||||
m_Models.NormalHWLit = new BatchModelRenderer(m_Models.VertexHWLit);
|
||||
m_Models.PlayerHWLit = new BatchModelRenderer(m_Models.VertexHWLit);
|
||||
m_Models.TranspHWLit = new SortModelRenderer(m_Models.VertexHWLit);
|
||||
m->Model.VertexInstancing[AmbientDiffuse] = ModelVertexRendererPtr(new InstancingModelRenderer(false));
|
||||
m->Model.VertexInstancing[OnlyDiffuse] = ModelVertexRendererPtr(new InstancingModelRenderer(true));
|
||||
}
|
||||
m->Model.VertexPolygonSort = ModelVertexRendererPtr(new PolygonSortModelRenderer);
|
||||
|
||||
for(int vertexType = 0; vertexType < NumVertexTypes; ++vertexType)
|
||||
{
|
||||
m->Model.pal_NormalFF[vertexType] = new BatchModelRenderer(m->Model.VertexFF[vertexType]);
|
||||
m->Model.pal_PlayerFF[vertexType] = new BatchModelRenderer(m->Model.VertexFF[vertexType]);
|
||||
m->Model.pal_TranspFF[vertexType] = new SortModelRenderer(m->Model.VertexFF[vertexType]);
|
||||
if (m->Model.VertexHWLit[vertexType])
|
||||
{
|
||||
m->Model.pal_NormalHWLit[vertexType] = new BatchModelRenderer(m->Model.VertexHWLit[vertexType]);
|
||||
m->Model.pal_PlayerHWLit[vertexType] = new BatchModelRenderer(m->Model.VertexHWLit[vertexType]);
|
||||
m->Model.pal_TranspHWLit[vertexType] = new SortModelRenderer(m->Model.VertexHWLit[vertexType]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Models.NormalHWLit = NULL;
|
||||
m_Models.PlayerHWLit = NULL;
|
||||
m_Models.TranspHWLit = NULL;
|
||||
m->Model.pal_NormalHWLit[vertexType] = NULL;
|
||||
m->Model.pal_PlayerHWLit[vertexType] = NULL;
|
||||
m->Model.pal_TranspHWLit[vertexType] = NULL;
|
||||
}
|
||||
if (m_Models.VertexInstancing)
|
||||
if (m->Model.VertexInstancing[vertexType])
|
||||
{
|
||||
m_Models.NormalInstancing = new BatchModelRenderer(m_Models.VertexInstancing);
|
||||
m_Models.PlayerInstancing = new BatchModelRenderer(m_Models.VertexInstancing);
|
||||
m->Model.pal_NormalInstancing[vertexType] = new BatchModelRenderer(m->Model.VertexInstancing[vertexType]);
|
||||
m->Model.pal_PlayerInstancing[vertexType] = new BatchModelRenderer(m->Model.VertexInstancing[vertexType]);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Models.NormalInstancing = NULL;
|
||||
m_Models.PlayerInstancing = NULL;
|
||||
m->Model.pal_NormalInstancing[vertexType] = NULL;
|
||||
m->Model.pal_PlayerInstancing[vertexType] = NULL;
|
||||
}
|
||||
}
|
||||
m_Models.TranspSortAll = new SortModelRenderer(m_Models.VertexPolygonSort);
|
||||
|
||||
m_Models.ModWireframe = RenderModifierPtr(new WireframeRenderModifier);
|
||||
m_Models.ModPlain = RenderModifierPtr(new PlainRenderModifier);
|
||||
m->Model.pal_TranspSortAll = new SortModelRenderer(m->Model.VertexPolygonSort);
|
||||
|
||||
m->Model.ModWireframe = RenderModifierPtr(new WireframeRenderModifier);
|
||||
m->Model.ModPlain = RenderModifierPtr(new PlainRenderModifier);
|
||||
m->Model.ModPlainLit = LitRenderModifierPtr(new PlainLitRenderModifier);
|
||||
SetFastPlayerColor(true);
|
||||
m_Models.ModSolidColor = RenderModifierPtr(new SolidColorRenderModifier);
|
||||
m_Models.ModTransparent = RenderModifierPtr(new TransparentRenderModifier);
|
||||
m_Models.ModTransparentShadow = RenderModifierPtr(new TransparentShadowRenderModifier);
|
||||
m_Models.ModTransparentDepthShadow = RenderModifierPtr(new TransparentDepthShadowModifier);
|
||||
m->Model.ModPlayerLit = LitRenderModifierPtr(new LitPlayerColorRender);
|
||||
m->Model.ModSolidColor = RenderModifierPtr(new SolidColorRenderModifier);
|
||||
m->Model.ModTransparentUnlit = RenderModifierPtr(new TransparentRenderModifier);
|
||||
m->Model.ModTransparentLit = LitRenderModifierPtr(new LitTransparentRenderModifier);
|
||||
m->Model.ModTransparentShadow = RenderModifierPtr(new TransparentShadowRenderModifier);
|
||||
m->Model.ModTransparentDepthShadow = RenderModifierPtr(new TransparentDepthShadowModifier);
|
||||
|
||||
m_ShadowZBias = 0.001f;
|
||||
|
||||
@ -319,15 +389,18 @@ CRenderer::CRenderer()
|
||||
CRenderer::~CRenderer()
|
||||
{
|
||||
// model rendering
|
||||
delete m_Models.NormalFF;
|
||||
delete m_Models.PlayerFF;
|
||||
delete m_Models.TranspFF;
|
||||
delete m_Models.NormalHWLit;
|
||||
delete m_Models.PlayerHWLit;
|
||||
delete m_Models.TranspHWLit;
|
||||
delete m_Models.NormalInstancing;
|
||||
delete m_Models.PlayerInstancing;
|
||||
delete m_Models.TranspSortAll;
|
||||
for(int vertexType = 0; vertexType < NumVertexTypes; ++vertexType)
|
||||
{
|
||||
delete m->Model.pal_NormalFF[vertexType];
|
||||
delete m->Model.pal_PlayerFF[vertexType];
|
||||
delete m->Model.pal_TranspFF[vertexType];
|
||||
delete m->Model.pal_NormalHWLit[vertexType];
|
||||
delete m->Model.pal_PlayerHWLit[vertexType];
|
||||
delete m->Model.pal_TranspHWLit[vertexType];
|
||||
delete m->Model.pal_NormalInstancing[vertexType];
|
||||
delete m->Model.pal_PlayerInstancing[vertexType];
|
||||
}
|
||||
delete m->Model.pal_TranspSortAll;
|
||||
|
||||
// general
|
||||
delete m_VertexShader;
|
||||
@ -514,7 +587,7 @@ void CRenderer::SetRenderPath(RenderPath rp)
|
||||
{
|
||||
if (rp == RP_DEFAULT)
|
||||
{
|
||||
if (m_Models.NormalHWLit && m_Models.PlayerHWLit)
|
||||
if (m->Model.pal_NormalHWLit && m->Model.pal_PlayerHWLit)
|
||||
rp = RP_VERTEXSHADER;
|
||||
else
|
||||
rp = RP_FIXED;
|
||||
@ -522,7 +595,7 @@ void CRenderer::SetRenderPath(RenderPath rp)
|
||||
|
||||
if (rp == RP_VERTEXSHADER)
|
||||
{
|
||||
if (!m_Models.NormalHWLit || !m_Models.PlayerHWLit)
|
||||
if (!m->Model.pal_NormalHWLit || !m->Model.pal_PlayerHWLit)
|
||||
{
|
||||
LOG(WARNING, LOG_CATEGORY, "Falling back to fixed function\n");
|
||||
rp = RP_FIXED;
|
||||
@ -573,9 +646,9 @@ void CRenderer::SetFastPlayerColor(bool fast)
|
||||
}
|
||||
|
||||
if (m_FastPlayerColor)
|
||||
m_Models.ModPlayer = RenderModifierPtr(new FastPlayerColorRender);
|
||||
m->Model.ModPlayerUnlit = RenderModifierPtr(new FastPlayerColorRender);
|
||||
else
|
||||
m_Models.ModPlayer = RenderModifierPtr(new SlowPlayerColorRender);
|
||||
m->Model.ModPlayerUnlit = RenderModifierPtr(new SlowPlayerColorRender);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -598,8 +671,65 @@ void CRenderer::BeginFrame()
|
||||
|
||||
// init per frame stuff
|
||||
m->shadow->SetupFrame(m_CullCamera, m_LightEnv->GetSunDir());
|
||||
|
||||
// choose model renderers for this frame
|
||||
int vertexType;
|
||||
|
||||
if (m_Options.m_Shadows && m->shadow->GetUseDepthTexture())
|
||||
{
|
||||
vertexType = OnlyDiffuse;
|
||||
m->Model.ModNormal = m->Model.ModPlainLit;
|
||||
m->Model.ModPlainLit->SetShadowMap(m->shadow);
|
||||
m->Model.ModPlainLit->SetLightEnv(m_LightEnv);
|
||||
|
||||
m->Model.ModPlayer = m->Model.ModPlayerLit;
|
||||
m->Model.ModPlayerLit->SetShadowMap(m->shadow);
|
||||
m->Model.ModPlayerLit->SetLightEnv(m_LightEnv);
|
||||
|
||||
m->Model.ModTransparent = m->Model.ModTransparentLit;
|
||||
m->Model.ModTransparentLit->SetShadowMap(m->shadow);
|
||||
m->Model.ModTransparentLit->SetLightEnv(m_LightEnv);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexType = AmbientDiffuse;
|
||||
m->Model.ModNormal = m->Model.ModPlain;
|
||||
m->Model.ModPlayer = m->Model.ModPlayerUnlit;
|
||||
m->Model.ModTransparent = m->Model.ModTransparentUnlit;
|
||||
}
|
||||
|
||||
if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
{
|
||||
if (m->Model.pal_NormalInstancing)
|
||||
m->Model.NormalInstancing = m->Model.pal_NormalInstancing[vertexType];
|
||||
else
|
||||
m->Model.NormalInstancing = m->Model.pal_NormalHWLit[vertexType];
|
||||
m->Model.Normal = m->Model.pal_NormalHWLit[vertexType];
|
||||
|
||||
if (m->Model.pal_PlayerInstancing)
|
||||
m->Model.PlayerInstancing = m->Model.pal_PlayerInstancing[vertexType];
|
||||
else
|
||||
m->Model.PlayerInstancing = m->Model.pal_PlayerHWLit[vertexType];
|
||||
m->Model.Player = m->Model.pal_PlayerHWLit[vertexType];
|
||||
}
|
||||
else
|
||||
{
|
||||
m->Model.NormalInstancing = m->Model.pal_NormalFF[vertexType];
|
||||
m->Model.Normal = m->Model.pal_NormalFF[vertexType];
|
||||
|
||||
m->Model.PlayerInstancing = m->Model.pal_PlayerFF[vertexType];
|
||||
m->Model.Player = m->Model.pal_PlayerFF[vertexType];
|
||||
}
|
||||
|
||||
if (m_SortAllTransparent)
|
||||
m->Model.Transp = m->Model.pal_TranspSortAll;
|
||||
else if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
m->Model.Transp = m->Model.pal_TranspHWLit[vertexType];
|
||||
else
|
||||
m->Model.Transp = m->Model.pal_TranspFF[vertexType];
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetClearColor: set color used to clear screen in BeginFrame()
|
||||
void CRenderer::SetClearColor(u32 color)
|
||||
@ -620,10 +750,10 @@ void CRenderer::RenderShadowMap()
|
||||
glColor3f(shadowTransp, shadowTransp, shadowTransp);
|
||||
|
||||
// Figure out transparent rendering strategy
|
||||
RenderModifierPtr transparentShadows = m_Models.ModTransparentShadow;
|
||||
RenderModifierPtr transparentShadows = m->Model.ModTransparentShadow;
|
||||
|
||||
if (m->shadow->GetUseDepthTexture())
|
||||
transparentShadows = m_Models.ModTransparentDepthShadow;
|
||||
transparentShadows = m->Model.ModTransparentDepthShadow;
|
||||
|
||||
// Render all closed models (i.e. models where rendering back faces will produce
|
||||
// the correct result)
|
||||
@ -637,22 +767,14 @@ void CRenderer::RenderShadowMap()
|
||||
// Render models that aren't closed
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
m_Models.NormalFF->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
m_Models.PlayerFF->Render(m_Models.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
if (m_Models.NormalHWLit)
|
||||
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->Model.Normal->Render(m->Model.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
if (m->Model.Normal != m->Model.NormalInstancing)
|
||||
m->Model.NormalInstancing->Render(m->Model.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
m->Model.Player->Render(m->Model.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
if (m->Model.Player != m->Model.PlayerInstancing)
|
||||
m->Model.PlayerInstancing->Render(m->Model.ModSolidColor, MODELFLAG_CASTSHADOWS);
|
||||
|
||||
|
||||
m_Models.TranspFF->Render(transparentShadows, MODELFLAG_CASTSHADOWS);
|
||||
if (m_Models.TranspHWLit)
|
||||
m_Models.TranspHWLit->Render(transparentShadows, MODELFLAG_CASTSHADOWS);
|
||||
m_Models.TranspSortAll->Render(transparentShadows, MODELFLAG_CASTSHADOWS);
|
||||
m->Model.Transp->Render(transparentShadows, MODELFLAG_CASTSHADOWS);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
@ -722,31 +844,23 @@ void CRenderer::RenderModels()
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
}
|
||||
|
||||
m_Models.NormalFF->Render(m_Models.ModPlain, 0);
|
||||
m_Models.PlayerFF->Render(m_Models.ModPlayer, 0);
|
||||
if (m_Models.NormalHWLit)
|
||||
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);
|
||||
m->Model.Normal->Render(m->Model.ModNormal, 0);
|
||||
m->Model.Player->Render(m->Model.ModPlayer, 0);
|
||||
if (m->Model.Normal != m->Model.NormalInstancing)
|
||||
m->Model.NormalInstancing->Render(m->Model.ModNormal, 0);
|
||||
if (m->Model.Player != m->Model.PlayerInstancing)
|
||||
m->Model.PlayerInstancing->Render(m->Model.ModPlayer, 0);
|
||||
|
||||
if (m_ModelRenderMode==WIREFRAME) {
|
||||
// switch wireframe off again
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
} else if (m_ModelRenderMode==EDGED_FACES) {
|
||||
m_Models.NormalFF->Render(m_Models.ModWireframe, 0);
|
||||
m_Models.PlayerFF->Render(m_Models.ModWireframe, 0);
|
||||
if (m_Models.NormalHWLit)
|
||||
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);
|
||||
m->Model.Normal->Render(m->Model.ModWireframe, 0);
|
||||
m->Model.Player->Render(m->Model.ModWireframe, 0);
|
||||
if (m->Model.Normal != m->Model.NormalInstancing)
|
||||
m->Model.NormalInstancing->Render(m->Model.ModWireframe, 0);
|
||||
if (m->Model.Player != m->Model.PlayerInstancing)
|
||||
m->Model.PlayerInstancing->Render(m->Model.ModWireframe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -759,19 +873,13 @@ void CRenderer::RenderTransparentModels()
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
|
||||
}
|
||||
|
||||
m_Models.TranspFF->Render(m_Models.ModTransparent, 0);
|
||||
if (m_Models.TranspHWLit)
|
||||
m_Models.TranspHWLit->Render(m_Models.ModTransparent, 0);
|
||||
m_Models.TranspSortAll->Render(m_Models.ModTransparent, 0);
|
||||
m->Model.Transp->Render(m->Model.ModTransparent, 0);
|
||||
|
||||
if (m_ModelRenderMode==WIREFRAME) {
|
||||
// switch wireframe off again
|
||||
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
||||
} else if (m_ModelRenderMode==EDGED_FACES) {
|
||||
m_Models.TranspFF->Render(m_Models.ModWireframe, 0);
|
||||
if (m_Models.TranspHWLit)
|
||||
m_Models.TranspHWLit->Render(m_Models.ModWireframe, 0);
|
||||
m_Models.TranspSortAll->Render(m_Models.ModWireframe, 0);
|
||||
m->Model.Transp->Render(m->Model.ModWireframe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,20 +896,13 @@ void CRenderer::FlushFrame()
|
||||
|
||||
// Prepare model renderers
|
||||
PROFILE_START("prepare models");
|
||||
m_Models.NormalFF->PrepareModels();
|
||||
m_Models.PlayerFF->PrepareModels();
|
||||
m_Models.TranspFF->PrepareModels();
|
||||
if (m_Models.NormalHWLit)
|
||||
m_Models.NormalHWLit->PrepareModels();
|
||||
if (m_Models.PlayerHWLit)
|
||||
m_Models.PlayerHWLit->PrepareModels();
|
||||
if (m_Models.TranspHWLit)
|
||||
m_Models.TranspHWLit->PrepareModels();
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->PrepareModels();
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->PrepareModels();
|
||||
m_Models.TranspSortAll->PrepareModels();
|
||||
m->Model.Normal->PrepareModels();
|
||||
m->Model.Player->PrepareModels();
|
||||
if (m->Model.Normal != m->Model.NormalInstancing)
|
||||
m->Model.NormalInstancing->PrepareModels();
|
||||
if (m->Model.Player != m->Model.PlayerInstancing)
|
||||
m->Model.PlayerInstancing->PrepareModels();
|
||||
m->Model.Transp->PrepareModels();
|
||||
PROFILE_END("prepare models");
|
||||
|
||||
PROFILE_START("prepare terrain");
|
||||
@ -862,20 +963,13 @@ void CRenderer::FlushFrame()
|
||||
m->terrainRenderer->EndFrame();
|
||||
|
||||
// Finish model renderers
|
||||
m_Models.NormalFF->EndFrame();
|
||||
m_Models.PlayerFF->EndFrame();
|
||||
m_Models.TranspFF->EndFrame();
|
||||
if (m_Models.NormalHWLit)
|
||||
m_Models.NormalHWLit->EndFrame();
|
||||
if (m_Models.PlayerHWLit)
|
||||
m_Models.PlayerHWLit->EndFrame();
|
||||
if (m_Models.TranspHWLit)
|
||||
m_Models.TranspHWLit->EndFrame();
|
||||
if (m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->EndFrame();
|
||||
if (m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->EndFrame();
|
||||
m_Models.TranspSortAll->EndFrame();
|
||||
m->Model.Normal->EndFrame();
|
||||
m->Model.Player->EndFrame();
|
||||
if (m->Model.Normal != m->Model.NormalInstancing)
|
||||
m->Model.NormalInstancing->EndFrame();
|
||||
if (m->Model.Player != m->Model.PlayerInstancing)
|
||||
m->Model.PlayerInstancing->EndFrame();
|
||||
m->Model.Transp->EndFrame();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -968,36 +1062,21 @@ void CRenderer::Submit(CModel* model)
|
||||
|
||||
if (model->GetMaterial().IsPlayer())
|
||||
{
|
||||
if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
{
|
||||
if (canUseInstancing && m_Models.PlayerInstancing)
|
||||
m_Models.PlayerInstancing->Submit(model);
|
||||
if (canUseInstancing)
|
||||
m->Model.PlayerInstancing->Submit(model);
|
||||
else
|
||||
m_Models.PlayerHWLit->Submit(model);
|
||||
}
|
||||
else
|
||||
m_Models.PlayerFF->Submit(model);
|
||||
m->Model.Player->Submit(model);
|
||||
}
|
||||
else if (model->GetMaterial().UsesAlpha())
|
||||
{
|
||||
if (m_SortAllTransparent)
|
||||
m_Models.TranspSortAll->Submit(model);
|
||||
else if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
m_Models.TranspHWLit->Submit(model);
|
||||
else
|
||||
m_Models.TranspFF->Submit(model);
|
||||
m->Model.Transp->Submit(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Options.m_RenderPath == RP_VERTEXSHADER)
|
||||
{
|
||||
if (canUseInstancing && m_Models.NormalInstancing)
|
||||
m_Models.NormalInstancing->Submit(model);
|
||||
if (canUseInstancing)
|
||||
m->Model.NormalInstancing->Submit(model);
|
||||
else
|
||||
m_Models.NormalHWLit->Submit(model);
|
||||
}
|
||||
else
|
||||
m_Models.NormalFF->Submit(model);
|
||||
m->Model.Normal->Submit(model);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,7 @@ enum ERenderMode { WIREFRAME, SOLID, EDGED_FACES };
|
||||
#define STREAM_UV2 0x20
|
||||
#define STREAM_UV3 0x40
|
||||
#define STREAM_POSTOUV0 0x80
|
||||
#define STREAM_TEXGENTOUV1 0x100
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SVertex3D: simple 3D vertex declaration
|
||||
@ -429,33 +430,6 @@ protected:
|
||||
*/
|
||||
bool m_DisableCopyShadow;
|
||||
|
||||
// Various model renderers
|
||||
struct Models {
|
||||
ModelRenderer* NormalFF;
|
||||
ModelRenderer* PlayerFF;
|
||||
ModelRenderer* NormalHWLit;
|
||||
ModelRenderer* PlayerHWLit;
|
||||
ModelRenderer* NormalInstancing;
|
||||
ModelRenderer* PlayerInstancing;
|
||||
|
||||
ModelRenderer* TranspFF;
|
||||
ModelRenderer* TranspHWLit;
|
||||
ModelRenderer* TranspSortAll;
|
||||
|
||||
ModelVertexRendererPtr VertexFF;
|
||||
ModelVertexRendererPtr VertexHWLit;
|
||||
ModelVertexRendererPtr VertexInstancing;
|
||||
ModelVertexRendererPtr VertexPolygonSort;
|
||||
|
||||
RenderModifierPtr ModWireframe;
|
||||
RenderModifierPtr ModPlain;
|
||||
RenderModifierPtr ModPlayer;
|
||||
RenderModifierPtr ModSolidColor;
|
||||
RenderModifierPtr ModTransparent;
|
||||
RenderModifierPtr ModTransparentShadow;
|
||||
RenderModifierPtr ModTransparentDepthShadow;
|
||||
} m_Models;
|
||||
|
||||
public:
|
||||
/**
|
||||
* m_ShadowZBias: Z bias used when rendering shadows into a depth texture.
|
||||
|
@ -346,12 +346,12 @@ void ShadowMap::EndRender()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Retrieve the texture handle and texture matrix for shadowing
|
||||
GLuint ShadowMap::GetTexture()
|
||||
GLuint ShadowMap::GetTexture() const
|
||||
{
|
||||
return m->Texture;
|
||||
}
|
||||
|
||||
const CMatrix3D& ShadowMap::GetTextureMatrix()
|
||||
const CMatrix3D& ShadowMap::GetTextureMatrix() const
|
||||
{
|
||||
return m->TextureMatrix;
|
||||
}
|
||||
@ -359,7 +359,7 @@ const CMatrix3D& ShadowMap::GetTextureMatrix()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Using depth textures vs. a simple luminance map
|
||||
bool ShadowMap::GetUseDepthTexture()
|
||||
bool ShadowMap::GetUseDepthTexture() const
|
||||
{
|
||||
return m->UseDepthTexture;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ public:
|
||||
*
|
||||
* @return whether shadow rendering uses depth textures
|
||||
*/
|
||||
bool GetUseDepthTexture();
|
||||
bool GetUseDepthTexture() const;
|
||||
|
||||
/**
|
||||
* SetUseDepthTexture: Set whether shadowing should use depth textures.
|
||||
@ -109,7 +109,7 @@ public:
|
||||
*
|
||||
* @return the texture name of the shadow map texture
|
||||
*/
|
||||
GLuint GetTexture();
|
||||
GLuint GetTexture() const;
|
||||
|
||||
/**
|
||||
* GetTextureMatrix: Retrieve the world-space to shadow map texture coordinates
|
||||
@ -118,7 +118,7 @@ public:
|
||||
* @return the matrix that transforms world-space coordinates into homogenous
|
||||
* shadow map texture coordinates
|
||||
*/
|
||||
const CMatrix3D& GetTextureMatrix();
|
||||
const CMatrix3D& GetTextureMatrix() const;
|
||||
|
||||
/**
|
||||
* RenderDebugDisplay: Visualize shadow mapping calculations to help in
|
||||
|
@ -21,12 +21,14 @@
|
||||
#include "Vector3D.h"
|
||||
#include "Vector4D.h"
|
||||
|
||||
#include "graphics/LightEnv.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "graphics/ModelDef.h"
|
||||
|
||||
#include "ps/Profile.h"
|
||||
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/ShadowMap.h"
|
||||
#include "renderer/TransparencyRenderer.h"
|
||||
#include "renderer/VertexArray.h"
|
||||
|
||||
@ -235,7 +237,7 @@ void PolygonSortModelRenderer::UpdateModelData(CModel* model, void* data, u32 up
|
||||
|
||||
VertexArrayIterator<SColor4ub> Color = psmdl->m_Color.GetIterator<SColor4ub>();
|
||||
|
||||
ModelRenderer::BuildColor4ub(model, Normal, Color);
|
||||
ModelRenderer::BuildColor4ub(model, Normal, Color, false);
|
||||
|
||||
// upload everything to vertex buffer
|
||||
psmdl->m_Array.Upload();
|
||||
@ -266,8 +268,10 @@ void PolygonSortModelRenderer::DestroyModelData(CModel* UNUSED(model), void* dat
|
||||
|
||||
|
||||
// Prepare for one rendering pass
|
||||
void PolygonSortModelRenderer::BeginPass(uint streamflags)
|
||||
void PolygonSortModelRenderer::BeginPass(uint streamflags, const CMatrix3D* UNUSED(texturematrix))
|
||||
{
|
||||
debug_assert(streamflags == streamflags & (STREAM_POS|STREAM_COLOR|STREAM_UV0));
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (streamflags & STREAM_UV0) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
@ -477,10 +481,14 @@ void SortModelRenderer::Render(RenderModifierPtr modifier, u32 flags)
|
||||
do
|
||||
{
|
||||
u32 streamflags = modifier->BeginPass(pass);
|
||||
const CMatrix3D* texturematrix = 0;
|
||||
CModelDefPtr lastmdef;
|
||||
CTexture* lasttex = 0;
|
||||
|
||||
m->vertexRenderer->BeginPass(streamflags);
|
||||
if (streamflags & STREAM_TEXGENTOUV1)
|
||||
texturematrix = modifier->GetTexGenMatrix(pass);
|
||||
|
||||
m->vertexRenderer->BeginPass(streamflags, texturematrix);
|
||||
|
||||
for(std::vector<SModel*>::iterator it = m->models.begin(); it != m->models.end(); ++it)
|
||||
{
|
||||
@ -608,6 +616,143 @@ void TransparentRenderModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(m
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LitTransparentRenderModifier implementation
|
||||
|
||||
LitTransparentRenderModifier::LitTransparentRenderModifier()
|
||||
{
|
||||
}
|
||||
|
||||
LitTransparentRenderModifier::~LitTransparentRenderModifier()
|
||||
{
|
||||
}
|
||||
|
||||
u32 LitTransparentRenderModifier::BeginPass(uint pass)
|
||||
{
|
||||
debug_assert(GetShadowMap() && GetShadowMap()->GetUseDepthTexture());
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
// First pass: Put down Z for opaque parts of the model,
|
||||
// don't touch the color buffer.
|
||||
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_CONSTANT);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_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);
|
||||
|
||||
// Set the proper LOD bias
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
|
||||
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_GREATER,0.975f);
|
||||
|
||||
// render everything with color writes off to setup depth buffer correctly
|
||||
glColorMask(0,0,0,0);
|
||||
|
||||
return STREAM_POS|STREAM_UV0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second pass: Put down color, disable Z write
|
||||
glColorMask(1,1,1,1);
|
||||
|
||||
glDepthMask(0);
|
||||
|
||||
// Ambient + Diffuse * Shadow
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
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_PRIMARY_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE1);
|
||||
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);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->GetTexture());
|
||||
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);
|
||||
|
||||
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &GetLightEnv()->m_UnitsAmbientColor.X);
|
||||
|
||||
// Incoming color is ambient + diffuse light
|
||||
pglActiveTextureARB(GL_TEXTURE2);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, GetShadowMap()->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_TEXTURE0);
|
||||
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_TEXTURE0);
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
glAlphaFunc(GL_GREATER,0);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Set the proper LOD bias
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, g_Renderer.m_Options.m_LodBias);
|
||||
|
||||
return STREAM_POS|STREAM_COLOR|STREAM_UV0|STREAM_TEXGENTOUV1;
|
||||
}
|
||||
}
|
||||
|
||||
bool LitTransparentRenderModifier::EndPass(uint pass)
|
||||
{
|
||||
if (pass == 0)
|
||||
return false; // multi-pass
|
||||
|
||||
pglActiveTextureARB(GL_TEXTURE1);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
pglActiveTextureARB(GL_TEXTURE2);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
pglActiveTextureARB(GL_TEXTURE0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDepthMask(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const CMatrix3D* LitTransparentRenderModifier::GetTexGenMatrix(uint UNUSED(pass))
|
||||
{
|
||||
return &GetShadowMap()->GetTextureMatrix();
|
||||
}
|
||||
|
||||
void LitTransparentRenderModifier::PrepareTexture(uint UNUSED(pass), CTexture* texture)
|
||||
{
|
||||
g_Renderer.SetTexture(0, texture);
|
||||
}
|
||||
|
||||
void LitTransparentRenderModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(model))
|
||||
{
|
||||
// No per-model setup necessary
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TransparentShadowRenderModifier implementation
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
void UpdateModelData(CModel* model, void* data, u32 updateflags);
|
||||
void DestroyModelData(CModel* model, void* data);
|
||||
|
||||
void BeginPass(uint streamflags);
|
||||
void BeginPass(uint streamflags, const CMatrix3D* texturematrix);
|
||||
void EndPass(uint streamflags);
|
||||
void PrepareModelDef(uint streamflags, CModelDefPtr def);
|
||||
void RenderModel(uint streamflags, CModel* model, void* data);
|
||||
@ -100,6 +100,30 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class LitTransparentRenderModifier: Modifier for transparent models,
|
||||
* including alpha blending and shadowed lighting.
|
||||
*
|
||||
* @note Use only when depth textures are used for shadows and thus supported by the OpenGL
|
||||
* implementation.
|
||||
*/
|
||||
class LitTransparentRenderModifier : public LitRenderModifier
|
||||
{
|
||||
public:
|
||||
LitTransparentRenderModifier();
|
||||
~LitTransparentRenderModifier();
|
||||
|
||||
// Implementation
|
||||
u32 BeginPass(uint pass);
|
||||
bool EndPass(uint pass);
|
||||
const CMatrix3D* GetTexGenMatrix(uint pass);
|
||||
void PrepareTexture(uint pass, CTexture* texture);
|
||||
void PrepareModel(uint pass, CModel* model);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class TransparentShadowRenderModifier: Use to render shadow data for
|
||||
* transparent models into a luminance map.
|
||||
|
Loading…
Reference in New Issue
Block a user