如何在THREE.js中使用GLSL实现MeshNormalMaterial?

3

我想实现一个像MeshNormalMaterial这样的着色器,但是我不知道如何将法线转换为颜色。

在THREE.js中:

enter image description here

我的测试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);
}

The result is really bad

我的测试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);
}

This is better than above.

这只是测试,我找不到任何关于如何计算颜色的资源...
有人可以帮帮我吗?
谢谢。
1个回答

8
如果您想在视图空间中查看法线向量,则必须将法线向量从模型空间转换为世界空间,然后从世界空间转换到视图空间。这可以通过使用normalMatrix一步完成对法线向量的变换。
varying vec3 vNormal;

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

由于变量在从顶点着色器传递到片元着色器时会根据其重心坐标进行插值,因此颜色的转换应在片元着色器中完成。请注意,在插值后,法向量必须再次归一化。

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值,则具有相同大小的正负值具有相同的颜色表示。颜色的强度随着值的梯度增加而增加。

enter image description here

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

enter image description here

通常情况下,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);
}

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接