basicsky.cpp

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

CPP
809
字号
			}

		}
		int ifade=(int)((3*fade*fade-2*fade*fade*fade)*256);

		for(int y=0;y<32;y++){
			for(int x=0;x<32;x++){
				blendMatrix[a][y][x]=(randMatrix[a][y][x]*ifade+randMatrix[a+8][y][x]*(256-ifade))>>8;
			}
		}
	}
	int rawClouds[CLOUD_SIZE][CLOUD_SIZE];//=SAFE_NEW int[CLOUD_SIZE][CLOUD_SIZE];

	for(int a=0;a<CLOUD_SIZE*CLOUD_SIZE;a++){
		rawClouds[0][a]=0;
	}

	int kernel[CLOUD_SIZE/4*CLOUD_SIZE/4];
	for(int a=0;a<CLOUD_DETAIL;a++){
		for(int y=0;y<(CLOUD_SIZE/4)>>a;++y){
			float ydist=fabs((float)1+y-((CLOUD_SIZE/8)>>a))/((CLOUD_SIZE/8)>>a);
			ydist=3*ydist*ydist-2*ydist*ydist*ydist;
			for(int x=0;x<(CLOUD_SIZE/4)>>a;++x){
				float xdist=fabs((float)1+x-((CLOUD_SIZE/8)>>a))/((CLOUD_SIZE/8)>>a);
				xdist=3*xdist*xdist-2*xdist*xdist*xdist;

				float contrib=(1-xdist)*(1-ydist);
				kernel[y*CLOUD_SIZE/4+x]=(int)( contrib*((4<<CLOUD_DETAIL)>>a));
			}
		}
		unsigned int by=0,bx=0;
		for(int y=0;y<CLOUD_SIZE-((CLOUD_SIZE/8)>>a);y+=(CLOUD_SIZE/8)>>a){
			for(int x=0;x<CLOUD_SIZE-((CLOUD_SIZE/8)>>a);x+=(CLOUD_SIZE/8)>>a){
				int blend=blendMatrix[a][by&31][bx&31];
				for(int y2=0;y2<((CLOUD_SIZE/4)>>a)-1;++y2){
					for(int x2=0;x2<((CLOUD_SIZE/4)>>a)-1;++x2){
						rawClouds[y+y2][x+x2]+=blend*kernel[y2*CLOUD_SIZE/4+x2];
					}
				}
				bx++;
			}
			by++;
		}
		by=0;
		bx=31;
		for(int y=0;y<CLOUD_SIZE-((CLOUD_SIZE/8)>>a);y+=(CLOUD_SIZE/8)>>a){
			int x=CLOUD_SIZE-((CLOUD_SIZE/8)>>a);
			int blend=blendMatrix[a][by&31][bx&31];
			for(int y2=0;y2<((CLOUD_SIZE/4)>>a)-1;++y2){
				for(int x2=0;x2<((CLOUD_SIZE/4)>>a)-1;++x2){
					if(x+x2<CLOUD_SIZE)
						rawClouds[y+y2][x+x2]+=blend*kernel[y2*CLOUD_SIZE/4+x2];
					else
						rawClouds[y+y2][x+x2-CLOUD_SIZE]+=blend*kernel[y2*CLOUD_SIZE/4+x2];
				}
			}
			by++;
		}
		bx=0;
		by=31;
		for(int x=0;x<CLOUD_SIZE-((CLOUD_SIZE/8)>>a);x+=(CLOUD_SIZE/8)>>a){
			int y=CLOUD_SIZE-((CLOUD_SIZE/8)>>a);
			int blend=blendMatrix[a][by&31][bx&31];
			for(int y2=0;y2<((CLOUD_SIZE/4)>>a)-1;++y2){
				for(int x2=0;x2<((CLOUD_SIZE/4)>>a)-1;++x2){
					if(y+y2<CLOUD_SIZE)
						rawClouds[y+y2][x+x2]+=blend*kernel[y2*CLOUD_SIZE/4+x2];
					else
						rawClouds[y+y2-CLOUD_SIZE][x+x2]+=blend*kernel[y2*CLOUD_SIZE/4+x2];
				}
			}
			bx++;
		}
	}

	for(int a=0;a<CLOUD_SIZE*CLOUD_SIZE;a++){
		cloudThickness[a*4+3]=alphaTransform[rawClouds[0][a]>>7];
	}
	cloudThickness[CLOUD_SIZE*CLOUD_SIZE*4+3]=alphaTransform[rawClouds[0][0]>>7];
        // next line unused
	cloudThickness[CLOUD_SIZE*CLOUD_SIZE*4+0]=cloudThickness[CLOUD_SIZE*CLOUD_SIZE*4+1]=cloudThickness[CLOUD_SIZE*CLOUD_SIZE*4+2]=0;

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

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

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

		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;

		cloudThickness[a*4+0]=128+dif;
		cloudThickness[a*4+1]=thicknessTransform[rawClouds[0][a]>>7];
		cloudThickness[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]+=cloudThickness[(a-3*CLOUD_SIZE+1)*4+3];
		ydif[(a+1)&255]-=cloudThickness[(a+1)*4+3]*2;
		ydif[(a+1)&255]+=cloudThickness[(a+4*CLOUD_SIZE+1)*4+3];

		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;

		cloudThickness[a*4+0]=128+dif;
		cloudThickness[a*4+1]=thicknessTransform[rawClouds[0][a]>>7];
		cloudThickness[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]+=cloudThickness[(a-3*CLOUD_SIZE+1)*4+3];
		ydif[(a+1)&255]-=cloudThickness[(a+1)*4+3]*2;
		ydif[(a+1)&255]+=cloudThickness[(a+4*CLOUD_SIZE+1-CLOUD_SIZE*CLOUD_SIZE)*4+3];

		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;

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

