0

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

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

// 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);

这是我的照明缓冲区的屏幕截图。你可以看到最前面的桶根本没有镜面高光,而远处的桶则过于强烈。中间的枪管根据需要点亮。

远高光太强,近高光消失

我究竟做错了什么?

4

2 回答 2

2

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

这就像在此图中使用 V 而不是 L:

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

于 2014-01-23T22:47:54.593 回答
1

我认为变量命名会让你感到困惑。根据我正在阅读的内容(假设您在相机空间并且没有惯用手知识)

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

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

确保normal(它可能已经标准化) 和position(the lookat) 已标准化。

一个不太容易混淆的代码是:

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));

没有规范化positionreflection就会有偏差。position当远离相机时,偏差会很大vec3(0,0,0)

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

于 2014-01-24T19:14:32.490 回答