简体   繁体   中英

How to determine the orientation of a geometry surface in Scenekit

I'm trying to write a shader to colorize a custom geometry in SceneKit. I want to set the colors so that horizontal surfaces that are facing up are white, horizontal surfaces that are facing downward are black, and all other surfaces in between are shades of gray based on their orientation. I used the material's surface entry point to call the following shader

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

It appears that the normal.z is relative to the camera (or view). I assume I need to transform the value, so that it's in another space. I tried multiple transforms (and combinations of transforms) such as u_inverseViewTransform , but the results all seem to be in view space. Does anyone know how to colorize a geometry based on the orientation of its surfaces?

Since _surface.normal is a vector in view space, you have to transform the vector to world space.

The transformation of a point form world space to view space is done by u_viewTransform , so the inverse operation (from view space to world space) can be done by u_inverseViewTransform .

_surface.normal is a direction vector, but not a point. A vector has to be transformed by the normal matrix, which is the transposed, inverse of the upper left 3*3 matrix of a 4*4 matrix:

transpose(inverse(mat3(u_viewTransform)))

See 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?

But since u_viewTransform and u_inverseViewTransform are Orthogonal matrices the transposed, inverse can be skipped, because the inverse matrix and the transposed matrix are equal. See In which cases is the inverse matrix equal to the transpose? .

This follows you have to transform by 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM