10. 颜色贴图map(顶点UV坐标)
# 颜色贴图map(顶点UV坐标)
通过基础课程的学习,大家对网格材质的颜色贴图属性.map
,肯定不陌生。
const texture = new THREE.TextureLoader().load('./Earth.png');
const material = new THREE.MeshBasicMaterial({
map: texture,
});
本节课任务就是用shader材质ShaderMaterial
替换网格材质MeshBasicMaterial
材质,用着色器GLSL ES代码实现一个颜色贴图.map
的功能。
本节课演示的代码如下:
const vertexShader = `
varying vec2 vUv;
void main(){
vUv = uv;// UV坐标插值计算
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
const fragmentShader = `
uniform sampler2D map;//颜色贴图变量
varying vec2 vUv;
void main() {
// 通过几何体的UV坐标从颜色贴图获取像素值
gl_FragColor = texture2D( map, vUv );
}
`
# 知识回顾:顶点UV坐标
学习本节课课程之前,先确保你对顶点UV坐标有一定的概念,具体知识可以参考前面课程参考前面课程5.2.自定义UV坐标 (opens new window)。
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([
0, 0, 0, //顶点1坐标
160, 0, 0, //顶点2坐标
160, 80, 0, //顶点3坐标
0, 80, 0, //顶点4坐标
]);
geometry.attributes.position = new THREE.BufferAttribute(vertices, 3);;
const indexes = new Uint16Array([
0, 1, 2, 0, 2, 3,// 矩形两个三角形对应顶点位置索引值
])
geometry.index = new THREE.BufferAttribute(indexes, 1); // 索引数据赋值给几何体的index属性
/**纹理坐标0~1之间随意定义*/
const uvs = new Float32Array([
0, 0, //图片左下角
1, 0, //图片右下角
1, 1, //图片右上角
0, 1, //图片左上角
]);
geometry.attributes.uv = new THREE.BufferAttribute(uvs, 2); //2个为一组,表示一个顶点的纹理坐标
纹理与网格模型面不同区域之间的映射关系是由几何体自身的UV坐标决定的。
const geometry = new THREE.PlaneGeometry(100, 50);
const geometry = new THREE.BoxGeometry(100, 100, 100); //立方体
const geometry = new THREE.SphereGeometry(60, 25, 25); //球体
// threejs自带几何体也有自己默认UV坐标
console.log('uv',geometry.attributes.uv);
# 顶点UV坐标内置变量uv
前面几节课给大家介绍过shader材质ShaderMaterial
的两个内置变量顶点位置position
、顶点颜色color
。这节课给大家介绍一个新的顶点变量,顶点UV坐标uv
,uv
的数据来自几何体uv属性geometry.attributes.uv
attribute vec3 position;//默认提供,不用自己写
attribute vec3 color;//默认提供,不用自己写
attribute vec2 uv;//默认提供,不用自己写
const vertexShader = `
attribute vec2 uv;//默认提供,不用自己写
void main(){
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
# 1. 顶点UV坐标插值计算
仿照前面两节课顶点位置position
、顶点颜色color
插值计算语法,对顶点uv
坐标进行插值计算。
const vertexShader = `
// attribute vec2 uv;//默认提供,不用自己写
varying vec2 vUv;
void main(){
vUv = uv;// UV坐标插值计算
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`
# 2. 声明颜色贴图变量uniform sampler2D map
uniform
关键字声明一个颜色贴图相关的变量map
,纹理贴图对应数据类型需要用关键字sampler2D
表示。
// 片元着色器代码
const fragmentShader = `
uniform sampler2D map;//颜色贴图变量
void main() {
gl_FragColor = vec4(0.0,1.0,1.0,1.0);
}
`
# 3. 给uniform变量map
传值
查看Uniform
的文档,能看到着色器语言数据类型sampler2D
对应threejs的数据类型THREE.Texture
。
const texture = new THREE.TextureLoader().load('./Earth.png');
const material = new THREE.ShaderMaterial({
uniforms: {
// 给着色器中同名uniform变量map传值
map: {value: texture},
},
vertexShader: vertexShader,// 顶点着色器
fragmentShader: fragmentShader,// 片元着色器
});
# 4. 采样纹理赋值给gl_FragColor
执行varying vec2 vUv;
从顶点着色器获取插值后UV坐标vUv
,然后执行texture2D( map, vUv );
从颜色贴图上提取像素值,赋值给模型的片元gl_FragColor
。
// 片元着色器代码
const fragmentShader = `
uniform sampler2D map;//颜色贴图变量
varying vec2 vUv;
void main() {
// 通过几何体的UV坐标从颜色贴图获取像素值
gl_FragColor = texture2D( map, vUv );
}
`