void CAdvTreeDrawer::DrawShadowPass(void) { float treeDistance=oldTreeDistance; int activeFarTex=camera->forward.z<0 ? treeGen->farTex[0] : treeGen->farTex[1]; bool drawDetailed=true; if(treeDistance<4) drawDetailed=false; glBindTexture(GL_TEXTURE_2D, activeFarTex); glEnable(GL_TEXTURE_2D); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeFarShadowVP ); glEnable( GL_VERTEX_PROGRAM_ARB ); glEnable(GL_ALPHA_TEST); glPolygonOffset(1,1); glEnable(GL_POLYGON_OFFSET_FILL); CAdvTreeSquareDrawer_SP drawer; int cx = drawer.cx=(int)(camera->pos.x/(SQUARE_SIZE*TREE_SQUARE_SIZE)); 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; GML_STDMUTEX_LOCK(tree); // DrawShadowPass // draw with extraSize=1 readmap->GridVisibility (camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer, 1); if(drawDetailed){ int xstart=std::max(0,cx-2); int xend=std::min(gs->mapx/TREE_SQUARE_SIZE-1,cx+2); int ystart=std::max(0,cy-2); int yend=std::min(gs->mapy/TREE_SQUARE_SIZE-1,cy+2); glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glEnable(GL_TEXTURE_2D); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeShadowVP ); glEnable( GL_VERTEX_PROGRAM_ARB ); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13, camera->right.x,camera->right.y,camera->right.z,0); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9, camera->up.x,camera->up.y,camera->up.z,0); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, 1,1,1,0.85f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,12, 0,0,0,0.20f*(1.0f/MAX_TREE_HEIGHT)); //w=alpha/height modifier glAlphaFunc(GL_GREATER,0.5f); glEnable(GL_ALPHA_TEST); glColor4f(1,1,1,1); va=GetVertexArray(); va->Initialize(); struct FadeTree{ float3 pos; float relDist; float deltaY; int type; }; 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){ TreeStruct* ts=&ti->second; float3 pos(ts->pos); int type=ts->type; float dy; unsigned int displist; if(type<8){ dy=0.5f; displist=treeGen->pineDL+type; } else { type-=8; dy=0; displist=treeGen->leafDL+type; } if(camera->InView(pos+float3(0,MAX_TREE_HEIGHT/2,0),MAX_TREE_HEIGHT/2+150)){ float camDist=(pos-camera->pos).SqLength(); if(camDist<SQUARE_SIZE*SQUARE_SIZE*110*110){ //draw detailed tree glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,pos.x,pos.y,pos.z,0); glCallList(displist); } else if(camDist<SQUARE_SIZE*SQUARE_SIZE*125*125){ //draw fading tree float relDist=(pos.distance(camera->pos)-SQUARE_SIZE*110)/(SQUARE_SIZE*15); glAlphaFunc(GL_GREATER,0.8f+relDist*0.2f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,pos.x,pos.y,pos.z,0); glCallList(displist); glAlphaFunc(GL_GREATER,0.5f); pFT->pos=pos; pFT->deltaY=dy; pFT->type=type; pFT->relDist=relDist; ++pFT; } else { //draw undetailed tree DrawTreeVertex(pos, type*0.125f, dy, false); } } } } } //draw trees that have been marked as falling glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,0,0,0,0); for(std::list<FallingTree>::iterator fti=fallingTrees.begin(); fti!=fallingTrees.end(); ++fti){ float3 pos=fti->pos-UpVector*(fti->fallPos*20); if(camera->InView(pos+float3(0,MAX_TREE_HEIGHT/2,0),MAX_TREE_HEIGHT/2)){ float ang=fti->fallPos*PI; float3 up(fti->dir.x*sin(ang),cos(ang),fti->dir.z*sin(ang)); float3 z(up.cross(float3(1,0,0))); z.ANormalize(); float3 x(z.cross(up)); CMatrix44f transMatrix(pos,x,up,z); 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(); } } glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeFarShadowVP ); 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); DrawTreeVertex(pFTree->pos, pFTree->type*0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER,1-pFTree->relDist*0.5f); va->DrawArrayT(GL_QUADS); } } glDisable(GL_POLYGON_OFFSET_FILL); glDisable( GL_VERTEX_PROGRAM_ARB ); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); }
void CAdvTreeDrawer::DrawShadowPass(void) { 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); varr = GetVertexArray(); varr->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; varr->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 { DrawTreeVertex(varr, 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); varr->DrawArrayT(GL_QUADS); for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) { // faded close trees varr = GetVertexArray(); varr->Initialize(); varr->CheckInitSize(12 * VA_SIZE_T); DrawTreeVertex(varr, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f)); varr->DrawArrayT(GL_QUADS); } po->Disable(); } glEnable(GL_CULL_FACE); glDisable(GL_POLYGON_OFFSET_FILL); glDisable(GL_TEXTURE_2D); glDisable(GL_ALPHA_TEST); }
void CAdvTreeDrawer::Draw(float treeDistance,bool drawReflection) { int activeFarTex=camera->forward.z<0 ? treeGen->farTex[0] : treeGen->farTex[1]; bool drawDetailed=true; if(treeDistance<4) drawDetailed=false; if(drawReflection) drawDetailed=false; CBaseGroundDrawer *gd = readmap->GetGroundDrawer (); glEnable(GL_ALPHA_TEST); if(gu->drawFog) { glFogfv(GL_FOG_COLOR, mapInfo->atmosphere.fogColor); glEnable(GL_FOG); } if(shadowHandler->drawShadows && !gd->DrawExtraTex()){ glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeFarVP ); glEnable(GL_VERTEX_PROGRAM_ARB); 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); if(shadowHandler->useFPShadows){ glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, treeGen->treeFPShadow ); glEnable( GL_FRAGMENT_PROGRAM_ARB ); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,10, mapInfo->light.groundAmbientColor.x,mapInfo->light.groundAmbientColor.y,mapInfo->light.groundAmbientColor.z,1); glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,11, 0,0,0,1-mapInfo->light.groundShadowDensity*0.5f); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, activeFarTex); } else { glEnable(GL_TEXTURE_2D); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, 1-mapInfo->light.groundShadowDensity*0.5f); float texConstant[]={mapInfo->light.groundAmbientColor.x,mapInfo->light.groundAmbientColor.y,mapInfo->light.groundAmbientColor.z,0.0f}; glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,texConstant); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE2_RGB_ARB,GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND2_RGB_ARB,GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_INTERPOLATE_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB,GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_ALPHA_ARB,GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB,GL_ADD); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB); glActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, activeFarTex); } glActiveTextureARB(GL_TEXTURE0_ARB); glMatrixMode(GL_MATRIX0_ARB); glLoadMatrixf(shadowHandler->shadowMatrix.m); glMatrixMode(GL_MODELVIEW); } else { glBindTexture(GL_TEXTURE_2D, activeFarTex); } glEnable(GL_TEXTURE_2D); int cx=(int)(camera->pos.x/(SQUARE_SIZE*TREE_SQUARE_SIZE)); int cy=(int)(camera->pos.z/(SQUARE_SIZE*TREE_SQUARE_SIZE)); CAdvTreeSquareDrawer drawer; drawer.td = this; drawer.cx = cx; drawer.cy = cy; drawer.treeDistance = treeDistance * SQUARE_SIZE * TREE_SQUARE_SIZE; drawer.drawDetailed = drawDetailed; GML_STDMUTEX_LOCK(tree); // Draw // draw far away trees using the map dependent grid visibility oldTreeDistance=treeDistance; readmap->GridVisibility (camera, TREE_SQUARE_SIZE, drawer.treeDistance * 2.0f, &drawer); if(drawDetailed){ int xstart=std::max(0,cx-2); int xend=std::min(gs->mapx/TREE_SQUARE_SIZE-1,cx+2); int ystart=std::max(0,cy-2); int yend=std::min(gs->mapy/TREE_SQUARE_SIZE-1,cy+2); if(shadowHandler->drawShadows && !gd->DrawExtraTex()){ glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeVP ); glActiveTextureARB(GL_TEXTURE1_ARB); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glActiveTextureARB(GL_TEXTURE0_ARB); } else { glBindTexture(GL_TEXTURE_2D, treeGen->barkTex); glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeNSVP ); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,15, 1.0f/(gs->pwr2mapx*SQUARE_SIZE),1.0f/(gs->pwr2mapy*SQUARE_SIZE),1.0f/(gs->pwr2mapx*SQUARE_SIZE),1); } glEnable( GL_VERTEX_PROGRAM_ARB ); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13, camera->right.x,camera->right.y,camera->right.z,0); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9, camera->up.x,camera->up.y,camera->up.z,0); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, mapInfo->light.groundSunColor.x,mapInfo->light.groundSunColor.y,mapInfo->light.groundSunColor.z,0.85f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,14, mapInfo->light.groundAmbientColor.x,mapInfo->light.groundAmbientColor.y,mapInfo->light.groundAmbientColor.z,0.85f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,12, 0,0,0,0.20f*(1.0f/MAX_TREE_HEIGHT)); //w=alpha/height modifier glAlphaFunc(GL_GREATER,0.5f); glDisable(GL_BLEND); glColor4f(1,1,1,1); va=GetVertexArray(); va->Initialize(); struct FadeTree{ float3 pos; float relDist; float deltaY; int type; }; 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){ TreeStruct* ts=&ti->second; float3 pos(ts->pos); int type=ts->type; float dy; unsigned int displist; if(type<8){ dy=0.5f; displist=treeGen->pineDL+type; } else { type-=8; dy=0; displist=treeGen->leafDL+type; } if(camera->InView(pos+float3(0,MAX_TREE_HEIGHT/2,0),MAX_TREE_HEIGHT/2)){ float camDist=(pos-camera->pos).SqLength(); if(camDist<SQUARE_SIZE*SQUARE_SIZE*110*110){ //draw detailed tree glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,pos.x,pos.y,pos.z,0); glCallList(displist); } else if(camDist<SQUARE_SIZE*SQUARE_SIZE*125*125){ //draw fading tree float relDist=(pos.distance(camera->pos)-SQUARE_SIZE*110)/(SQUARE_SIZE*15); glAlphaFunc(GL_GREATER,0.8f+relDist*0.2f); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,pos.x,pos.y,pos.z,0); glCallList(displist); glAlphaFunc(GL_GREATER,0.5f); pFT->pos=pos; pFT->deltaY=dy; pFT->type=type; pFT->relDist=relDist; ++pFT; } else { //draw undetailed tree DrawTreeVertex(pos, type*0.125f, dy, false); } } } } } //draw trees that has been marked as falling glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10,0,0,0,0); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13, camera->right.x,camera->right.y,camera->right.z,0); glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9, camera->up.x,camera->up.y,camera->up.z,0); for(std::list<FallingTree>::iterator fti=fallingTrees.begin(); fti!=fallingTrees.end(); ++fti){ float3 pos=fti->pos-UpVector*(fti->fallPos*20); if(camera->InView(pos+float3(0,MAX_TREE_HEIGHT/2,0),MAX_TREE_HEIGHT/2)){ float ang=fti->fallPos*PI; float3 up(fti->dir.x*sin(ang),cos(ang),fti->dir.z*sin(ang)); float3 z(up.cross(float3(-1,0,0))); z.ANormalize(); float3 x(up.cross(z)); CMatrix44f transMatrix(pos,x,up,z); 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(); } } glDisable( GL_VERTEX_PROGRAM_ARB ); if(shadowHandler->drawShadows && !gd->DrawExtraTex()){ glBindProgramARB( GL_VERTEX_PROGRAM_ARB, treeGen->treeFarVP ); glEnable(GL_VERTEX_PROGRAM_ARB); glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, activeFarTex); glActiveTextureARB(GL_TEXTURE0_ARB); } else { 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); DrawTreeVertex(pFTree->pos, pFTree->type*0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER,1-pFTree->relDist*0.5f); va->DrawArrayT(GL_QUADS); } } if(shadowHandler->drawShadows && !gd->DrawExtraTex()){ glDisable( GL_VERTEX_PROGRAM_ARB ); if(shadowHandler->useFPShadows){ glDisable(GL_FRAGMENT_PROGRAM_ARB); } glActiveTextureARB(GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE0_ARB); 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); } glDisable(GL_FOG); glDisable(GL_ALPHA_TEST); //clean out squares from memory that are no longer visible int startClean=lastListClean*20%(nTrees); lastListClean=gs->frameNum; int endClean=gs->frameNum*20%(nTrees); 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 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; #define L mapInfo->light glEnable(GL_ALPHA_TEST); glEnable(GL_TEXTURE_2D); if (globalRendering->drawFog) { glFogfv(GL_FOG_COLOR, mapInfo->atmosphere.fogColor); glEnable(GL_FOG); } 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, L.groundAmbientColor.x, L.groundAmbientColor.y, L.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) { #define MX (gs->pwr2mapx * SQUARE_SIZE) #define 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); #undef MX #undef MY } } 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, L.groundSunColor.x, L.groundSunColor.y, L.groundSunColor.z, 0.85f); treeShader->SetUniform4f(14, L.groundAmbientColor.x, L.groundAmbientColor.y, L.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); varr = GetVertexArray(); varr->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; varr->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 DrawTreeVertex(varr, 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 varr->DrawArrayT(GL_QUADS); // draw faded mid-distance trees for (FadeTree* pFTree = fadeTrees; pFTree < pFT; ++pFTree) { varr = GetVertexArray(); varr->Initialize(); varr->CheckInitSize(12 * VA_SIZE_T); DrawTreeVertex(varr, pFTree->pos, pFTree->type * 0.125f, pFTree->deltaY, false); glAlphaFunc(GL_GREATER, 1.0f - (pFTree->relDist * 0.5f)); varr->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; } } } #undef L }