如何确定Scenekit中几何图形表面的方向

时间:2018-12-15 18:16:10

标签: ios glsl shader scenekit coordinate-transformation

我正在尝试编写一个着色器来为SceneKit中的自定义几何着色。我要设置颜色,以使面向上的水平表面为白色,面向下的水平表面为黑色,而介于两者之间的所有其他表面根据其方向都是灰色阴影。我使用了材质的表面入口点来调用以下着色器

vec4 normal = vec4(_surface.normal, 1.0);

// Assume value is [-1, 1], scale to [0, 1]
float color = normal.z * 0.5 + 0.5;

_surface.diffuse = vec4(color, color, color, 1.0);

看来normal.z是相对于相机(或视图)的。我假设我需要转换值,以便它在另一个空间中。我尝试了多个转换(以及转换的组合),例如u_inverseViewTransform,但是结果似乎都在视图空间中。有人知道如何根据几何图形的表面方向为其着色吗?

1 个答案:

答案 0 :(得分:4)

由于_surface.normal是视图空间中的向量,因此必须将向量转换为世界空间。

将点从世界空间转换为视图空间是由u_viewTransform完成的,因此逆操作(从视图空间到世界空间)可以由u_inverseViewTransform完成。

_surface.normal是方向矢量,但不是点。向量必须由法线矩阵转换,该法线矩阵是4 * 4矩阵左上3 * 3矩阵的逆矩阵:

transpose(inverse(mat3(u_viewTransform)))

请参见Why is the transposed inverse of the model view matrix used to transform the normal vectors?Why transforming normals with the transpose of the inverse of the modelview matrix?

但是由于u_viewTransformu_inverseViewTransformOrthogonal matrices的转置,因此可以跳过逆,因为逆矩阵和转置矩阵相等。参见In which cases is the inverse matrix equal to the transpose?

接下来,您必须按mat3(u_inverseViewTransform)进行转换:

vec3 normal = mat3(u_inverseViewTransform) * _surface.normal;

float color = normal.z * 0.5 + 0.5;

_surface.diffuse = vec4(color, color, color, 1.0);