5. 顶点位置插值(设置片元颜色)2
# 顶点位置插值(设置片元颜色)2
接着2.4小节讲解,你可以尝试改变上节课模型mesh的y坐标或者进行旋转,看看光带的变化。
// 分别测试下面的不同值
mesh.position.y = 0;
mesh.position.y = 25;
mesh.position.y = 50;
mesh.rotateZ(Math.PI / 6);
模型位置改变的时候,光带对应的片元相对世界坐标系高度始终是20左右,不过如果以自身底部为参照点,光带高度位置是变化的。
if(vPosition.y > 20.0 && vPosition.y < 21.0 ){
gl_FragColor = vec4(1.0,1.0,0.0,1.0);
}
因为顶点插值计算时候,使用模型矩阵modelMatrix
进行了变换,模型矩阵包含了模型的旋转缩放平移信息。
shader.vertexShader = shader.vertexShader.replace(
'void main() {',
`
varying vec3 vPosition;
void main(){
vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
`
);
# 不使用模型矩阵进行变换
去掉模型矩阵对顶点坐标的影响,只根据几何体的顶点坐标来设置模型Mesh的片元的颜色。
不考虑mesh的旋转缩放平移,仅仅根据mesh.geometry顶点
位置插值坐标设置片元颜色。
void main(){
// vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
// 顶点位置坐标插值计算
vPosition = position;//不考虑模型旋转缩放平移变换(modelMatrix)
}
这时候如果你想实现和上节课相似效果,精确控制光带相对模型自身的位置,就需要根据Geometry顶点分布特点设置代码。
# 知识回顾:局部坐标系查看顶点位置
你可以把辅助坐标轴AxesHelper
作为mesh
的子对象,就可以查看mesh
的局部坐标系。
通过mesh的局部坐标系,方便你查看mesh
对应几何体mesh.geometry
顶点位置分布状态。
// 查看模型局部坐标系:判断几何体顶点坐标分布情况
const axesHelper = new THREE.AxesHelper(100);
mesh.add(axesHelper);
你可以浏览器控制台查看几何体顶点位置坐标
const geometry = new THREE.BoxGeometry(40, 100, 40);
console.log('顶点位置', geometry.attributes.position);
# 知识回顾:改变局部坐标系
你可以再次改变mesh位置,局部坐标系相对世界坐标原点偏移,但是相对自身几何体mesh.geometry
位置不变,也就是几何体的顶点坐标不受影响。
mesh.position.x = 100;
几何体平移,改变几何体顶点坐标,这时候局部坐标系原点相对geometry
位置发生变化。
geometry.translate(0,50,0);
console.log('顶点位置', geometry.attributes.position);
扩展:blender等建模软件中,建模的时候,也可以根据需要调整局部坐标系相对自身顶点坐标的位置。
# 根据顶点坐标设置片元颜色
position直接插值,不用modelMatrix变换,通过下面代码,在几何体高度y = 30.0
位置设置光带。
// 片元着色器代码
void main(){
if(vPosition.y > 30.0 && vPosition.y < 31.0 ){
gl_FragColor = vec4(1.0,1.0,0.0,1.0);
}
}
// 顶点着色器代码
void main(){
// vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
// 顶点位置坐标插值计算
vPosition = position;//不考虑模型旋转缩放平移变换(modelMatrix)
}
在这种情况下,你再平移旋转缩放mesh,你会发现光带位置始终在mesh局部坐标系的高度y=30位置。
mesh.position.y = 50;
mesh.rotateZ(Math.PI / 6);
你可以在渲染循环中,设置一个旋转动画,查看vPosition = position
与vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
区别
function render() {
model.rotateZ(0.01)
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
# 顶点位置插值计算总结
插值后获取,可以或获取每个片元对应的局部坐标
void main(){
// 布局坐标
vPosition = position;//只考虑几何体的顶点位置xyz
}
插值后获取,可以或获取每个片元对应的世界坐标
void main(){
// 世界坐标
vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
}
# 外部三维模型
提醒:三维建模软件,比如blender与threejs交互的时候,要注意blender中模型局部坐标系的设置对代码的影响。
如果美术给你一个三维模型,你可以用辅助坐标系AxesHelper
可视化查看顶点位置坐标分布。
如果你用vPosition = position
进行插值计算,来控制片元颜色,要注意局部坐标系坐标原点的设置。一般选择一个特殊的位置,没有固定要求,只要方便你写代码就行了。比如课程案例,是一个光带环绕长方体四周,这时候最好让局部坐标系的随便某个轴,沿着立方体高度方向,坐标原点与底部或中心重合。
loader.load("../外部模型.glb", function (gltf) {
model.add(gltf.scene);
const mesh = model.getObjectByName('长方体');
// 查看模型局部坐标系:判断几何体顶点坐标分布情况
const axesHelper = new THREE.AxesHelper(200);
mesh.add(axesHelper);
})