因此,检查“lenght(fragment - sphereCenter) <= sphereRadius”在这里并不真正意味着什么,因为片段不在球体上。
所以呢?
灯光的标准延迟着色解决方案是渲染全屏四边形。相反,渲染球体的目的是避免对光源效果之外的片段进行大量的每片段计算。这意味着该球体的中心是光源,其半径表示光源产生影响的最大距离。
因此,从片段(即从您的 g 缓冲区数据重建,而不是由立方体产生的片段)到球体中心的长度非常相关。这是片段和光源之间的长度。如果它大于球体半径(AKA:光的最大范围),那么您可以剔除片段。
或者你可以让你的光衰减计算做同样的工作。毕竟,为了使灯光看起来不像被裁剪,该球体半径还必须与某种形式的光衰减一起使用。也就是说,当片段处于该距离时,光的衰减必须为 0 或小到可以忽略不计。
因此......无论您渲染的是球体、立方体还是全屏四边形都没有关系。您可以剔除片段或让光衰减完成其工作。
但是,如果您想通过在读取任何 g 缓冲区之前丢弃片段来节省性能,您可以这样做。假设您可以访问 FS 中球体/立方体中心的相机空间位置:
将立方体片段的位置转换为相机空间。您可以通过 reverse-transforming 来做到这一点gl_FragCoord
,但将相机空间位置传递给片段着色器可能会更快。这不像你的VS正在做很多工作或任何事情。
因为相机空间位置在相机空间中,它已经代表了从相机到场景的方向。所以现在,使用这个方向来执行部分射线/球体相交。也就是说,一旦计算出判别式,就停止(以避免昂贵的平方根)。判别式是:
float A = dot(cam_position, cam_position);
float B = -2 * (dot(cam_position, cam_sphere_center);
float C = (dot(cam_sphere_center, cam_sphere_center)) - (radius * radius)
float Discriminant = (B * B) - 4 * A * C;
如果判别式是否定的,则丢弃该片段。否则,做你平常的事情。