three.js艺术火焰shader

2,916 阅读3分钟

three.js艺术火焰shader

下载 (2).png

Three.js 是一个用于创建 3D 图形的 JavaScript 库。它是一款非常强大和灵活的库,可以用于创建各种各样的 3D 图形和动画效果。在这篇文章中,我们将介绍如何使用 Three.js 创建一个全屏平面,并在平面上应用一个着色器材质绘制艺术火焰的效果。让我们开始吧!

  1. 创建场景和相机
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 10;

我们首先创建了一个 Three.js 场景和一个透视相机。透视相机是一种常用的 3D 相机类型,它可以创建一个透视效果,使得远处的物体看起来比近处的物体小。我们将相机的位置设置为 z = 10,这样我们可以看到平面的正面。

  1. 创建平面几何体
let pre = 80;
let width = window.innerWidth/pre;
let height = window.innerHeight/pre;
const geometry = new THREE.PlaneGeometry(width, height)

我们使用 THREE.PlaneGeometry 创建了一个平面几何体,用于表示平面的形状。我们定义了一个比例因子 pre,用于将窗口大小缩小到更小的尺寸,以便于在屏幕上渲染。通过将窗口的宽度和高度除以 pre,我们可以计算出平面的宽度和高度。

  1. 创建着色器材质
const material = new THREE.ShaderMaterial({
  uniforms: {
    iTime: { value: 0 },
  },
  fragmentShader: fragmentShader,
  vertexShader: vertexShader,
  transparent: true,
});

我们使用 THREE.ShaderMaterial 创建了一个着色器材质,用于渲染平面。着色器材质是 Three.js 中非常强大的特性之一,它可以用于实现各种各样的效果,例如水面模拟、光线追踪、镜面反射等等。在这个例子中,我们使用了一个 fragment shader(片元着色器)来对平面进行渲染。

我们还定义了一些 uniform 变量,包括时间。这些 uniform 变量可以在 JavaScript 代码中进行设置和更新,以便在渲染时传递给着色器。在这个例子中,我们将时间值每帧都自动增加,用于控制动画。

  1. 编写着色器

全部代码见:码上掘金。

void main() {
    vec2 uv = vUv;
    uv.x *= 4.0;
    float t = iTime * 3.0;    
    vec3 col = vec3(0);
    float noise = getNoise(uv, t);
    CUTOFF = uv.y;    
    CUTOFF += pow(abs(uv.x*0.5 - 1.),1.0);   
    if (noise < CUTOFF){       
        col = vec3(0.);
    }else{
        float d = pow(getDepth(noise),0.7);        
        vec3 hsv = vec3(d *0.17,0.8 - d/4., d + 0.8);
        col = hsv2rgb(hsv);
    }
    gl_FragColor = vec4(col,col.r); 
}

  1. 创建平面网格
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

我们使用 THREE.Mesh 将平面几何体和着色器材质组合成一个网格,并将其添加到场景中。网格是 Three.js 中用于表示 3D 对象的基本单位之一,它由一个几何体和一个材质组成。在这个例子中,我们将平面几何体和着色器材质传递给网格,得到一个可以渲染的平面对象。

  1. 创建渲染器并渲染场景
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

function animate() {
  requestAnimationFrame(animate);
  material && (material.uniforms.iTime.value += 0.01);
  renderer.render(scene, camera);
}
animate();

我们创建了一个 THREE.WebGLRenderer 对象,并设置了渲染器的大小。我们还将渲染器的 domElement 添加到 HTML 文档中,以便将 Three.js 场景渲染到屏幕上。

我们创建了一个 animate 函数,它使用 requestAnimationFrame 方法来循环执行渲染,并在每个帧上更新着色器材质的 uniform 变量。我们还检查了着色器材质是否存在,以避免出现错误。

  1. 更新窗口大小
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

window.addEventListener('resize', onWindowResize, false);

最后,我们创建了一个 onWindowResize 函数,该函数会在窗口大小改变时调用,更新相机和渲染器的参数。我们还将 onWindowResize 函数绑定到 resize 事件上,以便在窗口大小改变时自动调用。

这就是使用 Three.js 创建全屏平面的全部步骤。通过这个例子,我们可以看到 Three.js 的强大和灵活性,以及着色器材质的基本用法。

艺术火焰.gif