静态世界
使用three.js 创建相机,场景什么的太基础不写了。直接看shader代码
Shader
vertexShader
// vertex.glsl
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
简单解释下,three.js 会帮我们声明好投影矩阵projectionMatrix,模型视图矩阵,以及uv。直接拿来用就好
fragmentShader
// fragment.glsl
precision mediump float;
precision lowp sampler2D;
uniform sampler2D noiseTexture;
uniform sampler2D boxTexture;
uniform float threshold;
varying vec2 vUv;
void main() {
vec4 noise = texture2D(noiseTexture, vUv);
vec4 box = texture2D(boxTexture, vUv);
vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
if (noise.g < threshold) {
discard;
}
float t = 1.0 - smoothstep(0.0, 1.0, noise.g - threshold);
vec4 dissolveColor = mix(box, color, t);
gl_FragColor = mix(box, dissolveColor, t * step(0.0001, threshold));
}
这里我们用噪声图创建 随机消融。
color为消融边缘色, 这里设置的是白色
因为噪声图是灰度图,rgb3个值相同,所以这里随机取一个值noise.g(鸡你太美,笑) 与 阈值 比对,做到消融
后面就是颜色混合了
最后一行 t * step(0.001, threshold)是为了处理bug。
有时候噪声通道的值noise.g - threshold 不一定大于线宽
Typescript
ts大概的代码
import { BoxGeometry, Mesh, ShaderMaterial,LoadingManager, TextureLoader, DoubleSide } from 'three';
// 我这里使用vite加载glsl。
import vertexShader from './vertex.glsl?raw';
import fragmentShader from './fragment.glsl?raw';
// 用manage统一管理资源加载
const manage = new LoadingManager();
const textureLoader = new TextureLoader(manage);
const noiseTexture = textureLoader.load('/noise.png');
const boxTexture = textureLoader.load('/box.png');
/** 以下需要判断manage.onLoad 加载完毕在进行 **/
let threshold = 0.0;
const boxGeometry = new BoxGeometry(10, 10, 10);
const uniforms: ShaderMaterial['uniforms'] = {
noiseTexture: {
value: noiseTexture,
},
boxTexture: {
value: boxTexture,
},
threshold: {
value: threshold,
}
}
const shaderMaterial = new ShaderMaterial({
uniforms: this.uniforms,
vertexShader: vertexShader,
fragmentShader: boxFramentShader,
side: DoubleSide
});
const mesh = new Mesh(boxGeometry, shaderMaterial)
/**
* 剩下的就是把mesh加载到场景中渲染
* 在 requestAnimationFrame 修改 threshold 的值即可
*/
以上 消融特效 非常简单的实现