advsky.cpp

来自「这是整套横扫千军3D版游戏的源码」· C++ 代码 · 共 859 行 · 第 1/2 页

CPP
859
字号
					}
				}
				bx++;
			}
		}

		for(int a=0;a<CLOUD_SIZE*CLOUD_SIZE;a++){
			cloudThickness2[a]=alphaTransform[rawClouds[0][a]>>7];
		}
		cloudThickness2[CLOUD_SIZE*CLOUD_SIZE]=cloudThickness2[CLOUD_SIZE*CLOUD_SIZE-1];	//this one is read in one place, so to avoid reading uninitialized mem ...

		//create the cloud shading
		int ydif[CLOUD_SIZE];
		for(int a=0;a<CLOUD_SIZE;++a){
			ydif[a]=0;
			ydif[a]+=cloudThickness2[(a+3*CLOUD_SIZE)];
			ydif[a]+=cloudThickness2[(a+2*CLOUD_SIZE)];
			ydif[a]+=cloudThickness2[(a+1*CLOUD_SIZE)];
			ydif[a]+=cloudThickness2[(a+0*CLOUD_SIZE)];
			ydif[a]-=cloudThickness2[(a-1*CLOUD_SIZE+CLOUD_SIZE*CLOUD_SIZE)];
			ydif[a]-=cloudThickness2[(a-2*CLOUD_SIZE+CLOUD_SIZE*CLOUD_SIZE)];
			ydif[a]-=cloudThickness2[(a-3*CLOUD_SIZE+CLOUD_SIZE*CLOUD_SIZE)];
		}

		int b=0;
		ydif[(b)&255]+=cloudThickness2[(b-3*CLOUD_SIZE+CLOUD_SIZE*CLOUD_SIZE)];
		ydif[(b)&255]-=cloudThickness2[(b)]*2;
		ydif[(b)&255]+=cloudThickness2[(b+4*CLOUD_SIZE)];

		for(int a=0;a<CLOUD_SIZE*3-1;a++){
			ydif[(a+1)&255]+=cloudThickness2[(a-3*CLOUD_SIZE+1+CLOUD_SIZE*CLOUD_SIZE)];
			ydif[(a+1)&255]-=cloudThickness2[(a+1)]*2;
			ydif[(a+1)&255]+=cloudThickness2[(a+4*CLOUD_SIZE+1)];

			int dif=0;

			dif+=ydif[(a)&255];
			dif+=ydif[(a+1)&255]>>1;
			dif+=ydif[(a-1)&255]>>1;
			dif+=ydif[(a+2)&255]>>2;
			dif+=ydif[(a-2)&255]>>2;
			dif/=16;

			cloudTexMem[a*4+0]=128+dif;
			cloudTexMem[a*4+1]=thicknessTransform[rawClouds[0][a]>>7];
			cloudTexMem[a*4+2]=255;
		}

		for(int a=CLOUD_SIZE*3-1;a<CLOUD_SIZE*CLOUD_SIZE-CLOUD_SIZE*4-1;a++){
			ydif[(a+1)&255]+=cloudThickness2[(a-3*CLOUD_SIZE+1)];
			ydif[(a+1)&255]-=cloudThickness2[(a+1)]*2;
			ydif[(a+1)&255]+=cloudThickness2[(a+4*CLOUD_SIZE+1)];

			int dif=0;

			dif+=ydif[(a)&255];
			dif+=ydif[(a+1)&255]>>1;
			dif+=ydif[(a-1)&255]>>1;
			dif+=ydif[(a+2)&255]>>2;
			dif+=ydif[(a-2)&255]>>2;
			dif/=16;

			cloudTexMem[a*4+0]=128+dif;
			cloudTexMem[a*4+1]=thicknessTransform[rawClouds[0][a]>>7];
			cloudTexMem[a*4+2]=255;
		}

		for(int a=CLOUD_SIZE*CLOUD_SIZE-CLOUD_SIZE*4-1;a<CLOUD_SIZE*CLOUD_SIZE;a++){
			ydif[(a+1)&255]+=cloudThickness2[(a-3*CLOUD_SIZE+1)];
			ydif[(a+1)&255]-=cloudThickness2[(a+1)]*2;
			ydif[(a+1)&255]+=cloudThickness2[(a+4*CLOUD_SIZE+1-CLOUD_SIZE*CLOUD_SIZE)];

			int dif=0;

			dif+=ydif[(a)&255];
			dif+=ydif[(a+1)&255]>>1;
			dif+=ydif[(a-1)&255]>>1;
			dif+=ydif[(a+2)&255]>>2;
			dif+=ydif[(a-2)&255]>>2;
			dif/=16;

			cloudTexMem[a*4+0]=128+dif;
			cloudTexMem[a*4+1]=thicknessTransform[rawClouds[0][a]>>7];
			cloudTexMem[a*4+2]=255;
		}

		int modDensity=(int) ((1-cloudDensity)*256);
		for(int a=0;a<CLOUD_SIZE*CLOUD_SIZE;a++){
			int f=(rawClouds[0][a]>>8)-modDensity;
			if(f<0)
				f=0;
			if(f>255)
				f=255;
			cloudTexMem[a*4+3]=f;
		}

		delete[] rawClouds;

		glBindTexture(GL_TEXTURE_2D, cloudDot3Tex);
		glTexSubImage2D(GL_TEXTURE_2D,0, 0,0,CLOUD_SIZE, CLOUD_SIZE,GL_RGBA, GL_UNSIGNED_BYTE, cloudTexMem);
	}
}