//	delete[] rawClouds;
/*
	for(int a=0;a<CLOUD_SIZE;++a){
		cloudThickness[((int(48+camera->pos.z*CLOUD_SIZE*0.000025f)%256)*CLOUD_SIZE+a)*4+3]=0;
	}
	for(int a=0;a<CLOUD_SIZE;++a){
		cloudThickness[(a*CLOUD_SIZE+int(gs->frameNum*0.00009f*256+camera->pos.x*CLOUD_SIZE*0.000025f))*4+3]=0;
	}
/**/
	glBindTexture(GL_TEXTURE_2D, cloudDot3Tex);
	glTexSubImage2D(GL_TEXTURE_2D,0, 0,0,CLOUD_SIZE, CLOUD_SIZE,GL_RGBA, GL_UNSIGNED_BYTE, cloudThickness);
}

void CBasicSky::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 CBasicSky::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]=(unsigned char)(alpha*255);

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

void CBasicSky::DrawSun()
{
	glPushMatrix();
//	glTranslatef(camera->pos.x,camera->pos.y,camera->pos.z);
	CMatrix44f m(camera->pos,sundir1,UpVector,sundir2);
	glMultMatrixf(m.m);
	glDisable(GL_DEPTH_TEST);

	unsigned char buf[32];
	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))%256;
	fy-=floor(fy);
	float fx=gs->frameNum*0.00005f*CLOUD_SIZE+modCamera.x*CLOUD_SIZE*0.000025f;
	int baseX=int(floor(fx))%256;
	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]);
	}

	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;

		buf[x]=(unsigned char)(255-cover*2);
	}
	glBindTexture(GL_TEXTURE_2D, sunFlareTex);
	glTexSubImage2D(GL_TEXTURE_2D,0,0,0,32,1,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 CBasicSky::SetCloudShadow(int texunit)
{
}

void CBasicSky::ResetCloudShadow(int texunit)
{
}

void CBasicSky::DrawShafts()
{
}


void CBasicSky::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<2;++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);
//	gluBuild2DMipmaps(GL_TEXTURE_2D,1 ,32, 2, GL_ALPHA, GL_UNSIGNED_BYTE, mem);
	glTexImage2D(GL_TEXTURE_2D,0,1 ,32, 2,0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);

	delete[] mem;

	float3 ldir=modSunDir.cross(UpVector);
	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.25f);
			glVertexf3(modSunDir*5+ldir*dx*0.0014f+udir*dy*0.0014f);
			glTexCoord2f(x/256.0f,0.75f);
			glVertexf3(modSunDir*5+ldir*dx*4+udir*dy*4);
		}
		glEnd();
		if (gu->drawFog) glEnable(GL_FOG);

	glEndList();
}

inline unsigned char CBasicSky::GetCloudThickness(int x,int y)
{
	assert (CLOUD_SIZE==256);
	x &= 0xff;
	y &= 0xff;

	//assert (x>=0 && x<CLOUD_SIZE);
	//assert (y>=0 && y<CLOUD_SIZE);
	return cloudThickness [ (y * CLOUD_SIZE + x) * 4 + 3 ];
}

void CBasicSky::CreateCover(int baseX, int baseY, float *buf)
{
	static 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++];
			cover1+=255-GetCloudThickness(baseX-dx,baseY+dy);
			cover2+=255-GetCloudThickness(baseX-dy,baseY-dx);//*(num-x);
			cover3+=255-GetCloudThickness(baseX+dx,baseY-dy);//*(num-x);
			cover4+=255-GetCloudThickness(baseX+dy,baseY+dx);//*(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;
	}
}

float3 CBasicSky::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 CBasicSky::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 + -
显示快捷键?