Ánh xạ phương sai theo hàm mũ


7

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.


Có vẻ như bạn có một lỗi đánh máy ở đây: vec2 warpDepth = (pos, neg)- nên là vec2(pos, neg)
Nathan Reed

Cảm ơn, nhưng tôi đã ngay lập tức sửa lỗi đó vì tôi gặp lỗi trình biên dịch glsl. Một vấn đề nằm ở một nơi khác.
Irbis

Tôi sẽ rất vui khi thấy một ảnh chụp màn hình, Irbis!
danijar

Câu trả lời:


5

Ánh xạ bóng phương sai, đặt đơn giản, chỉ bị các vấn đề chảy máu nhẹ này.

Cá nhân tôi thích triển khai ESM (xem trang 257 của ShaderX6) vì áp lực bộ nhớ là một nửa của bản đồ VSM và các vật phẩm này ít bị mài mòn hơn đối với tôi: (Phần đầu của bóng quá sáng.)

Với điều này, đây là một bản PDF (khá cũ) với đầy đủ các kỹ thuật tuyệt vời để bạn suy nghĩ. (hoặc chỉ để hiển thị cho bạn thuật toán nếu bạn không có ShaderX6) http: //developer.doad.nvidia.com/presentations/2008/GDC/GDC08_SoftShadowMapping.pdf

Trong công cụ hiện tại của tôi, tôi có một phép lai cơ bản là ESM, nhưng sử dụng bản đồ bóng 2 phút (hoặc cao hơn) để tính toán phương sai và giảm các tạo phẩm ESM ở những nơi mà bộ lọc quá gần với máy thu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.