如何使用顶点着色器根据高度为陡峭的平面着色?

问题描述 投票:0回答:1

我使用 Mesh、PlaneGeometry 和 ShaderMaterial 在三个 js 中制作了一个平面。这是一个非常简单/基本的形式。我应用了一个简单的 phormula 来使平原更加陡峭。现在我正在尝试使用顶点着色器根据地形的高度对地形进行着色。例如,顶部可以是颜色 1,中间颜色 2 等等......

这是我尝试过的:

顶点着色器:

varying vec3 vColor;

void main(void) {
    float uAmp = 20.0;

    float z = uAmp * sin(position.x*0.7) * cos(position.y*0.7);

    gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0);

    if (gl_Position.z <= 2.0*uAmp/3.0) {
        vColor = vec3(1.0, 0.0, 0.0);
    }
    else if (gl_Position.z <= 2.0*uAmp*(2.0/3.0)) {
        vColor = vec3(0.0, 1.0, 0.0); //this goes to fragment shader
    }
    else {
        vColor = vec3(0.0, 0.0, 1.0); //this goes to fragment shader
    }
}

片段着色器:

precision mediump float;

        varying vec3 vColor;
        
        void main(void) {   
            gl_FragColor = vec4(vColor, 1.0);
            }

这不会产生预期的结果。相反,该对象几乎是全蓝色的:

three.js graphics glsl shader webgl
1个回答
0
投票

你想做的应该在片段着色器中完成。顶点着色器只运行角顶点(你的线网的角)。片段着色器是“绘制”面部的东西。片段着色器在角顶点之间插入 z 值,因此每个像素都有唯一的 z 值。如果你在顶点着色器中这样做,你只会得到角点值,而不会得到中间的 z 值。

varying vec4 v_pos;

void main(void) {

    float z = uAmp * sin(position.x*0.7) * cos(position.y*0.7);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0);
    // pass to fragment shader
    v_pos = projectionMatrix * modelViewMatrix * vec4(position.x, position.y, z, 1.0);
}
precision mediump float;
varying vec3 v_pos;
        
void main(void) {  
    vec3 vColor = vec3(0.0, 0.0, 0.0);

    float uAmp = 20.0;
    if (v_pos.z <= 2.0*uAmp/3.0) {
        vColor = vec3(1.0, 0.0, 0.0);
    }
    else if (v_pos.z <= 2.0*uAmp*(2.0/3.0)) {
        vColor = vec3(0.0, 1.0, 0.0);
    }
    else {
        vColor = vec3(0.0, 0.0, 1.0);
    } 
    gl_FragColor = vec4(vColor, 1.0);
}

此页面上的动画很好地展示了绘画是如何发生的,以及片段着色器如何对角顶点进行插值以填充三角形:https://webglfundamentals.org/webgl/lessons/webgl-how-it- works.html

© www.soinside.com 2019 - 2024. All rights reserved.