Appearance
着色器
普通的着色器
普通的着色器,能够使用默认的配置进行基本的着色器创建。
javascript
// 创建着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader: `
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0)
`,
fragmentShader: `
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0)
`
});
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(1,1,64,64),
shaderMaterial
)
scene.add(floor);
直接在js中写着色器没有代码提示。在vscode中安装插件Shader languages suport for VS Code
,可以让我们在外面书写shader文件。
在src目录下创建Shader/basic文件夹路径。在basic文件夹里创建两个文件:vertex.glsl和fragment.glsl。
glsl
// vertex.glsl
void main(){
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}
glsl
// fragment.glsl
void main(){
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
这样一来将shader代码写在了外部,通过导入的方式进行使用
javascript
import basicFragmentShader from '../shader/basic/fragment.glsl';
import basicVertexShader from '../shader/basic/vertex.glsl';
// 创建着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
vertexShader: basicVertexShader,
fragmentShader: basicFragmentShader
});
原生着色器
原生着色器需要我们更多的配置,但这也意味着更加灵活。
javascript
import basicFragmentShader from '../shader/basic/fragment.glsl';
import basicVertexShader from '../shader/basic/vertex.glsl';
// 创建着色器材质。注意下面用的是RawShaderMaterial
const shaderMaterial = new THREE.RawShaderMaterial({
vertexShader: basicVertexShader,
fragmentShader: basicFragmentShader
});
glsl
// vertex.glsl
// highp -2^16 ~ 2^16
// mediump -2^10 ~ 2^10
// lowp -2^8 ~ 2^8
precision lowp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
varying vec2 vUv;
void main(){
vUv = uv;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}
glsl
// fragment.glsl
precision lowp float;
varying vec2 vUv;
void main(){
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
线框效果
javascript
import basicFragmentShader from '../shader/basic/fragment.glsl';
import basicVertexShader from '../shader/basic/vertex.glsl';
// 创建着色器材质
const shaderMaterial = new THREE.RawShaderMaterial({
vertexShader: basicVertexShader,
fragmentShader: basicFragmentShader,
wireframe: true, // 线框
});
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(1,1,1,1), // 注意这里后两个参数,18已经很大了。太大了点数密集,不能够很好展示线框。
shaderMaterial
)
scene.add(floor);
形变
glsl
// vertex.glsl
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;
}
glsl
// fragment.glsl
precision lowp float;
varying vec2 vUv;
varying float vElevation;
void main(){
float height = (vElevation + 0.05) * 10.0;
gl_FragColor = vec4(1.0 * height, 0.0, 0.0, 1.0);
}
顶点运动
就是让形变动起来
javascript
// 创建着色器材质
const shaderMaterial = new THREE.RawShaderMaterial({
vertexShader: basicVertexShader,
fragmentShader: basicFragmentShader,
// 这里的值会传给着色器去使用
uniforms: {
uTime: {
value: 0,
}
}
});
function animate() {
// 其他代码略
// 将变量赋值
shaderMaterial.uniforms.uTime.value = clock.getElapsedTime();
}
glsl
// vertex.glsl
precision lowp float;
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
// 获取时间
uniform float uTime;
varying vec2 vUv;
varying float vElevation;
void main(){
vUv = uv;
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
modelPosition.z = sin((modelPosition.x+uTime) * 10.0) * 0.05;
modelPosition.z += sin((modelPosition.y+uTime) *10.0) * 0.05;
vElevation = modelPosition.z;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
纹理映射
javascript
// 创建纹理对象
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./imgs/123.jpg"); // 文件路径要根据实际情况来写
// 创建着色器材质
const shaderMaterial = new THREE.RawShaderMaterial({
vertexShader: basicVertexShader,
fragmentShader: basicFragmentShader,
uniforms: {
uTime: {
value: 0,
},
uTexture: {
value: texture,
}
}
});
glsl
precision lowp float;
varying vec2 vUv;
varying float vElevation;
// 创建纹理
uniform sampler2D uTexture;
void main(){
// float height = (vElevation + 0.05) * 10.0;
// gl_FragColor = vec4(1.0 * height, 0.0, 0.0, 1.0);
// UV采样
vec4 textureColor = texture2D(uTexture, vUv);
gl_FragColor = textureColor;
}
如果希望带有本身的明暗,可以写成
glsl
// 其他忽略
void main(){
// UV采样
vec4 textureColor = texture2D(uTexture, vUv);
float height = (vElevation + 0.05) * 10.0;
textureColor.rgb *= height;
gl_FragColor = textureColor;
}