@@ -50,6 +50,99 @@ void CascadedShadowMap::calcOrthoProjs(Camera* mainCam)
{

if (true)
{
splitPlanes[0].x = mainCam->getNearPlane();
splitPlanes[0].y = 20.0f;

splitPlanes[1].x = 20.0f;
splitPlanes[1].y = 80.0f;

splitPlanes[2].x = 80.0f;
splitPlanes[2].y = 400.0f;

for (int CascadeID = 0; CascadeID < NUM_CASCADEDS; CascadeID++)
{
glm::vec3 frustumCorners[8] =
{
glm::vec3(-1.0f, 1.0f, 0.0f),
glm::vec3(1.0f, 1.0f, 0.0f),
glm::vec3(1.0f, -1.0f, 0.0f),
glm::vec3(-1.0f, -1.0f, 0.0f),
glm::vec3(-1.0f, 1.0f, 1.0f),
glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(1.0f, -1.0f, 1.0f),
glm::vec3(-1.0f, -1.0f, 1.0f),
};
glm::mat4 invViewProj = glm::transpose(mainCam->getProjectionWithNearFar(splitPlanes[CascadeID].x, splitPlanes[CascadeID].y) * mainCam->getViewMatrix());
invViewProj = glm::inverse(invViewProj);
//for (int i = 0; i < 8; i++)
//{
// glm::vec4 temp = invViewProj * glm::vec4(frustumCorners[i],1);
// frustumCorners[i] = glm::vec3(temp) / temp.w;
//}

//glm::mat4 cameraviewprojMatrix = mainCam->getViewMatrix();
//cameraviewprojMatrix = mainCam->getProjectionWithNearFar(splitPlanes[CascadeID].x, splitPlanes[CascadeID].y) * cameraviewprojMatrix;
//glm::mat4 invViewProj;
//cameraviewprojMatrix = glm::transpose(cameraviewprojMatrix);
//invViewProj = glm::inverse(cameraviewprojMatrix);

for (int i = 0; i < 8; i++)
{
glm::vec3 result;
glm::vec4 temp(frustumCorners[i].x, frustumCorners[i].y, frustumCorners[i].z, 1); //need a 4-part vector in order to multiply by a 4x4 matrix
glm::vec4 temp2;

temp2.x = invViewProj[0][0] * temp.x + invViewProj[0][1] * temp.y + invViewProj[0][2] * temp.z + invViewProj[0][3] * temp.w;
temp2.y = invViewProj[1][0] * temp.x + invViewProj[1][1] * temp.y + invViewProj[1][2] * temp.z + invViewProj[1][3] * temp.w;
temp2.z = invViewProj[2][0] * temp.x + invViewProj[2][1] * temp.y + invViewProj[2][2] * temp.z + invViewProj[2][3] * temp.w;
temp2.w = invViewProj[2][0] * temp.x + invViewProj[3][1] * temp.y + invViewProj[3][2] * temp.z + invViewProj[3][3] * temp.w;

result.x = temp2.x / temp2.w; //view projection matrices make use of the w component
result.y = temp2.y / temp2.w;
result.z = temp2.z / temp2.w;
frustumCorners[i] = result;

//temp2 = invViewProj * glm::vec4(frustumCorners[i], 1);
//result = glm::vec3(temp2) / temp2.w;

frustumCorners[i] = result;
}
glm::vec3 frustumCenter;
for (int i = 0; i < 8; i++)
{
frustumCenter = frustumCenter + frustumCorners[i];
}
frustumCenter = frustumCenter / 8.0f;

float radius = (frustumCorners[0] - frustumCorners[6]).length() / 2.0f;

float texelsPerUnit = (float)this->height / (radius * 2.0f);
glm::mat4 scalar = glm::scale(glm::vec3(texelsPerUnit));

glm::vec3 zero(0, 0, 0);
glm::vec3 upDir(0, 1, 0);
glm::mat4 lookat, lookatInv;
glm::vec3 baselookAt(-light.direction);

lookat = glm::lookAt(zero, baselookAt, upDir);
lookat *= scalar;
lookatInv = glm::inverse(lookat);

frustumCenter = glm::vec3(lookat * glm::vec4(frustumCenter, 1));
frustumCenter.x = (float)floor(frustumCenter.x);
frustumCenter.y = (float)floor(frustumCenter.y);
frustumCenter = glm::vec3(lookatInv * glm::vec4(frustumCenter, 1));

glm::vec3 eye = frustumCenter - (light.direction * radius * 2.0f);

viewMatrices[CascadeID] = glm::lookAt(eye, frustumCenter, upDir);

projectionMatrices[CascadeID] = glm::ortho(-radius, radius, -radius, radius, -radius * 6.0f, radius * 6.0f);
}
}
//-----------------------------------------------------------------------------------------------------
if (false)
{

pos.z = 100 * sinf(sinCount) + 50;
@@ -77,8 +170,9 @@ void CascadedShadowMap::calcOrthoProjs(Camera* mainCam)
//pos = glm::vec3(200.0f, 10.0f, 200.0f);// mainCam->getPosition();
glm::vec3 direction = mainCam->getDirection();
glm::vec3 right = glm::normalize(glm::cross(glm::normalize(direction), glm::vec3(0.0f, 1.0f, 0.0f)));
glm::vec3 up = glm::normalize(glm::cross((mainCam->getPosition() + direction), right));
glm::vec3 up = glm::normalize(glm::cross(right, glm::normalize(direction)));

printf("right: %s up: %s\n", glm::to_string(right).c_str(), glm::to_string(up).c_str());

glm::vec3 lookat((pos + direction));
glm::mat4 camView = glm::lookAt(pos, lookat, up);
@@ -132,7 +226,7 @@ void CascadedShadowMap::calcOrthoProjs(Camera* mainCam)

glm::vec3 center = nc + ((fc - nc) / 2.0f);

glm::mat4 t_modelview = glm::lookAt(glm::vec3(0.0f), light.direction, glm::vec3(0, 1, 0));
glm::mat4 t_modelview = glm::lookAt(center - light.direction * 50.0f, center, glm::vec3(0, 1, 0));

glm::vec4 t_transf = t_modelview * vertices[0];

@@ -181,217 +275,11 @@ void CascadedShadowMap::calcOrthoProjs(Camera* mainCam)

}
}
//-----------------------------------------------------------------------------------------------------
if (false)
{
for (int i = 0; i < NUM_CASCADEDS; i++)
{
float splitNear = i > 0 ? glm::mix(nearPlane + (static_cast<float>(i) / (float)NUM_CASCADEDS) * (farPlane - nearPlane), nearPlane * pow(farPlane / nearPlane, static_cast<float>(i) / (float)NUM_CASCADEDS), splitLambda) : nearPlane;
float splitFar = i < NUM_CASCADEDS - 1 ? glm::mix(nearPlane + (static_cast<float>(i + 1) / (float)NUM_CASCADEDS) * (farPlane - nearPlane), nearPlane * pow(farPlane / nearPlane, static_cast<float>(i + 1) / (float)NUM_CASCADEDS), splitLambda) : farPlane;

splitPlanes[i] = glm::vec2(splitNear, splitFar);
}

for (int i = 0; i < NUM_CASCADEDS; i++)
{
frustumCorners[0] = glm::vec3(-1.0f, 1.0f, 0.0f);
frustumCorners[1] = glm::vec3(1.0f, 1.0f, 0.0f);
frustumCorners[2] = glm::vec3(1.0f, -1.0f, 0.0f);
frustumCorners[3] = glm::vec3(-1.0f, -1.0f, 0.0f);
frustumCorners[4] = glm::vec3(-1.0f, 1.0f, 1.0f);
frustumCorners[5] = glm::vec3(1.0f, 1.0f, 1.0f);
frustumCorners[6] = glm::vec3(1.0f, -1.0f, 1.0f);
frustumCorners[7] = glm::vec3(-1.0f, -1.0f, 1.0f);

glm::mat4 invViewProj = glm::inverse(mainCam->getViewPers());
for (int j = 0; j < 8; j++)
{
frustumCorners[j] = glm::vec3(invViewProj * glm::vec4(frustumCorners[j], 1));
}

for (int j = 0; j < 4; j++)
{
glm::vec3 cornerRay = frustumCorners[j + 4] - frustumCorners[j];
glm::vec3 nearCornerRay = cornerRay * splitPlanes[i].x;
glm::vec3 farCornerRay = cornerRay * splitPlanes[i].y;

frustumCorners[i + 4] = frustumCorners[i] + farCornerRay;
frustumCorners[i] = frustumCorners[i] + nearCornerRay;
}

glm::vec3 frustrumCenter = glm::vec3(0);
for (int j = 0; j < 8; j++)
{
frustrumCenter += frustumCorners[j];
}
frustrumCenter /= 8.0f;

glm::vec3 upDir = glm::normalize(glm::cross(glm::normalize(mainCam->getDirection()), glm::vec3(0.0f, 1.0f, 0.0f)));

glm::vec3 minExtents;
glm::vec3 maxExtents;

bool StabilizeCascades = true;
if (StabilizeCascades)
{
upDir = glm::vec3(0.0f, 1.0f, 0.0f);

float sphereRadius = 0.0f;
for (int j = 0; j < 8; j++)
{
float dist = (frustumCorners[j] - frustrumCenter).length();
sphereRadius = fmaxf(sphereRadius, dist);
}

sphereRadius = ceilf(sphereRadius * 16.0f) / 16.0f;

maxExtents = glm::vec3(sphereRadius);
minExtents = -maxExtents;
}

minAABB[i] = minExtents;
maxAABB[i] = maxExtents;

glm::vec3 cascadeExtents = maxExtents - minExtents;

glm::vec3 shadowCameraPos = frustrumCenter + light.direction * -minExtents.z;

projectionMatrices[i] = glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, cascadeExtents.z);

viewMatrices[i] = glm::lookAt(shadowCameraPos, frustrumCenter, upDir);

if (StabilizeCascades)
{
glm::mat4 shadowMatrixTemp = projectionMatrices[i] * viewMatrices[i];
glm::vec4 shadowOrigin(0.0f, 0.0f, 0.0f, 1.0f);
shadowOrigin = shadowMatrixTemp * shadowOrigin;
shadowOrigin = shadowOrigin * (WINDOW_HEIGHT / 2.0f);

glm::vec4 roundedOrigin = glm::round(shadowOrigin);
glm::vec4 roundOffset = roundedOrigin - shadowOrigin;
roundOffset = roundOffset * (2.0f / WINDOW_HEIGHT);
roundOffset.z = 0.0f;
roundOffset.w = 0.0f;

glm::mat4 shadowProj = projectionMatrices[i];

shadowProj[3][0] += roundOffset.x;
shadowProj[3][1] += roundOffset.y;
shadowProj[3][2] += roundOffset.z;
shadowProj[3][3] += roundOffset.w;
}
}
}

//-----------------------------------------------------------------------------------------------------
if (false)
{
pos.z += 0.5f;
if (pos.z > 300)
pos.z = 0.0f;

//pos = glm::vec3(200.0f, 10.0f, 200.0f);// mainCam->getPosition();
glm::vec3 direction = glm::vec3(1.0f, 0.0f, 0.0f);//mainCam->getDirection();
glm::vec3 right = glm::normalize(glm::cross(glm::normalize(direction), glm::vec3(0.0f, 1.0f, 0.0f)));
glm::vec3 up = glm::normalize(glm::cross(right, (pos + direction)));


glm::vec3 lookat((pos + direction));
glm::mat4 camView = glm::lookAt(pos, lookat, up);
glm::mat4 view = camView;
glm::mat4 camInv = glm::inverse(view);

viewMatrices[NUM_CASCADEDS] = view;

for (int i = 0; i < NUM_CASCADEDS; i++)
{
float splitNear = i > 0 ? glm::mix(nearPlane + (static_cast<float>(i) / (float)NUM_CASCADEDS) * (farPlane - nearPlane), nearPlane * pow(farPlane / nearPlane, static_cast<float>(i) / (float)NUM_CASCADEDS), splitLambda) : nearPlane;
float splitFar = i < NUM_CASCADEDS - 1 ? glm::mix(nearPlane + (static_cast<float>(i + 1) / (float)NUM_CASCADEDS) * (farPlane - nearPlane), nearPlane * pow(farPlane / nearPlane, static_cast<float>(i + 1) / (float)NUM_CASCADEDS), splitLambda) : farPlane;

splitPlanes[i] = glm::vec2(splitNear, splitFar);
}

float ar = WINDOW_HEIGHT / WINDOW_WIDTH;
float tanHalfHFOV = tanf(glm::radians(45.0f / 2.0f));
float tanHalfVFOV = tanf(glm::radians((45.0f * ar) / 2.0f));

for (int i = 0; i < NUM_CASCADEDS; i++)
{
float xn = splitPlanes[i].x * tanHalfHFOV;
float xf = splitPlanes[i].y * tanHalfHFOV;
float yn = splitPlanes[i].x * tanHalfVFOV;
float yf = splitPlanes[i].y * tanHalfVFOV;

glm::vec4 frustumCorners[8] = {
// near face
glm::vec4(xn, yn, splitPlanes[i].x, 1.0),
glm::vec4(-xn, yn, splitPlanes[i].x, 1.0),
glm::vec4(xn, -yn, splitPlanes[i].x, 1.0),
glm::vec4(-xn, -yn, splitPlanes[i].x, 1.0),

// far face
glm::vec4(xf, yf, splitPlanes[i].y, 1.0),
glm::vec4(-xf, yf, splitPlanes[i].y, 1.0),
glm::vec4(xf, -yf, splitPlanes[i].y, 1.0),
glm::vec4(-xf, -yf, splitPlanes[i].y, 1.0)
};

glm::vec4 frustumCornersL[8];
glm::vec4 frustumCornersW[8];

float minX = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::min();
float minY = std::numeric_limits<float>::max();
float maxY = std::numeric_limits<float>::min();
float minZ = std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::min();

glm::vec4 center;

for (int j = 0; j < 8; j++) {
glm::vec4 vW = camInv * frustumCorners[j];

center += vW;

minX = std::fmin(minX, vW.x);
maxX = std::fmax(maxX, vW.x);
minY = std::fmin(minY, vW.y);
maxY = std::fmax(maxY, vW.y);
minZ = std::fmin(minZ, vW.z);
maxZ = std::fmax(maxZ, vW.z);
}

minAABB[i] = glm::vec3(minX, minY, minZ);
maxAABB[i] = glm::vec3(maxX, maxY, maxZ);

center /= 8;
viewMatrices[i] = glm::lookAt(glm::vec3(center) - light.direction * (splitPlanes[i].y - splitPlanes[i].x), glm::vec3(center), glm::vec3(0.f, 1.f, 0.f));
//viewMatrices[i] = glm::lookAt(glm::vec3(0.0f), light.direction, glm::vec3(0.0f, 1.0f, 0.0f));

minX = std::numeric_limits<float>::max();
maxX = std::numeric_limits<float>::min();
minY = std::numeric_limits<float>::max();
maxY = std::numeric_limits<float>::min();
minZ = std::numeric_limits<float>::max();
maxZ = std::numeric_limits<float>::min();

for (int j = 0; j < 8; j++)
{
glm::vec4 vW = camInv * frustumCorners[j];
frustumCornersL[j] = viewMatrices[i] * vW;

minX = std::fmin(minX, frustumCornersL[j].x);
maxX = std::fmax(maxX, frustumCornersL[j].x);
minY = std::fmin(minY, frustumCornersL[j].y);
maxY = std::fmax(maxY, frustumCornersL[j].y);
minZ = std::fmin(minZ, frustumCornersL[j].z);
maxZ = std::fmax(maxZ, frustumCornersL[j].z);
}
}

projectionMatrices[i] = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);
//viewMatrices[i] = glm::lookAt(glm::vec3(center) - light.direction * (splitPlanes[i].y - splitPlanes[i].x), glm::vec3(center), glm::vec3(0.f, 1.f, 0.f));
}
}
void CascadedShadowMap::calculateShadowMatrices(Camera * cam)
{

}

void CascadedShadowMap::initFramebuffer(int windowWidth, int windowHeight)
@@ -3,10 +3,14 @@
#include "ShaderProgram.h"
#include "Light.h"
#include "Camera.h"
#include "GearStructs.h"
#include "glm\gtx\string_cast.hpp"
#include <glm\gtc\matrix_transform.hpp>
#include <glm\gtx\transform.hpp>
class CascadedShadowMap
{
private:
const static int NUM_CASCADEDS = 4;
const static int NUM_CASCADEDS = 3;
GLuint textureIDs[NUM_CASCADEDS];
GLuint framebufferID;
GLuint renderBuffer;
@@ -30,12 +34,13 @@ class CascadedShadowMap
void unBind();
void bindTexture(ShaderProgram *shader, const char *name, GLuint textureLoc, GLuint textureid);
void calcOrthoProjs(Camera* mainCam);
void calculateShadowMatrices(Camera* cam);
int getNumCascades() { return this->NUM_CASCADEDS; }
glm::mat4 viewMatrices[NUM_CASCADEDS+1];
glm::mat4 projectionMatrices[NUM_CASCADEDS+1];
glm::mat4 cropMatrices[NUM_CASCADEDS];
glm::mat4 textureMatrices[NUM_CASCADEDS];
glm::vec3 frustumCorners[8];
glm::vec4 frustumCorners[8];

glm::vec3 pos;
float sinCount;
@@ -271,7 +271,6 @@ namespace Gear
queue.update(*transformCount, *allTrans);
map.calcOrthoProjs(camera);
Camera tempCamera;

glm::vec3 offset;
offset.x = camera->getDirection().x * 20.0f;
offset.y = 0.0f;
@@ -451,20 +450,16 @@ namespace Gear
gBuffer.BindTexturesToProgram(lightPassShader, "gAlbedoSpec", 0, 0); //binds textures
gBuffer.BindTexturesToProgram(lightPassShader, "gNormal", 1, 1);
gBuffer.BindTexturesToProgram(lightPassShader, "gDepth", 2, 2);
//shadowMap.BindTexturesToProgram(lightPassShader, "gShadowMap", 3, 0);
map.bindTexture(lightPassShader, "gShadowMap", 3, 0);


glUniform1fv(glGetUniformLocation(lightPassShader->getProgramID(), "farbounds"), 4, &map.farbound[0]);
glUniformMatrix4fv(glGetUniformLocation(lightPassShader->getProgramID(), "lightMatrixList"), 4, GL_FALSE, &map.cropMatrices[0][0][0]);

map.bindTexture(lightPassShader, "shadowmap1", 3, 0);
map.bindTexture(lightPassShader, "shadowmap2", 4, 1);
map.bindTexture(lightPassShader, "shadowmap3", 5, 2);
map.bindTexture(lightPassShader, "shadowmap4", 6, 3);


lightPassShader->addUniform(camera->getPosition(), "viewPos");
lightPassShader->addUniform(tempCam->getViewPers(), "shadowVPM");
lightPassShader->addUniform(map.projectionMatrices[0] * map.viewMatrices[0], "shadowVPM");
lightPassShader->addUniform(drawMode, "drawMode"); //sets the draw mode to show diffrent lights calculations and textures for debugging
lightPassShader->addUniform(glm::inverse(camera->getViewMatrix()), "invView");
lightPassShader->addUniform(glm::inverse(camera->getProjectionMatrix()), "invProj");
@@ -158,6 +158,7 @@
<ClInclude Include="Debug.h" />
<ClInclude Include="DebugHandler.h" />
<ClInclude Include="Gear.h" />
<ClInclude Include="GearStructs.h" />
<ClInclude Include="Inputs.h" />
<ClInclude Include="Model.h" />
<ClInclude Include="Light.h" />