void CAdvSky::CreateRandMatrix(int matrix[32][32],float mod)
{
	for(int y=0;y<32;y++){
		for(int x=0;x<32;x++){
			float r = ((float)( rand() )) / (float)RAND_MAX;
			matrix[y][x]=((int)(r * 255.0f));
		}
	}
}

void CAdvSky::CreateRandDetailMatrix(unsigned char* matrix,int size)
{
	for(int a=0;a<size*size;a++){
		float  r = ((float)( rand() )) / (float)RAND_MAX;
		matrix[a]=((int)(r * 255.0f));
	}
}

void CAdvSky::CreateTransformVectors()
{
	for(int a=0;a<1024;++a){
		float f=(1023.0f-(a+cloudDensity*1024-512))/1023.0f;
		float alpha=pow(f*2,3);
		if(alpha>1)
			alpha=1;
		alphaTransform[a]=(int) (alpha*255);

		float d=f*2;
		if(d>1)
			d=1;
		thicknessTransform[a]=(unsigned char) (128+d*64+alphaTransform[a]*255/(4*255));
	}
}

void CAdvSky::DrawSun()
{
	glPushMatrix();
	CMatrix44f m(camera->pos,sundir1,UpVector,sundir2);
	glMultMatrixf(m.m);

	glDisable(GL_DEPTH_TEST);
	glDisable(GL_ALPHA_TEST);
	unsigned char buf[128];
	glEnable(GL_TEXTURE_2D);

	float3 modCamera=sundir1*camera->pos.x+sundir2*camera->pos.z;

	float ymod=(sunTexCoordY-0.5f)*domeWidth*0.025f*256;
	float fy=ymod+modCamera.z*CLOUD_SIZE*0.000025f;
	int baseY=int(floor(fy))&CLOUD_MASK;
	fy-=floor(fy);
	float fx=gs->frameNum*0.00005f*CLOUD_SIZE+modCamera.x*CLOUD_SIZE*0.000025f;
	int baseX=int(floor(fx))&CLOUD_MASK;
	fx-=floor(fx);

	if(baseX!=oldCoverBaseX || baseY!=oldCoverBaseY){
		oldCoverBaseX=baseX;
		oldCoverBaseY=baseY;
		CreateCover(baseX,baseY,covers[0]);
		CreateCover(baseX+1,baseY,covers[1]);
		CreateCover(baseX,baseY+1,covers[2]);
		CreateCover(baseX+1,baseY+1,covers[3]);
	}

	float mid=0;
	for(int x=0;x<32;++x){
		float cx1=covers[0][x]*(1-fx)+covers[1][x]*fx;
		float cx2=covers[2][x]*(1-fx)+covers[3][x]*fx;

		float cover=cx1*(1-fy)+cx2*fy;
		if(cover>127.5f)
			cover=127.5f;
		mid+=cover;

		buf[x+32]=(unsigned char)(255-cover*2);
		buf[x+64]=(unsigned char)(128-cover);
	}
	mid*=1.0f/32;
	for(int x=0;x<32;++x){
		buf[x]=(unsigned char)(255-mid*2);
	}

	glBindTexture(GL_TEXTURE_2D, sunFlareTex);
	glTexSubImage2D(GL_TEXTURE_2D,0,0,0,32,3,GL_LUMINANCE,GL_UNSIGNED_BYTE,buf);

	glColor4f(0.4f*sunColor.x,0.4f*sunColor.y,0.4f*sunColor.z,0.0f);
	glCallList(sunFlareList);

	glEnable(GL_DEPTH_TEST);
	glPopMatrix();
}

