Tôi sử dụng ánh xạ bóng phương sai với sửa lỗi chảy máu ánh sáng "tiêu chuẩn" trong công cụ đồ họa của mình dựa trên kết xuất bị trì hoãn .. Tôi có một bản đồ bóng duy nhất cho ánh sáng định hướng trong bối cảnh thử nghiệm tương đối nhỏ. Tiết kiệm độ sâu trông như thế này:
float moment1 = gl_FragCoord.z;
float moment2 = moment1 * moment1;
outColor = vec2(moment1, moment2);
Sau đó, tôi thực hiện một gaussian mờ có thể tách rời trên kết cấu đó.
Kiểm tra bóng:
float Chebyshev(vec2 moments, float mean, float minVariance)
{
float shadow = 1.0f;
if(mean <= moments.x)
{
shadow = 1.0f;
return shadow;
}
else
{
float variance = moments.y - (moments.x * moments.x);
variance = max(variance, minVariance);
float d = mean - moments.x;
shadow = variance / (variance + (d * d));
float amount = 0.3f;
shadow = clamp((shadow - amount) / (1.0f - amount), 0.0f, 1.0f); // standard light bleeding fix
return shadow;
}
}
vec4 shadowCoord = shadowMatrix * vec4(viewSpacePosition, 1.0f);
vec2 moments = texture(ShadowMap, shadowCoord.xy).xy;
float minVariance = 0.000001f;
float shadow = Chebyshev(moments, shadowCoord.z, minVariance);
Tôi tìm thấy một kỹ thuật thú vị - Bản đồ bóng phương sai theo hàm mũ sẽ giúp khắc phục chảy máu nhẹ tốt hơn. Đây là tiết kiệm độ sâu cho kỹ thuật đó:
float positiveExponent = 40.0f;
float negativeExponent = 5.0f
float depth = gl_FragCoord.z;
vec2 exponents = vec2(positiveExponent, negativeExponent);
depth = 2.0f * depth - 1.0f;
float pos = exp(exponents.x * depth);
float neg = -exp(-exponents.y * depth);
vec2 warpDepth = (pos, neg);
outColor = vec4(warpDepth, warpDepth * warpDepth);
Làm thế nào để thực hiện một bài kiểm tra bóng cho kỹ thuật đó? Đây là nỗ lực của tôi:
float positiveExponent = 40.0f;
float negativeExponent = 5.0f;
vec2 exponents = vec2(positiveExponent, negativeExponent);
vec2 warpDepth(float depth)
{
depth = 2.0f * depth - 1.0f;
float pos = exp(exponents.x * depth);
float neg = -exp(-exponents.y * depth);
vec2 wDepth = vec2(pos, neg);
return wDepth;
}
float Chebyshev(vec2 moments, float mean, float minVariance)
{
float shadow = 1.0f;
if(mean <= moments.x)
{
shadow = 1.0f;
return shadow;
}
else
{
float variance = moments.y - (moments.x * moments.x);
variance = max(variance, minVariance);
float d = mean - moments.x;
shadow = variance / (variance + (d * d));
return shadow;
}
}
vec4 shadowCoord = shadowMatrix * vec4(viewSpacePosition, 1.0f);
vec4 moments = texture(ShadowMap, shadowCoord.xy).xyzw;
vec2 posMoments = vec2(moments.x, moments.z);
vec2 negMoments = vec2(moments.y, moments.w);
vec2 wDepth = warpDepth(shadowCoord.z);
//float minVariance = 0.000001f;
//Edit
vec2 depthScale = 0.0001f * exponents * wDepth;
vec2 minVariance = depthScale * depthScale;
float posResult = Chebyshev(posMoments, wDepth.x, minVariance.x);
float negResult = Chebyshev(negMoments, wDepth.y, minVariance.y);
shadow = min(posResult, negResult);
Thật không may, nó không loại bỏ chảy máu nhẹ. Tôi đã làm gì sai sao ? Có lẽ tôi nên tính hai phương sai khác nhau dựa trên số mũ dương và âm?
Chỉnh sửa1 : Tính toán phương sai theo cách này:
vec2 depthScale = 0.0001f * exponents * wDepth;
vec2 minVariance = depthScale * depthScale;
float posResult = Chebyshev(posMoments, wDepth.x, minVariance.x);
float negResult = Chebyshev(negMoments, wDepth.y, minVariance.y);
cho kết quả tốt hơn nhưng chảy máu nhẹ vẫn khá rõ.
Edit2: Chảy máu nhẹ: EVSM với minVariance được tính toán như trên cho kết quả tốt hơn VSM mà không cần sửa chữa chảy máu nhẹ tiêu chuẩn, nhưng để có kết quả tốt nhất tôi cũng sử dụng sửa chữa chảy máu nhẹ tiêu chuẩn với EVSM. Một sửa chữa chảy máu nhẹ được thực hiện trong chức năng Ch Quashev nhưng có lẽ tôi nên thêm nó sau khi tính toán sau: Shadow = min (posResult, negResult)?
EVSM gây ra các tạo tác nhỏ ở phía được chiếu sáng của các đối tượng, vì vậy tôi thêm một số glPolygon Offerset khi lưu độ sâu EVSM.
vec2 warpDepth = (pos, neg)
- nên làvec2(pos, neg
)