Three.js网格材质都有一个map
属性,该属性用来设置网格模型的颜色贴图,渲染器系统会调用网格材质对应的着色器代码解析map属性的值进行渲染。本节课通过自定义着色器的纹理贴图代码来展示网格材质map
属性对应的着色器原理。
通过Three.js的球体、矩形平面、立方体等特定几何体构造函数创建一个几何体对象,构造函数会按照特定的算法生成顶点位置position、顶点法向量normal、顶点纹理坐标uv数据。
//球体
var geometry = new THREE.SphereBufferGeometry(60, 25, 25);
// 查看几何体的顶点数据
console.log(geometry.attributes);
// 顶点纹理坐标attributes.uv的itemSize属性值是2,意味着顶点纹理坐标是二维向量
// 查看几何体顶点纹理坐标数据uv
console.log(geometry.attributes.uv);
在ShaderMaterial
中设置一个属性来表示纹理贴图,对应着色器中texture变量。
uniforms: {
// texture对应顶点着色器中uniform声明的texture变量
texture: {
// 加载纹理贴图返回Texture对象作为texture的值
// Texture对象对应着色器中sampler2D数据类型变量
value: new THREE.TextureLoader().load('./Earth.png')
},
},
编写着色器代码从纹理贴图上采集像素值然后赋值给片元。
使用ShaderMaterial API的时候顶点纹理坐标变量uv和顶点位置变量position一样不需要手动声明,系统会自动声明attribute vec2 uv;
// varying关键字声明一个变量表示顶点纹理坐标插值后的结果
varying vec2 vUv;
void main(){
// 顶点纹理坐标uv数据进行插值计算
vUv = uv;
// 投影矩阵projectionMatrix、视图矩阵viewMatrix、模型矩阵modelMatrix
gl_Position = projectionMatrix*viewMatrix*modelMatrix*vec4( position, 1.0 );
}
uniform关键字声明一个数据类型为sampler2D的变量texture,对应uniforms中texture的值。
// 声明一个纹理对象变量
uniform sampler2D texture;
// 顶点片元化后有多少个片元就有多少个纹理坐标数据vUv
varying vec2 vUv;
void main() {
//内置函数texture2D通过纹理坐标vUv获得贴图texture的像素值
gl_FragColor = texture2D( texture, vUv );
}
// 声明一个纹理对象变量
uniform sampler2D texture;
// 顶点片元化后有多少个片元就有多少个纹理坐标数据vUv
varying vec2 vUv;
void main() {
//内置函数texture2D通过纹理坐标vUv获得贴图texture的像素值
vec4 tColor = texture2D( texture, vUv );
//计算RGB三个分量光能量之和,也就是亮度
float luminance = 0.299*tColor.r+0.587*tColor.g+0.114*tColor.b;
//逐片元赋值,RGB相同均为亮度值,用黑白两色表达图片的明暗变化
gl_FragColor = vec4(luminance,luminance,luminance,1);
}