京东的网站是怎么建设的,深圳 网站设计师 招聘,做小程序商城,网络营销是什么专业大家好#xff01;我是 [数擎 AI]#xff0c;一位热爱探索新技术的前端开发者#xff0c;在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情#xff0c;欢迎关注我的文章#xff0c;我们一起成长、进步#xff01; 开发领域#xff1a;前端开发 | A… 大家好我是 [数擎 AI]一位热爱探索新技术的前端开发者在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情欢迎关注我的文章我们一起成长、进步 开发领域前端开发 | AI 应用 | Web3D | 元宇宙 技术栈JavaScript、React、ThreeJs、WebGL、Go 经验经验6 年 前端开发经验专注于图形渲染和 AI 技术 演示地址演示地址 开源项目智简未来、晓智元宇宙、数字孪生引擎 、源码地址 演示地址:https://shader.shuqin.cc/4sfywn 源码地址]:https://github.com/dezhizhang/shadertoy
在这篇文章中我们将通过 Three.js 实现一个简单而炫酷的热力渐变效果。我们将使用着色器Shader来模拟热力图创造出动态的渐变效果。这种效果常用于可视化数据或者只是为了增加网页的视觉冲击力。
项目概述
我们使用 Three.js 来创建一个全屏的 WebGL 场景通过自定义的着色器Shader渲染一个动态的热力渐变效果。这个效果展示了从冷到热的渐变色并通过动态的点位置变化模拟热力分布的变化。
环境搭建
首先需要在 HTML 中引入 Three.js 库我们使用了 CDN 来引入
script srchttps://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js/script这将为我们提供 Three.js 的核心功能如创建场景、相机、渲染器以及应用自定义着色器等。
创建基本场景
在 JavaScript 中我们首先创建了一个基础的 3D 场景其中包括相机、渲染器以及全屏的平面几何体来显示效果。
let scene, camera, renderer, material;function init() {scene new THREE.Scene();camera new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);renderer new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);
}
相机我们使用了正交相机THREE.OrthographicCamera来渲染二维平面这种相机没有透视效果适合渲染平面效果。渲染器通过 THREE.WebGLRenderer 实现高效的 3D 渲染。全屏平面为了将热力渐变效果显示为全屏我们使用了一个 2x2 的平面几何体 (THREE.PlaneGeometry)并将其拉伸到全屏。
const plane new THREE.PlaneGeometry(2, 2);
const mesh new THREE.Mesh(plane, material);
scene.add(mesh);
自定义着色器
着色器Shader是实现热力渐变效果的核心部分。我们通过自定义的顶点着色器和片段着色器来控制每个像素的颜色变化。
顶点着色器
顶点着色器的作用是计算每个顶点的坐标和纹理坐标在这里我们只是将纹理坐标传递给片段着色器
vertexShader: varying vec2 vUv;void main() {vUv uv;gl_Position vec4(position, 1.0);}片段着色器
片段着色器的主要任务是根据热力分布计算每个像素的颜色。我们使用了一个简单的色彩渐变算法将不同的权重值映射到不同的颜色并生成最终的热力图效果。
fragmentShader: precision highp float;uniform float iTime;uniform vec2 iResolution;varying vec2 vUv;// 渐变颜色定义const vec3 colors[5] vec3[](vec3(0.,0.,0.6),vec3(0.,1.,1.),vec3(0.0,1.0,0.),vec3(1.0,1.0,0.),vec3(1.0,0.0,0.));const float points[5] float[](0.0, 0.15, 0.5, 0.65, 1.0);vec3 gradian(vec3 c1, vec3 c2, float a) {return mix(c1, c2, a);}vec3 heat4(float weight) {if(weight points[0]) return colors[0];if(weight points[4]) return colors[4];for(int i 1; i 5; i) {if(weight points[i]) {float a (weight - points[i-1]) / (points[i] - points[i-1]);return gradian(colors[i-1], colors[i], a);}}return vec3(0.0);}float d(vec2 a, vec2 b) {return pow(max(0.0, 1.0 - distance(a, b) / 0.6), 2.0);}void main() {vec2 uv vUv * 4.0 - vec2(2.0);uv.x * iResolution.x / iResolution.y;float totalWeight 0.0;// 优化循环次数为常量表达式for (float i 0.0; i 112.0; i 1.0) {totalWeight 0.5 * d(uv, vec2(sin(iTime * 0.3 i) * 2.0 2.0 * sin(i * i),cos(iTime * 0.4 i * 1.5) * 2.0));}gl_FragColor vec4(heat4(totalWeight), 1.0);}渐变颜色我们定义了五个颜色从深蓝到红色代表从冷到热的渐变。权重计算我们使用了一个简单的函数 d() 来计算每个像素的权重根据距离和时间动态生成热力分布。
动画效果
我们使用 requestAnimationFrame 来创建一个平滑的动画效果。每一帧时间和分辨率都会被更新从而动态改变热力渐变效果的颜色。
function animate() {requestAnimationFrame(animate);material.uniforms.iTime.value performance.now() / 1000;renderer.render(scene, camera);
}animate();
响应式设计
为了确保热力渐变效果在不同屏幕尺寸下都能正常显示我们通过监听窗口尺寸变化事件来动态调整渲染器的尺寸和分辨率
function onWindowResize() {const width window.innerWidth;const height window.innerHeight;renderer.setSize(width, height);material.uniforms.iResolution.value.set(width, height);
}window.addEventListener(resize, onWindowResize);
完整代码
import * as THREE from three;let scene, camera, renderer, material;function init() {// 初始化场景scene new THREE.Scene();camera new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);renderer new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 着色器材质配置const uniforms {iTime: { value: 0 },iResolution: { value: new THREE.Vector2() }};material new THREE.ShaderMaterial({uniforms: uniforms,vertexShader: varying vec2 vUv;void main() {vUv uv;gl_Position vec4(position, 1.0);},fragmentShader: precision highp float;uniform float iTime;uniform vec2 iResolution;varying vec2 vUv;// 渐变颜色定义const vec3 colors[5] vec3[](vec3(0.,0.,0.6),vec3(0.,1.,1.),vec3(0.0,1.0,0.),vec3(1.0,1.0,0.),vec3(1.0,0.0,0.));const float points[5] float[](0.0, 0.15, 0.5, 0.65, 1.0);vec3 gradian(vec3 c1, vec3 c2, float a) {return mix(c1, c2, a);}vec3 heat4(float weight) {if(weight points[0]) return colors[0];if(weight points[4]) return colors[4];for(int i 1; i 5; i) {if(weight points[i]) {float a (weight - points[i-1]) / (points[i] - points[i-1]);return gradian(colors[i-1], colors[i], a);}}return vec3(0.0);}float d(vec2 a, vec2 b) {return pow(max(0.0, 1.0 - distance(a, b) / 0.6), 2.0);}void main() {vec2 uv vUv * 4.0 - vec2(2.0);uv.x * iResolution.x / iResolution.y;float totalWeight 0.0;// 优化循环次数为常量表达式for (float i 0.0; i 112.0; i 1.0) {totalWeight 0.5 * d(uv, vec2(sin(iTime * 0.3 i) * 2.0 2.0 * sin(i * i),cos(iTime * 0.4 i * 1.5) * 2.0));}gl_FragColor vec4(heat4(totalWeight), 1.0);}});// 创建全屏平面const plane new THREE.PlaneGeometry(2, 2);const mesh new THREE.Mesh(plane, material);scene.add(mesh);// 初始化分辨率onWindowResize();window.addEventListener(resize, onWindowResize);
}function onWindowResize() {const width window.innerWidth;const height window.innerHeight;renderer.setSize(width, height);material.uniforms.iResolution.value.set(width, height);
}function animate() {requestAnimationFrame(animate);material.uniforms.iTime.value performance.now() / 1000;renderer.render(scene, camera);
}init();
animate();总结
通过自定义的着色器和 Three.js我们可以创建出动态的热力渐变效果这在数据可视化、交互式网页中非常有用。希望这篇博客能帮助你理解如何使用 Three.js 和着色器创建炫酷的视觉效果。如果你对 Three.js 或者着色器有任何疑问欢迎在评论区留言讨论。