在three.js中自己写shader语言的时候,我们需要把glsl与JavaScript两种语言结合起来,即在ShaderMaterial中传入对象,从而引入shader。实际上,对象中的vertexShader和fragmentShader两属性的值是String,所以最简单的办法就是将整个shader代码作为字符串:
// precision lowp float // 设置一个低精度,精度范围 高精度(-2^16 - 2^16), 中等精度(-2^10 - 2^10), 低精度(-2^8 - 2^8)
// attribute vec3 position; // 因为是三位的,所以是vec3
// attribute vec2 uv; // uv 是二维的, 所以是vec2
//
// uniform mat4 modelMatrix; // 4维矩阵, mat4
// varying vec2 vUv; // 声明一个变量可以传递给 片元着色器的
// void main(){
// vUv = uv // 把uv的值给到vUv
// gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ) ;
// }
const VERTEX_SHADER = `
precision lowp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
varying vec2 vUv;
varying float vElevation;
void main(){
vUv = uv;
vec4 modelPosition = modelMatrix * vec4( position, 1.0 );
modelPosition.z = sin(modelPosition.x * 10.0) * 0.05;
modelPosition.z += sin(modelPosition.y * 10.0) * 0.05;
vElevation = modelPosition.z;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
`
// precision lowp float // 设置一个低精度,精度范围 高精度(-2^16 - 2^16), 中等精度(-2^10 - 2^10), 低精度(-2^8 - 2^8)
// varying vec2 vUv; // 接收到顶点着色器传递过来的vUv
// void main(){
// gl_FragColor = vec4(vUv, 0.0, 1.0); // vUv 用在一个四维数组中
// }
const FRAGMENT_SHADER = `
precision lowp float;
varying vec2 vUv;
varying float vElevation;
void main(){
float deep = vElevation + 0.05 * 10.0;
gl_FragColor = vec4(1.0 * deep, 0.0, 0.0, 1.0);
}
`
// 创建着色器材质
const rawShaderMaterial = new THREE.RawShaderMaterial({
// wireframe: true, // 线框效果
vertexShader: VERTEX_SHADER,
fragmentShader: FRAGMENT_SHADER,
side: THREE.DoubleSide
})
glsl文件与js文件分开
这样在three.js中引入shader语言当然可以运行,但问题在于这样shader语言和JavaScript原因在同一个文件夹中,不好管理,我们需要将js文件和glsl文件单独成两个文件,最好形成如下的文件结构:
但问题在于js并不能importglsl文件,所以我能只好将.glsl改成.js,将shader语言作为js的字符串进行import,上述的文件结构就变成了:
确实这样就将js文件和glsl文件分开了,但是这样shader语言以字符串导入到js中,其本身没有问题,因为在js中,shader就是以一段字符串传的形式给GPU。但一个问题在于,我们在编辑器中看到的shader语言没有高亮,因为它们只是一段字符串,全部一样颜色,这是非常不方便的。
高亮显示glsl代码
这里需要下载插件Comment target templates.
使用步骤非常简单,只需加上/glsl/,告诉插件字符串里的东西是glsl语言:
最终在vscode中的显示效果:
vertex.js
const vertexShader = /*glsl*/ `
attribute vec3 position;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
void main(){
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ) ;
}`
export default vertexShader
最终
// 顶点着色器
import basicVertexShader from '../../shader/basic/vertex.js'
// 片元着色器
import basicFragmentShader from '../../shader/basic/fragment.js'
// 创建着色器材质
const rawShaderMaterial = new THREE.RawShaderMaterial({
vertexShader: basicVertexShader,
fragmentShader: basicFragmentShader
})