一、实现一个光影墙
1. 根据自定义坐标点,输出一个光影墙
/** * 添加光影墙 */ function addLightWall() { const geometry = new THREE.BufferGeometry(); const vertices = new Float32Array([ 5, 0, 2, 3, 0, 5, -2, 0, 5, -4, 0, 2, -4, 5, 2, -2, 5, 5, 3, 5, 5, 5, 5, 2 ]); const indices = new Uint16Array([ 0, 1, 7, 1, 6, 7, 1, 2, 6, 2, 5, 6, 2, 3, 5, 3, 4, 5 ]) geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); geometry.setIndex(new THREE.BufferAttribute(indices, 1)); geometry.setAttribute('aHeight', new THREE.BufferAttribute(new Float32Array(new Array(geometry.getAttribute('position').count).fill(5.0)), 1)); const uniforms = { uTime: { value: 0.01 }, }; setShader(geometry, vertex, frag, [0, 2.5, 0], uniforms) } function setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine = false) { material = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide, uniforms: uniforms, transparent: true, // blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色 }); material.depthTest = true; material.depthWrite = false; let planeMesh = new THREE.Mesh(geometry, material); if (isLine) { planeMesh = new THREE.Points(geometry, material); } planeMesh.position.x = position[0]; planeMesh.position.y = position[1]; planeMesh.position.z = position[2]; scene.add(planeMesh); }
自定义坐标
2. 圆柱体的光影墙
/** * 添加光影墙 */ function addLightWall() { const geometry = new THREE.CylinderGeometry(3, 3, 5.0, 32, 32, true); geometry.setAttribute('aHeight', new THREE.BufferAttribute(new Float32Array(new Array(geometry.getAttribute('position').count).fill(5.0)), 1)); // 生成一个渐变色的光影墙 const vertex = ` varying vec3 vPosition; varying vec2 vUv; varying float vHeight; attribute float aHeight; void main() { vHeight = aHeight; vUv = uv; vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const frag = ` varying vec3 vPosition; varying vec2 vUv; varying float vHeight; void main() { float d = (vHeight - distance(vPosition, vec3(vPosition.x, -2.5, vPosition.z))) / vHeight; gl_FragColor = vec4(0.0, 1.0, 1.0, d); } `; const uniforms = { uTime: { value: 0.01 }, }; setShader(geometry, vertex, frag, [0, 2.5, 0], uniforms) } function setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine = false) { material = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide, uniforms: uniforms, transparent: true, // blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色 }); material.depthTest = true; material.depthWrite = false; let planeMesh = new THREE.Mesh(geometry, material); if (isLine) { planeMesh = new THREE.Points(geometry, material); } planeMesh.position.x = position[0]; planeMesh.position.y = position[1]; planeMesh.position.z = position[2]; scene.add(planeMesh); }
圆柱体光影墙
3. 为圆柱体添加可移动的线圈
/** * 添加光影墙 */ function addLightWall() { const geometry = new THREE.CylinderGeometry(3, 3, 5.0, 32, 32, true); geometry.setAttribute('aHeight', new THREE.BufferAttribute(new Float32Array(new Array(geometry.getAttribute('position').count).fill(5.0)), 1)); // 生成一个可以向上移动的墙体线 const vertex = ` varying vec3 vPosition; varying vec2 vUv; varying float vHeight; attribute float aHeight; void main() { vHeight = aHeight; vUv = uv; vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const frag = ` uniform float uTime; varying vec3 vPosition; varying vec2 vUv; varying float vHeight; void main() { float dis = distance(vPosition, vec3(vPosition.x, -2.5, vPosition.z)); float highlightPos = mod(uTime * 5.0, vHeight) - 2.5; float highlightDis = distance(vec3(vPosition.x, highlightPos, vPosition.z), vec3(vPosition.x, -2.5, vPosition.z)); float highlightOpa = (vHeight - highlightDis) / vHeight; float opacity = (vHeight - dis) / vHeight; if (abs(dis - highlightDis) ) { gl_FragColor = vec4(0.04, 0.95, 0.95, highlightOpa + 0.2); } else { gl_FragColor = vec4(0.0, 1.0, 1.0, opacity); } } `; const uniforms = { uTime: { value: 0.01 }, }; setShader(geometry, vertex, frag, [0, 2.5, 0], uniforms) } function setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine = false) { material = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide, uniforms: uniforms, transparent: true, // blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色 }); material.depthTest = true; material.depthWrite = false; let planeMesh = new THREE.Mesh(geometry, material); if (isLine) { planeMesh = new THREE.Points(geometry, material); } planeMesh.position.x = position[0]; planeMesh.position.y = position[1]; planeMesh.position.z = position[2]; scene.add(planeMesh); }
移动线圈光影墙
二、实现一个渐变色的波纹圆圈
1. 实现一个固定的渐变色圆圈
原理:
1) UV点的范围是[0, 1],所以各个像素点距离圆心的距离范围是0~0.5,如果乘以2刚好是透明度的范围(0~1),这样就可以实现一个简单的渐变圆
2) 假设厚度为t,那么颜色的透明度的范围是[1, 1-t],而我们实际需要的是[1, 0],可以用图二来表示两个线性关系,可以得到两个方程式
方程式1:y = -x + 1;
方程式2:y = -t + 1;
现在我们知道方程式二中的y的值(像素点到中心的距离distance),通过解方程式就可以得到方程式1中所对应的透明度的值为 (distance – 1) / t + 1;
/** * 添加一个扩散面 */ function addDiffuseCircle() { const geometry = new THREE.CircleGeometry(3, 48); // 绘制一个渐变圈宽度可控的圆弧 const vertex = ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const frag = ` uniform float uTime; uniform float uThickness; varying vec2 vUv; void main() { // 使用UV坐标计算各个点到中心点的距离,需要减0.5,将圆心移动到(0.5, 0.5)的位置,半径为0.5,透明度范围为0~1,所以需要乘以2 float distance = length(vUv - 0.5) * 2.0; float opacity = (distance - 1.0) / uThickness + 1.0; gl_FragColor = vec4(0.0, 1.0, 1.0, opacity); } `; const uniforms = { uThickness: { value: 0.8, range: [0, 1] }, // 渐变色的厚度 uSpeed: { value: 0.5, range: [0, 5] }, uTime: { value: 0.01 }, }; setGui(uniforms); setShader(geometry, vertex, frag, [0,0,0], uniforms); } function setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine = false) { material = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide, uniforms: uniforms, transparent: true, // blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色 }); material.depthTest = true; material.depthWrite = false; let planeMesh = new THREE.Mesh(geometry, material); if (isLine) { planeMesh = new THREE.Points(geometry, material); } planeMesh.position.x = position[0]; planeMesh.position.y = position[1]; planeMesh.position.z = position[2]; planeMesh.rotateX(Math.PI / 2); scene.add(planeMesh); }
厚度可变的渐变圆
2. 半径自动缩放的渐变圆
/** * 添加一个扩散面 */ function addDiffuseCircle() { const geometry = new THREE.CircleGeometry(3, 48); // 创建一个大小可控的渐变圆弧 const vertex = ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const frag = ` uniform float uTime; uniform float uThickness; uniform float uSpeed; varying vec2 vUv; void main() { // 使用UV坐标计算各个点到中心点的距离,需要减0.5,将圆心移动到(0.5, 0.5)的位置,半径为0.5,透明度范围为0~1,所以需要乘以2 // 假设从内像外开始扩散,距离和时间关系是 最内部: 距离0,时间0;最外部:距离1,时间1,如果用1-时间的话, // 所以此时1-时间+距离和样例1中的透明度相同 float timeDis = fract(uTime * uSpeed); float distance = length(vUv - 0.5) * 2.0; if (timeDis distance) { gl_FragColor = vec4(0.0, 0.0, 1.0, 0.0); } else { float opacity = (1.0 - timeDis + distance - 1.0) / uThickness + 1.0; gl_FragColor = vec4(0.0, 1.0, 1.0, opacity); } } `; const uniforms = { uThickness: { value: 0.8, range: [0, 1] }, // 渐变色的厚度 uSpeed: { value: 0.5, range: [0, 5] }, uTime: { value: 0.01 }, }; setShader(geometry, vertex, frag, [0,0,0], uniforms); } function setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine = false) { material = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide, uniforms: uniforms, transparent: true, // blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色 }); material.depthTest = true; material.depthWrite = false; let planeMesh = new THREE.Mesh(geometry, material); if (isLine) { planeMesh = new THREE.Points(geometry, material); } planeMesh.position.x = position[0]; planeMesh.position.y = position[1]; planeMesh.position.z = position[2]; planeMesh.rotateX(Math.PI / 2); scene.add(planeMesh); }
自动缩放的渐变圆
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容