1

我正在尝试按照 SIGGRAPH 2013 中的 Epic 注释来实现区域灯。它们为我已经实现并且正在工作的管状区域灯提供了一种方法。现在我也在尝试实现矩形区域灯,采用与管灯类似的方法。

考虑到管灯只是一个矩形灯,总是对着边缘有两个半球的阴影点,所以我修改了 Epic 给出的最具代表性的点的计算。

这是计算 MRP 计算的输入数据的方式:

vec3 R  = reflect(-viewDirection, normal);

vec3 P0 = LightPosition + LightLeft * -halfWidth;
vec3 P1 = LightPosition + LightLeft *  halfWidth;
vec3 L0 = P0 - worldPosition;
vec3 L1 = P1 - worldPosition;

vec3 LightVector = GetRectangularLightLForSpecular(L0, L1, R, halfHeight, LightUp);

这是我修改后的计算 MRP 的函数:

vec3 GetRectangularLightLForSpecular(vec3 L0, vec3 L1, vec3 R, float halfHeight, vec3 up)
{
    float distL0 = length(L0);
    float distL1 = length(L1);

    vec3 Ld = L1 - L0;
    float RdotL0 = dot(R, L0);
    float RdotLd = dot(R, Ld);
    float L0dotLd = dot(L0, Ld);
    float distLd = length(Ld);
    float t = (RdotL0 * RdotLd - L0dotLd) / (distLd * distLd - RdotLd * RdotLd);

    vec3 closestPoint = L0 + Ld * clamp(t, 0.0f, 1.0f);
    vec3 centerToRay = dot(closestPoint, R) * R - closestPoint;

    // This is where I made the change
    // This is the original line of code from Epic's notes: 
    // closestPoint = closestPoint + centerToRay * clamp(radius / length(centerToRay), 0.0f, 1.0f);
    // The following line is my version:
    closestPoint = closestPoint + centerToRay * halfHeight;

    return normalize(closestPoint);
}

正如您从这张图片中看到的那样,结果并不正确,因为平面 surgafe 上反射光的形状在每一端都有“帽子”。

在此处输入图像描述

4

0 回答 0