advsky.cpp

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

CPP
859
字号
// Sky.cpp: implementation of the CAdvSky class.
//
//////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "AdvSky.h"

#include "Rendering/GL/myGL.h"
#include <GL/glu.h>			// Header File For The GLu32 Library
#include "Game/Camera.h"
#include "Map/ReadMap.h"
#include "Rendering/Textures/Bitmap.h"
#include "Rendering/GL/VertexArray.h"
#include "LogOutput.h"
#include "TimeProfiler.h"
#include "Matrix44f.h"
#include "mmgr.h"

extern GLfloat FogBlack[];
extern GLfloat FogLand[];

#define Y_PART 10.0
#define X_PART 10.0

#define CLOUD_DETAIL 6
#define CLOUD_SIZE 256
#define CLOUD_MASK (CLOUD_SIZE-1)

//static unsigned int cdtex;

using namespace std;

CAdvSky::CAdvSky()
{
	PrintLoadMsg("Creating sky");
	domeheight=cos(PI/16)*1.01f;
	domeWidth=sin(2*PI/32)*400*1.7f;

	sundir2=gs->sunVector;
	sundir2.y=0;
	if(sundir2.Length()==0)
		sundir2.x=1;
	sundir2.Normalize();
	sundir1=sundir2.cross(UpVector);

	modSunDir.y=gs->sunVector.y;
	modSunDir.x=0;
	modSunDir.z=sqrt(gs->sunVector.x*gs->sunVector.x+gs->sunVector.z*gs->sunVector.z);

	sunTexCoordX=0.5f;
	sunTexCoordY=GetTexCoordFromDir(modSunDir);

	for(int a=0;a<CLOUD_DETAIL;a++)
		cloudDown[a]=false;
	for(int a=0;a<5;a++)
		cloudDetailDown[a]=false;

//	dynamicSky=!!regHandler.GetInt("DynamicSky",0);
	dynamicSky=false;
	lastCloudUpdate=-30;
	readmap->mapDefParser.GetDef(cloudDensity,"0.5","MAP\\ATMOSPHERE\\CloudDensity");
	readmap->mapDefParser.GetDef(fogStart,"0.1","MAP\\ATMOSPHERE\\FogStart");
	if (fogStart>0.99f) gu->drawFog = false;
	skyColor=readmap->mapDefParser.GetFloat3(float3(0.1f,0.15f,0.7f),"MAP\\ATMOSPHERE\\SkyColor");
	sunColor=readmap->mapDefParser.GetFloat3(float3(1,1,1),"MAP\\ATMOSPHERE\\SunColor");
	cloudColor=readmap->mapDefParser.GetFloat3(float3(1,1,1),"MAP\\ATMOSPHERE\\CloudColor");

	CreateClouds();
	InitSun();
	oldCoverBaseX=-5;

	cloudFP=LoadFragmentProgram("clouds.fp");

	glGetError();
	displist=glGenLists(1);
	glNewList(displist, GL_COMPILE);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_BLEND);
	glFogi(GL_FOG_MODE,GL_LINEAR);
	glFogf(GL_FOG_START,-20);
	glFogf(GL_FOG_END,50);
	glFogf(GL_FOG_DENSITY,1.0f/15);
	glEnable(GL_FOG);
	glColor4f(1,1,1,1);

	glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, cloudFP );
	glEnable( GL_FRAGMENT_PROGRAM_ARB );
	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,10, sunColor.x,sunColor.y,sunColor.z,0);
	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,11, sunColor.x*cloudColor.x,sunColor.y*cloudColor.y,sunColor.z*cloudColor.z,0);
	glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB,12, cloudColor.x,cloudColor.y,cloudColor.z,0);

	glBindTexture(GL_TEXTURE_2D, skyTex);
	glActiveTextureARB(GL_TEXTURE1_ARB);
	glBindTexture(GL_TEXTURE_2D, skyDot3Tex);
	glActiveTextureARB(GL_TEXTURE2_ARB);
	glBindTexture(GL_TEXTURE_2D, cloudDot3Tex);
	glActiveTextureARB(GL_TEXTURE3_ARB);
	glBindTexture(GL_TEXTURE_2D, cdtex);
	glActiveTextureARB(GL_TEXTURE0_ARB);

	for(int y=0;y<Y_PART;y++){
		for(int x=0;x<X_PART;x++){
			glBegin(GL_TRIANGLE_STRIP);
			float3 c=GetCoord(x,y);

			glMultiTexCoord2fARB(GL_TEXTURE0_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE2_ARB,c.x*0.025f,c.z*0.025f);
			glMultiTexCoord2fARB(GL_TEXTURE3_ARB,c.x,c.z);
			glVertex3f(c.x,c.y,c.z);

			c=GetCoord(x,y+1);

			glMultiTexCoord2fARB(GL_TEXTURE0_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE2_ARB,c.x*0.025f,c.z*0.025f);
			glMultiTexCoord2fARB(GL_TEXTURE3_ARB,c.x,c.z);
			glVertex3f(c.x,c.y,c.z);

			c=GetCoord(x+1,y);

			glMultiTexCoord2fARB(GL_TEXTURE0_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE2_ARB,c.x*0.025f,c.z*0.025f);
			glMultiTexCoord2fARB(GL_TEXTURE3_ARB,c.x,c.z);
			glVertex3f(c.x,c.y,c.z);

			c=GetCoord(x+1,y+1);

			glMultiTexCoord2fARB(GL_TEXTURE0_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE1_ARB,c.x/domeWidth+0.5f,c.z/domeWidth+0.5f);
			glMultiTexCoord2fARB(GL_TEXTURE2_ARB,c.x*0.025f,c.z*0.025f);
			glMultiTexCoord2fARB(GL_TEXTURE3_ARB,c.x,c.z);
			glVertex3f(c.x,c.y,c.z);

			glEnd();
		}
	}

	glDisable( GL_FRAGMENT_PROGRAM_ARB );
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	glColor4f(1,1,1,1);
	glEndList();
}

