镜面高光取决于相机距离

时间:2014-01-23 22:02:46

标签: opengl glsl lighting specular phong

我刚尝试实现镜面高光。问题是,当远离表面移动时,高光变得越来越强烈,高光的边缘变得非常刺眼。当移动太靠近表面时,高光完全消失。

这是我的片段着色器的相关部分。所有计算都在视图空间中。我使用定向太阳光。

// samplers
vec3  normal    = texture2D(normals,   coord).xyz;
vec3  position  = texture2D(positions, coord).xyz;
float shininess = texture2D(speculars, coord).x;

// normalize directional light source
vec3 source;
if(directional) source = position + normalize(light);
else source = light;

// reflection
float specular = 0;
vec3 lookat = vec3(0, 0, 1);
float reflection = max(0, dot(reflect(position, normal), lookat));
int power = 5;
specular = shininess * pow(reflection, power);

// ...

// output
image = color * attenuation * intensity * (fraction + specular);

这是我的灯光缓冲区的截图。你可以看到,最重要的镜筒根本没有镜面高光,而远处的镜筒则闪耀得太强烈。中间的桶根据需要点亮。

far highlights are too strong and near highlights disappear

我做错了什么?

2 个答案:

答案 0 :(得分:2)

您正在从物体位置计算反射矢量,而不是使用反转的光线方向(从物体指向光源)。

这就像在图中使用V代替L:

另外,我认为光泽应该是你的表达的指数,而不是线性增加镜面贡献的东西。

答案 1 :(得分:1)

我认为变量命名让你很困惑。 从我正在阅读的内容(假设你处于相机空间而没有习惯性知识)

vec3 lookat = vec3(0, 0, 1);
float reflection = max(0, dot(reflect(position, normal), lookat));

lookat是定向灯,position是实际的lookat

确保normal(它可能已经规范化)并positionlookat)已标准化。

一个不太混乱的代码是:

vec3 light_direction = vec3(0, 0, 1);
vec3 lookat = normalize(position-vec3(0,0,0));
float reflection = max(0, dot(reflect(light_direction, normal), -lookat));

如果不对position进行规范化,则reflection会有偏差。当position远离相机vec3(0,0,0)

时,偏差会很大

注意lookat不是常数;它会改变每个位置。 lookat = vec3(0,0,1)正在查看视图空间中的单个位置。