Working shadows, no cascade blend yet
This commit is contained in:
@@ -9,7 +9,8 @@
|
|||||||
#include "ShadowPassState.h"
|
#include "ShadowPassState.h"
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
#define MAX_SPLITS 5
|
#define MAX_SPLITS 3
|
||||||
|
#define MAP_SIZE 216.f
|
||||||
|
|
||||||
enum NearFar { Near = 0, Far = 1 };
|
enum NearFar { Near = 0, Far = 1 };
|
||||||
enum LRBT { Left = 0, Right = 1, Bottom = 2, Top = 3 };
|
enum LRBT { Left = 0, Right = 1, Bottom = 2, Top = 3 };
|
||||||
@@ -19,6 +20,18 @@ struct ShadowCamera{
|
|||||||
std::array<glm::vec3, 8> frustumCorners;
|
std::array<glm::vec3, 8> frustumCorners;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Frustum
|
||||||
|
{
|
||||||
|
float NearClip;
|
||||||
|
float FarClip;
|
||||||
|
float FOV;
|
||||||
|
float AspectRatio;
|
||||||
|
glm::vec3 MiddlePoint;
|
||||||
|
float Radius;
|
||||||
|
std::array<float, 4> LRTB;
|
||||||
|
std::array<glm::vec3, 8> CornerPoint;
|
||||||
|
};
|
||||||
|
|
||||||
class ShadowPass
|
class ShadowPass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -31,15 +44,23 @@ public:
|
|||||||
void ClearBuffer();
|
void ClearBuffer();
|
||||||
void Draw(RenderScene& scene);
|
void Draw(RenderScene& scene);
|
||||||
|
|
||||||
GLuint DepthMap() const { return m_DepthMap[m_ShadowLevel]; }
|
GLuint DepthMap(int level) const { return m_DepthMap[level]; }
|
||||||
glm::mat4 lightP() const { return m_LightProjection[m_ShadowLevel]; }
|
std::array<glm::mat4, MAX_SPLITS> lightP() const { return m_LightProjection; }
|
||||||
glm::mat4 lightV() const { return m_LightView[m_ShadowLevel]; }
|
std::array<glm::mat4, MAX_SPLITS> lightV() const { return m_LightView; }
|
||||||
|
std::array<float, MAX_SPLITS> farDistance() const { return { m_shadFrusta[0].FarClip, m_shadFrusta[1].FarClip, m_shadFrusta[2].FarClip }; }
|
||||||
|
int CurrentNrOfSplits() const { return m_CurrentNrOfSplits; }
|
||||||
private:
|
private:
|
||||||
|
void UpdateFrustumPoints(Frustum& frustum, glm::vec3 camera_position, glm::vec3 view_dir, glm::mat4 p, glm::mat4 v);
|
||||||
|
void UpdateSplitDist(std::array<Frustum, MAX_SPLITS>& frusta, float near_distance, float far_distance);
|
||||||
|
glm::mat4 ApplyCropMatrix(Frustum& frustum, glm::mat4 m, glm::mat4 v);
|
||||||
|
|
||||||
glm::mat4 CalculateFrustum(RenderScene & scene, std::shared_ptr<DirectionalLightJob> directionalLightJob, ShadowCamera shad_cam);
|
glm::mat4 CalculateFrustum(RenderScene & scene, std::shared_ptr<DirectionalLightJob> directionalLightJob, ShadowCamera shad_cam);
|
||||||
std::array<glm::vec3, 8> UpdateFrustumPoints(Camera* cam, glm::vec3 center, glm::vec3 view_dir);
|
glm::mat4 FindNewFrustum(Frustum frustum, glm::mat4 v, glm::mat4 p);
|
||||||
void UpdateSplitDist(std::array<ShadowCamera, MAX_SPLITS> shadow_cams, float far_distance, float near_distance);
|
void InitializeCameras(RenderScene & scene);
|
||||||
glm::mat4 FindNewFrustum(ShadowCamera shadow_cam);
|
float FindRadius(Frustum& frustum);
|
||||||
|
void PointsToLightspace(Frustum& frustum, glm::mat4 v);
|
||||||
|
void RadiusToLightspace(Frustum& frustum, glm::mat4 v);
|
||||||
|
|
||||||
|
|
||||||
EventBroker* m_EventBroker;
|
EventBroker* m_EventBroker;
|
||||||
const IRenderer* m_Renderer;
|
const IRenderer* m_Renderer;
|
||||||
@@ -63,9 +84,11 @@ private:
|
|||||||
int m_ShadowLevel = 0;
|
int m_ShadowLevel = 0;
|
||||||
|
|
||||||
int m_CurrentNrOfSplits = 3;
|
int m_CurrentNrOfSplits = 3;
|
||||||
float m_SplitWeight = 0.5f;
|
float m_SplitWeight = 0.75f;
|
||||||
|
|
||||||
std::array<ShadowCamera, MAX_SPLITS> m_shadCams;
|
//std::array<ShadowCamera, MAX_SPLITS> m_shadCams;
|
||||||
|
Frustum m_MainCamera;
|
||||||
|
std::array<Frustum, MAX_SPLITS> m_shadFrusta;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
|
#define MAX_SPLITS 3
|
||||||
|
|
||||||
uniform mat4 M;
|
uniform mat4 M;
|
||||||
uniform mat4 V;
|
uniform mat4 V;
|
||||||
uniform mat4 P;
|
uniform mat4 P;
|
||||||
@@ -22,7 +24,7 @@ in VertexData{
|
|||||||
vec2 TextureCoordinate;
|
vec2 TextureCoordinate;
|
||||||
vec4 ExplosionColor;
|
vec4 ExplosionColor;
|
||||||
float ExplosionPercentageElapsed;
|
float ExplosionPercentageElapsed;
|
||||||
vec4 PositionLightSpace;
|
vec4 PositionLightSpace[MAX_SPLITS];
|
||||||
}Input[];
|
}Input[];
|
||||||
|
|
||||||
out VertexData{
|
out VertexData{
|
||||||
@@ -33,7 +35,7 @@ out VertexData{
|
|||||||
vec2 TextureCoordinate;
|
vec2 TextureCoordinate;
|
||||||
vec4 ExplosionColor;
|
vec4 ExplosionColor;
|
||||||
float ExplosionPercentageElapsed;
|
float ExplosionPercentageElapsed;
|
||||||
vec4 PositionLightSpace;
|
vec4 PositionLightSpace[MAX_SPLITS];
|
||||||
}Output;
|
}Output;
|
||||||
|
|
||||||
layout(triangles) in;
|
layout(triangles) in;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
|
#define MAX_SPLITS 3
|
||||||
|
|
||||||
uniform mat4 M;
|
uniform mat4 M;
|
||||||
uniform mat4 V;
|
uniform mat4 V;
|
||||||
uniform mat4 P;
|
uniform mat4 P;
|
||||||
@@ -9,11 +11,15 @@ uniform vec2 ScreenDimensions;
|
|||||||
uniform vec4 FillColor;
|
uniform vec4 FillColor;
|
||||||
uniform vec4 AmbientColor;
|
uniform vec4 AmbientColor;
|
||||||
uniform float FillPercentage;
|
uniform float FillPercentage;
|
||||||
|
uniform float FarDistance[MAX_SPLITS];
|
||||||
|
|
||||||
layout (binding = 0) uniform sampler2D DiffuseTexture;
|
layout (binding = 0) uniform sampler2D DiffuseTexture;
|
||||||
layout (binding = 1) uniform sampler2D NormalMapTexture;
|
layout (binding = 1) uniform sampler2D NormalMapTexture;
|
||||||
layout (binding = 2) uniform sampler2D SpecularMapTexture;
|
layout (binding = 2) uniform sampler2D SpecularMapTexture;
|
||||||
layout (binding = 3) uniform sampler2D GlowMapTexture;
|
layout (binding = 3) uniform sampler2D GlowMapTexture;
|
||||||
layout (binding = 4) uniform sampler2DShadow DepthMap;
|
layout (binding = 4) uniform sampler2DShadow DepthMap0;
|
||||||
|
layout (binding = 5) uniform sampler2DShadow DepthMap1;
|
||||||
|
layout (binding = 6) uniform sampler2DShadow DepthMap2;
|
||||||
|
|
||||||
#define TILE_SIZE 16
|
#define TILE_SIZE 16
|
||||||
|
|
||||||
@@ -57,7 +63,7 @@ in VertexData{
|
|||||||
vec2 TextureCoordinate;
|
vec2 TextureCoordinate;
|
||||||
vec4 ExplosionColor;
|
vec4 ExplosionColor;
|
||||||
float ExplosionPercentageElapsed;
|
float ExplosionPercentageElapsed;
|
||||||
vec4 PositionLightSpace;
|
vec4 PositionLightSpace[MAX_SPLITS];
|
||||||
}Input;
|
}Input;
|
||||||
|
|
||||||
out vec4 sceneColor;
|
out vec4 sceneColor;
|
||||||
@@ -186,8 +192,52 @@ float CalcShadowValue(vec4 positionLightSpace, vec3 normal, vec3 lightDir, sampl
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getShadowIndex(float far_distance[MAX_SPLITS])
|
||||||
|
{
|
||||||
|
int index = 2;
|
||||||
|
if( gl_FragCoord.z < far_distance[0] )
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
else if( gl_FragCoord.z < far_distance[1] && gl_FragCoord.z > far_distance[0] )
|
||||||
|
{
|
||||||
|
index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
//sampler2DShadow whichDepthMap( int DepthMapIndex )
|
||||||
|
//{
|
||||||
|
// if( DepthMapIndex == 0 )
|
||||||
|
// {
|
||||||
|
// return DepthMap0;
|
||||||
|
// }
|
||||||
|
// else if( DepthMapIndex == 1 )
|
||||||
|
// {
|
||||||
|
// return DepthMap1;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// return DepthMap2;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
//sampler2DShadow DepthMaps[3] = { sampler2DShadow(DepthMap0), sampler2DShadow(DepthMap1), sampler2DShadow(DepthMap2) };
|
||||||
|
//sampler2DShadow DepthMaps[3] = { DepthMap0, DepthMap1, DepthMap2 };
|
||||||
|
//sampler2DShadow DepthMaps[3] = sampler2DShadow[]( DepthMap0, DepthMap1, DepthMap2 );
|
||||||
|
//sampler2DShadow DepthMaps[3] = sampler2DShadow[3]( DepthMap0, DepthMap1, DepthMap2 );
|
||||||
|
//sampler2DShadow DepthMaps[3];
|
||||||
|
|
||||||
|
//sampler2DShadow DepthMapOne = DepthMap0;
|
||||||
|
|
||||||
|
//DepthMaps[0] = DepthMap0;
|
||||||
|
//DepthMaps[1] = DepthMap1;
|
||||||
|
//DepthMaps[2] = DepthMap2;
|
||||||
|
|
||||||
vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate);
|
vec4 diffuseTexel = texture2D(DiffuseTexture, Input.TextureCoordinate);
|
||||||
vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate);
|
vec4 glowTexel = texture2D(GlowMapTexture, Input.TextureCoordinate);
|
||||||
vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate);
|
vec4 specularTexel = texture2D(SpecularMapTexture, Input.TextureCoordinate);
|
||||||
@@ -220,18 +270,32 @@ void main()
|
|||||||
if(light.Type == 1) { // point
|
if(light.Type == 1) { // point
|
||||||
light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff);
|
light_result = CalcPointLightSource(V * light.Position, light.Radius, light.Color, light.Intensity, viewVec, position, normal, light.Falloff);
|
||||||
} else if (light.Type == 2) { //Directional
|
} else if (light.Type == 2) { //Directional
|
||||||
|
int DepthMapIndex = getShadowIndex(FarDistance);
|
||||||
|
//sampler2DShadow WhichDepthMap = whichDepthMap(DepthMapIndex);
|
||||||
|
|
||||||
light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal);
|
light_result = CalcDirectionalLightSource(V * light.Direction, light.Color, light.Intensity, viewVec, normal);
|
||||||
shadowFactor = CalcShadowValue(Input.PositionLightSpace, Input.Normal, vec3(light.Direction), DepthMap);
|
|
||||||
|
shadowFactor = CalcShadowValue(Input.PositionLightSpace[0], Input.Normal, vec3(light.Direction), DepthMap0);
|
||||||
|
//if( DepthMapIndex == 0 )
|
||||||
|
//{
|
||||||
|
// shadowFactor = CalcShadowValue(Input.PositionLightSpace[DepthMapIndex], Input.Normal, vec3(light.Direction), DepthMap0);
|
||||||
|
//}
|
||||||
|
//else if( DepthMapIndex == 1 )
|
||||||
|
//{
|
||||||
|
// shadowFactor = CalcShadowValue(Input.PositionLightSpace[DepthMapIndex], Input.Normal, vec3(light.Direction), DepthMap1);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// shadowFactor = CalcShadowValue(Input.PositionLightSpace[DepthMapIndex], Input.Normal, vec3(light.Direction), DepthMap2);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
totalLighting.Diffuse += light_result.Diffuse;
|
totalLighting.Diffuse += light_result.Diffuse;
|
||||||
totalLighting.Specular += light_result.Specular;
|
totalLighting.Specular += light_result.Specular;
|
||||||
}
|
}
|
||||||
|
|
||||||
//totalLighting.Diffuse *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0);
|
totalLighting.Diffuse *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0);
|
||||||
//totalLighting.Specular *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0);
|
totalLighting.Specular *= (1.5 + vec4(AmbientColor.rgb, 1.0)) - vec4(vec3(shadowFactor), 0.0);
|
||||||
totalLighting.Diffuse *= (1.0 + vec4(AmbientColor.rgb, 1.0)) + vec4(vec3(shadowFactor, shadowFactor, 0.0), 0.0);
|
|
||||||
totalLighting.Specular *= (1.0 + vec4(AmbientColor.rgb, 1.0)) + vec4(vec3(shadowFactor, shadowFactor, 0.0), 0.0);
|
|
||||||
|
|
||||||
//LightResult getInformation;
|
//LightResult getInformation;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
#version 430
|
#version 430
|
||||||
|
|
||||||
|
#define MAX_SPLITS 3
|
||||||
|
|
||||||
uniform mat4 M;
|
uniform mat4 M;
|
||||||
uniform mat4 V;
|
uniform mat4 V;
|
||||||
uniform mat4 P;
|
uniform mat4 P;
|
||||||
uniform mat4 LightV;
|
uniform mat4 LightV[MAX_SPLITS];
|
||||||
uniform mat4 LightP;
|
uniform mat4 LightP[MAX_SPLITS];
|
||||||
uniform mat4 Bones[100];
|
uniform mat4 Bones[100];
|
||||||
|
|
||||||
layout(location = 0) in vec3 Position;
|
layout(location = 0) in vec3 Position;
|
||||||
@@ -23,7 +25,7 @@ out VertexData{
|
|||||||
vec2 TextureCoordinate;
|
vec2 TextureCoordinate;
|
||||||
vec4 ExplosionColor;
|
vec4 ExplosionColor;
|
||||||
float ExplosionPercentageElapsed;
|
float ExplosionPercentageElapsed;
|
||||||
vec4 PositionLightSpace;
|
vec4 PositionLightSpace[MAX_SPLITS];
|
||||||
}Output;
|
}Output;
|
||||||
|
|
||||||
// N
|
// N
|
||||||
@@ -60,5 +62,8 @@ void main()
|
|||||||
Output.ExplosionPercentageElapsed = 0.0;
|
Output.ExplosionPercentageElapsed = 0.0;
|
||||||
|
|
||||||
//Output.PositionLightSpace = lightPos; // N
|
//Output.PositionLightSpace = lightPos; // N
|
||||||
Output.PositionLightSpace = LightP * LightV * M * vec4(Position, 1.0);
|
for(int i = 0; i < MAX_SPLITS; i++)
|
||||||
|
{
|
||||||
|
Output.PositionLightSpace[i] = LightP[i] * LightV[i] * M * vec4(Position, 1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -244,8 +244,11 @@ void DrawFinalPass::BindModelUniforms(GLuint shaderHandle, std::shared_ptr<Model
|
|||||||
glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor));
|
glUniform4fv(glGetUniformLocation(shaderHandle, "AmbientColor"), 1, glm::value_ptr(scene.AmbientColor));
|
||||||
|
|
||||||
//Shadow
|
//Shadow
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightP"), 1, GL_FALSE, glm::value_ptr(m_ShadowPass->lightP()));
|
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightP"), MAX_SPLITS, GL_FALSE, glm::value_ptr(*m_ShadowPass->lightP().data()));
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightV"), 1, GL_FALSE, glm::value_ptr(m_ShadowPass->lightV()));
|
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "LightV"), MAX_SPLITS, GL_FALSE, glm::value_ptr(*m_ShadowPass->lightV().data()));
|
||||||
|
glUniform1fv(glGetUniformLocation(shaderHandle, "FarDistance"), MAX_SPLITS, m_ShadowPass->farDistance().data());
|
||||||
|
|
||||||
|
|
||||||
//GLfloat m_NearFarPlane[2] = { -40.f, 30.f };
|
//GLfloat m_NearFarPlane[2] = { -40.f, 30.f };
|
||||||
//GLfloat m_LRBT[4] = { -40.f, 100.f, -50.f, 50.f };
|
//GLfloat m_LRBT[4] = { -40.f, 100.f, -50.f, 50.f };
|
||||||
//glm::mat4 m_LightProjection = glm::ortho(m_LRBT[Left], m_LRBT[Right], m_LRBT[Bottom], m_LRBT[Top], m_NearFarPlane[Near], m_NearFarPlane[Far]);
|
//glm::mat4 m_LightProjection = glm::ortho(m_LRBT[Left], m_LRBT[Right], m_LRBT[Bottom], m_LRBT[Top], m_NearFarPlane[Near], m_NearFarPlane[Far]);
|
||||||
@@ -317,11 +320,16 @@ void DrawFinalPass::BindModelTextures(std::shared_ptr<ModelJob>& job)
|
|||||||
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
glBindTexture(GL_TEXTURE_2D, m_BlackTexture->m_Texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE4);
|
for (int i = 0; i < m_ShadowPass->CurrentNrOfSplits(); i++)
|
||||||
if (m_ShadowPass->DepthMap() != NULL) {
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, m_ShadowPass->DepthMap());
|
glActiveTexture(GL_TEXTURE4 + i);
|
||||||
} else {
|
if (m_ShadowPass->DepthMap(i) != NULL) {
|
||||||
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
glBindTexture(GL_TEXTURE_2D, m_ShadowPass->DepthMap(i));
|
||||||
}
|
} else {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ void Renderer::Draw(RenderFrame& frame)
|
|||||||
m_DrawScreenQuadPass->Draw(m_PickingPass->PickingTexture());
|
m_DrawScreenQuadPass->Draw(m_PickingPass->PickingTexture());
|
||||||
}
|
}
|
||||||
if (m_DebugTextureToDraw == 5) {
|
if (m_DebugTextureToDraw == 5) {
|
||||||
m_DrawScreenQuadPass->Draw(m_ShadowPass->DepthMap());
|
m_DrawScreenQuadPass->Draw(m_ShadowPass->DepthMap(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ImGuiRenderPass->Draw();
|
m_ImGuiRenderPass->Draw();
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#include "Rendering/ShadowPass.h"
|
#include "Rendering/ShadowPass.h"
|
||||||
|
|
||||||
|
|
||||||
ShadowPass::ShadowPass(IRenderer * renderer)
|
ShadowPass::ShadowPass(IRenderer * renderer)
|
||||||
{
|
{
|
||||||
m_Renderer = renderer;
|
m_Renderer = renderer;
|
||||||
|
|
||||||
InitializeFrameBuffers();
|
InitializeFrameBuffers();
|
||||||
InitializeShaderPrograms();
|
InitializeShaderPrograms();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadowPass::~ShadowPass()
|
ShadowPass::~ShadowPass()
|
||||||
@@ -13,101 +14,94 @@ ShadowPass::~ShadowPass()
|
|||||||
// m_shadCams
|
// m_shadCams
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the 8 corner points of the current view frustum
|
void ShadowPass::InitializeCameras(RenderScene & scene)
|
||||||
std::array<glm::vec3, 8> ShadowPass::UpdateFrustumPoints(Camera* cam, glm::vec3 center, glm::vec3 view_dir)
|
|
||||||
{
|
{
|
||||||
glm::vec3 up = glm::vec3(0.f, 1.f, 0.f);
|
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
||||||
glm::vec3 right = glm::normalize(glm::cross(view_dir, up));
|
m_shadFrusta[i].AspectRatio = scene.Camera->AspectRatio();
|
||||||
|
m_shadFrusta[i].FOV = scene.Camera->FOV();
|
||||||
//glm::vec3 farCenter = center + view_dir * cam->FarClip();
|
}
|
||||||
//glm::vec3 nearCenter = center + view_dir * cam->NearClip();
|
|
||||||
glm::vec3 farCenter = view_dir * cam->FarClip();
|
|
||||||
glm::vec3 nearCenter = view_dir * cam->NearClip();
|
|
||||||
|
|
||||||
up = glm::normalize(glm::cross(right, view_dir));
|
|
||||||
|
|
||||||
float near_height = tan(cam->FOV() / 2.f) * cam->NearClip();
|
|
||||||
float near_width = near_height * cam->AspectRatio();
|
|
||||||
float far_height = tan(cam->FOV() / 2.f) * cam->FarClip();
|
|
||||||
float far_width = far_height * cam->AspectRatio();
|
|
||||||
|
|
||||||
std::array<glm::vec3, 8> frustumPoints;
|
|
||||||
frustumPoints[0] = nearCenter - up * near_height - right * near_width;
|
|
||||||
frustumPoints[1] = nearCenter + up * near_height - right * near_width;
|
|
||||||
frustumPoints[2] = nearCenter + up * near_height + right * near_width;
|
|
||||||
frustumPoints[3] = nearCenter - up * near_height + right * near_width;
|
|
||||||
|
|
||||||
frustumPoints[4] = farCenter - up * far_height - right * far_width;
|
|
||||||
frustumPoints[5] = farCenter + up * far_height - right * far_width;
|
|
||||||
frustumPoints[6] = farCenter + up * far_height + right * far_width;
|
|
||||||
frustumPoints[7] = farCenter - up * far_height + right * far_width;
|
|
||||||
|
|
||||||
return frustumPoints;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSplitDist computes the near and far distances for every frustum slice
|
// UpdateSplitDist computes the near and far distances for every frustum slice
|
||||||
// in camera eye space - that is, at what distance does a slice start and end
|
// in camera eye space - that is, at what distance does a slice start and end
|
||||||
void ShadowPass::UpdateSplitDist(std::array<ShadowCamera, MAX_SPLITS> shadow_cams, float near_distance, float far_distance)
|
void ShadowPass::UpdateSplitDist(std::array<Frustum, MAX_SPLITS>& frusta, float near_distance, float far_distance)
|
||||||
{
|
{
|
||||||
float lambda = m_SplitWeight;
|
float lambda = m_SplitWeight;
|
||||||
float ratio = far_distance / near_distance;
|
float ratio = far_distance / near_distance;
|
||||||
|
|
||||||
shadow_cams[0].camera->SetNearClip(near_distance);
|
frusta[0].NearClip = near_distance;
|
||||||
|
|
||||||
for (int i = 1; i < m_CurrentNrOfSplits; i++) {
|
for (int i = 1; i < m_CurrentNrOfSplits; i++) {
|
||||||
float si = i / static_cast<float>(m_CurrentNrOfSplits);
|
float si = i / static_cast<float>(m_CurrentNrOfSplits);
|
||||||
|
|
||||||
shadow_cams[i].camera->SetNearClip(lambda * (near_distance * powf(ratio, si)) + (1 - lambda) * (near_distance + (far_distance - near_distance) * si));
|
frusta[i].NearClip = lambda * (near_distance * powf(ratio, si)) + (1 - lambda) * (near_distance + (far_distance - near_distance) * si);
|
||||||
shadow_cams[i - 1].camera->SetFarClip(shadow_cams[i].camera->NearClip() * 1.005f);
|
frusta[i - 1].FarClip = frusta[i].NearClip * 1.005f;
|
||||||
}
|
}
|
||||||
|
|
||||||
shadow_cams[m_CurrentNrOfSplits - 1].camera->SetFarClip(far_distance);
|
frusta[m_CurrentNrOfSplits - 1].FarClip = far_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new light frustum based on the 8 corner points of a view frustum segment
|
// Compute the 8 corner points of the current view frustum in world space
|
||||||
glm::mat4 ShadowPass::FindNewFrustum(ShadowCamera shadow_cam)
|
void ShadowPass::UpdateFrustumPoints(Frustum& frustum, glm::vec3 camera_position, glm::vec3 view_dir, glm::mat4 p, glm::mat4 v)
|
||||||
{
|
{
|
||||||
float maxX = -1000.0f;
|
glm::vec3 up = glm::vec3(0.f, 1.f, 0.f);
|
||||||
float maxY = -1000.0f;
|
glm::vec3 right = glm::normalize(glm::cross(view_dir, up));
|
||||||
float maxZ;
|
|
||||||
float minX = 1000.0f;
|
|
||||||
float minY = 1000.0f;
|
|
||||||
float minZ;
|
|
||||||
|
|
||||||
glm::vec4 transf;
|
glm::vec3 far_center = camera_position + glm::normalize(view_dir) * frustum.FarClip;
|
||||||
|
glm::vec3 near_center = camera_position + glm::normalize(view_dir) * frustum.NearClip;
|
||||||
|
frustum.MiddlePoint = near_center + (far_center - near_center) * 0.5f;
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++)
|
up = glm::normalize(glm::cross(right, view_dir));
|
||||||
{
|
|
||||||
transf = glm::vec4(shadow_cam.frustumCorners[i], 1.f);
|
|
||||||
|
|
||||||
if (transf.x > maxX) maxX = transf.x;
|
// these heights and widths are half the heights and widths of the near and far plane rectangles.
|
||||||
if (transf.x < minX) minX = transf.x;
|
float near_height = tan(frustum.FOV / 2.f) * frustum.NearClip;
|
||||||
if (transf.y > maxY) maxY = transf.y;
|
float near_width = near_height * frustum.AspectRatio;
|
||||||
if (transf.y < minY) minY = transf.y;
|
float far_height = tan(frustum.FOV / 2.f) * frustum.FarClip;
|
||||||
|
float far_width = far_height * frustum.AspectRatio;
|
||||||
|
|
||||||
|
frustum.CornerPoint[0] = near_center - up * near_height - right * near_width;
|
||||||
|
frustum.CornerPoint[1] = near_center + up * near_height - right * near_width;
|
||||||
|
frustum.CornerPoint[2] = near_center + up * near_height + right * near_width;
|
||||||
|
frustum.CornerPoint[3] = near_center - up * near_height + right * near_width;
|
||||||
|
|
||||||
|
frustum.CornerPoint[4] = far_center - up * far_height - right * far_width;
|
||||||
|
frustum.CornerPoint[5] = far_center + up * far_height - right * far_width;
|
||||||
|
frustum.CornerPoint[6] = far_center + up * far_height + right * far_width;
|
||||||
|
frustum.CornerPoint[7] = far_center - up * far_height + right * far_width;
|
||||||
|
|
||||||
|
// Alternative way
|
||||||
|
//std::array<glm::vec4, 8> CornerPoint = {
|
||||||
|
// glm::vec4(-1.f, -1.f, -1.f, 1.f),
|
||||||
|
// glm::vec4(-1.f, 1.f, -1.f, 1.f),
|
||||||
|
// glm::vec4(1.f, 1.f, -1.f, 1.f),
|
||||||
|
// glm::vec4(1.f, -1.f, -1.f, 1.f),
|
||||||
|
// glm::vec4(-1.f, -1.f, 1.f, 1.f),
|
||||||
|
// glm::vec4(-1.f, 1.f, 1.f, 1.f),
|
||||||
|
// glm::vec4(1.f, 1.f, 1.f, 1.f),
|
||||||
|
// glm::vec4(1.f, -1.f, 1.f, 1.f) };
|
||||||
|
|
||||||
|
//std::array<glm::vec3, 8> final;
|
||||||
|
|
||||||
|
//for (int i = 0; i < 8; i++) {
|
||||||
|
// glm::vec4 anus = glm::inverse(p) * CornerPoint[i];
|
||||||
|
// anus = anus / anus.w;
|
||||||
|
// final[i] = glm::vec3(glm::inverse(v) * anus);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
float ShadowPass::FindRadius(Frustum& frustum)
|
||||||
|
{
|
||||||
|
float radius = 0.f;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
float distance = glm::distance(frustum.MiddlePoint, frustum.CornerPoint[i]);
|
||||||
|
if (distance > radius) {
|
||||||
|
radius = distance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//float scaleX = 2.0f / (maxX - minX);
|
frustum.Radius = radius;
|
||||||
//float scaleY = 2.0f / (maxY - minY);
|
return radius;
|
||||||
//float offsetX = -0.5f * (maxX + minX) * scaleX;
|
|
||||||
//float offsetY = -0.5f * (maxY + minY) * scaleY;
|
|
||||||
//
|
|
||||||
//glm::mat4 nv_mvp = glm::mat4();
|
|
||||||
//nv_mvp[0][0] = scaleX;
|
|
||||||
//nv_mvp[1][1] = scaleY;
|
|
||||||
//nv_mvp[0][3] = offsetX;
|
|
||||||
//nv_mvp[1][3] = offsetY;
|
|
||||||
//glm::transpose(nv_mvp);
|
|
||||||
|
|
||||||
glm::mat4 p = glm::ortho(minX, maxX, minY, maxY, m_NearFarPlane[Near], m_NearFarPlane[Far]);
|
|
||||||
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 ShadowPass::CalculateFrustum(RenderScene & scene, std::shared_ptr<DirectionalLightJob> directionalLightJob, ShadowCamera shad_cam)
|
|
||||||
{
|
|
||||||
glm::vec3 middle = shad_cam.camera->Position() + (shad_cam.camera->Forward() * shad_cam.camera->FarClip() * 0.5f);
|
|
||||||
|
|
||||||
return glm::lookAt(glm::vec3(0.f) + middle, glm::vec3(directionalLightJob->Direction) + middle, glm::vec3(-1.f, 0.f, 0.f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShadowPass::InitializeFrameBuffers()
|
void ShadowPass::InitializeFrameBuffers()
|
||||||
@@ -154,6 +148,36 @@ void ShadowPass::ClearBuffer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShadowPass::PointsToLightspace(Frustum& frustum, glm::mat4 v)
|
||||||
|
{
|
||||||
|
float left = INFINITY;
|
||||||
|
float right = -INFINITY;
|
||||||
|
float bottom = INFINITY;
|
||||||
|
float top = -INFINITY;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
glm::vec3 tempPoint = glm::vec3(v * glm::vec4(frustum.CornerPoint[i], 1.f));
|
||||||
|
|
||||||
|
if (tempPoint.x < left) { left = tempPoint.x; }
|
||||||
|
if (tempPoint.x > right) { right = tempPoint.x; }
|
||||||
|
if (tempPoint.y < bottom) { bottom = tempPoint.y; }
|
||||||
|
if (tempPoint.y > top) { top = tempPoint.y; }
|
||||||
|
}
|
||||||
|
|
||||||
|
frustum.LRTB = { left, right, bottom, top };
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShadowPass::RadiusToLightspace(Frustum& frustum, glm::mat4 v)
|
||||||
|
{
|
||||||
|
float left = -frustum.Radius;
|
||||||
|
float right = frustum.Radius;
|
||||||
|
float bottom = -frustum.Radius;
|
||||||
|
float top =frustum.Radius;
|
||||||
|
|
||||||
|
frustum.LRTB = { left, right, bottom, top };
|
||||||
|
}
|
||||||
|
|
||||||
void ShadowPass::Draw(RenderScene & scene)
|
void ShadowPass::Draw(RenderScene & scene)
|
||||||
{
|
{
|
||||||
ImGui::DragFloat4("ShadowMapCam", m_LRBT, 1.f, -1000.f, 1000.f);
|
ImGui::DragFloat4("ShadowMapCam", m_LRBT, 1.f, -1000.f, 1000.f);
|
||||||
@@ -161,15 +185,12 @@ void ShadowPass::Draw(RenderScene & scene)
|
|||||||
ImGui::Checkbox("EnableShadow", &m_ShadowOn);
|
ImGui::Checkbox("EnableShadow", &m_ShadowOn);
|
||||||
ImGui::DragInt("ShadowLevel", &m_ShadowLevel, 0.05f, 0, m_CurrentNrOfSplits - 1);
|
ImGui::DragInt("ShadowLevel", &m_ShadowLevel, 0.05f, 0, m_CurrentNrOfSplits - 1);
|
||||||
|
|
||||||
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
InitializeCameras(scene);
|
||||||
m_shadCams[i].camera = new Camera(*scene.Camera);
|
UpdateSplitDist(m_shadFrusta, scene.Camera->NearClip(), scene.Camera->FarClip());
|
||||||
//m_shadCams[i].frustumCorners = tempPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateSplitDist(m_shadCams, scene.Camera->NearClip(), scene.Camera->FarClip());
|
|
||||||
|
|
||||||
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
for (int i = 0; i < m_CurrentNrOfSplits; i++) {
|
||||||
m_shadCams[i].frustumCorners = UpdateFrustumPoints(m_shadCams[i].camera, m_shadCams[i].camera->Position(), m_shadCams[i].camera->Forward());
|
UpdateFrustumPoints(m_shadFrusta[i], scene.Camera->Position(), scene.Camera->Forward(), scene.Camera->ProjectionMatrix(), scene.Camera->ViewMatrix());
|
||||||
|
//float test = FindRadius(m_shadFrusta[i]);
|
||||||
|
|
||||||
ShadowPassState* state = new ShadowPassState(m_DepthBuffer[i].GetHandle());
|
ShadowPassState* state = new ShadowPassState(m_DepthBuffer[i].GetHandle());
|
||||||
|
|
||||||
@@ -187,8 +208,11 @@ void ShadowPass::Draw(RenderScene & scene)
|
|||||||
auto directionalLightJob = std::dynamic_pointer_cast<DirectionalLightJob>(job);
|
auto directionalLightJob = std::dynamic_pointer_cast<DirectionalLightJob>(job);
|
||||||
|
|
||||||
if (directionalLightJob) {
|
if (directionalLightJob) {
|
||||||
m_LightView[i] = CalculateFrustum(scene, directionalLightJob, m_shadCams[i]);
|
m_LightView[i] = glm::lookAt(glm::vec3(-directionalLightJob->Direction) + m_shadFrusta[i].MiddlePoint, m_shadFrusta[i].MiddlePoint, glm::vec3(0.f, 1.f, 0.f));
|
||||||
m_LightProjection[i] = FindNewFrustum(m_shadCams[i]);
|
|
||||||
|
PointsToLightspace(m_shadFrusta[i], m_LightView[i]);
|
||||||
|
m_LightProjection[i] = glm::ortho(m_shadFrusta[i].LRTB[Left], m_shadFrusta[i].LRTB[Right], m_shadFrusta[i].LRTB[Bottom], m_shadFrusta[i].LRTB[Top], -30.f, 30.f);
|
||||||
|
//m_LightProjection[i] = glm::ortho(m_shadFrusta[i].LRTB[Left], m_shadFrusta[i].LRTB[Right], m_shadFrusta[i].LRTB[Bottom], m_shadFrusta[i].LRTB[Top], -0.f, 300.f);
|
||||||
|
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i]));
|
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_LightProjection[i]));
|
||||||
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_LightView[i]));
|
glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_LightView[i]));
|
||||||
|
|||||||
Reference in New Issue
Block a user