【发布时间】:2011-08-04 07:18:15
【问题描述】:
我的顶点法线有点问题。
结果似乎有点奇怪。先来看看图片:
3D 软件中的原始模型。
每片段光照,直接从 OBJ 文件导入网格(使用文件中的法线)。
Per-Fragment 光照,用我自己的例程计算法线。
你注意到了吗? 使用 OBJ 文件中的法线一切正常。但是,当我使用自己的例程根据顶点计算法线时,似乎出现了问题。
当 Z 变为负时(使用右手方向),法线看起来很奇怪。在对象的其他部分,一切正常,但只有一条穿过网格的假想线看起来很奇怪。这个问题在其他网格上仍然存在,总是在同一个地方,Z = 0。
我计算法线的例程是每个人都知道的,假设一个顶点为 ABC 的三角形:
vec3 normal = normalize(cross(C - A, B - A));
然后将正常结果添加到已经计算好的正常缓冲区中。
我见过一些人说要计算每个三角形的面积并将其乘以法线,甚至检查缓冲区法线和新法线之间的点积,但我已经尝试过这些方法并且我发现了一些小变化,但仍然遇到同样的问题。
你以前见过这个吗?你知道怎么解决吗?
这里有一些代码:
// Looping at each triangle
vec3 distBA = vec3Subtract(vB, vA);
vec3 distCA = vec3Subtract(vC, vA);
vec3 normal = vec3Cross(distBA, distCA);
// Each normalBuffer represents one vertex.
normalBuffer[i1] = vec3Add(normal, normalBuffer[i1]);
normalBuffer[i2] = vec3Add(normal, normalBuffer[i2]);
normalBuffer[i3] = vec3Add(normal, normalBuffer[i3]);
// After pass through all faces/triangles.
// Looping at each Vertex structure.
normal = vec3Normalize(normalBuffer[i]);
【问题讨论】:
-
鉴于错误似乎是每个像素而不是每个多边形,因此错误可能在着色器中,您能否也发布代码?
-
另外,我不确定我为什么要添加法线到普通缓冲区而不是仅仅设置它们?
-
两种情况下的着色器是相同的(来自 OBJ 的法线,由我计算)。使用来自 OBJ 的法线,一切正常,所以我认为问题不存在。缓冲区是对同一顶点但来自不同三角形的法线求和,就像三角形相邻。我真的不明白为什么会这样。
-
但问题可能出在代码的两个部分,例如着色器可能无法处理输入数据的某些问题(例如,非标准化法线,尽管我可以看到您确实在对它们进行标准化)。我要做的另一个测试是:只使用第一个计算的法线而不是添加 + 规范化,这样可以排除这部分代码的任何问题。
-
另一个要运行的测试:渲染一个三角形穿越
z=0线。这将清楚地显示问题的一部分是否在阴影中。另外:禁用镜面反射。一般来说,尽量简化测试用例,排除各种“干扰”。