我试图在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轴上改变位置,光线也总是直接来自顶部。
当我使用光线位置的方向作为平面法线时,它似乎有效,但我很确定它仍然不正确。