#include "Main.h"
void ShadowSceneObject::Init(GraphicsDevice &GD, const String &SimplifiedFilename, const String &FullFilename, float _Theta, float _LocalZOffset)
{
Mesh NewSimplifiedMesh(GD);
NewSimplifiedMesh.LoadObj(SimplifiedFilename);
Mesh NewFullMesh(GD);
NewFullMesh.LoadObj(FullFilename);
NewSimplifiedMesh.ApplyMatrix(NewSimplifiedMesh.UnitSphereTransform() * Matrix4::Scaling(3.0f));
NewSimplifiedMesh.ApplyMatrix(Matrix4::Translation(Vec3f::eZ * -NewSimplifiedMesh.BoundingBox().Min.z));
NewFullMesh.ApplyMatrix(NewFullMesh.UnitSphereTransform() * Matrix4::Scaling(3.0f));
NewFullMesh.ApplyMatrix(Matrix4::Translation(Vec3f::eZ * -NewFullMesh.BoundingBox().Min.z));
Init(GD, NewSimplifiedMesh, NewFullMesh, _Theta, _LocalZOffset);
}
void UpdateMeshTexture(BaseMesh &M)
{
float XFrequency = 0.5f;
float ZFrequency = 0.5f;
for(UINT VertexIndex = 0; VertexIndex < M.VertexCount(); VertexIndex++)
{
MeshVertex &Vtx = M.Vertices()[VertexIndex];
Vtx.TexCoord.x = Vtx.Pos.x * XFrequency;
Vtx.TexCoord.y = Vtx.Pos.z * ZFrequency;
}
}
void ShadowSceneObject::Init(GraphicsDevice &GD, const BaseMesh &_SimplifiedMesh, const BaseMesh &_FullMesh, float _Theta, float _LocalZOffset)
{
LocalZOffset = _LocalZOffset;
Theta = _Theta;
SimplifiedMesh.SetGD(GD);
SimplifiedMesh = _SimplifiedMesh;
SimplifiedMesh.Optimize();
FullMesh.SetGD(GD);
FullMesh = _FullMesh;
FullMesh.Optimize();
UpdateMeshTexture(SimplifiedMesh);
UpdateMeshTexture(FullMesh);
}
void ShadowScene::ResetLight(const Vec3f &LightPos)
{
_LightCameras[0].Reset(LightPos, Vec3f::eY, LightPos + Vec3f::eX);
_LightCameras[1].Reset(LightPos, -Vec3f::eY, LightPos - Vec3f::eX);
_LightCameras[2].Reset(LightPos, Vec3f::eZ, LightPos + Vec3f::eY);
_LightCameras[3].Reset(LightPos, -Vec3f::eZ, LightPos - Vec3f::eY);
_LightCameras[4].Reset(LightPos, Vec3f::eX, LightPos + Vec3f::eZ);
_LightCameras[5].Reset(LightPos, -Vec3f::eX, LightPos - Vec3f::eZ);
}
void ShadowScene::StatusText(AppState &state)
{
}
void ShadowScene::UpdateScene(AppState &state)
{
if(!_Paused)
{
_ElapsedTime += state.timer.SPF();
}
if(state.input.KeyCheckOnce(KEY_B))
{
_BlurPasses = (_BlurPasses + 1) % 5;
}
if(state.input.KeyCheckOnce(KEY_P))
{
_Paused = !_Paused;
}
if(state.input.KeyCheckOnce(KEY_V))
{
_UseVarianceShadowMaps = !_UseVarianceShadowMaps;
}
if(state.input.KeyCheckOnce(KEY_M))
{
if(_ShadowMapResolution == 256)
{
_ShadowMapResolution = 512;
}
else if(_ShadowMapResolution == 512)
{
_ShadowMapResolution = 1024;
}
else if(_ShadowMapResolution == 1024)
{
_ShadowMapResolution = 256;
}
_ShadowMap.Init(state.graphics->CastD3D9(), _ShadowMapResolution);
}
if(state.input.KeyCheckOnce(KEY_SPACE))
{
_ViewMode = ShadowSceneViewModeType((_ViewMode + 1) % ShadowSceneViewModeCount);
ResetLight(Vec3f(0.0f, 0.0f, 2.25f));
}
if(_ViewMode == ShadowSceneViewModeLightRotatingAroundObjects)
{
float RotationTheta = _ElapsedTime * 1.0f;
float HeightTheta = _ElapsedTime * 1.4f;
const float LightRadius = 7.0f;
const float MinLightHeight = 2.5f;
const float MaxLightHeight = 5.0f;
Vec3f LightPos = Vec3f(cosf(RotationTheta) * LightRadius, sinf(RotationTheta) * LightRadius, (cosf(HeightTheta) * 0.5f + 0.5f) * (MaxLightHeight - MinLightHeight) + MinLightHeight);
ResetLight(LightPos);
}
}
void ShadowScene::Init(D3D9GraphicsDevice &GD)
{
_Paused = false;
_BlurPasses = 1;
_ShadowMapResolution = 512;
_UseVarianceShadowMaps = true;
_Timer.Start();
_ElapsedTime = 0.0f;
_LightPerspective = Matrix4::PerspectiveFov(110.0f * Math::PIf / 180.0f, 1.0f, 0.1f, 100.0f);
_ViewMode = ShadowSceneViewModeLightRotatingAroundObjects;
ResetLight(Vec3f(0.0f, 0.0f, 2.25f));
_Objects[0].Init(GD, "C:\\Data\\Models\\buddha10k.obj", "C:\\Data\\Models\\buddha.obj", 0.0f / 3.0f * Math::PIf * 2.0f, Math::PIf);
_Objects[1].Init(GD, "C:\\Data\\Models\\bunny10k.obj", "C:\\Data\\Models\\bunny.obj", 1.0f / 3.0f * Math::PIf * 2.0f, Math::PIf);
_Objects[2].Init(GD, "C:\\Data\\Models\\dragon10k.obj", "C:\\Data\\Models\\dragon.obj", 2.0f / 3.0f * Math::PIf * 2.0f, 0.0f);
for(UINT BoxWallIndex = 0; BoxWallIndex < 6; BoxWallIndex++)
{
_BoxWalls[BoxWallIndex].SetGD(GD);
_BoxTextures[BoxWallIndex].Init(GD);
_BoxTextureRepeat[BoxWallIndex] = Vec3f(1.0f, 1.0f, 0.0f);
}
_WoodTexture.Init(GD);
const float BoxSideLength = 15.0f;
const float BoxHeight = 8.0f;
const UINT BoxTessellation = 20;
_BoxWalls[0].CreatePlane(Vec3f(-BoxSideLength, -BoxSideLength, 0.0f), Vec3f(BoxSideLength, BoxSideLength, 0.0f), BoxTessellation, BoxTessellation);
_BoxWalls[1].CreatePlane(Vec3f(-BoxSideLength, -BoxSideLength, 0.0f), Vec3f(BoxSideLength, -BoxSideLength, BoxHeight), BoxTessellation, BoxTessellation);
_BoxWalls[2].CreatePlane(Vec3f(-BoxSideLength, -BoxSideLength, 0.0f), Vec3f(-BoxSideLength, BoxSideLength, BoxHeight), BoxTessellation, BoxTessellation);
_BoxWalls[3].CreatePlane(Vec3f(-BoxSideLength, -BoxSideLength, BoxHeight), Vec3f(BoxSideLength, BoxSideLength, BoxHeight), BoxTessellation, BoxTessellation);
_BoxWalls[4].CreatePlane(Vec3f(-BoxSideLength, BoxSideLength, 0.0f), Vec3f(BoxSideLength, BoxSideLength, BoxHeight), BoxTessellation, BoxTessellation);
_BoxWalls[5].CreatePlane(Vec3f(BoxSideLength, -BoxSideLength, 0.0f), Vec3f(BoxSideLength, BoxSideLength, BoxHeight), BoxTessellation, BoxTessellation);
Bitmap Bmp;
Bmp.LoadPNG("Assets\\Ceiling.png");
_BoxTextures[3].Load(Bmp);
Bmp.LoadPNG("Assets\\Floor.png");
_BoxTextures[0].Load(Bmp);
Bmp.LoadPNG("Assets\\Wall.png");
_BoxTextures[1].Load(Bmp);
_BoxTextures[2].Load(Bmp);
_BoxTextures[4].Load(Bmp);
_BoxTextures[5].Load(Bmp);
Bmp.LoadPNG("Assets\\Wood.png");
_WoodTexture.Load(Bmp);
_BoxTextureRepeat[3] = Vec3f(5.0f, 5.0f, 0.0f);
_BoxTextureRepeat[0] = Vec3f(2.0f, 2.0f, 0.0f);
for(UINT BoxWallIndex = 0; BoxWallIndex < 6; BoxWallIndex++)
{
_BoxWalls[BoxWallIndex].GCNormals();
}
}
void ShadowScene::RenderFrame(D3D9GraphicsDevice &GD, MatrixController &MC)
{
IDirect3DDevice9 *Device = GD.GetDevice();
MatrixController LightMC;
LightMC.Perspective = _LightPerspective;
for(UINT ShadowMapIndex = 0; ShadowMapIndex < ShadowMapCount; ShadowMapIndex++)
{
D3D9ProtectRenderTarget Protector(Device, true, true);
_ShadowMap.SetAsRenderTarget(ShadowMapIndex, Device);
LightMC.View = _LightCameras[ShadowMapIndex].Matrix();
RenderScene(GD, LightMC, ShadowMapShaderCreate);
}
for(UINT Index = 0; Index < _BlurPasses; Index++)
{
_ShadowMap.BlurAllShadowMaps(Device);
}
_ShadowMap.SetAsTextures(Device);
for(UINT ShadowMapIndex = 0; ShadowMapIndex < ShadowMapCount; ShadowMapIndex++)
{
Device->SetSamplerState(ShadowMapIndex + 1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(ShadowMapIndex + 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(ShadowMapIndex + 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(ShadowMapIndex + 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
Device->SetSamplerState(ShadowMapIndex + 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
_ShadowMap.SetLightMatrices(ShadowMapIndex, _LightCameras[ShadowMapIndex], _LightPerspective);
}
RenderScene(GD, MC, ShadowMapShaderRender);
}
void ShadowScene::RenderScene(D3D9GraphicsDevice &GD, MatrixController &MC, ShadowMapShaderType Shader)
{
IDirect3DDevice9 *Device = GD.GetDevice();
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
MC.World = Matrix4::Identity();
_ShadowMap.SetCameraMatrices(MC, Shader);
for(UINT BoxWallIndex = 0; BoxWallIndex < 6; BoxWallIndex++)
{
_BoxTextures[BoxWallIndex].Set(0);
_ShadowMap._VShaderRender.SetVec3("TextureRepeat", _BoxTextureRepeat[BoxWallIndex]);
_ShadowMap._PShaderRender.SetFloat("LightTermMinValue", 1.0f);
_BoxWalls[BoxWallIndex].Render();
}
Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
_WoodTexture.Set(0);
float LocalRotationTheta = 0.0f;
float OrbitalRotationTheta = 0.0f;
float ObjectRadius = 0.0f;
if(_ViewMode == ShadowSceneViewModeObjectsRotatingAroundLight)
{
LocalRotationTheta = _ElapsedTime * 1.647f;
OrbitalRotationTheta = _ElapsedTime * 1.0f;
ObjectRadius = 7.0f;
}
else if(_ViewMode == ShadowSceneViewModeLightRotatingAroundObjects)
{
LocalRotationTheta = 1.2f;
ObjectRadius = 5.0f;
}
for(UINT ObjectIndex = 0; ObjectIndex < ShadowSceneObjectCount; ObjectIndex++)
{
const ShadowSceneObject &CurObject = _Objects[ObjectIndex];
Matrix4 LocalRotation = Matrix4::RotationZ(LocalRotationTheta + CurObject.LocalZOffset);
Matrix4 Translation = Matrix4::Translation(Vec3f::eX * ObjectRadius);
Matrix4 OrbitalRotation = Matrix4::RotationZ(CurObject.Theta + OrbitalRotationTheta);
MC.World = LocalRotation * Translation * OrbitalRotation;
_ShadowMap.SetCameraMatrices(MC, Shader);
_ShadowMap._VShaderRender.SetVec3("TextureRepeat", Vec3f(1.0f, 1.0f, 1.0f));
_ShadowMap._PShaderRender.SetFloat("LightTermMinValue", 0.4f);
if(Shader == ShadowMapShaderCreate)
{
CurObject.SimplifiedMesh.Render();
}
else if(Shader == ShadowMapShaderRender)
{
CurObject.FullMesh.Render();
}
}
}
void ShadowScene::RenderLight(D3D9GraphicsDevice &GD)
{
}