CAdvSky::~CAdvSky()
{
	glDeleteTextures(1, &skyTex);
	glDeleteTextures(1, &skyDot3Tex);
	glDeleteTextures(1, &cloudDot3Tex);
	glDeleteLists(displist,1);

	glDeleteTextures(1, &sunTex);
	glDeleteTextures(1, &sunFlareTex);
	glDeleteLists(sunFlareList,1);

	delete[] cloudThickness2;
	delete[] cloudTexMem;

	glSafeDeleteProgram( cloudFP );
}

void CAdvSky::Draw()
{
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);

	glPushMatrix();
//	glTranslatef(camera->pos.x,camera->pos.y,camera->pos.z);
	CMatrix44f m(camera->pos,sundir1,UpVector,sundir2);
	glMultMatrixf(m.m);

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

	glMatrixMode(GL_TEXTURE);
	  glActiveTextureARB(GL_TEXTURE2_ARB);
		glPushMatrix();
		glTranslatef((gs->frameNum%20000)*0.00005f+modCamera.x*0.000025f,modCamera.z*0.000025f,0);
	  glActiveTextureARB(GL_TEXTURE3_ARB);
		glPushMatrix();
		glTranslatef((gs->frameNum%20000)*0.0020f+modCamera.x*0.001f,modCamera.z*0.001f,0);
	  glActiveTextureARB(GL_TEXTURE0_ARB);
	glMatrixMode(GL_MODELVIEW);

	glCallList(displist);

	if (gu->drawFog) {
		glEnable(GL_FOG);
		glFogfv(GL_FOG_COLOR,FogLand);
		glFogf(GL_FOG_START,gu->viewRange*fogStart);
		glFogf(GL_FOG_END,gu->viewRange);
		glFogf(GL_FOG_DENSITY,1.0f);
		glFogi(GL_FOG_MODE,GL_LINEAR);
	} else {
		glDisable(GL_FOG);
	}

	glMatrixMode(GL_TEXTURE);
	  glActiveTextureARB(GL_TEXTURE2_ARB);
		glPopMatrix();
	  glActiveTextureARB(GL_TEXTURE3_ARB);
		glPopMatrix();
	  glActiveTextureARB(GL_TEXTURE0_ARB);
	glMatrixMode(GL_MODELVIEW);

	glPopMatrix();

	glEnable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);
}

float3 CAdvSky::GetCoord(int x, int y)
{
	float3 c;
	float fy=((float)y/Y_PART)*2*PI;
	float fx=((float)x/X_PART)*2*PI;

	c.x=sin(fy/32)*sin(fx)*400;
	c.y=(cos(fy/32)-domeheight)*400;
	c.z=sin(fy/32)*cos(fx)*400;
	return c;
}