void CAdvSky::SetCloudShadow(int texunit)
{
}

void CAdvSky::ResetCloudShadow(int texunit)
{
}

void CAdvSky::DrawShafts()
{
}


void CAdvSky::InitSun()
{
	unsigned char* mem=SAFE_NEW unsigned char[128*128*4];

	for(int y=0;y<128;++y){
		for(int x=0;x<128;++x){
			mem[(y*128+x)*4+0]=255;
			mem[(y*128+x)*4+1]=255;
			mem[(y*128+x)*4+2]=255;
			float dist=sqrt((float)(y-64)*(y-64)+(x-64)*(x-64));
			if(dist>60)
				mem[(y*128+x)*4+3]=0;
			else
				mem[(y*128+x)*4+3]=255;
		}
	}

	glGenTextures(1, &sunTex);
	glBindTexture(GL_TEXTURE_2D, sunTex);
	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);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,128, 128, GL_RGBA, GL_UNSIGNED_BYTE, mem);

	for(int y=0;y<4;++y){
		for(int x=0;x<32;++x){
			if(y==0 && x%2)
				mem[(y*32+x)]=255;
			else
				mem[(y*32+x)]=0;
		}
	}

	glGenTextures(1, &sunFlareTex);
	glBindTexture(GL_TEXTURE_2D, sunFlareTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
//	gluBuild2DMipmaps(GL_TEXTURE_2D,1 ,32, 2, GL_ALPHA, GL_UNSIGNED_BYTE, mem);
	glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE ,32, 4,0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);

	delete[] mem;

	float3 ldir=modSunDir.cross(UpVector);
	ldir.Normalize();
	float3 udir=modSunDir.cross(ldir);

	sunFlareList=glGenLists(1);
	glNewList(sunFlareList, GL_COMPILE);
		glDisable(GL_FOG);
		glBindTexture(GL_TEXTURE_2D, sunFlareTex);
		glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE);
		glBegin(GL_TRIANGLE_STRIP);
		for(int x=0;x<257;++x){
			float dx=sin(x*2*PI/256.0f);
			float dy=cos(x*2*PI/256.0f);

			glTexCoord2f(x/256.0f,0.125f);
			glVertexf3(modSunDir*5+ldir*dx*0.0014f+udir*dy*0.0014f);
			glTexCoord2f(x/256.0f,0.875f);
			glVertexf3(modSunDir*5+ldir*dx*4+udir*dy*4);
		}
		glEnd();
		if (gu->drawFog) glEnable(GL_FOG);
	glEndList();
}

void CAdvSky::CreateCover(int baseX, int baseY, float *buf)
{
	static const int line[]={
		5, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5,
		5, 0, 1, 0, 2, 1, 3, 1, 4, 1, 5,
		5, 0, 1, 1, 2, 1, 3, 2, 4, 2, 5,
		4, 1, 1, 2, 2, 2, 3, 3, 4,
		4, 1, 1, 2, 2, 3, 3, 4, 4,
		4, 1, 1, 2, 2, 3, 2, 4, 3,
		5, 1, 0, 2, 1, 3, 1, 4, 2, 5, 2,
		5, 1, 0, 2, 0, 3, 1, 4, 1, 5, 1
	};
	int i=0;

	for(int l=0;l<8;++l){
		int num=line[i++];
		int cover1=0;
		int cover2=0;
		int cover3=0;
		int cover4=0;
		float total=0;
		for(int x=0;x<num;++x){
			int dx=line[i++];
			int dy=line[i++];
			int incy = ((baseY+dy) & CLOUD_MASK) * CLOUD_SIZE;
			int decy = ((baseY-dy) & CLOUD_MASK) * CLOUD_SIZE;
			int incx = (baseX+dx) & CLOUD_MASK;
			int decx = (baseX-dx) & CLOUD_MASK;

			cover1+=255-cloudThickness2[incy+decx];//*(num-x);
			cover2+=255-cloudThickness2[decy+decx];//*(num-x);
			cover3+=255-cloudThickness2[decy+incx];//*(num-x);
			cover4+=255-cloudThickness2[incy+incx];//*(num-x);
			total+=1;//(num-x);
		}

		buf[l]=cover1/total;
		buf[l+8]=cover2/total;
		buf[l+16]=cover3/total;
		buf[l+24]=cover4/total;
	}
}

