【发布时间】:2019-09-07 19:34:51
【问题描述】:
已经生成了一个测地线球体,并且正在使用 perlin 噪声来生成山丘等。将研究使用镶嵌着色器来进一步划分。但是,我使用的是法线贴图,为此我在以下代码中生成切线和双切线:
//Calulate the tangents
deltaPos1 = v1 - v0;
deltaPos2 = v2 - v0;
deltaUV1 = t1 - t0;
deltaUV2 = t2 - t0;
float r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
tangent = (deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r;
bitangent = (deltaPos2 * deltaUV1.x - deltaPos1 * deltaUV2.x) * r;
在我使用高度映射之前,球体上的法线很简单。
normal = normalize(point-origin);
但显然,一旦涉及高度图,情况就会大不相同。我目前正在穿越着色器中的切线和副切线以找出法线,但这会产生一些奇怪的结果
mat3 normalMat = transpose(inverse(mat3(transform)));
//vec3 T = normalize(vec3(transform*tangent));
vec3 T = normalize(vec3(normalMat * tangent.xyz));
vec3 B = normalize(vec3(normalMat * bitangent.xyz));
vec3 N = normalize(cross(T, B));
//old normal line here
//vec3 N = normalize(vec3(normalMat * vec4(normal, 0.0).xyz));
TBN = mat3(T, B, N);
outputVertex.TBN = TBN;
然而,这会产生如下所示的结果:
我做错了什么?
谢谢
编辑-
已恢复为不进行任何高度映射。这只是将地球投影到测地线球体上,带有镜面反射和法线贴图。你可以看到我在所有三角形上都得到了奇怪的照明,尤其是在光线角度更陡峭的地方(所以瓷砖自然会更暗)。我应该注意,我现在根本没有索引三角形,我在某处读到我的切线和双切线应该是所有相似点的平均值,不太了解这将实现什么或如何做到这一点。这是我需要调查的事情吗?
对于这个例子,我也恢复使用原始法线normalize(point-origin),这意味着我的 TBN 矩阵计算看起来像
mat3 normalMat = transpose(inverse(mat3(transform)));
vec3 T = normalize(vec3(transform * tangent));
vec3 B = normalize(vec3(transform * bitangent));
vec3 N = normalize(vec3(normalMat * vec4(normal, 0.0).xyz));
TBN = mat3(T, B, N);
outputVertex.TBN = TBN;
立方体只是我的“玩家”,我用它来帮助照明等并查看相机的位置。另请注意,完全删除法线贴图并仅使用输入法线可修复照明。
谢谢大家。
【问题讨论】:
-
@WillHain 了解Gram–Schmidt process
-
你为什么不直接跨越
deltaPos1和deltaPos2呢?根据定义,它们应该跨越与切线相同的子空间。 -
@DavisHerring 会给出正确的法线吗?谢谢
-
一些事情:1)您计算的切线和双切线对于线性地图是正确的(例如在三角形内)。您如何使用它来导出每个顶点向量? 2)对于法线映射,除非您的参数化是正交的,否则您不需要正交切线框架。所以不要正交化。 3)您不应该使用反转置来转换切线和双切线,而只需使用
transform--- 最后,这些都不是它应该如此剧烈地中断的真正原因。尝试可视化这些向量,看看发生了什么。 -
啊,4)从切线和双切线计算法线是完全有效的。