📄 unitdrawer.cpp
字号:
}
for (ui = drawRadarIcon.begin(); ui != drawRadarIcon.end(); ++ui) {
DrawIcon(*ui, true);
}
glDisable(GL_TEXTURE_2D);
for (ui = drawStat.begin(); ui != drawStat.end(); ++ui) {
(*ui)->DrawStats();
}
}
glDisable(GL_TEXTURE_2D);
}
/******************************************************************************/
/******************************************************************************/
static void DrawBins(LuaMatType type)
{
const LuaMatBinSet& bins = luaMatHandler.GetBins(type);
if (bins.empty()) {
return;
}
luaDrawing = true;
glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT);
const LuaMaterial* currMat = &LuaMaterial::defMat;
LuaMatBinSet::const_iterator it;
for (it = bins.begin(); it != bins.end(); ++it) {
LuaMatBin* bin = *it;
bin->Execute(*currMat);
currMat = (LuaMaterial*)bin;
const vector<CUnit*>& units = bin->GetUnits();
const int count = (int)units.size();
for (int i = 0; i < count; i++) {
CUnit* unit = units[i];
const LuaUnitMaterial& unitMat = unit->luaMats[type];
const LuaUnitLODMaterial* lodMat = unitMat.GetMaterial(unit->currentLOD);
lodMat->uniforms.Execute(unit);
unitDrawer->SetS3OTeamColour(unit->team);
unit->DrawWithLists(lodMat->preDisplayList, lodMat->postDisplayList);
}
}
LuaMaterial::defMat.Execute(*currMat);
luaMatHandler.ClearBins(type);
glPopAttrib();
luaDrawing = false;
}
/******************************************************************************/
static void SetupShadowDrawing()
{
glColor3f(1.0f, 1.0f, 1.0f);
glDisable(GL_TEXTURE_2D);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, unitDrawer->unitShadowGenVP);
glEnable(GL_VERTEX_PROGRAM_ARB);
glPolygonOffset(1.0f, 1.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
const CShadowHandler* sh = shadowHandler;
glProgramEnvParameter4fARB(
GL_VERTEX_PROGRAM_ARB, 16, sh->xmid, sh->ymid, 0.0f, 0.0f);
glProgramEnvParameter4fARB(
GL_VERTEX_PROGRAM_ARB, 17, sh->p17, sh->p17, 0.0f, 0.0f);
glProgramEnvParameter4fARB(
GL_VERTEX_PROGRAM_ARB, 18, sh->p18, sh->p18, 0.0f, 0.0f);
}
static void CleanUpShadowDrawing()
{
glDisable(GL_VERTEX_PROGRAM_ARB);
glDisable(GL_POLYGON_OFFSET_FILL);
}
/******************************************************************************/
static void SetupOpaque3DO() { unitDrawer->SetupForUnitDrawing(); }
static void ResetOpaque3DO() { unitDrawer->CleanUpUnitDrawing(); }
static void SetupOpaqueS3O() { unitDrawer->SetupForS3ODrawing(); }
static void ResetOpaqueS3O() { unitDrawer->CleanUpS3ODrawing(); }
static void SetupAlpha3DO() { unitDrawer->SetupForGhostDrawing(); }
static void ResetAlpha3DO() { unitDrawer->CleanUpGhostDrawing(); }
static void SetupAlphaS3O() { unitDrawer->SetupForGhostDrawing();
unitDrawer->SetupForGhostDrawingS3O(); }
static void ResetAlphaS3O() { unitDrawer->CleanUpGhostDrawing(); }
static void SetupShadow3DO() { SetupShadowDrawing(); }
static void ResetShadow3DO() { CleanUpShadowDrawing(); }
static void SetupShadowS3O() { SetupShadowDrawing(); }
static void ResetShadowS3O() { CleanUpShadowDrawing(); }
/******************************************************************************/
void CUnitDrawer::DrawOpaqueShaderUnits()
{
luaMatHandler.setup3doShader = SetupOpaque3DO;
luaMatHandler.reset3doShader = ResetOpaque3DO;
luaMatHandler.setupS3oShader = SetupOpaqueS3O;
luaMatHandler.resetS3oShader = ResetOpaqueS3O;
const LuaMatType matType =
(water->drawReflection) ? LUAMAT_OPAQUE_REFLECT : LUAMAT_OPAQUE;
DrawBins(matType);
}
void CUnitDrawer::DrawCloakedShaderUnits()
{
luaMatHandler.setup3doShader = SetupAlpha3DO;
luaMatHandler.reset3doShader = ResetAlpha3DO;
luaMatHandler.setupS3oShader = SetupAlphaS3O;
luaMatHandler.resetS3oShader = ResetAlphaS3O;
const LuaMatType matType =
(water->drawReflection) ? LUAMAT_ALPHA_REFLECT : LUAMAT_ALPHA;
DrawBins(matType);
}
void CUnitDrawer::DrawShadowShaderUnits()
{
luaMatHandler.setup3doShader = SetupShadow3DO;
luaMatHandler.reset3doShader = ResetShadow3DO;
luaMatHandler.setupS3oShader = SetupShadowS3O;
luaMatHandler.resetS3oShader = ResetShadowS3O;
DrawBins(LUAMAT_SHADOW);
}
/******************************************************************************/
/******************************************************************************/
void CUnitDrawer::DrawShadowPass(void)
{
ASSERT_UNSYNCED_MODE;
glColor3f(1.0f, 1.0f, 1.0f);
glDisable(GL_TEXTURE_2D);
// glEnable(GL_TEXTURE_2D);
// texturehandler->SetTexture();
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, unitShadowGenVP);
glEnable(GL_VERTEX_PROGRAM_ARB);
glPolygonOffset(1.0f, 1.0f);
glEnable(GL_POLYGON_OFFSET_FILL);
CUnit::SetLODFactor(LODScale * LODScaleShadow);
list<CUnit*>::iterator usi;
for (usi = uh->activeUnits.begin(); usi != uh->activeUnits.end(); ++usi) {
CUnit* unit = *usi;
if ((gs->Ally(unit->allyteam, gu->myAllyTeam) ||
(unit->losStatus[gu->myAllyTeam] & LOS_INLOS) ||
gu->spectatingFullView)
&& camera->InView(unit->midPos, unit->radius + 700)) {
// FIXME: test against the shadow projection intersection
float sqDist = (unit->pos-camera->pos).SqLength();
float farLength = unit->sqRadius * (unitDrawDist * unitDrawDist);
if (sqDist < farLength) {
float iconDistMult = iconHandler->GetDistance(unit->unitDef->iconType);
float realIconLength = iconLength * (iconDistMult * iconDistMult);
if (sqDist < realIconLength) {
if (!unit->isCloaked) {
if (unit->lodCount <= 0) {
unit->Draw();
} else {
LuaUnitMaterial& unitMat = unit->luaMats[LUAMAT_SHADOW];
const unsigned lod = unit->CalcLOD(unitMat.GetLastLOD());
unit->currentLOD = lod;
LuaUnitLODMaterial* lodMat = unitMat.GetMaterial(lod);
if ((lodMat != NULL) && lodMat->IsActive()) {
lodMat->AddUnit(unit);
} else {
unit->Draw();
}
}
}
}
}
}
}
glDisable(GL_VERTEX_PROGRAM_ARB);
glDisable(GL_POLYGON_OFFSET_FILL);
DrawShadowShaderUnits();
// glDisable(GL_TEXTURE_2D);
}
inline void CUnitDrawer::DrawFar(CUnit *unit)
{
float3 interPos = unit->pos + unit->speed * gu->timeOffset + UpVector * unit->model->height * 0.5f;
int snurr =- unit->heading + GetHeadingFromVector(camera->pos.x - unit->pos.x, camera->pos.z - unit->pos.z) + (0xffff >> 4);
if (snurr < 0)
snurr += 0xffff;
if (snurr > 0xffff)
snurr -= 0xffff;
snurr = snurr >> 13;
float r = 1.0f / 64.0f;
float tx = (unit->model->farTextureNum % 8) * (1.0f / 8.0f) + snurr * r;
float ty = (unit->model->farTextureNum / 8) * r;
float offset = 0;
va->AddVertexTN(interPos - (camera->up * unit->radius * 1.4f - offset) + camera->right * unit->radius, tx, ty, camNorm);
va->AddVertexTN(interPos + (camera->up * unit->radius * 1.4f + offset) + camera->right * unit->radius, tx, ty + r, camNorm);
va->AddVertexTN(interPos + (camera->up * unit->radius * 1.4f + offset) - camera->right * unit->radius, tx + r, ty + r, camNorm);
va->AddVertexTN(interPos - (camera->up * unit->radius * 1.4f - offset) - camera->right * unit->radius, tx + r, ty, camNorm);
}
void CUnitDrawer::DrawIcon(CUnit * unit, bool asRadarBlip)
{
// If the icon is to be drawn as a radar blip, we want to get the default icon.
std::string iconType;
if(asRadarBlip){
iconType="default";
} else {
iconType=unit->unitDef->iconType;
}
// Fetch the icon information.
CIcon* icon=iconHandler->GetIcon(iconType);
unsigned char color[4];
color[3]=255;
// Calculate the icon size. It scales with:
// * The square root of the camera distance.
// * The mod defined 'iconSize' (which acts a multiplier).
// * The unit radius, depending on whether the mod defined 'radiusadjust' is true or false.
float3 pos;
if (gu->spectatingFullView) {
pos = unit->midPos;
} else {
pos = helper->GetUnitErrorPos(unit,gu->myAllyTeam);
}
float dist=sqrt((pos-camera->pos).Length());
float scale=0.4f*icon->size*dist;
if (icon->radiusAdjust && !asRadarBlip) {
scale=scale*unit->radius/30; // I take the standard unit radius to be 30 ... call it an educated guess. (Teake Nutma)
}
unit->iconRadius = scale; // store the icon size so that we don't have to calculate it again
// Is the unit selected? Then draw it white.
if (unit->commandAI->selected) {
color[0] = 255;
color[1] = 255;
color[2] = 255;
} else {
color[0] = gs->Team(unit->team)->color[0];
color[1] = gs->Team(unit->team)->color[1];
color[2] = gs->Team(unit->team)->color[2];
}
// If the icon is partly under the ground, move it up.
const float h = ground->GetHeight(pos.x, pos.z);
if (pos.y < (h + scale)) {
pos.y = (h + scale);
}
// Draw the icon.
glBindTexture(GL_TEXTURE_2D, icon->texture);
va = GetVertexArray();
va->Initialize();
va->AddVertexTC(pos + camera->up * scale + camera->right * scale, 1, 0, color);
va->AddVertexTC(pos - camera->up * scale + camera->right * scale, 1, 1, color);
va->AddVertexTC(pos - camera->up * scale - camera->right * scale, 0, 1, color);
va->AddVertexTC(pos + camera->up * scale - camera->right * scale, 0, 0, color);
va->DrawArrayTC(GL_QUADS);
}
void CUnitDrawer::SetupForGhostDrawing()
{
glPushAttrib (GL_TEXTURE_BIT | GL_ENABLE_BIT);
glEnable(GL_TEXTURE_2D);
texturehandler->SetTATexture();
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_SOURCE1_RGB_ARB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
}
void CUnitDrawer::SetupForGhostDrawingS3O()
{
SetupBasicS3OTexture0();
SetupBasicS3OTexture1();
// use the alpha given by glColor for the outgoing alpha.
// (might need to change this if we ever have transparent bits on units?)
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
void CUnitDrawer::CleanUpGhostDrawing()
{
glPopAttrib();
glDisable(GL_TEXTURE_2D);
glDepthMask(1);
glDisable(GL_ALPHA_TEST);
// clean up s3o drawing stuff
// reset texture1 state
CleanupBasicS3OTexture1();
// also reset the alpha generation
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
// reset texture0 state
CleanupBasicS3OTexture0();
}
void CUnitDrawer::DrawCloakedUnits(void)
{
SetupForGhostDrawing();
glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GREATER, 0.1f);
glEnable(GL_ALPHA_TEST);
glColor4f(1, 1, 1, 0.3f);
glDepthMask(0);
// units drawn by AI, these aren't really
// cloaked but the effect is the same
for (std::multimap<int, TempDrawUnit>::iterator ti = tempTransparentDrawUnits.begin(); ti != tempTransparentDrawUnits.end(); ++ti) {
if (camera->InView(ti->second.pos, 100)) {
glPushMatrix();
glTranslatef3(ti->second.pos);
glRotatef(ti->second.rotation * 180 / PI, 0, 1, 0);
S3DOModel* model = ti->second.unitdef->LoadModel(ti->second.team);
model->DrawStatic();
glPopMatrix();
}
if (ti->second.drawBorder) {
float3 pos = ti->second.pos;
const UnitDef *unitdef = ti->second.unitdef;
BuildInfo bi(unitdef, pos, ti->second.facing);
pos = helper->Pos2BuildPos(bi);
float xsize = bi.GetXSize() * 4;
float ysize = bi.GetYSize() * 4;
glColor4f(0.2f, 1, 0.2f, 0.7f);
glDisable(GL_TEXTURE_2D);
glBegin(GL_LINE_STRIP);
glVertexf3(pos+float3( xsize, 1, ysize));
glVertexf3(pos+float3(-xsize, 1, ysize));
glVertexf3(pos+float3(-xsize, 1, -ysize));
glVertexf3(pos+float3( xsize, 1, -ysize));
glVertexf3(pos+float3( xsize, 1, ysize));
glEnd();
glColor4f(1, 1, 1, 0.3f);
glEnable(GL_TEXTURE_2D);
}
}
// 3dos
DrawCloakedUnitsHelper(drawCloaked, ghostBuildings, false);
// s3os
SetupForGhostDrawingS3O();
glColor4f(1, 1, 1, 0.3f);
DrawCloakedUnitsHelper(drawCloakedS3O, ghostBuildingsS3O, true);
// reset gl states
CleanUpGhostDrawing();
// shader rendering
DrawCloakedShaderUnits();
}
void CUnitDrawer::DrawCloakedUnitsHelper(std::vector<CUnit*>& dC, std::list<GhostBuilding*>& gB, bool is_s3o)
{
// cloaked units and living ghosted buildings (stored in same vector)
for (vector<CUnit*>::iterator ui = dC.begin(); ui != dC.end(); ++ui) {
CUnit* unit = *ui;
if ((unit->losStatus[gu->myAllyTeam] & LOS_INLOS) || gu->spectatingFullView) {
if (is_s3o) {
SetBasicS3OTeamColour(unit->team);
texturehandler->SetS3oTexture(unit->model->textureType);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -