改善CSM分层
parent
3bf1444092
commit
ddff01d880
|
@ -43,7 +43,7 @@ public:
|
||||||
float Zoom;
|
float Zoom;
|
||||||
float Ratio;
|
float Ratio;
|
||||||
float NearPlane = 10.f;
|
float NearPlane = 10.f;
|
||||||
float FarPlane = 10000.f;
|
float FarPlane = 5000.f;
|
||||||
|
|
||||||
// constructor with vectors
|
// constructor with vectors
|
||||||
Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH);
|
Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH);
|
||||||
|
|
|
@ -2,136 +2,146 @@
|
||||||
#include <qDebug>
|
#include <qDebug>
|
||||||
|
|
||||||
Light::Light(Camera* camera)
|
Light::Light(Camera* camera)
|
||||||
: camera(camera)
|
: camera(camera)
|
||||||
, shadowCascadeLevels{ camera->FarPlane / 50.0f, camera->FarPlane / 25.0f, camera->FarPlane / 10.0f, camera->FarPlane / 2.0f }
|
//, shadowCascadeLevels{ camera->FarPlane / 25.0f, camera->FarPlane / 12.0f, camera->FarPlane / 6.0f, camera->FarPlane / 3.0f }
|
||||||
{
|
{
|
||||||
|
const float levelCount = 5;
|
||||||
|
const float lambda = 0.5;
|
||||||
|
for (int i = 1; i < levelCount; i++)
|
||||||
|
{
|
||||||
|
shadowCascadeLevels.push_back(
|
||||||
|
lambda * camera->NearPlane * pow(camera->FarPlane / camera->NearPlane, i / levelCount)
|
||||||
|
+ (1 - lambda) * (camera->NearPlane + i / levelCount * (camera->FarPlane - camera->NearPlane)));
|
||||||
|
//qDebug() << shadowCascadeLevels[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<QVector4D> Light::getFrustumCornersWorldSpace(const QMatrix4x4& projview)
|
std::vector<QVector4D> Light::getFrustumCornersWorldSpace(const QMatrix4x4& projview)
|
||||||
{
|
{
|
||||||
const auto inv = projview.inverted();
|
const auto inv = projview.inverted();
|
||||||
|
|
||||||
std::vector<QVector4D> frustumCorners;
|
std::vector<QVector4D> frustumCorners;
|
||||||
for (unsigned int x = 0; x < 2; ++x)
|
for (unsigned int x = 0; x < 2; ++x)
|
||||||
{
|
{
|
||||||
for (unsigned int y = 0; y < 2; ++y)
|
for (unsigned int y = 0; y < 2; ++y)
|
||||||
{
|
{
|
||||||
for (unsigned int z = 0; z < 2; ++z)
|
for (unsigned int z = 0; z < 2; ++z)
|
||||||
{
|
{
|
||||||
const QVector4D pt = inv * QVector4D(2.0f * x - 1.0f, 2.0f * y - 1.0f, 2.0f * z - 1.0f, 1.0f);
|
const QVector4D pt = inv * QVector4D(2.0f * x - 1.0f, 2.0f * y - 1.0f, 2.0f * z - 1.0f, 1.0f);
|
||||||
frustumCorners.push_back(pt / pt.w());
|
frustumCorners.push_back(pt / pt.w());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return frustumCorners;
|
return frustumCorners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<QVector4D> Light::getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view)
|
std::vector<QVector4D> Light::getFrustumCornersWorldSpace(const QMatrix4x4& proj, const QMatrix4x4& view)
|
||||||
{
|
{
|
||||||
return getFrustumCornersWorldSpace(proj * view);
|
return getFrustumCornersWorldSpace(proj * view);
|
||||||
}
|
}
|
||||||
|
|
||||||
QMatrix4x4 Light::getLightSpaceMatrix(const float nearPlane, const float farPlane)
|
QMatrix4x4 Light::getLightSpaceMatrix(const float nearPlane, const float farPlane)
|
||||||
{
|
{
|
||||||
QMatrix4x4 proj;
|
QMatrix4x4 proj;
|
||||||
proj.perspective(camera->Zoom, camera->Ratio, nearPlane, farPlane);
|
proj.perspective(camera->Zoom, camera->Ratio, nearPlane, farPlane);
|
||||||
|
|
||||||
const std::vector<QVector4D> corners = getFrustumCornersWorldSpace(proj, camera->GetViewMatrix());
|
const std::vector<QVector4D> corners = getFrustumCornersWorldSpace(proj, camera->GetViewMatrix());
|
||||||
|
|
||||||
QVector3D center = QVector3D(0, 0, 0);
|
QVector3D center = QVector3D(0, 0, 0);
|
||||||
for (const QVector4D& v : corners)
|
for (const QVector4D& v : corners)
|
||||||
{
|
{
|
||||||
center += QVector3D(v);
|
center += QVector3D(v);
|
||||||
}
|
}
|
||||||
center /= corners.size();
|
center /= corners.size();
|
||||||
|
|
||||||
|
|
||||||
QVector3D right = QVector3D::crossProduct(lightDirection, QVector3D(1, 0, 0)).normalized();
|
QVector3D right = QVector3D::crossProduct(lightDirection, QVector3D(1, 0, 0)).normalized();
|
||||||
QVector3D up = QVector3D::crossProduct(right, lightDirection).normalized();
|
QVector3D up = QVector3D::crossProduct(right, lightDirection).normalized();
|
||||||
QMatrix4x4 lightView;
|
QMatrix4x4 lightView;
|
||||||
//qDebug() << "lightDirection:" << lightDirection << "up:" << up;
|
//qDebug() << "lightDirection:" << lightDirection << "up:" << up;
|
||||||
lightView.lookAt(center, center - lightDirection, up);
|
lightView.lookAt(center, center - lightDirection, up);
|
||||||
|
|
||||||
float minX = std::numeric_limits<float>::max();
|
float minX = std::numeric_limits<float>::max();
|
||||||
float maxX = std::numeric_limits<float>::min();
|
float maxX = std::numeric_limits<float>::min();
|
||||||
float minY = std::numeric_limits<float>::max();
|
float minY = std::numeric_limits<float>::max();
|
||||||
float maxY = std::numeric_limits<float>::min();
|
float maxY = std::numeric_limits<float>::min();
|
||||||
float minZ = std::numeric_limits<float>::max();
|
float minZ = std::numeric_limits<float>::max();
|
||||||
float maxZ = std::numeric_limits<float>::min();
|
float maxZ = std::numeric_limits<float>::min();
|
||||||
for (const QVector4D& v : corners)
|
for (const QVector4D& v : corners)
|
||||||
{
|
{
|
||||||
QVector4D trf = lightView * v;
|
QVector4D trf = lightView * v;
|
||||||
//qDebug() << v;
|
//qDebug() << v;
|
||||||
//qDebug() << trf;
|
//qDebug() << trf;
|
||||||
minX = std::min(minX, trf.x());
|
minX = std::min(minX, trf.x());
|
||||||
maxX = std::max(maxX, trf.x());
|
maxX = std::max(maxX, trf.x());
|
||||||
minY = std::min(minY, trf.y());
|
minY = std::min(minY, trf.y());
|
||||||
maxY = std::max(maxY, trf.y());
|
maxY = std::max(maxY, trf.y());
|
||||||
minZ = std::min(minZ, -trf.z());
|
minZ = std::min(minZ, -trf.z());
|
||||||
maxZ = std::max(maxZ, -trf.z());
|
maxZ = std::max(maxZ, -trf.z());
|
||||||
}
|
}
|
||||||
for (const QVector3D& v : model->AABB)
|
for (const QVector3D& v : model->AABB)
|
||||||
{
|
{
|
||||||
const QVector4D trf = lightView * QVector4D(v, 1);
|
const QVector4D trf = lightView * QVector4D(v, 1);
|
||||||
//qDebug() << v;
|
//qDebug() << v;
|
||||||
//qDebug() << trf;
|
//qDebug() << trf;
|
||||||
//minX = std::min(minX, trf.x());
|
//minX = std::min(minX, trf.x());
|
||||||
//maxX = std::max(maxX, trf.x());
|
//maxX = std::max(maxX, trf.x());
|
||||||
//minY = std::min(minY, trf.y());
|
//minY = std::min(minY, trf.y());
|
||||||
//maxY = std::max(maxY, trf.y());
|
//maxY = std::max(maxY, trf.y());
|
||||||
minZ = std::min(minZ, -trf.z());
|
minZ = std::min(minZ, -trf.z());
|
||||||
//maxZ = std::max(maxZ, trf.z());
|
//maxZ = std::max(maxZ, trf.z());
|
||||||
|
|
||||||
}
|
}
|
||||||
//qDebug() << minZ;
|
//qDebug() << minZ;
|
||||||
// Tune this parameter according to the scene
|
// Tune this parameter according to the scene
|
||||||
/* constexpr float zMult = 10.0f;
|
/* constexpr float zMult = 10.0f;
|
||||||
if (minZ < 0)
|
if (minZ < 0)
|
||||||
{
|
{
|
||||||
minZ *= zMult;
|
minZ *= zMult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
minZ /= zMult;
|
minZ /= zMult;
|
||||||
}
|
}
|
||||||
if (maxZ < 0)
|
if (maxZ < 0)
|
||||||
{
|
{
|
||||||
maxZ /= zMult;
|
maxZ /= zMult;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
maxZ *= zMult;
|
maxZ *= zMult;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
QMatrix4x4 lightProjection;
|
QMatrix4x4 lightProjection;
|
||||||
//qDebug() << minX<< maxX<< minY<< maxY<< minZ<< maxZ;
|
//qDebug() << minX<< maxX<< minY<< maxY<< minZ<< maxZ;
|
||||||
lightProjection.ortho(minX, maxX, minY, maxY, minZ, maxZ);
|
lightProjection.ortho(minX, maxX, minY, maxY, minZ, maxZ);
|
||||||
frustumSizes.push_back(std::max(maxX - minX, maxY - minY));
|
frustumSizes.push_back(std::max(maxX - minX, maxY - minY));
|
||||||
return lightProjection * lightView;
|
return lightProjection * lightView;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<QMatrix4x4> Light::getLightSpaceMatrices()
|
std::vector<QMatrix4x4> Light::getLightSpaceMatrices()
|
||||||
{
|
{
|
||||||
std::vector<QMatrix4x4> ret;
|
std::vector<QMatrix4x4> ret;
|
||||||
frustumSizes.clear();
|
frustumSizes.clear();
|
||||||
for (size_t i = 0; i < shadowCascadeLevels.size() + 1; ++i)
|
for (size_t i = 0; i < shadowCascadeLevels.size() + 1; ++i)
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
ret.push_back(getLightSpaceMatrix(camera->NearPlane, shadowCascadeLevels[i]));
|
ret.push_back(getLightSpaceMatrix(camera->NearPlane, shadowCascadeLevels[i]));
|
||||||
}
|
}
|
||||||
else if (i < shadowCascadeLevels.size())
|
else if (i < shadowCascadeLevels.size())
|
||||||
{
|
{
|
||||||
ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], shadowCascadeLevels[i]));
|
ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], shadowCascadeLevels[i]));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], camera->FarPlane));
|
ret.push_back(getLightSpaceMatrix(shadowCascadeLevels[i - 1], camera->FarPlane));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,13 +84,13 @@ float Calculate_Avg_Dblockreceiver(vec2 projCoords , int AvgTextureSize)
|
||||||
return result/(AvgTextureSize*AvgTextureSize*2*2);
|
return result/(AvgTextureSize*AvgTextureSize*2*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal)
|
float ShadowCalculation(vec3 fragPosWorldSpace, vec3 normal, out int layer)
|
||||||
{
|
{
|
||||||
// select cascade layer
|
// select cascade layer
|
||||||
vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0);
|
vec4 fragPosViewSpace = view * vec4(fragPosWorldSpace, 1.0);
|
||||||
float depthValue = abs(fragPosViewSpace.z);
|
float depthValue = abs(fragPosViewSpace.z);
|
||||||
|
|
||||||
int layer = -1;
|
layer = -1;
|
||||||
for (int i = 0; i < shadowCascadeCount; ++i)
|
for (int i = 0; i < shadowCascadeCount; ++i)
|
||||||
{
|
{
|
||||||
if (depthValue < shadowCascadePlaneDistances[i])
|
if (depthValue < shadowCascadePlaneDistances[i])
|
||||||
|
@ -225,11 +225,14 @@ void main()
|
||||||
|
|
||||||
//vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0);
|
//vec4 FragPosLightSpace = lightSpaceMatrix * vec4(WorldPos, 1.0);
|
||||||
//float bias = 0.08 * max(0.05 * (1.0 - dot(N, L)), 0.005);
|
//float bias = 0.08 * max(0.05 * (1.0 - dot(N, L)), 0.005);
|
||||||
float shadow = ShadowCalculation(WorldPos, N);
|
int debugLayer;
|
||||||
|
float shadow = ShadowCalculation(WorldPos, N, debugLayer);
|
||||||
|
|
||||||
//vec3 color = ambient + Lo;
|
//vec3 color = ambient + Lo;
|
||||||
//vec3 color = indirect*1;
|
//vec3 color = indirect*1;
|
||||||
vec3 color = ambient + (1.0 - shadow) * Lo;
|
vec3 color = ambient + (1.0 - shadow) * Lo;
|
||||||
|
//color*=mix(mix(vec3(1,0,0), vec3(0,1,0), float(debugLayer)/shadowCascadeCount/0.5),
|
||||||
|
//mix(vec3(0,1,0), vec3(0,0,1), float(debugLayer)/(shadowCascadeCount)/0.5-1), float(debugLayer)/(shadowCascadeCount));
|
||||||
//vec3 color = (1.0 - shadow) * Lo;
|
//vec3 color = (1.0 - shadow) * Lo;
|
||||||
//vec3 color = (1.0 - shadow) * Lo + indirect*10;
|
//vec3 color = (1.0 - shadow) * Lo + indirect*10;
|
||||||
color = color / (color + vec3(1.0));
|
color = color / (color + vec3(1.0));
|
||||||
|
|
Loading…
Reference in New Issue