我使用 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);
}
你想做的应该在片段着色器中完成。顶点着色器只运行角顶点(你的线网的角)。片段着色器是“绘制”面部的东西。片段着色器在角顶点之间插入 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