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