three 遮罩层
three 实现遮罩模型的效果,主要使用mesh 的material,构建shader来完成,通过可以是一个特定的图片,也可以是canvas绘制2D图形,之后转图片,来实现
1.shader代码
this.vertex = ShaderLib.standard.vertexShader.replace( `void main() {`, ` varying vec2 maskUV; // 遮罩UV uniform vec2 maxBound; // 最大边界 uniform vec2 minBound; // 最小边界 void main() { vec4 p=modelMatrix*vec4(position,1.0); // 将顶点位置转换到世界坐标系中 // 计算出顶点遮罩UV坐标 /w 齐次坐标 maskUV=(vec2(p.x/p.w,p.z/p.w)-minBound)/(maxBound-minBound); ` ); this.fragment = ShaderLib.standard.fragmentShader.replace( `void main() {`, ` uniform sampler2D maskTexture; // 遮罩贴图 varying vec2 maskUV; // 遮罩UV坐标 顶点着色器传过来的 uniform int state; // 裁剪状态 0 不裁剪 1 显示裁剪贴图 2 裁剪模型 void main() { // 采样遮罩贴图 vec4 c = texture(maskTexture,maskUV); if(state!=0){ if(state==1){ gl_FragColor=c; return; }else{ // 因为 遮罩贴图是红绿图 红色通道>0.5 表示超出裁剪范围 需要剔除 if(c.x>0.5) { discard; } } } `
构建一个遮罩的shader,根据图像的区域来分割
tiles.group.traverse((x) => { if (x instanceof Mesh && x.material instanceof Material) { x.material.onBeforeCompile = (shader: Shader) => { console.log(tiles.group.rotation) shader.uniforms.maxBound = maxBound; shader.uniforms.minBound = minBound; // shader.uniforms.state = { value: 1 }; shader.uniforms.state = { value: tiles.group.userData.state } let texture = (tiles.group as any).texture; texture.value.rotation = 10*Math.random() shader.uniforms.maskTexture = texture; // shader.uniforms.maskTexture.value.rotation = 10*Math.random() // shader.uniforms.maskTexture = maskTexture; shader.vertexShader = vertex; shader.fragmentShader = fragment; }; } });
这段js是遍历group 给group里面的mesh赋值、使得动态绘制遮罩层