如何通过 GLSL 在 THREE.js 中实现 MeshNormalMaterial?

How to implement MeshNormalMaterial in THREE.js by GLSL?

我想实现类似 MeshNormalMaterial 的着色器,但我不知道如何将法线转换为颜色。

在THREE.js中:

我的测试1:

varying vec3 vNormal;

void main(void) {
    vNormal = abs(normal);
    gl_Position = matrix_viewProjection * matrix_model * vec4(position, 1.0);
}

varying vec3 vNormal;

void main(void) {
    gl_FragColor = vec4(vNormal, 1.0);
}

我的测试2:

varying vec3 vNormal;

void main(void) {
    vNormal = normalize(normal) * 0.5 + 0.5;
    gl_Position = matrix_viewProjection * matrix_model * vec4(position, 1.0);
}

varying vec3 vNormal;

void main(void) {
    gl_FragColor = vec4(vNormal, 1.0);
}

这些只是测试,我找不到任何关于如何计算颜色的资源...

谁能帮帮我?

谢谢。

如果您想在视图 space 中看到法向量,您必须将法向量从模型 space 转换到世界 space 并从世界 space 到视图 space。这可以通过使用 normalMatrix.

变换法向量一步完成
varying vec3 vNormal;

void main(void)
{
    vNormal      = normalMatrix * normalize(normal); 
    gl_Position  = matrix_viewProjection * matrix_model * vec4(position, 1.0);
}

由于一个可变变量在从顶点着色器传递到片段着色器时被插值,根据它的Barycentric coordinates,颜色的转换应该在片段着色器中完成。注意,插值后法向量必须再次归一化

varying vec3 vNormal;

void main(void)
{
    vec3 view_nv  = normalize(vNormal);
    vec3 nv_color = view_nv * 0.5 + 0.5; 
    gl_FragColor  = vec4(nv_color, 1.0);
}

由于法向量被归一化,其分量在[-1.0, 1.0]范围内。如何将其表示为颜色由您决定。
如果使用 abs 值,则具有相同大小的正值和负值具有相同的颜色表示。颜色的强度随着值的渐变而增加。

使用公式 normal * 0.5 + 0.5 强度从 0 增加到 1。

通常x分量代表红色,y分量代表绿色,z分量代表蓝色。

颜色可以饱和,除以其分量的最大值:

varying vec3 vNormal;

void main(void)
{
    vec3 view_nv  = normalize(vNormal);
    vec3 nv_color = abs(view_nv); 
    nv_color     /= max(nv_color.x, max(nv_color.y, nv_color.z));
    gl_FragColor  = vec4(nv_color, 1.0);
}