basicsky.cpp

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

CPP
809
字号
// Sky.cpp: implementation of the CBasicSky class.
//
//////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#pragma warning(disable:4258)
#endif

#include "StdAfx.h"
#include "BasicSky.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 "TimeProfiler.h"
#include "Platform/ConfigHandler.h"
#include "Matrix44f.h"
#include "LogOutput.h"
#include "mmgr.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
#include <assert.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

using namespace std;

CBasicSky::CBasicSky()
{
	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);

	readmap->mapDefParser.GetDef(cloudDensity,"0.5","MAP\\ATMOSPHERE\\CloudDensity");
	cloudDensity=0.25f+cloudDensity*0.5f;
	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");

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

	lastCloudUpdate=-30;
	cloudThickness=SAFE_NEW unsigned char[CLOUD_SIZE*CLOUD_SIZE*4+4];
	CreateClouds();
	InitSun();
	oldCoverBaseX=-5;

	int y;
	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);
	glEnable(GL_FOG);
	glColor4f(1,1,1,1);

	glDisable(GL_TEXTURE_2D);

	glActiveTextureARB(GL_TEXTURE1_ARB);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, skyTex);
	glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  glActiveTextureARB(GL_TEXTURE0_ARB);

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

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

			c=GetCoord(x,y+1);

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

			c=GetCoord(x+1,y);

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

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

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

			glEnd();
		}
	}/**/

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
/*
  glActiveTextureARB(GL_TEXTURE1_ARB);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D,sunTex);
	float3 sundir(0,0.5f,1);
	sundir.Normalize();

	float3 ldir=sundir.cross(UpVector);
	float3 udir=sundir.cross(ldir);

	glDisable(GL_FOG);
	glColor4f(1,1,1,1);
	glBegin(GL_QUADS);
	glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,0);
	glVertexf3(sundir*5+ldir*0.15f+udir*0.15f);
	glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0,1);
	glVertexf3(sundir*5+ldir*0.15f-udir*0.15f);
	glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1,1);
	glVertexf3(sundir*5-ldir*0.15f-udir*0.15f);
	glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1,0);
	glVertexf3(sundir*5-ldir*0.15f+udir*0.15f);
	glEnd();
*/  glActiveTextureARB(GL_TEXTURE0_ARB);
	glColor4f(1,1,1,1);
//	glEnable(GL_FOG);  Why not, glDisable is commented out above -- this text is so people don't accidentally uncomment just one

	if(GLEW_ARB_texture_env_dot3){
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_BLEND);

		glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, cloudDot3Tex);

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, skyDot3Tex);
		glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB);
		glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT3_RGB_ARB);

		glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_ALPHA_ARB,GL_PREVIOUS_ARB);
		glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_ALPHA_ARB,GL_TEXTURE);
		glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_ALPHA_ARB,GL_MODULATE);
		glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_ALPHA_ARB,GL_ONE_MINUS_SRC_ALPHA);

		glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB);
		glActiveTextureARB(GL_TEXTURE0_ARB);

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

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

				c=GetCoord(x,y+1);

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

				c=GetCoord(x+1,y);

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

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

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

				glEnd();
			}
		}
//		glDisable(GL_TEXTURE_SHADER_NV);

	}
	glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);

	glActiveTextureARB(GL_TEXTURE1_ARB);
	glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_ALPHA_ARB,GL_SRC_ALPHA);
	glDisable(GL_TEXTURE_2D);
  glActiveTextureARB(GL_TEXTURE2_ARB);
	glDisable(GL_TEXTURE_2D);
  glActiveTextureARB(GL_TEXTURE0_ARB);

	glEndList();
	dynamicSky=!!configHandler.GetInt("DynamicSky",0);
}

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

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

	delete[] cloudThickness;
}

void CBasicSky::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);
		glPushMatrix();
		glTranslatef((gs->frameNum%20000)*0.00005f+modCamera.x*0.000025f,modCamera.z*0.000025f,0);
	glMatrixMode(GL_MODELVIEW);



	glCallList(displist);

	glMatrixMode(GL_TEXTURE);						// Select The Projection Matrix
		glPopMatrix();
	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix

	glPopMatrix();

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

float3 CBasicSky::GetTexCoord(int x, int y)
{
	float3 c;
	float a=((float)y/Y_PART)*0.5f;
	float b=((float)x/X_PART)*2*PI;
	c.x=0.5f+sin(b)*a;
	c.y=0.5f+cos(b)*a;
	return c;
}

float3 CBasicSky::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 CBasicSky::CreateClouds()
{
	glGenTextures(1, &skyTex);
	glGenTextures(1, &skyDot3Tex);
	glGenTextures(1, &cloudDot3Tex);
	int y;

	static unsigned char skytex[512][512][4];//=SAFE_NEW unsigned char[512][512][4];
	static unsigned char skytex2[256][256][4];

	for(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;

	for(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)+2.0f/sunDist;
			float green=(0.55f+sunMod);
			if(green>1)
				green=1;
			skytex2[y][x][0]=255-y/2;
			skytex2[y][x][1]=(unsigned char)(green*255);
			skytex2[y][x][2]=203;
			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 CBasicSky::Update()
{
	if(lastCloudUpdate>gs->frameNum-10 || !dynamicSky)
		return;

	SCOPED_TIMER("Drawing sky");

	lastCloudUpdate=gs->frameNum;

	int blendMatrix[CLOUD_DETAIL][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);

⌨️ 快捷键说明

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