📄 grassdrawer.cpp
字号:
const int blockMapSize=grassSquareSize*grassBlockSize;
CGrassBlockDrawer drawer;
drawer.cx=(int)(camera->pos.x/(SQUARE_SIZE*blockMapSize));
drawer.cy=(int)(camera->pos.z/(SQUARE_SIZE*blockMapSize));
drawer.gd = this;
readmap->GridVisibility (camera, blockMapSize, maxGrassDist, &drawer);
CVertexArray *va = drawer.va;
float grassDistance=maxGrassDist;
std::sort(drawer.inviewGrass.begin(),drawer.inviewGrass.end(),GrassSort);
std::sort(drawer.inviewNearGrass.begin(),drawer.inviewNearGrass.end(),GrassSortNear);
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_VERTEX_PROGRAM_ARB );
glAlphaFunc(GL_GREATER,0.01f);
glDepthMask(false);
if(shadowHandler->drawShadows && !gd->DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE3_ARB);
glBindTexture(GL_TEXTURE_2D, farTex);
glActiveTextureARB(GL_TEXTURE0_ARB);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glBindProgramARB( GL_VERTEX_PROGRAM_ARB, grassFarVP );
} else {
glBindProgramARB( GL_VERTEX_PROGRAM_ARB, grassFarNSVP );
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,12, 1.0f/(gs->mapx*SQUARE_SIZE),1.0f/(gs->mapy*SQUARE_SIZE),0,1);
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,13, 1.0f/(gs->pwr2mapx*SQUARE_SIZE),1.0f/(gs->pwr2mapy*SQUARE_SIZE),0,1);
glBindTexture(GL_TEXTURE_2D, farTex);
if(gd->DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE3_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glActiveTextureARB(GL_TEXTURE2_ARB);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
for(std::vector<InviewGrass*>::iterator gi=drawer.inviewGrass.begin();gi!=drawer.inviewGrass.end();++gi){
if((*gi)->dist+128<grassDistance)
glColor4f(0.62f,0.62f,0.62f,1);
else
glColor4f(0.62f,0.62f,0.62f,1-((*gi)->dist+128-grassDistance)/128.0f);
float3 v=grass[(*gi)->num].pos-camera->pos;
v.Normalize();
float3 side(v.cross(UpVector));
side.Normalize();
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,8, side.x,side.y,side.z,0);
float3 up(side.cross(v));
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9, up.x,up.y,up.z,0);
float ang=acos(v.y);
int texPart=min(15,(int)max(0,(int)((ang+PI/16-PI/2)/PI*30)));
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10, texPart/16.0f,0,0,0.0f);
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, -v.x,-v.y,-v.z,0);
grass[(*gi)->num].va->DrawArrayTN(GL_QUADS);
delete *gi;
}
glColor4f(0.62f,0.62f,0.62f,1);
for(std::vector<InviewNearGrass*>::iterator gi=drawer.inviewNearGrass.begin();gi!=drawer.inviewNearGrass.end();++gi){
int x=(*gi)->x;
int y=(*gi)->y;
if(grassMap[(y)*gs->mapx/grassSquareSize+(x)]){
float3 squarePos((x+0.5f)*SQUARE_SIZE*grassSquareSize, 0, (y+0.5f)*SQUARE_SIZE*grassSquareSize);
squarePos.y=ground->GetHeight2(squarePos.x,squarePos.z);
float3 v=squarePos-camera->pos;
v.Normalize();
float3 side(v.cross(UpVector));
side.Normalize();
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,8, side.x,side.y,side.z,0);
float3 up(side.cross(v));
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,9, up.x,up.y,up.z,0);
float ang=acos(v.y);
int texPart=min(15,int(max(0,int((ang+PI/16-PI/2)/PI*30))));
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,10, texPart/16.0f,0,0,0.0f);
glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB,11, -v.x,-v.y,-v.z,0);
srand(y*1025+x);
rand();
rand();
int numGrass=numTurfs;
va=GetVertexArray();
va->Initialize();
for(int a=0;a<numGrass;a++){
float dx=(x+fRand(1))*SQUARE_SIZE*grassSquareSize;
float dy=(y+fRand(1))*SQUARE_SIZE*grassSquareSize;
float3 pos(dx,ground->GetHeight2(dx,dy)+0.5f,dy);
pos.y-=ground->GetSlope(dx,dy)*10+0.03f;
float col=1;
if(camera->InView(pos,turfSize*0.7f)){
va->AddVertexTN(pos,0,0,float3(-turfSize*0.6f,-turfSize*0.6f,col));
va->AddVertexTN(pos,1/16.0f,0,float3(turfSize*0.6f,-turfSize*0.6f,col));
va->AddVertexTN(pos,1/16.0f,1,float3(turfSize*0.6f,turfSize*0.6f,col));
va->AddVertexTN(pos,0,1,float3(-turfSize*0.6f,turfSize*0.6f,col));
}
}
va->DrawArrayTN(GL_QUADS);
}
delete *gi;
}
//cleanup stuff
glDisable( GL_VERTEX_PROGRAM_ARB );
glDepthMask(true);
glEnable(GL_FOG);
glDisable(GL_ALPHA_TEST);
if(shadowHandler->drawShadows && !gd->DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE_ARB,1);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glActiveTextureARB(GL_TEXTURE1_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);
glActiveTextureARB(GL_TEXTURE3_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
if(gd->DrawExtraTex()){
glActiveTextureARB(GL_TEXTURE3_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE0_ARB);
}
glActiveTextureARB(GL_TEXTURE1_ARB);
glDisable(GL_TEXTURE_2D);
glActiveTextureARB(GL_TEXTURE2_ARB);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV,GL_RGB_SCALE_ARB,1);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glActiveTextureARB(GL_TEXTURE0_ARB);
int startClean=lastListClean*20%(32*32);
lastListClean=gs->frameNum;
int endClean=gs->frameNum*20%(32*32);
if(startClean>endClean){
for(int a=startClean;a<32*32;a++){
if(grass[a].lastSeen<gs->frameNum-50 && grass[a].va){
delete grass[a].va;
grass[a].va=0;
}
}
for(int a=0;a<endClean;a++){
if(grass[a].lastSeen<gs->frameNum-50 && grass[a].va){
delete grass[a].va;
grass[a].va=0;
}
}
} else {
for(int a=startClean;a<endClean;a++){
if(grass[a].lastSeen<gs->frameNum-50 && grass[a].va){
delete grass[a].va;
grass[a].va=0;
}
}
}
}
void CGrassDrawer::ResetPos(const float3& pos)
{
if(grassOff)
return;
int a=(int(pos.z/(SQUARE_SIZE*grassSquareSize*grassBlockSize))&31)*32+(int(pos.x/(SQUARE_SIZE*grassSquareSize*grassBlockSize))&31);
if(grass[a].va){
delete grass[a].va;
grass[a].va=0;
}
grass[a].square=-1;
}
void CGrassDrawer::CreateGrassDispList(int listNum)
{
CVertexArray* va=GetVertexArray();
va->Initialize();
for(int a=0;a<strawPerTurf;++a){
float maxAng=fRand(PI/2);
float3 sideVect(fRand(1)-0.5f,0,fRand(1)-0.5f);
sideVect.Normalize();
float3 forwardVect=sideVect.cross(UpVector);
sideVect*=0.32f;
float3 basePos(30,0,30);
while(basePos.SqLength2D()>turfSize*turfSize/4)
basePos=float3(fRand(turfSize)-turfSize*0.5f,0,fRand(turfSize)-turfSize*0.5f);
float length=4+fRand(4);
int tex=(int)fRand(15.9999f);
float xtexBase=tex*(1/16.0f);
int numSections=1+(int)(maxAng*5);
for(int b=0;b<numSections;++b){
float h=b*(1.0f/numSections);
float ang=maxAng*h;
if(b==0){
va->AddVertexT(basePos+sideVect*(1-h)+(UpVector*cos(ang)+forwardVect*sin(ang))*length*h-float3(0,0.1f,0), xtexBase, h);
va->AddVertexT(basePos+sideVect*(1-h)+(UpVector*cos(ang)+forwardVect*sin(ang))*length*h-float3(0,0.1f,0), xtexBase, h);
} else {
va->AddVertexT(basePos+sideVect*(1-h)+(UpVector*cos(ang)+forwardVect*sin(ang))*length*h, xtexBase, h);
}
va->AddVertexT(basePos-sideVect*(1-h)+(UpVector*cos(ang)+forwardVect*sin(ang))*length*h, xtexBase+1.0f/16, h);
}
va->AddVertexT(basePos+(UpVector*cos(maxAng)+forwardVect*sin(maxAng))*length, xtexBase+1.0f/32, 1);
va->AddVertexT(basePos+(UpVector*cos(maxAng)+forwardVect*sin(maxAng))*length, xtexBase+1.0f/32, 1);
}
glNewList(listNum,GL_COMPILE);
va->DrawArrayT(GL_TRIANGLE_STRIP);
glEndList();
}
void CGrassDrawer::CreateGrassBladeTex(unsigned char* buf)
{
float3 col(0.59f+fRand(0.11f),0.81f+fRand(0.08f),0.57f+fRand(0.11f));
for(int y=0;y<64;++y){
for(int x=0;x<16;++x){
buf[(y*256+x)*4+0]=(unsigned char) ((col.x+y*0.0005f+fRand(0.05f))*255);
buf[(y*256+x)*4+1]=(unsigned char) ((col.y+y*0.0006f+fRand(0.05f))*255);
buf[(y*256+x)*4+2]=(unsigned char) ((col.z+y*0.0004f+fRand(0.05f))*255);
buf[(y*256+x)*4+3]=1;
}
}
for(int y=0;y<64;++y){
for(int x=7;x<9;++x){
buf[(y*256+x)*4+0]=(unsigned char) ((col.x+y*0.0005f+fRand(0.05f)-0.03f)*255);
buf[(y*256+x)*4+1]=(unsigned char) ((col.y+y*0.0006f+fRand(0.05f)-0.03f)*255);
buf[(y*256+x)*4+2]=(unsigned char) ((col.z+y*0.0004f+fRand(0.05f)-0.03f)*255);
}
}
for(int y=4;y<64;y+=4+(int)fRand(3)){
for(int a=0;a<7 && a+y<64;++a){
buf[((a+y)*256+a+9)*4+0]=(unsigned char) ((col.x+y*0.0005f+fRand(0.05f)-0.03f)*255);
buf[((a+y)*256+a+9)*4+1]=(unsigned char) ((col.y+y*0.0006f+fRand(0.05f)-0.03f)*255);
buf[((a+y)*256+a+9)*4+2]=(unsigned char) ((col.z+y*0.0004f+fRand(0.05f)-0.03f)*255);
buf[((a+y)*256+6-a)*4+0]=(unsigned char) ((col.x+y*0.0005f+fRand(0.05f)-0.03f)*255);
buf[((a+y)*256+6-a)*4+1]=(unsigned char) ((col.y+y*0.0006f+fRand(0.05f)-0.03f)*255);
buf[((a+y)*256+6-a)*4+2]=(unsigned char) ((col.z+y*0.0004f+fRand(0.05f)-0.03f)*255);
}
}
/* for(int y=0;y<64;++y){
for(int x=0;x<16;++x){
buf[(y*256+x)*4+0]=255;
buf[(y*256+x)*4+1]=255;
buf[(y*256+x)*4+2]=255;
buf[(y*256+x)*4+3]=1;
}
}*/
}
void CGrassDrawer::CreateFarTex(void)
{
int sizeMod=2;
unsigned char* buf=SAFE_NEW unsigned char[64*sizeMod*1024*sizeMod*4];
unsigned char* buf2=SAFE_NEW unsigned char[256*sizeMod*256*sizeMod*4];
memset(buf,0,64*sizeMod*1024*sizeMod*4);
memset(buf2,0,256*sizeMod*256*sizeMod*4);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glBindTexture(GL_TEXTURE_2D, grassBladeTex);
glEnable(GL_TEXTURE_2D);
glDisable(GL_FOG);
glDisable(GL_BLEND);
glColor4f(1,1,1,1);
glViewport(0,0,256*sizeMod,256*sizeMod);
for(int a=0;a<16;++a){
glClearColor(0.0f,0.0f,0.0f,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef((a-1)*90/15.0f,1,0,0);
glTranslatef(0,-0.5f,0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-turfSize*0.6f, turfSize*0.6f, -turfSize*0.6f, turfSize*0.6f, -turfSize, turfSize);
glCallList(grassDL);
glReadPixels(0,0,256*sizeMod,256*sizeMod,GL_RGBA,GL_UNSIGNED_BYTE,buf2);
// CBitmap bm(buf2,512,512);
// bm.Save("ft.bmp");
int dx=a*64*sizeMod;
for(int y=0;y<64*sizeMod;++y){
for(int x=0;x<64*sizeMod;++x){
float r=0,g=0,b=0,a=0;
for(int y2=0;y2<4;++y2){
for(int x2=0;x2<4;++x2){
if(buf2[((y*4+y2)*256*sizeMod+x*4+x2)*4]==0 && buf2[((y*4+y2)*256*sizeMod+x*4+x2)*4+1]==0 && buf2[((y*4+y2)*256*sizeMod+x*4+x2)*4+2]==0){
} else {
float s=1;
if(y!=0 && y!=64*sizeMod-1 && (buf2[((y*4+y2)*256*sizeMod+x*4+x2+1)*4+1]==0 || buf2[((y*4+y2)*256*sizeMod+x*4+x2-1)*4+1]==0 || buf2[((y*4+y2+1)*256*sizeMod+x*4+x2)*4+1]==0 || buf2[((y*4+y2-1)*256*sizeMod+x*4+x2)*4+1]==0)){
s=0.5f;
}
r+=s*buf2[((y*4+y2)*256*sizeMod+x*4+x2)*4+0];
g+=s*buf2[((y*4+y2)*256*sizeMod+x*4+x2)*4+1];
b+=s*buf2[((y*4+y2)*256*sizeMod+x*4+x2)*4+2];
a+=s;
}
}
}
if(a==0){
buf[((y)*1024*sizeMod+x+dx)*4+0]=190;
buf[((y)*1024*sizeMod+x+dx)*4+1]=230;
buf[((y)*1024*sizeMod+x+dx)*4+2]=190;
buf[((y)*1024*sizeMod+x+dx)*4+3]=0;
} else {
buf[((y)*1024*sizeMod+x+dx)*4+0]=(unsigned char) (r/a);
buf[((y)*1024*sizeMod+x+dx)*4+1]=(unsigned char) (g/a);
buf[((y)*1024*sizeMod+x+dx)*4+2]=(unsigned char) (b/a);
buf[((y)*1024*sizeMod+x+dx)*4+3]=(unsigned char) (min((float)255,a*16));
}
}
}
}
// CBitmap bm(buf,1024*sizeMod,64*sizeMod);
// bm.Save("fartex.bmp");
glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
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);
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,1024*sizeMod, 64*sizeMod, GL_RGBA, GL_UNSIGNED_BYTE, buf);
delete[] buf;
delete[] buf2;
}
void CGrassDrawer::AddGrass(float3 pos)
{
if(grassOff)
return;
grassMap[(int(pos.z)/SQUARE_SIZE/grassSquareSize)*gs->mapx/grassSquareSize+int(pos.x)/SQUARE_SIZE/grassSquareSize]=1;
}
void CGrassDrawer::RemoveGrass(int x, int z)
{
if(grassOff)
return;
grassMap[(z/grassSquareSize)*gs->mapx/grassSquareSize+x/grassSquareSize]=0;
ResetPos(float3(x*SQUARE_SIZE,0,z*SQUARE_SIZE));
}
void CGrassDrawer::SetTexGen(float scalex,float scaley, float offsetx, float offsety)
{
GLfloat plan[]={scalex,0,0,offsetx};
glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGenfv(GL_S,GL_EYE_PLANE,plan);
glEnable(GL_TEXTURE_GEN_S);
GLfloat plan2[]={0,0,scaley,offsety};
glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGenfv(GL_T,GL_EYE_PLANE,plan2);
glEnable(GL_TEXTURE_GEN_T);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -