在实现建筑模型蓝色科技线框效果后,进阶制作的表面纹理流动效果。初始思路是建筑物基础材质用MeshLambertMaterial,后面替换ShaderMaterial材质使用pngt贴图,透明区域填充底色,制作流动动画。目前来看色值有偏差。(ps:blender贴图展开投影即可,ShaderMaterial需要对照uv坐标实现贴图定位)
首先基础材质替换。
node.material = new THREE.MeshLambertMaterial({
color: 0x0440A3,
transparent: true,
opacity: 0.5,
})
// 模型边线设置
const edges = new THREE.EdgesGeometry(node.geometry,30)
const edgesMaterial = new THREE.LineBasicMaterial({
color: 0x0440A3 ,
linewidth:0.5,
transparent: true,
opacity: 0.5,
depthWrite: false,
side: THREE.DoubleSide,
})
const line = new THREE.LineSegments(
edges,
edgesMaterial
)
node.add(line)
这是蓝色科技线框效果,EdgesGeometry的第二个参数是可以减少模型内部三角面的效果参数。
然后是选中需要的模型做ShaderMaterial材质替换。在这个过程中加载贴图需要属性定义(在blender里贴图属性为重复的参数),所以要写在外面重新定义赋值。
const texture1 = new THREE.TextureLoader().load('textures/62.png');
// 设置纹理的包裹模式为重复
texture1.wrapS = THREE.RepeatWrapping; // 水平方向重复
texture1.wrapT = THREE.RepeatWrapping; // 垂直方向重复
// 设置纹理重复次数
texture1.repeat.set(3, 3); // 在X轴和Y轴上各重复2次
然后设置 ShaderMaterial材质。
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
vUv.x = uv.x * 3.3; // 缩放UV坐标,使纹理在X轴上重复
vUv.y = uv.y * 3.3; // 缩放UV坐标,使纹理在Y轴上重复
vUv += vec2(-0.2, 0); // 如果需要平移UV坐标 xy
//float angle = 0.5; // 如果需要旋转UV坐标
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
uniform sampler2D texture1;
uniform vec3 fillColor;
uniform float fillOpacity;
uniform float time;
uniform float speed;
uniform vec2 uvRepeat;
uniform vec2 uvScale;
varying vec2 vUv;
uniform float intensity;
uniform float transitionProgress;
//uniform vec3 emissiveColor;
void main() {
//vec2 uv = vUv;
//缩放暂时没用
//vec2 uv = vUv * uvScale;
// Example: a simple wave effect
//左右来回移动
//uv.y += sin(uv.x * 10.0 + time) * 0.1;
vec2 uv = vUv + vec2(0.0, time * speed);
vec4 color = texture2D(texture1, uv);
vec3 finalColor = color.rgb * intensity;
// 从上到下的过渡效果
float alpha = smoothstep(transitionProgress - 0.1, transitionProgress + 0.1, vUv.x);
// 如果透明区域,使用填充颜色和透明度
if (color.a < 0.1) {
gl_FragColor = vec4(fillColor, fillOpacity * alpha);
} else {
gl_FragColor = vec4(finalColor, color.a * alpha); // 输出颜色
}
//gl_FragColor = color;
}
`;
首先是顶点着色器和片段着色器单独写出,需要赋值的定义过多,主要是uv的设置和blender里对应,我在blender里对uv位置做出调整,所以需要在顶点着色器里对uv矫正。在片端着色器中主要传递图片到模型uv上,做啦一个条件判断,透明度值是透明时使用底色,不透明区域使用贴图的显示色。 vec2 uv = vUv + vec2(0.0, time * speed);是贴图流动设置,后面在animate要更新其值。alpha这个参数是做动画从左到右过渡效果的参数。
后面是重复执行调用代码animate
/* fresnelMat.uniforms.time.value += 0.05; */
progress += 0.01;
fresnelMat.uniforms.transitionProgress.value = Math.min(progress, 4.3);
注释的是图片流动速度
做啦区间值,4.3是测试过透明度隐藏最大值,最小值是0。
大致是实现两个效果,图片流动和过渡效果。