GPU Pro 5区域灯

时间:2014-08-24 10:20:22

标签: opengl graphics 3d glsl

我试图在GLSL中实现GPU Pro 5中描述的区域灯光,但我在预测方面遇到了一些麻烦。

这是我目前用于漫射闪电的着色器代码:

vec3 linePlaneIntersection
    (
    vec3 linePoint, vec3 lineNormal, 
    vec3 planeCenter, vec3 planeNormal
    )
{
    float t = (dot(planeNormal, planeCenter - linePoint) / dot(planeNormal, lineNormal));
    return linePoint + lineNormal * t;
}

vec3 projectOnPlane(vec3 point, vec3 planeCenter, vec3 planeNormal)
{
    float distance = dot(planeNormal, point - planeCenter);

    return point - distance * planeNormal;
}

vec3 diffuse_color(vec3 p, vec3 surfaceDiffuseColor, vec3 n)
{
    // for point p with normal n

    vec3 directionToLight = normalize(light.position.xyz - p);
    vec3 planeNormal = directionToLight;
    planeNormal = light.orientation.xyz;

    // intersect a ray from p in direction nII with light plane, 
    // creating point pI

    vec3 nII = n;

    if(dot(n, light.orientation.xyz) > 0.0)
    {
        // light plane points away from n, skew in direction of light plane
        nII = -light.orientation.xyz;
    }

    vec3 pI = linePlaneIntersection(p, nII, light.position.xyz, planeNormal);

    // project point p on the light plane, creating point pII
    vec3 pII = projectOnPlane(p, light.position.xyz, planeNormal);

    // create halfway vector h between ppI and ppII
    vec3 ppI = pI - p;
    vec3 ppII = pII - p;
    vec3 h = normalize(ppI + ppII);

    // intersect ray from p in direction h with the light plane,
    // creating point pd
    vec3 pd = linePlaneIntersection(p, h, light.position.xyz, planeNormal);

    // treat vector ppd as light vector for diffuse equation
    vec3 ppd = normalize(pd - p);

    // distance from point p to point pI on dArea
    float r = distance(p, pI);

    // angle between light vector ppd and surface normal n
    float cosP = clamp(dot(ppd, n), 0.0, 1.0);
    // angle between surface normal and light plane orientation normal
    float cosO = clamp(dot(n, -light.orientation.xyz), 0.0, 1.0);

    float dArea = light.dAreaRadiance.x;
    float radiance = light.dAreaRadiance.y;

    return radiance * surfaceDiffuseColor * cosP * cosO * dArea / (r * r);
}

灯光的位置为{0,100,0},方向为{0,-1,0}。

如果我使用光线方向作为投影的平面法线,即使我在x轴上改变位置,光线也总是直接来自顶部。

当我使用光线位置的方向作为平面法线时,它似乎有效,但我很确定它仍然不正确。

0 个答案:

没有答案