1
0
forked from 0ad/0ad
0ad/source/terrain/TransparencyRenderer.cpp
2004-04-13 11:09:36 +00:00

139 lines
4.1 KiB
C++
Executable File

#include <algorithm>
#include "Renderer.h"
#include "TransparencyRenderer.h"
#include "terrain/Model.h"
#include "terrain/Visual.h"
extern CRenderer g_Renderer;
CTransparencyRenderer g_TransparencyRenderer;
struct SortObjectsByDist {
typedef CTransparencyRenderer::SObject SortObj;
bool operator()(const SortObj& lhs,const SortObj& rhs) {
return lhs.m_Dist>rhs.m_Dist? true : false;
}
};
void CTransparencyRenderer::Render()
{
// coarsely sort submitted objects in back to front manner
std::sort(m_Objects.begin(),m_Objects.end(),SortObjectsByDist());
// switch on wireframe if we need it
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
}
// switch on client states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// setup texture environment to modulate diffuse color with texture color
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
// just pass through texture's alpha
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER,0.975f);
uint i;
for (i=0;i<m_Objects.size();++i) {
CVisual* visual=m_Objects[i].m_Visual;
CModelRData* modeldata=(CModelRData*) visual->m_Model->m_RenderData;
modeldata->Render(visual->GetTransform(),true);
}
glDepthMask(0);
glAlphaFunc(GL_LEQUAL,0.975f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
for (i=0;i<m_Objects.size();++i) {
CVisual* visual=m_Objects[i].m_Visual;
CModelRData* modeldata=(CModelRData*) visual->m_Model->m_RenderData;
modeldata->Render(visual->GetTransform(),true);
}
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glDepthMask(1);
// switch off client states
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (g_Renderer.m_ModelRenderMode==WIREFRAME) {
// switch wireframe off again
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
} else if (g_Renderer.m_ModelRenderMode==EDGED_FACES) {
// edged faces: need to make a second pass over the data:
// first switch on wireframe
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
// setup some renderstate ..
glDepthMask(0);
g_Renderer.SetTexture(0,0);
glColor4f(1,1,1,0.75f);
glLineWidth(1.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
// .. and some client states
glEnableClientState(GL_VERTEX_ARRAY);
// render each model
for (uint i=0;i<m_Objects.size();++i) {
CVisual* visual=m_Objects[i].m_Visual;
CModelRData* modeldata=(CModelRData*) visual->m_Model->m_RenderData;
modeldata->RenderWireframe(visual->GetTransform(),true);
}
// .. and switch off the client states
glDisableClientState(GL_VERTEX_ARRAY);
// .. and restore the renderstates
glDisable(GL_BLEND);
glDepthMask(1);
// restore fill mode, and we're done
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}
// all transparent objects rendered; release them
m_Objects.clear();
}
void CTransparencyRenderer::Add(CVisual* visual)
{
// resize array, get last object in list
m_Objects.resize(m_Objects.size()+1);
SObject& obj=m_Objects.back();
obj.m_Visual=visual;
// build transform from object to camera space
CMatrix3D objToCam,invcam;
g_Renderer.m_Camera.m_Orientation.Invert(objToCam);
objToCam*=visual->GetTransform();
// resort model indices from back to front, according to camera position - and store
// the returned sqrd distance to the centre of the nearest triangle
CModelRData* modeldata=(CModelRData*) visual->m_Model->m_RenderData;
obj.m_Dist=modeldata->BackToFrontIndexSort(objToCam);
}