void CAdvSky::CreateDetailTex(void)
{
	glViewport(0,0,256,256);
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0,1,0,1,-1,1);
	glMatrixMode(GL_MODELVIEW);
	glDisable(GL_FOG);
	glDisable(GL_LIGHTING);
	glEnable(GL_TEXTURE_2D);
	glClearColor(0,0,0,0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	glDisable(GL_DEPTH_TEST);

	unsigned char randDetailMatrix[32*32];

	for(int a=0;a<5;++a){
		float fade=(gs->frameNum/float(30<<a));
		fade-=floor(fade/2)*2;
		int size=min(32,256>>a);

		if(fade>1){
			fade=2-fade;
			if(!cloudDetailDown[a]){
				cloudDetailDown[a]=true;
				CreateRandDetailMatrix(randDetailMatrix,size);
				glBindTexture(GL_TEXTURE_2D, detailTextures[a+6]);
				glTexSubImage2D(GL_TEXTURE_2D,0, 0,0,size, size, GL_LUMINANCE, GL_UNSIGNED_BYTE, randDetailMatrix);
			}
		} else {
			if(cloudDetailDown[a]){
				cloudDetailDown[a]=false;
				CreateRandDetailMatrix(randDetailMatrix,size);
				glBindTexture(GL_TEXTURE_2D, detailTextures[a]);
				glTexSubImage2D(GL_TEXTURE_2D,0, 0,0,size, size, GL_LUMINANCE, GL_UNSIGNED_BYTE, randDetailMatrix);
			}

		}
		float tSize=max(1,8>>a);
		float c=pow(2.0f,a)*6/255.0f;
//		logOutput.Print("%f",c);
		CVertexArray* va=GetVertexArray();
		va->Initialize();

		va->AddVertexT(ZeroVector,0,0);
		va->AddVertexT(float3(1,0,0),tSize,0);
		va->AddVertexT(float3(1,1,0),tSize,tSize);
		va->AddVertexT(UpVector,0,tSize);

		float ifade=(3*fade*fade-2*fade*fade*fade);

		glBindTexture(GL_TEXTURE_2D, detailTextures[a+6]);
		glColor4f(c,c,c,1-ifade);
		va->DrawArrayT(GL_QUADS);
		glBindTexture(GL_TEXTURE_2D, detailTextures[a]);
		glColor4f(c,c,c,ifade);
		va->DrawArrayT(GL_QUADS);
	}
/*	unsigned char buf[256*256*4];
	glReadPixels(0,0,256,256,GL_RGBA,GL_UNSIGNED_BYTE,buf);
	CBitmap bm(buf,256,256);
	bm.Save("dc.bmp");
*/
	glBindTexture(GL_TEXTURE_2D, cdtex);
	glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,256,256);
//	SwapBuffers(hDC);
//	SleepEx(500,true);

	glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);
	glEnable(GL_DEPTH_TEST);
}

float3 CAdvSky::GetDirFromTexCoord(float x, float y)
{
	float3 dir;

	dir.x=(x-0.5f)*domeWidth;
	dir.z=(y-0.5f)*domeWidth;

	float hdist=sqrt(dir.x*dir.x+dir.z*dir.z);
	float fy=asin(hdist/400);
	dir.y=(cos(fy)-domeheight)*400;

	dir.Normalize();

	return dir;
}

//should be improved
//only take stuff in yz plane
float CAdvSky::GetTexCoordFromDir(float3 dir)
{
	float tp=0.5f;
	float step=0.25f;

	for(int a=0;a<10;++a){
		float tx=0.5f+tp;
		float3 d=GetDirFromTexCoord(tx,0.5f);
		if(d.y<dir.y)
			tp-=step;
		else
			tp+=step;
		step*=0.5f;
	}
	return 0.5f+tp;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?