void DebugDrawerAI::TexSet::Draw() { if (!textures.empty()) { glEnable(GL_TEXTURE_2D); font->Begin(); font->SetTextColor(0.0f, 0.0f, 0.0f, 1.0f); CVertexArray* va = GetVertexArray(); for (std::map<int, TexSet::Texture*>::iterator it = textures.begin(); it != textures.end(); ++it) { const TexSet::Texture* tex = it->second; const float3& pos = tex->GetPos(); const float3& size = tex->GetSize(); glBindTexture(GL_TEXTURE_2D, tex->GetID()); va->Initialize(); va->AddVertexT(pos, 0.0f, 1.0f); va->AddVertexT(pos + float3(size.x, 0.0f, 0.0f), 1.0f, 1.0f); va->AddVertexT(pos + float3(size.x, size.y, 0.0f), 1.0f, 0.0f); va->AddVertexT(pos + float3( 0.0f, size.y, 0.0f), 0.0f, 0.0f); va->DrawArrayT(GL_QUADS); glBindTexture(GL_TEXTURE_2D, 0); const float tx = pos.x + size.x * 0.5f - ((tex->GetLabelWidth() * 0.5f) / globalRendering->viewSizeX) * size.x; const float ty = pos.y + size.y + ((tex->GetLabelHeight() * 0.5f) / globalRendering->viewSizeY) * size.y; font->glFormat(tx, ty, 1.0f, FONT_SCALE | FONT_NORM, "%s", tex->GetLabel().c_str()); } font->End(); glDisable(GL_TEXTURE_2D); } }
void CGrassDrawer::CreateGrassDispList(int listNum) { CVertexArray* va = GetVertexArray(); va->Initialize(); for (int a = 0; a < strawPerTurf; ++a) { const float maxAng = mapInfo->grass.bladeAngle * rng.RandFloat(); const float length = mapInfo->grass.bladeHeight + mapInfo->grass.bladeHeight * rng.RandFloat(); float3 sideVect(rng.RandFloat() - 0.5f, 0.0f, rng.RandFloat() - 0.5f); sideVect.ANormalize(); float3 forwardVect = sideVect.cross(UpVector); sideVect *= mapInfo->grass.bladeWidth; float3 basePos(30.0f, 0.0f, 30.0f); while (basePos.SqLength2D() > (turfSize * turfSize / 4)) { basePos = float3(rng.RandFloat() - 0.5f, 0.f, rng.RandFloat() - 0.5f) * turfSize; } const float xtexCoord = int(14.9999f * rng.RandFloat()) / 16.0f; const int numSections = 1 + int(maxAng * 5.0f); // draw single blade for (float h = 0; h <= 1.0f; h += (1.0f / numSections)) { const float ang = maxAng * h; const float3 edgePos = (UpVector * std::cos(ang) + forwardVect * std::sin(ang)) * length * h; const float3 edgePosL = edgePos - sideVect * (1.0f - h); const float3 edgePosR = edgePos + sideVect * (1.0f - h); if (h == 0.0f) { // start with a degenerated triangle va->AddVertexT(basePos + edgePosR - float3(0.0f, 0.1f, 0.0f), xtexCoord, h); va->AddVertexT(basePos + edgePosR - float3(0.0f, 0.1f, 0.0f), xtexCoord, h); } else { va->AddVertexT(basePos + edgePosR, xtexCoord, h); } va->AddVertexT(basePos + edgePosL, xtexCoord + (1.0f / 16), h); } // end with a degenerated triangle // -> this way we can render multiple blades in a single GL_TRIANGLE_STRIP const float3 edgePos = (UpVector * std::cos(maxAng) + forwardVect * std::sin(maxAng)) * length; va->AddVertexT(basePos + edgePos, xtexCoord + (1.0f / 32), 1.0f); va->AddVertexT(basePos + edgePos, xtexCoord + (1.0f / 32), 1.0f); } glNewList(listNum, GL_COMPILE); va->DrawArrayT(GL_TRIANGLE_STRIP); glEndList(); }
void CFarTextureHandler::Draw() { if (queuedForRender.empty()) { return; } if (!fbo.IsValid()) { queuedForRender.clear(); return; } // create new far-icons for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) { const CSolidObject* obj = *it; if (!HaveFarIcon(obj)) { CreateFarTexture(obj); } } // render current queued far icons on the screen { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, farTextureID); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glNormal3fv((const GLfloat*) &unitDrawer->camNorm.x); ISky::SetupFog(); CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(queuedForRender.size() * 4, 0, VA_SIZE_T); for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) { DrawFarTexture(*it, va); } va->DrawArrayT(GL_QUADS); glDisable(GL_ALPHA_TEST); } queuedForRender.clear(); }
void CFarTextureHandler::Draw() { if (queuedForRender.empty()) { return; } //! create new faricons for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) { const CSolidObject& obj = **it; if (cache.size()<=obj.team || cache[obj.team].size()<=obj.model->id || !cache[obj.team][obj.model->id]) { CreateFarTexture(*it); } } glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, farTexture); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glNormal3fv((const GLfloat*) &unitDrawer->camNorm.x); if (globalRendering->drawFog) { glFogfv(GL_FOG_COLOR, mapInfo->atmosphere.fogColor); glEnable(GL_FOG); } CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(queuedForRender.size() * 4, 0, VA_SIZE_T); for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) { DrawFarTexture(*it, va); } va->DrawArrayT(GL_QUADS); glDisable(GL_ALPHA_TEST); queuedForRender.clear(); }
void CAdvWater::UpdateWater(CGame* game) { if ((!mapInfo->water.forceRendering && (readmap->currMinHeight > 1.0f)) || mapInfo->map.voidWater) { return; } glPushAttrib(GL_FOG_BIT); glPushAttrib(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); bumpFBO.Bind(); glViewport(0, 0, 128, 128); glClearColor(0.0f, 0.0f, 0.0f, 1); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor3f(0.2f, 0.2f, 0.2f); CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(12, 0, VA_SIZE_T); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[0]); va->AddVertexQT(float3(0, 0, 0), 0, 0 + gs->frameNum*0.0046f); va->AddVertexQT(float3(0, 1, 0), 0, 2 + gs->frameNum*0.0046f); va->AddVertexQT(float3(1, 1, 0), 2, 2 + gs->frameNum*0.0046f); va->AddVertexQT(float3(1, 0, 0), 2, 0 + gs->frameNum*0.0046f); va->AddVertexQT(float3(0, 0, 0), 0, 0 + gs->frameNum*0.0026f); va->AddVertexQT(float3(0, 1, 0), 0, 4 + gs->frameNum*0.0026f); va->AddVertexQT(float3(1, 1, 0), 2, 4 + gs->frameNum*0.0026f); va->AddVertexQT(float3(1, 0, 0), 2, 0 + gs->frameNum*0.0026f); va->AddVertexQT(float3(0, 0, 0), 0, 0 + gs->frameNum*0.0012f); va->AddVertexQT(float3(0, 1, 0), 0, 8 + gs->frameNum*0.0012f); va->AddVertexQT(float3(1, 1, 0), 2, 8 + gs->frameNum*0.0012f); va->AddVertexQT(float3(1, 0, 0), 2, 0 + gs->frameNum*0.0012f); va->DrawArrayT(GL_QUADS); va->Initialize(); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[1]); va->AddVertexQT(float3(0, 0, 0), 0, 0 + gs->frameNum*0.0036f); va->AddVertexQT(float3(0, 1, 0), 0, 1 + gs->frameNum*0.0036f); va->AddVertexQT(float3(1, 1, 0), 1, 1 + gs->frameNum*0.0036f); va->AddVertexQT(float3(1, 0, 0), 1, 0 + gs->frameNum*0.0036f); va->DrawArrayT(GL_QUADS); va->Initialize(); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[2]); va->AddVertexQT(float3(0, 0, 0), 0, 0 + gs->frameNum*0.0082f); va->AddVertexQT(float3(0, 1, 0), 0, 1 + gs->frameNum*0.0082f); va->AddVertexQT(float3(1, 1, 0), 1, 1 + gs->frameNum*0.0082f); va->AddVertexQT(float3(1, 0, 0), 1, 0 + gs->frameNum*0.0082f); va->DrawArrayT(GL_QUADS); // this fixes a memory leak on ATI cards glBindTexture(GL_TEXTURE_2D, 0); glColor3f(1, 1, 1); // CCamera* realCam = camera; // camera = new CCamera(*realCam); char realCam[sizeof(CCamera)]; new (realCam) CCamera(*camera); // anti-crash workaround for multithreading camera->forward.y *= -1.0f; camera->pos.y *= -1.0f; camera->Update(false); reflectFBO.Bind(); glViewport(0, 0, 512, 512); glClear(GL_DEPTH_BUFFER_BIT); game->SetDrawMode(CGame::gameReflectionDraw); sky->Draw(); glEnable(GL_CLIP_PLANE2); double plane[4] = {0, 1, 0, 0}; glClipPlane(GL_CLIP_PLANE2, plane); drawReflection = true; readmap->GetGroundDrawer()->Draw(true); unitDrawer->Draw(true); featureDrawer->Draw(); unitDrawer->DrawCloakedUnits(true); featureDrawer->DrawFadeFeatures(true); projectileDrawer->Draw(true); eventHandler.DrawWorldReflection(); game->SetDrawMode(CGame::gameNormalDraw); drawReflection = false; glDisable(GL_CLIP_PLANE2); FBO::Unbind(); glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY); glClearColor(mapInfo->atmosphere.fogColor[0], mapInfo->atmosphere.fogColor[1], mapInfo->atmosphere.fogColor[2], 1); // delete camera; // camera = realCam; camera->~CCamera(); new (camera) CCamera(*(CCamera*)realCam); camera->Update(false); glPopAttrib(); glPopAttrib(); }
void CGrassDrawer::CreateFarTex() { //TODO create normalmap, too? const int sizeMod = 2; const int billboardSize = 256; const int numAngles = 16; const int texSizeX = billboardSize * numAngles; const int texSizeY = billboardSize; if (farTex == 0) { glGenTextures(1, &farTex); glBindTexture(GL_TEXTURE_2D, farTex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glSpringTexStorage2D(GL_TEXTURE_2D, -1, GL_RGBA8, texSizeX, texSizeY); } FBO fboTex; fboTex.Bind(); fboTex.AttachTexture(farTex); fboTex.CheckStatus("GRASSDRAWER1"); FBO fbo; fbo.Bind(); fbo.CreateRenderBuffer(GL_DEPTH_ATTACHMENT_EXT, GL_DEPTH_COMPONENT16, texSizeX * sizeMod, texSizeY * sizeMod); fbo.CreateRenderBuffer(GL_COLOR_ATTACHMENT0_EXT, GL_RGBA8, texSizeX * sizeMod, texSizeY * sizeMod); fbo.CheckStatus("GRASSDRAWER2"); if (!fboTex.IsValid() || !fbo.IsValid()) { grassOff = true; return; } glPushMatrix(); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glDisable(GL_FOG); glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBindTexture(GL_TEXTURE_2D, grassBladeTex); glEnable(GL_TEXTURE_2D); glEnable(GL_CLIP_PLANE0); glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); glColor4f(1,1,1,1); glViewport(0,0,texSizeX*sizeMod, texSizeY*sizeMod); glClearColor(mapInfo->grass.color.r,mapInfo->grass.color.g,mapInfo->grass.color.b,0.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.f,0.f,0.f,0.f); static const GLdouble eq[4] = {0.f, 1.f, 0.f, 0.f}; // render turf from different vertical angles for (int a=0;a<numAngles;++a) { glViewport(a*billboardSize*sizeMod, 0, billboardSize*sizeMod, billboardSize*sizeMod); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(a*90.f/(numAngles-1),1,0,0); //glTranslatef(0,-0.5f,0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-partTurfSize, partTurfSize, partTurfSize, -partTurfSize, -turfSize, turfSize); // has to be applied after the matrix transformations, // cause it uses those an `compiles` them into the clip plane glClipPlane(GL_CLIP_PLANE0, &eq[0]); glCallList(grassDL); } glDisable(GL_CLIP_PLANE0); // scale down the rendered fartextures (MSAA) and write to the final texture glBindFramebufferEXT(GL_READ_FRAMEBUFFER, fbo.fboId); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, fboTex.fboId); glBlitFramebufferEXT(0, 0, texSizeX*sizeMod, texSizeY*sizeMod, 0, 0, texSizeX, texSizeY, GL_COLOR_BUFFER_BIT, GL_LINEAR); // compute mipmaps glBindTexture(GL_TEXTURE_2D, farTex); glGenerateMipmap(GL_TEXTURE_2D); // blur non-rendered areas, so in mipmaps color data isn't blurred with background color { const int mipLevels = std::ceil(std::log((float)(std::max(texSizeX, texSizeY) + 1))); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glEnable(GL_BLEND); glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA, GL_ZERO, GL_DST_ALPHA); // copy each mipmap to its predecessor background // -> fill background with blurred color data fboTex.Bind(); for (int mipLevel = mipLevels - 2; mipLevel >= 0; --mipLevel) { fboTex.AttachTexture(farTex, GL_TEXTURE_2D, GL_COLOR_ATTACHMENT0_EXT, mipLevel); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, mipLevel + 1.f); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, mipLevel + 1.f); glViewport(0, 0, texSizeX>>mipLevel, texSizeY>>mipLevel); CVertexArray* va = GetVertexArray(); va->Initialize(); va->AddVertexT(float3(-1.0f, 1.0f, 0.0f), 0.0f, 1.0f); va->AddVertexT(float3( 1.0f, 1.0f, 0.0f), 1.0f, 1.0f); va->AddVertexT(float3( 1.0f, -1.0f, 0.0f), 1.0f, 0.0f); va->AddVertexT(float3(-1.0f, -1.0f, 0.0f), 0.0f, 0.0f); va->DrawArrayT(GL_QUADS); } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // recreate mipmaps from now blurred base level glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, -1000.f); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 1000.f); glGenerateMipmap(GL_TEXTURE_2D); } glViewport(globalRendering->viewPosX, 0, globalRendering->viewSizeX, globalRendering->viewSizeY); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); FBO::Unbind(); //glSaveTexture(farTex, "grassfar.png"); }
void CAdvTreeDrawer::DrawShadowPass() { const float treeDistance = oldTreeDistance; const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0] : treeGen->farTex[1]; const bool drawDetailed = (treeDistance >= 4.0f); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, activeFarTex); glEnable(GL_TEXTURE_2D); glEnable(GL_ALPHA_TEST); glDisable(GL_CULL_FACE); glPolygonOffset(1, 1); glEnable(GL_POLYGON_OFFSET_FILL); CAdvTreeSquareDrawer_SP drawer; const int cx = drawer.cx = (int)(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE)); const int cy = drawer.cy = (int)(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE)); drawer.drawDetailed = drawDetailed; drawer.td = this; drawer.treeDistance = treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE; Shader::IProgramObject* po = NULL; GML_STDMUTEX_LOCK(tree); // DrawShadowPass // draw with extraSize=1 readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer, 1); if (drawDetailed) { const int xstart = std::max( 0, cx - 2); const int xend = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2); const int ystart = std::max( 0, cy - 2); const int yend = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2); glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glEnable(GL_TEXTURE_2D); po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_NEAR); po->Enable(); if (globalRendering->haveGLSL) { po->SetUniform3fv(1, &camera->right[0]); po->SetUniform3fv(2, &camera->up[0]); } else { po->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); po->SetUniform4f(13, camera->right.x, camera->right.y, camera->right.z, 0.0f); po->SetUniform4f(9, camera->up.x, camera->up.y, camera->up.z, 0.0f); po->SetUniform4f(11, 1.0f, 1.0f, 1.0f, 0.85f ); po->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT)); // w = alpha/height modifier } glAlphaFunc(GL_GREATER, 0.5f); glEnable(GL_ALPHA_TEST); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CVertexArray* va = GetVertexArray(); va->Initialize(); static FadeTree fadeTrees[3000]; FadeTree* pFT = fadeTrees; for (TreeSquareStruct* pTSS = trees + (ystart * treesX); pTSS <= trees + (yend * treesX); pTSS += treesX) { for (TreeSquareStruct* tss = pTSS + xstart; tss <= pTSS + xend; ++tss) { tss->lastSeen = gs->frameNum; va->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) { const TreeStruct* ts = &ti->second; const float3 pos(ts->pos); if (!camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2 + 150)) { continue; } const float camDist = (pos - camera->pos).SqLength(); int type = ts->type; float dy = 0.0f; unsigned int dispList; if (type < 8) { dy = 0.5f; dispList = treeGen->pineDL + type; } else { type -= 8; dy = 0; dispList = treeGen->leafDL + type; } if (camDist < SQUARE_SIZE * SQUARE_SIZE * 110 * 110) { po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z); glCallList(dispList); } else if (camDist < SQUARE_SIZE * SQUARE_SIZE * 125 * 125) { const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15); glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f); po->SetUniform3f((globalRendering->haveGLSL? 3: 10), pos.x, pos.y, pos.z); glCallList(dispList); glAlphaFunc(GL_GREATER, 0.5f); pFT->pos = pos; pFT->deltaY = dy; pFT->type = type; pFT->relDist = relDist; ++pFT; } else { CAdvTreeDrawer::DrawTreeVertex(va, pos, type * 0.125f, dy, false); } } } } po->SetUniform3f((globalRendering->haveGLSL? 3: 10), 0.0f, 0.0f, 0.0f); for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) { const float3 pos = fti->pos - UpVector * (fti->fallPos * 20); if (camera->InView(pos + float3(0, MAX_TREE_HEIGHT / 2, 0), MAX_TREE_HEIGHT / 2)) { const float ang = fti->fallPos * PI; const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang)); const float3 zvec((yvec.cross(float3(1.0f, 0.0f, 0.0f))).ANormalize()); const float3 xvec(zvec.cross(yvec)); CMatrix44f transMatrix(pos, xvec, yvec, zvec); glPushMatrix(); glMultMatrixf(&transMatrix[0]); int type = fti->type; int dispList; if (type < 8) { dispList = treeGen->pineDL + type; } else { type -= 8; dispList = treeGen->leafDL + type; } glCallList(dispList); glPopMatrix(); } } po->Disable(); po = shadowHandler->GetShadowGenProg(CShadowHandler::SHADOWGEN_PROGRAM_TREE_FAR); po->Enable(); glBindTexture(GL_TEXTURE_2D, activeFarTex); va->DrawArrayT(GL_QUADS); for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) { // faded close trees va = GetVertexArray(); va->Initialize(); va->CheckInitSize(12 * VA_SIZE_T); CAdvTreeDrawer::DrawTreeVertex(va, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f)); va->DrawArrayT(GL_QUADS); } po->Disable(); } glEnable(GL_CULL_FACE); glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); }
void CAdvTreeSquareDrawer_SP::DrawQuad(int x, int y) { const int treesX = td->treesX; CAdvTreeDrawer::TreeSquareStruct* tss = &td->trees[(y * treesX) + x]; if ((abs(cy - y) <= 2) && (abs(cx - x) <= 2) && drawDetailed) { // skip the closest squares return; } float3 dif; dif.x = camera->pos.x - ((x * SQUARE_SIZE * TREE_SQUARE_SIZE) + (SQUARE_SIZE * TREE_SQUARE_SIZE / 2)); dif.y = 0.0f; dif.z = camera->pos.z - ((y * SQUARE_SIZE * TREE_SQUARE_SIZE) + (SQUARE_SIZE * TREE_SQUARE_SIZE / 2)); const float dist = dif.Length(); const float distFactor = dist / treeDistance; dif.Normalize(); if (distFactor < MID_TREE_DIST_FACTOR) { // midle distance trees tss->lastSeen = gs->frameNum; if (!tss->dispList) { CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes tss->dispList = glGenLists(1); for (std::map<int, CAdvTreeDrawer::TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) { CAdvTreeDrawer::TreeStruct* ts = &ti->second; if (ts->type < 8) { CAdvTreeDrawer::DrawTreeVertexMid(va, ts->pos, (ts->type ) * 0.125f, 0.5f, false); } else { CAdvTreeDrawer::DrawTreeVertexMid(va, ts->pos, (ts->type - 8) * 0.125f, 0.0f, false); } } glNewList(tss->dispList, GL_COMPILE); va->DrawArrayT(GL_QUADS); glEndList(); } glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glAlphaFunc(GL_GREATER, 0.5f); glCallList(tss->dispList); } else if (distFactor < FAR_TREE_DIST_FACTOR) { // far trees tss->lastSeenFar = gs->frameNum; if (!tss->farDispList || dif.dot(tss->viewVector) < 0.97f) { CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(4 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes tss->viewVector = dif; if (!tss->farDispList) tss->farDispList = glGenLists(1); const float3 side = UpVector.cross(dif); for (std::map<int, CAdvTreeDrawer::TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) { CAdvTreeDrawer::TreeStruct* ts = &ti->second; if (ts->type < 8) { CAdvTreeDrawer::DrawTreeVertexFar(va, ts->pos, side * HALF_MAX_TREE_HEIGHT, (ts->type ) * 0.125f, 0.5f, false); } else { CAdvTreeDrawer::DrawTreeVertexFar(va, ts->pos, side * HALF_MAX_TREE_HEIGHT, (ts->type - 8) * 0.125f, 0.0f, false); } } glNewList(tss->farDispList, GL_COMPILE); va->DrawArrayT(GL_QUADS); glEndList(); } if (distFactor > FADE_TREE_DIST_FACTOR) { // faded far trees const float alpha = 1.0f - (distFactor - FADE_TREE_DIST_FACTOR) / (FAR_TREE_DIST_FACTOR - FADE_TREE_DIST_FACTOR); glColor4f(1.0f, 1.0f, 1.0f, alpha); glAlphaFunc(GL_GREATER, alpha * 0.5f); } else { glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glAlphaFunc(GL_GREATER, 0.5f); } glCallList(tss->farDispList); } }
void CAdvTreeDrawer::Draw(float treeDistance, bool drawReflection) { const int activeFarTex = (camera->forward.z < 0.0f)? treeGen->farTex[0]: treeGen->farTex[1]; const bool drawDetailed = ((treeDistance >= 4.0f) || drawReflection); CBaseGroundDrawer* gd = readmap->GetGroundDrawer(); Shader::IProgramObject* treeShader = NULL; const CMapInfo::light_t& light = mapInfo->light; glEnable(GL_ALPHA_TEST); glEnable(GL_TEXTURE_2D); ISky::SetupFog(); if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, activeFarTex); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, shadowHandler->shadowTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW]; treeShader->Enable(); if (globalRendering->haveGLSL) { treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]); treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x)); } else { treeShader->SetUniformTarget(GL_FRAGMENT_PROGRAM_ARB); treeShader->SetUniform4f(10, light.groundAmbientColor.x, light.groundAmbientColor.y, light.groundAmbientColor.z, 1.0f); treeShader->SetUniform4f(11, 0.0f, 0.0f, 0.0f, 1.0f - (sky->GetLight()->GetGroundShadowDensity() * 0.5f)); treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); glMatrixMode(GL_MATRIX0_ARB); glLoadMatrixf(shadowHandler->shadowMatrix.m); glMatrixMode(GL_MODELVIEW); } } else { glBindTexture(GL_TEXTURE_2D, activeFarTex); } const int cx = int(camera->pos.x / (SQUARE_SIZE * TREE_SQUARE_SIZE)); const int cy = int(camera->pos.z / (SQUARE_SIZE * TREE_SQUARE_SIZE)); CAdvTreeSquareDrawer drawer(this, cx, cy, treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE, drawDetailed); GML_STDMUTEX_LOCK(tree); // Draw oldTreeDistance = treeDistance; // draw far-trees using map-dependent grid-visibility readmap->GridVisibility(camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer); if (drawDetailed) { // draw near-trees const int xstart = std::max( 0, cx - 2); const int xend = std::min(gs->mapx / TREE_SQUARE_SIZE - 1, cx + 2); const int ystart = std::max( 0, cy - 2); const int yend = std::min(gs->mapy / TREE_SQUARE_SIZE - 1, cy + 2); if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { treeShader->Disable(); treeShader = treeShaders[TREE_PROGRAM_NEAR_SHADOW]; treeShader->Enable(); if (globalRendering->haveGLSL) { treeShader->SetUniformMatrix4fv(7, false, &shadowHandler->shadowMatrix.m[0]); treeShader->SetUniform4fv(8, &(shadowHandler->GetShadowParams().x)); } glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glActiveTexture(GL_TEXTURE0); } else { glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); treeShader = treeShaders[TREE_PROGRAM_NEAR_BASIC]; treeShader->Enable(); if (!globalRendering->haveGLSL) { const int mx = gs->pwr2mapx * SQUARE_SIZE; const int my = gs->pwr2mapy * SQUARE_SIZE; treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); treeShader->SetUniform4f(15, 1.0f / mx, 1.0f / my, 1.0f / mx, 1.0f); } } if (globalRendering->haveGLSL) { treeShader->SetUniform3fv(0, &camera->right[0]); treeShader->SetUniform3fv(1, &camera->up[0]); treeShader->SetUniform2f(5, 0.20f * (1.0f / MAX_TREE_HEIGHT), 0.85f); } else { treeShader->SetUniformTarget(GL_VERTEX_PROGRAM_ARB); treeShader->SetUniform3f(13, camera->right.x, camera->right.y, camera->right.z); treeShader->SetUniform3f( 9, camera->up.x, camera->up.y, camera->up.z ); treeShader->SetUniform4f(11, light.groundSunColor.x, light.groundSunColor.y, light.groundSunColor.z, 0.85f); treeShader->SetUniform4f(14, light.groundAmbientColor.x, light.groundAmbientColor.y, light.groundAmbientColor.z, 0.85f); treeShader->SetUniform4f(12, 0.0f, 0.0f, 0.0f, 0.20f * (1.0f / MAX_TREE_HEIGHT)); // w = alpha/height modifier } glAlphaFunc(GL_GREATER, 0.5f); glDisable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); CVertexArray* va = GetVertexArray(); va->Initialize(); static FadeTree fadeTrees[3000]; FadeTree* pFT = fadeTrees; for (TreeSquareStruct* pTSS = trees + (ystart * treesX); pTSS <= trees + (yend * treesX); pTSS += treesX) { for (TreeSquareStruct* tss = pTSS + xstart; tss <= (pTSS + xend); ++tss) { tss->lastSeen = gs->frameNum; va->EnlargeArrays(12 * tss->trees.size(), 0, VA_SIZE_T); //!alloc room for all tree vertexes for (std::map<int, TreeStruct>::iterator ti = tss->trees.begin(); ti != tss->trees.end(); ++ti) { const TreeStruct* ts = &ti->second; const float3 pos(ts->pos); if (!camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2.0f, 0.0f), MAX_TREE_HEIGHT / 2.0f)) { continue; } const float camDist = (pos - camera->pos).SqLength(); int type = ts->type; float dy = 0.0f; unsigned int dispList; if (type < 8) { dy = 0.5f; dispList = treeGen->pineDL + type; } else { type -= 8; dy = 0.0f; dispList = treeGen->leafDL + type; } if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 110 * 110)) { // draw detailed near-distance tree (same as mid-distance trees without alpha) treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z); glCallList(dispList); } else if (camDist < (SQUARE_SIZE * SQUARE_SIZE * 125 * 125)) { // draw mid-distance tree const float relDist = (pos.distance(camera->pos) - SQUARE_SIZE * 110) / (SQUARE_SIZE * 15); treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), pos.x, pos.y, pos.z); glAlphaFunc(GL_GREATER, 0.8f + relDist * 0.2f); glCallList(dispList); glAlphaFunc(GL_GREATER, 0.5f); // save for second pass pFT->pos = pos; pFT->deltaY = dy; pFT->type = type; pFT->relDist = relDist; ++pFT; } else { // draw far-distance tree CAdvTreeDrawer::DrawTreeVertex(va, pos, type * 0.125f, dy, false); } } } } // reset the world-offset treeShader->SetUniform3f(((globalRendering->haveGLSL)? 2: 10), 0.0f, 0.0f, 0.0f); // draw trees that have been marked as falling for (std::list<FallingTree>::iterator fti = fallingTrees.begin(); fti != fallingTrees.end(); ++fti) { const float3 pos = fti->pos - UpVector * (fti->fallPos * 20); if (camera->InView(pos + float3(0.0f, MAX_TREE_HEIGHT / 2, 0.0f), MAX_TREE_HEIGHT / 2.0f)) { const float ang = fti->fallPos * PI; const float3 yvec(fti->dir.x * sin(ang), cos(ang), fti->dir.z * sin(ang)); const float3 zvec((yvec.cross(float3(-1.0f, 0.0f, 0.0f))).ANormalize()); const float3 xvec(yvec.cross(zvec)); CMatrix44f transMatrix(pos, xvec, yvec, zvec); glPushMatrix(); glMultMatrixf(&transMatrix[0]); int type = fti->type; int dispList = 0; if (type < 8) { dispList = treeGen->pineDL + type; } else { type -= 8; dispList = treeGen->leafDL + type; } glCallList(dispList); glPopMatrix(); } } if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { treeShader->Disable(); treeShader = treeShaders[TREE_PROGRAM_DIST_SHADOW]; treeShader->Enable(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, activeFarTex); glActiveTexture(GL_TEXTURE0); } else { treeShader->Disable(); glBindTexture(GL_TEXTURE_2D, activeFarTex); } // draw far-distance trees va->DrawArrayT(GL_QUADS); // draw faded mid-distance trees for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) { va = GetVertexArray(); va->Initialize(); va->CheckInitSize(12 * VA_SIZE_T); CAdvTreeDrawer::DrawTreeVertex(va, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f)); va->DrawArrayT(GL_QUADS); } } if (shadowHandler->shadowsLoaded && !gd->DrawExtraTex()) { treeShader->Disable(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE); } else { glBindTexture(GL_TEXTURE_2D, 0); } glDisable(GL_TEXTURE_2D); glDisable(GL_FOG); glDisable(GL_ALPHA_TEST); // clean out squares from memory that are no longer visible const int startClean = lastListClean * 20 % (nTrees); const int endClean = gs->frameNum * 20 % (nTrees); lastListClean = gs->frameNum; if (startClean > endClean) { for (TreeSquareStruct* pTSS = trees + startClean; pTSS < (trees + nTrees); ++pTSS) { if ((pTSS->lastSeen < gs->frameNum - 50) && pTSS->dispList) { glDeleteLists(pTSS->dispList, 1); pTSS->dispList = 0; } if ((pTSS->lastSeenFar < (gs->frameNum - 50)) && pTSS->farDispList) { glDeleteLists(pTSS->farDispList, 1); pTSS->farDispList = 0; } } for (TreeSquareStruct* pTSS = trees; pTSS < (trees + endClean); ++pTSS) { if ((pTSS->lastSeen < (gs->frameNum - 50)) && pTSS->dispList) { glDeleteLists(pTSS->dispList, 1); pTSS->dispList = 0; } if ((pTSS->lastSeenFar < (gs->frameNum - 50)) && pTSS->farDispList) { glDeleteLists(pTSS->farDispList, 1); pTSS->farDispList = 0; } } } else { for (TreeSquareStruct* pTSS = trees + startClean; pTSS < (trees + endClean); ++pTSS) { if ((pTSS->lastSeen < (gs->frameNum - 50)) && pTSS->dispList) { glDeleteLists(pTSS->dispList, 1); pTSS->dispList = 0; } if ((pTSS->lastSeenFar < (gs->frameNum - 50)) && pTSS->farDispList) { glDeleteLists(pTSS->farDispList, 1); pTSS->farDispList = 0; } } } }
void CAdvWater::UpdateWater(CGame* game) { if (!waterRendering->forceRendering && !readMap->HasVisibleWater()) return; glPushAttrib(GL_FOG_BIT | GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); { bumpFBO.Bind(); glViewport(0, 0, 128, 128); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glSpringMatrix2dSetupPV(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); glColor3f(0.2f, 0.2f, 0.2f); CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(12, 0, VA_SIZE_T); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[0]); va->AddVertexQT(ZeroVector, 0, 0 + gs->frameNum*0.0046f); va->AddVertexQT( UpVector, 0, 2 + gs->frameNum*0.0046f); va->AddVertexQT( XYVector, 2, 2 + gs->frameNum*0.0046f); va->AddVertexQT( RgtVector, 2, 0 + gs->frameNum*0.0046f); va->AddVertexQT(ZeroVector, 0, 0 + gs->frameNum*0.0026f); va->AddVertexQT( UpVector, 0, 4 + gs->frameNum*0.0026f); va->AddVertexQT( XYVector, 2, 4 + gs->frameNum*0.0026f); va->AddVertexQT( RgtVector, 2, 0 + gs->frameNum*0.0026f); va->AddVertexQT(ZeroVector, 0, 0 + gs->frameNum*0.0012f); va->AddVertexQT( UpVector, 0, 8 + gs->frameNum*0.0012f); va->AddVertexQT( XYVector, 2, 8 + gs->frameNum*0.0012f); va->AddVertexQT( RgtVector, 2, 0 + gs->frameNum*0.0012f); va->DrawArrayT(GL_QUADS); va = GetVertexArray(); va->Initialize(); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[1]); va->AddVertexQT(ZeroVector, 0, 0 + gs->frameNum*0.0036f); va->AddVertexQT( UpVector, 0, 1 + gs->frameNum*0.0036f); va->AddVertexQT( XYVector, 1, 1 + gs->frameNum*0.0036f); va->AddVertexQT( RgtVector, 1, 0 + gs->frameNum*0.0036f); va->DrawArrayT(GL_QUADS); va = GetVertexArray(); va->Initialize(); glBindTexture(GL_TEXTURE_2D, rawBumpTexture[2]); va->AddVertexQT(ZeroVector, 0, 0 + gs->frameNum*0.0082f); va->AddVertexQT( UpVector, 0, 1 + gs->frameNum*0.0082f); va->AddVertexQT( XYVector, 1, 1 + gs->frameNum*0.0082f); va->AddVertexQT( RgtVector, 1, 0 + gs->frameNum*0.0082f); va->DrawArrayT(GL_QUADS); // this fixes a memory leak on ATI cards glBindTexture(GL_TEXTURE_2D, 0); glColor3f(1.0f, 1.0f, 1.0f); } reflectFBO.Bind(); glClearColor(sky->fogColor[0], sky->fogColor[1], sky->fogColor[2], 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); const double clipPlaneEqs[2 * 4] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, }; CCamera* prvCam = CCamera::GetSetActiveCamera(CCamera::CAMTYPE_UWREFL); CCamera* curCam = CCamera::GetActiveCamera(); { curCam->CopyStateReflect(prvCam); curCam->UpdateLoadViewPort(0, 0, 512, 512); DrawReflections(&clipPlaneEqs[0], true, true); } CCamera::SetActiveCamera(prvCam->GetCamType()); prvCam->Update(); prvCam->LoadViewPort(); FBO::Unbind(); glPopAttrib(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }
void CFeatureDrawer::Draw() { drawFar.clear(); if(gu->drawFog) { glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, mapInfo->atmosphere.fogColor); } GML_RECMUTEX_LOCK(feat); // Draw fadeFeatures.clear(); fadeFeaturesS3O.clear(); CBaseGroundDrawer *gd = readmap->GetGroundDrawer(); if (gd->DrawExtraTex()) { glActiveTextureARB(GL_TEXTURE2_ARB); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_ADD_SIGNED_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB); SetTexGen(1.0f/(gs->pwr2mapx*SQUARE_SIZE),1.0f/(gs->pwr2mapy*SQUARE_SIZE),0,0); glBindTexture(GL_TEXTURE_2D, gd->infoTex); glActiveTextureARB(GL_TEXTURE0_ARB); } unitDrawer->SetupForUnitDrawing(); unitDrawer->SetupFor3DO(); DrawRaw(0, &drawFar); unitDrawer->CleanUp3DO(); unitDrawer->DrawQuedS3O(); unitDrawer->CleanUpUnitDrawing(); if (drawFar.size()>0) { glAlphaFunc(GL_GREATER, 0.5f); glEnable(GL_ALPHA_TEST); glBindTexture(GL_TEXTURE_2D, fartextureHandler->GetTextureID()); glColor3f(1.0f, 1.0f, 1.0f); glNormal3fv((const GLfloat*) &unitDrawer->camNorm.x); CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(drawFar.size() * 4, 0, VA_SIZE_T); for (vector<CFeature*>::iterator it = drawFar.begin(); it != drawFar.end(); ++it) { fartextureHandler->DrawFarTexture(camera, (*it)->model, (*it)->pos, (*it)->radius, (*it)->heading, va); } va->DrawArrayT(GL_QUADS); glDisable(GL_ALPHA_TEST); } if (gd->DrawExtraTex()) { glActiveTextureARB(GL_TEXTURE2_ARB); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); glActiveTextureARB(GL_TEXTURE0_ARB); } glDisable(GL_TEXTURE_2D); glDisable(GL_FOG); if(drawStat.size() > 0) { if(!water->drawReflection) { for (vector<CFeature *>::iterator fi = drawStat.begin(); fi != drawStat.end(); ++fi) DrawFeatureStats(*fi); } drawStat.clear(); } }
void CFarTextureHandler::Draw() { if (queuedForRender.empty()) { return; } { // check if there is enough free space in the atlas, if not try resizing // it (as many times as the number of models queued for iconification) unsigned int maxNewIcons = 0; for (unsigned int n = 0; n < queuedForRender.size(); n++) { if (!CheckResizeAtlas(n + 1)) { break; } maxNewIcons++; } // now create the new far-icons // NOTE: // the icons are RTT'ed using a snapshot of the // current state (advModelShading, sunDir, etc) // and will not track later state-changes unitDrawer->SetupForUnitDrawing(); GML_VECTOR<const CSolidObject*>::iterator it; for (it = queuedForRender.begin(); it != queuedForRender.end() && maxNewIcons > 0; ++it) { maxNewIcons--; const CSolidObject* obj = *it; const S3DModel* mdl = obj->model; unitDrawer->GetOpaqueModelRenderer(mdl->type)->PushRenderState(); unitDrawer->SetTeamColour(obj->team); if (mdl->type != MODELTYPE_3DO) { texturehandlerS3O->SetS3oTexture(mdl->textureType); } if ((int)cache.size() <= obj->team || (int)cache[obj->team].size() <= mdl->id || !cache[obj->team][mdl->id]) { CreateFarTexture(obj); } unitDrawer->GetOpaqueModelRenderer(mdl->type)->PopRenderState(); } unitDrawer->CleanUpUnitDrawing(); } glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, farTextureID); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glNormal3fv((const GLfloat*) &unitDrawer->camNorm.x); ISky::SetupFog(); CVertexArray* va = GetVertexArray(); va->Initialize(); va->EnlargeArrays(queuedForRender.size() * 4, 0, VA_SIZE_T); for (GML_VECTOR<const CSolidObject*>::iterator it = queuedForRender.begin(); it != queuedForRender.end(); ++it) { DrawFarTexture(*it, va); } va->DrawArrayT(GL_QUADS); glDisable(GL_ALPHA_TEST); queuedForRender.clear(); }