9. 顶点位置插值(实现渐变色)
# 顶点位置插值(实现渐变色)
这节课给大家讲解顶点位置插值position
,然后利用插值的顶点位置数据,逐片元操作,实现一个网格模型Mesh沿着y轴方向进行颜色渐变。
# 知识回顾:顶点颜色数据插值计算
上节课给大家讲解过,你通过着色器语言GLSL ES关键字varying声明一个变量vColor,然后main函数中执行vColor = color;
,就可以对顶点颜色数据color
进行插值计算,插值后vColor
的颜色数据量与片元数量一致,也就是说每一个片元都能对应一个顶点颜色插值数据vColor
// 顶点着色器代码
const vertexShader = `
// attribute vec3 color;//默认提供不用手写
varying vec3 vColor;// varying关键字声明一个变量表示顶点颜色插值后的结果
void main(){
vColor = color;// 顶点颜色数据进行插值计算
// 投影矩阵 * 模型视图矩阵 * 模型顶点坐标
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
// 片元着色器代码
const fragmentShader = `
varying vec3 vColor;// 顶点片元化后有多少个片元,顶点颜色插值后就有多少个颜色数据
void main() {
// gl_FragColor = vec4(0.0,1.0,1.0,1.0);
gl_FragColor = vec4(vColor,1.0);
}
`
# 顶点位置数据position
插值计算
不仅仅顶点颜色color数据可以通过顶点着色器插值计算,其实所有类型的顶点数据都可以,比如顶点位置数据position
。
你只需要记住一个规律,任何类型的顶点数据,插值计算后,都会生成和所有片元一一对应的新数据。
// 顶点着色器代码
const vertexShader = `
varying vec3 vPosition;//表示顶点插值后位置数据,与片元数量相同,一一对应
void main(){
vPosition = position;// 顶点位置坐标插值计算
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
# 使用positon
插值后数据vPosition
控制片元颜色
根据几何体顶点坐标控制Mesh的颜色,y坐标小于0部分,红色,其他部分绿色。
// 片元着色器代码
const fragmentShader = `
varying vec3 vPosition;//获取顶点着色器插值数据vPosition
void main() {
// 根据vPosition位置控制片元颜色
if(vPosition.y < 0.0){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}else{
gl_FragColor = vec4(0.0,0.0,1.0,1.0);
}
}
`
# 根据插值位置数据vPosition
设置渐变色
控制Mesh沿着y方向,从底部到顶部进行颜色渐变,底部是绿色,顶部是红色。
下面以Mesh的几何体为准,几何体是一个矩形平面PlaneGeometry
,底部顶点y坐标-25,顶部顶点y坐标25
const geometry = new THREE.PlaneGeometry(100, 50);
// 片元着色器代码
const fragmentShader = `
varying vec3 vPosition;
void main() {
float per = (vPosition.y + 25.0)/50.0;
// 几何体顶点y坐标25,颜色值:1 0 0(红色)
// 几何体顶点y坐标-25,颜色值:0 1 0(绿色)
gl_FragColor = vec4(per,1.0-per,0.0,1.0);
}
`
# positon
模型矩阵变换后插值
刚才说话所有类型顶点数据都可以插值,你也可以测试,把顶点数据先用模型矩阵modelMatrix进行变换,再插值计算。
这个时候vPosition
反应就不仅仅是几何体geometry顶点的位置了,也包含mesh自身的旋转、缩放、平移。
// 顶点着色器代码
const vertexShader = `
varying vec3 vPosition;
void main(){
// vPosition = position;
// 考虑mesh及其父对象旋转、缩放、平移的影响
vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
你可以把mesh向上平移mesh.position.y += 25;
。这时候你想想怎么写片元着色器代码,保证矩形平面底部绿色,顶部红色,然后进行渐变。
// 片元着色器代码
const fragmentShader = `
varying vec3 vPosition;
void main() {
float per = vPosition.y /50.0;
// Mesh y坐标50,颜色值:1 0 0(红色)
// Mesh y坐标0,颜色值:0 1 0(绿色)
gl_FragColor = vec4(per,1.0-per,0.0,1.0);
}
`