*
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
#ifndef Sky_h__
|
||||
#define Sky_h__
|
||||
#include "Globals.h"
|
||||
#include "DayTime.h"
|
||||
#include "math/LifeMath.h"
|
||||
|
||||
namespace LifeGraphics
|
||||
{
|
||||
struct SkyVertex
|
||||
{
|
||||
LifeMath::float3 Position;
|
||||
LifeMath::float2 Texcoord;
|
||||
SkyVertex()
|
||||
{
|
||||
}
|
||||
SkyVertex(LifeMath::float3& _pos, LifeMath::float2& _tex)
|
||||
{
|
||||
Position = _pos;
|
||||
Texcoord = _tex;
|
||||
}
|
||||
};
|
||||
|
||||
struct cbRenderData
|
||||
{
|
||||
LifeMath::float4x4 View;
|
||||
LifeMath::float4x4 Proj;
|
||||
LifeMath::float4x4 ViewProj;
|
||||
LifeMath::float3 SunDirection;
|
||||
float dummy;
|
||||
};
|
||||
class Sky
|
||||
{
|
||||
private:
|
||||
int DomeN;
|
||||
int DVSize;
|
||||
int DISize;
|
||||
int MrlTexSize;
|
||||
int MrlTexSizeHalf;
|
||||
|
||||
LifeMath::float3 SunrizeDirection;
|
||||
LifeMath::float3 ZenithDirection;
|
||||
LifeMath::float3 waveLengths;
|
||||
LifeMath::float3 invWaveLengths;
|
||||
LifeMath::float3 waveLengthsMie;
|
||||
|
||||
IVertexBuffer* skyVb;
|
||||
IIndexBuffer* skyIb;
|
||||
|
||||
IShader* VS_Render;
|
||||
IShader* VS_Update;
|
||||
IShader* PS_Render;
|
||||
IShader* PS_Update;
|
||||
|
||||
IConstantBuffer* cbUpdate;
|
||||
IConstantBuffer* cbRender;
|
||||
|
||||
ITexture2D* skyDepth;
|
||||
|
||||
IInputLayout* vertexLayout;
|
||||
|
||||
DayTime Time;
|
||||
DayTime SunsetTime;
|
||||
DayTime SunrizeTime;
|
||||
DayTime MidDayTime;
|
||||
DayTime MidNightTime;
|
||||
DayTime DayLength;
|
||||
DayTime NightLength;
|
||||
DayTime TimeStep;
|
||||
|
||||
int DayPhase;
|
||||
|
||||
float fExposure;
|
||||
float updateTimeElapsed;
|
||||
float StarsIntensity;
|
||||
float updatePeriod;
|
||||
bool ShouldUpdateData;
|
||||
|
||||
IDepthStencilState* dsZEnable;
|
||||
IDepthStencilState* dsZDisable;
|
||||
|
||||
void RecomputeData()
|
||||
{
|
||||
SunrizeDirection = LifeMath::float3(-1,0,0);
|
||||
ZenithDirection = LifeMath::float3(0,1,0);
|
||||
DayLength = SunsetTime - SunrizeTime;
|
||||
NightLength = SunrizeTime - SunsetTime;
|
||||
MidNightTime = SunsetTime + (NightLength / 2);
|
||||
MidDayTime = SunrizeTime + (DayLength / 2);
|
||||
|
||||
if (Time >= SunrizeTime && Time <= MidDayTime)
|
||||
DayPhase = 0;
|
||||
else if (Time >= MidDayTime && Time <= SunsetTime)
|
||||
DayPhase = 1;
|
||||
else if (MidNightTime - SunsetTime >= Time - SunsetTime)
|
||||
DayPhase = 2;
|
||||
else
|
||||
DayPhase = 3;
|
||||
float lamt = 0;
|
||||
switch (DayPhase)
|
||||
{
|
||||
case 0:
|
||||
lamt = (float)(Time - SunrizeTime).ToSeconds()
|
||||
/ (float)(MidDayTime - SunrizeTime).ToSeconds();
|
||||
SunDirection = Vec3Lerp(SunrizeDirection, ZenithDirection, lamt);
|
||||
LifeMath::Vec3Normalize(&SunDirection);
|
||||
StarsIntensity = 1.0f - lamt;
|
||||
break;
|
||||
case 1:
|
||||
lamt = (float)(Time - MidDayTime).ToSeconds()
|
||||
/ (float)(SunsetTime - MidDayTime).ToSeconds();
|
||||
SunDirection = Vec3Lerp(ZenithDirection, -SunrizeDirection, lamt);
|
||||
LifeMath::Vec3Normalize(&SunDirection);
|
||||
StarsIntensity = lamt;
|
||||
break;
|
||||
case 2:
|
||||
lamt = (float)(Time - SunsetTime).ToSeconds()
|
||||
/ (float)(MidNightTime - SunsetTime).ToSeconds();
|
||||
SunDirection = Vec3Lerp(-SunrizeDirection, -ZenithDirection, lamt);
|
||||
LifeMath::Vec3Normalize(&SunDirection);
|
||||
StarsIntensity = 1.0f;
|
||||
break;
|
||||
case 3:
|
||||
lamt = (float)(Time - MidNightTime).ToSeconds()
|
||||
/ (float)(SunrizeTime - MidNightTime).ToSeconds();
|
||||
SunDirection = Vec3Lerp(-ZenithDirection, SunrizeDirection, lamt);
|
||||
LifeMath::Vec3Normalize(&SunDirection);
|
||||
StarsIntensity = 1.0f;
|
||||
break;
|
||||
}
|
||||
StarsIntensity = pow(StarsIntensity,10);
|
||||
|
||||
invWaveLengths.X = 1.0f / pow(waveLengths.X, 4.0f);
|
||||
invWaveLengths.Y = 1.0f / pow(waveLengths.Y, 4.0f);
|
||||
invWaveLengths.Z = 1.0f / pow(waveLengths.Z, 4.0f);
|
||||
|
||||
waveLengthsMie.X = pow(waveLengths.X, -0.84f);
|
||||
waveLengthsMie.Y = pow(waveLengths.Y, -0.84f);
|
||||
waveLengthsMie.Z = pow(waveLengths.Z, -0.84f);
|
||||
}
|
||||
|
||||
void GenerateDome()
|
||||
{
|
||||
int Latitude = DomeN / 2;
|
||||
int Longitude = DomeN;
|
||||
DVSize = Longitude * Latitude;
|
||||
DISize = (Longitude - 1) * (Latitude - 1) * 2;
|
||||
DVSize *= 2;
|
||||
DISize *= 2;
|
||||
|
||||
IInputElement skyElements[] =
|
||||
{
|
||||
IInputElement("POSITION", 0, 0, FORMAT_R32G32B32_FLOAT, 0, 0, 0),
|
||||
IInputElement("TEXCOORD", 0, 12, FORMAT_R32G32_FLOAT, 0, 0, 0),
|
||||
};
|
||||
|
||||
vertexLayout = CG::me()->GetRenderer()->CreateInputLayout(skyElements, 2, VS_Render);
|
||||
|
||||
SkyVertex* domeVerts = new SkyVertex[DVSize];
|
||||
|
||||
// Fill Vertex Buffer
|
||||
int DomeIndex = 0;
|
||||
for (int i = 0; i < Longitude; i++)
|
||||
{
|
||||
float MoveXZ = 100.0f * ((float)i / (float)(Longitude - 1)) * 3.141592f / 180.0f;
|
||||
|
||||
for (int j = 0; j < Latitude; j++)
|
||||
{
|
||||
float MoveY = 3.1415f * (float)j / (float)(Latitude - 1);
|
||||
|
||||
domeVerts[DomeIndex] = SkyVertex();
|
||||
domeVerts[DomeIndex].Position.X = (sin(MoveXZ) * cos(MoveY));
|
||||
domeVerts[DomeIndex].Position.Y = cos(MoveXZ);
|
||||
domeVerts[DomeIndex].Position.Z = (sin(MoveXZ) * sin(MoveY));
|
||||
|
||||
domeVerts[DomeIndex].Position *= 10.0f;
|
||||
|
||||
domeVerts[DomeIndex].Texcoord.X = 0.5f / (float)Longitude + (float)i / (float)Longitude;
|
||||
domeVerts[DomeIndex].Texcoord.Y = 0.5f / (float)Latitude + (float)j / (float)Latitude;
|
||||
|
||||
DomeIndex++;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < Longitude; i++)
|
||||
{
|
||||
float MoveXZ = 100.0f * ((float)i / (float)(Longitude - 1)) * 3.1415f / 180.0f;
|
||||
|
||||
for (int j = 0; j < Latitude; j++)
|
||||
{
|
||||
float MoveY = (3.1415f * 2.0f) - (3.1415f * (float)j / (float)(Latitude - 1));
|
||||
|
||||
domeVerts[DomeIndex] = SkyVertex();
|
||||
domeVerts[DomeIndex].Position.X = (sin(MoveXZ) * cos(MoveY));
|
||||
domeVerts[DomeIndex].Position.Y = cos(MoveXZ);
|
||||
domeVerts[DomeIndex].Position.Z = (sin(MoveXZ) * sin(MoveY));
|
||||
|
||||
domeVerts[DomeIndex].Position *= 10.0f;
|
||||
|
||||
domeVerts[DomeIndex].Texcoord.X = 0.5f / (float)Longitude + (float)i / (float)Longitude;
|
||||
domeVerts[DomeIndex].Texcoord.Y = 0.5f / (float)Latitude + (float)j / (float)Latitude;
|
||||
|
||||
DomeIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill index buffer
|
||||
USHORT* ib = new USHORT[DISize * 3];
|
||||
int index = 0;
|
||||
for (USHORT i = 0; i < Longitude - 1; i++)
|
||||
{
|
||||
for (short j = 0; j < Latitude - 1; j++)
|
||||
{
|
||||
ib[index++] = (USHORT)(i * Latitude + j);
|
||||
ib[index++] = (USHORT)((i + 1) * Latitude + j);
|
||||
ib[index++] = (USHORT)((i + 1) * Latitude + j + 1);
|
||||
|
||||
ib[index++] = (USHORT)((i + 1) * Latitude + j + 1);
|
||||
ib[index++] = (USHORT)(i * Latitude + j + 1);
|
||||
ib[index++] = (USHORT)(i * Latitude + j);
|
||||
}
|
||||
}
|
||||
USHORT Offset = (USHORT)(Latitude * Longitude);
|
||||
for (USHORT i = 0; i < Longitude - 1; i++)
|
||||
{
|
||||
for (USHORT j = 0; j < Latitude - 1; j++)
|
||||
{
|
||||
ib[index++] = (USHORT)(Offset + i * Latitude + j);
|
||||
ib[index++] = (USHORT)(Offset + (i + 1) * Latitude + j + 1);
|
||||
ib[index++] = (USHORT)(Offset + (i + 1) * Latitude + j);
|
||||
|
||||
ib[index++] = (USHORT)(Offset + i * Latitude + j + 1);
|
||||
ib[index++] = (USHORT)(Offset + (i + 1) * Latitude + j + 1);
|
||||
ib[index++] = (USHORT)(Offset + i * Latitude + j);
|
||||
}
|
||||
}
|
||||
|
||||
skyIb = CG::me()->GetRenderer()->CreateIndexBuffer(DISize * 3 * sizeof(USHORT), ib, TRUE);
|
||||
skyVb = CG::me()->GetRenderer()->CreateVertexBuffer(DVSize * sizeof(SkyVertex), domeVerts, sizeof(SkyVertex));
|
||||
}
|
||||
|
||||
public:
|
||||
LifeMath::float3 SunDirection;
|
||||
ITexture2D* mieTex;
|
||||
ITexture2D* rayleighTex;
|
||||
Sky()
|
||||
:DayPhase(0), fExposure(-2.0f), updateTimeElapsed(0.0f), updatePeriod(2.0f), ShouldUpdateData(true)
|
||||
{
|
||||
waveLengths = LifeMath::float3(0.65f, 0.57f, 0.475f);
|
||||
TimeStep = DayTime(0, 0, 1);
|
||||
}
|
||||
~Sky()
|
||||
{
|
||||
SAFE_DELETE(skyVb);
|
||||
SAFE_DELETE(skyIb);
|
||||
|
||||
SAFE_DELETE(cbUpdate);
|
||||
SAFE_DELETE(cbRender);
|
||||
SAFE_DELETE(dsZDisable);
|
||||
SAFE_DELETE(dsZEnable);
|
||||
|
||||
SAFE_DELETE(vertexLayout);
|
||||
SAFE_DELETE(VS_Render);
|
||||
// SAFE_DELETE(VS_Update);
|
||||
SAFE_DELETE(PS_Render);
|
||||
SAFE_DELETE(PS_Update);
|
||||
SAFE_DELETE(mieTex);
|
||||
SAFE_DELETE(rayleighTex);
|
||||
SAFE_DELETE(skyDepth);
|
||||
}
|
||||
void Build()
|
||||
{
|
||||
cbUpdate = CG::me()->GetRenderer()->CreateConstantBuffer(sizeof(LifeMath::float4));
|
||||
cbRender = CG::me()->GetRenderer()->CreateConstantBuffer(sizeof(cbRenderData));
|
||||
|
||||
dsZDisable = CG::me()->GetRenderer()->CreateDSState(false,false, COMPARISON_NEVER);
|
||||
dsZEnable = CG::me()->GetRenderer()->CreateDSState(true,true, COMPARISON_LESS);
|
||||
|
||||
VS_Render = ResourceManager::me()->CompileUserShaderVS(String(_text("Sky.vsh")));
|
||||
PS_Render = ResourceManager::me()->CompileUserShaderPS(String(_text("Sky_render.psh")));
|
||||
PS_Update = ResourceManager::me()->CompileUserShaderPS(String(_text("Sky_update.psh")));
|
||||
|
||||
SunsetTime = DayTime(18, 2, 0);
|
||||
SunrizeTime = DayTime(7, 10, 0);
|
||||
Time = DayTime(12, 40, 0);
|
||||
|
||||
RecomputeData();
|
||||
|
||||
MrlTexSize = 512;
|
||||
MrlTexSizeHalf = MrlTexSize / 2;
|
||||
|
||||
DomeN = 32;
|
||||
GenerateDome();
|
||||
|
||||
mieTex = CG::me()->GetRenderer()->CreateRenderTarget(MrlTexSize, MrlTexSizeHalf, FORMAT_R16G16B16A16_FLOAT);
|
||||
rayleighTex = CG::me()->GetRenderer()->CreateRenderTarget(MrlTexSize, MrlTexSizeHalf, FORMAT_R16G16B16A16_FLOAT);
|
||||
skyDepth = CG::me()->GetRenderer()->CreateDepthTarget(MrlTexSize, MrlTexSizeHalf, FORMAT_D16_UNORM);
|
||||
|
||||
//g_screenQuad = new Quad(0, 0, MrlTexSize, MrlTexSizeHalf, true);
|
||||
}
|
||||
void SetDayTime(const DayTime& time)
|
||||
{
|
||||
Time = time;
|
||||
RecomputeData();
|
||||
}
|
||||
|
||||
void Update(float dt)
|
||||
{
|
||||
updateTimeElapsed += dt;
|
||||
if (updateTimeElapsed >= updatePeriod)
|
||||
{
|
||||
updateTimeElapsed = 0.0f;
|
||||
ShouldUpdateData = true;
|
||||
}
|
||||
Time.Add((int)(dt * (float)TimeStep.ToSeconds()));
|
||||
RecomputeData();
|
||||
}
|
||||
|
||||
void Render(ITexture2D* sceneRt, ITexture2D* sceneDt, Camera* cam)
|
||||
{
|
||||
IRenderer* renderer = CG::me()->GetRenderer();
|
||||
renderer->SetDepthStencilState(dsZDisable);
|
||||
|
||||
//Update mie and rayleigh textures
|
||||
if (ShouldUpdateData)
|
||||
{
|
||||
ITexture2D* tex[] = {rayleighTex, mieTex};
|
||||
|
||||
renderer->SetTargets(tex, 2, skyDepth);
|
||||
renderer->SetPixelShader(PS_Update);
|
||||
|
||||
cbUpdate->Update(&SunDirection, sizeof(SunDirection));
|
||||
renderer->SetPSConstantBuffer(cbUpdate, 1);
|
||||
|
||||
renderer->SetViewport(LifeMath::Rect2i(0,0, MrlTexSize, MrlTexSizeHalf));
|
||||
renderer->RenderToTextureNoPs();
|
||||
|
||||
renderer->UnbindRenderTargets();
|
||||
ShouldUpdateData = false;
|
||||
}
|
||||
|
||||
renderer->SetViewport(LifeMath::Rect2i(0,0, sceneRt->Width(), sceneRt->Height()));
|
||||
|
||||
renderer->SetVertexShader(VS_Render);
|
||||
renderer->SetPixelShader(PS_Render);
|
||||
|
||||
float starIntensity = 0.7f;
|
||||
float g = -0.990f;
|
||||
float g2 = (-0.990f) * (-0.990f);
|
||||
|
||||
LifeMath::float4x4 sm;
|
||||
Mat4x4LookAtLH(LifeMath::float3(0, 0, 0), cam->getDirection(), LifeMath::float3(0, 1, 0), sm);
|
||||
|
||||
cbRenderData data;
|
||||
data.View = sm;
|
||||
data.Proj = cam->getProj();
|
||||
data.ViewProj = data.View * data.Proj;
|
||||
data.SunDirection = SunDirection;
|
||||
|
||||
cbRender->Update(&data, sizeof(cbRenderData));
|
||||
renderer->SetPSConstantBuffer(cbRender, 1);
|
||||
renderer->SetVSConstantBuffer(cbRender, 1);
|
||||
|
||||
renderer->SetTargets(sceneRt, sceneDt);
|
||||
|
||||
////PS_Render.SetFloat("fExposure", fExposure);
|
||||
////PS_Render.SetFloat("starIntensity", StarsIntensity);
|
||||
|
||||
////PS_Render.SetTexture("starSampler", starTex);
|
||||
////PS_Render.SetTexture("mieSampler", mieTex);
|
||||
////PS_Render.SetTexture("rayleighSampler", rayleighTex);
|
||||
/*CG.Engine.Renderer.SetTextureFilterMin(TextureFilter.Point, 2);
|
||||
CG.Engine.Renderer.SetTextureFilterMip(TextureFilter.Point, 2);
|
||||
CG.Engine.Renderer.SetTextureFilterMag(TextureFilter.Point, 2);*/
|
||||
////PS_Render.SetFloat3("v3SunDir", SunDirection);
|
||||
|
||||
renderer->SetPSTexture(rayleighTex,0);
|
||||
renderer->SetPSTexture(mieTex,1);
|
||||
|
||||
////VS_Render.SetMatrix("matWorld", Matrix4x4.Identity);
|
||||
////VS_Render.SetMatrix("matView", sm);
|
||||
////VS_Render.SetMatrix("matProjection", renderer.MainCamera.ProjectionMatrix);
|
||||
|
||||
renderer->SetInputLayout(vertexLayout);
|
||||
|
||||
renderer->SetIndexBuffer(skyIb);
|
||||
renderer->SetVertexBuffer(skyVb);
|
||||
|
||||
renderer->SetPrimitiveTopology(PT_TRIANGLE_LIST);
|
||||
|
||||
renderer->DrawIndexed(0, DISize);
|
||||
|
||||
// renderer.DrawIndexedPrimitives(IPrimitiveTopology.TriangleList, 0, 0, SkyGeometry.NumberVertices, SkyGeometry.Subsets[0].Offset, SkyGeometry.Subsets[0].FaceCount);
|
||||
|
||||
renderer->SetDepthStencilState(dsZEnable);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // Sky_h__
|
||||
Reference in New Issue
Block a user