void CAdvSky::CreateClouds()
{
	cloudThickness2=SAFE_NEW unsigned char[CLOUD_SIZE*CLOUD_SIZE+1];
	cloudTexMem=SAFE_NEW unsigned char[CLOUD_SIZE*CLOUD_SIZE*4];

	glGenTextures(1, &skyTex);
	glGenTextures(1, &skyDot3Tex);
	glGenTextures(1, &cloudDot3Tex);

	unsigned char (* skytex)[512][4]=SAFE_NEW unsigned char[512][512][4];

	glGenTextures(1, &cdtex);
//	CBitmap pic("bitmaps/clouddetail.bmp");
	unsigned char mem[256*256];
//	for(int a=0;a<256*256;++a){
//		mem[a]=pic.mem[a*4];
//	}
	glBindTexture(GL_TEXTURE_2D, cdtex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_LUMINANCE ,256, 256, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);

	unsigned char randDetailMatrix[32*32];
	glGenTextures(12, detailTextures);
	for(int a=0;a<6;++a){
		int size=min(32,256>>a);
		CreateRandDetailMatrix(randDetailMatrix,size);
		glBindTexture(GL_TEXTURE_2D, detailTextures[a]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE, size, size,0,GL_LUMINANCE, GL_UNSIGNED_BYTE, randDetailMatrix);

		CreateRandDetailMatrix(randDetailMatrix,size);
		glBindTexture(GL_TEXTURE_2D, detailTextures[a+6]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE, size, size,0,GL_LUMINANCE, GL_UNSIGNED_BYTE, randDetailMatrix);
	}

	for(int y=0;y<512;y++){
		for(int x=0;x<512;x++){
			float3 dir=GetDirFromTexCoord(x/512.0f,y/512.0f);
			float sunDist=acos(dir.dot(modSunDir))*70;
			float sunMod=12.0f/(12+sunDist);

			float red=(skyColor.x+sunMod*sunColor.x);
			float green=(skyColor.y+sunMod*sunColor.y);
			float blue=(skyColor.z+sunMod*sunColor.z);
			if(red>1)
				red=1;
			if(green>1)
				green=1;
			if(blue>1)
				blue=1;
			skytex[y][x][0]=(unsigned char)(red*255);
			skytex[y][x][1]=(unsigned char)(green*255);
			skytex[y][x][2]=(unsigned char)(blue*255);
			skytex[y][x][3]=255;
		}
	}

	glBindTexture(GL_TEXTURE_2D, skyTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, skytex[0][0]);
	delete[] skytex;

	unsigned char skytex2[256][256][4];
	for(int y=0;y<256;y++){
		for(int x=0;x<256;x++){
			float3 dir=GetDirFromTexCoord(x/256.0f,y/256.0f);
			float sunDist=acos(dir.dot(modSunDir))*50;
			float sunMod=0.3f/sqrt(sunDist)+3.0f/(1+sunDist);
			float green=min(1.0f,(0.55f+sunMod));
			float blue=203-(40.0f/(3+sunDist));
			skytex2[y][x][0]=(unsigned char)(255-y/2);				//sun on borders
			skytex2[y][x][1]=(unsigned char)(green*255);			//sun light through
			skytex2[y][x][2]=(unsigned char) blue;						//ambient
			skytex2[y][x][3]=255;
		}
	}

	glBindTexture(GL_TEXTURE_2D, skyDot3Tex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 256, GL_RGBA, GL_UNSIGNED_BYTE, skytex2[0][0]);

	for(int a=0;a<CLOUD_DETAIL;a++){
		CreateRandMatrix(randMatrix[a],1-a*0.03f);
		CreateRandMatrix(randMatrix[a+8],1-a*0.03f);
	}

	char* scrap=SAFE_NEW char[CLOUD_SIZE*CLOUD_SIZE*4];
	glBindTexture(GL_TEXTURE_2D, cloudDot3Tex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8, CLOUD_SIZE, CLOUD_SIZE,0,GL_RGBA, GL_UNSIGNED_BYTE, scrap);
	delete[] scrap;

	dynamicSky=true;
	CreateTransformVectors();
	Update();
	dynamicSky=false;
}

void CAdvSky::Update()
{
	if(!dynamicSky)
		return;


	SCOPED_TIMER("Updating sky");

	CreateDetailTex();

	if(lastCloudUpdate<=gs->frameNum-3){
		lastCloudUpdate=gs->frameNum;

	//perlin noise matrices for the clouds
		int blendMatrix[8][32][32];
		for(int a=0;a<CLOUD_DETAIL;a++){
			float fade=(gs->frameNum/(70.0f*(2<<(CLOUD_DETAIL-1-a))));
			fade-=floor(fade/2)*2;
			if(fade>1){
				fade=2-fade;
				if(!cloudDown[a]){
					cloudDown[a]=true;
					CreateRandMatrix(randMatrix[a+8],1-a*0.03f);
				}
			} else {
				if(cloudDown[a]){
					cloudDown[a]=false;
					CreateRandMatrix(randMatrix[a],1-a*0.03f);
				}
			}
			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;
				}
			}
		}

		//create the raw clouds from the perlin noice octaves
		int (*rawClouds)[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];

⌨️ 快捷键说明

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