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