改善CSM分层

dev-VirtualTexture
wuyize 2022-08-24 13:30:09 +08:00
parent 3bf1444092
commit ddff01d880
3 changed files with 120 additions and 107 deletions

View File

@ -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);

View File

@ -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;
} }

View File

@ -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));