vue+js 创造动态的光晕圈

        嗨,我是小路。今天主要和大家分享的主题是“vue+js 创造动态的光晕圈”。        

对于着色器这块,功能确实强大,而自己才刚刚接触,确实需要花费时间进行学习。晚点找找着色器对应的课程进行学习。但今天还是按照视图例子,将项目跑起来,尽可能去理解它。

1.uniform vec2 iResolution;

定义:在着色器中的作用是定义着色器的大小,以适应整个画布。‌在着色器编程中,uniform变量用于传递不变的数据到着色器。iResolution是一个uniform vec2类型的变量,用于存储画布的分辨率信息。这允许着色器根据画布的尺寸来调整其输出,确保图形或效果能够正确地填充整个屏幕。

2.uniform float iTime;

定义:在着色器中用于表示程序运行的时间,单位为秒。这个变量通常用于在着色器中实现动态效果,比如动画或时间相关的计算。在GLSL(OpenGL着色语言)中,uniform 变量用于在着色器之间传递数据。iTime 是一个 uniform float 类型的变量,它表示从程序开始运行以来的时间,单位是秒。这个变量通常由应用程序在每一帧更新,并在着色器中使用来计算随时间变化的效果。


 

二、实例代码

<!--创建一个球体-->
<template>
  <div class="pageBox">
    <div class="leftBox" ref="leftRef"></div>
  </div>

</template>
<script setup>
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import * as THREE from 'three';
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { getRandomColor, createLight } from '../utils/commonThree';
const leftRef = ref();
// 定义相机输出画布的尺寸(单位:像素px)
let width = window.innerWidth; //宽度
let height = window.innerHeight; //高度
// 创建3D场景对象Scene
const scene = new THREE.Scene();
//设置背景色
scene.background = new THREE.Color(0x646d59);

const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
//三角形缩放过大时,会形成多种三角形形成的背景图
camera.position.z = 5;

// 创建渲染器对象
const renderer = new THREE.WebGLRenderer();



let tubes = [];
let material
const createTube = () => {
  // const points = [];
  // for (let i = 0; i < 5; i++) {
  //   points.push(new THREE.Vector3(Math.sin(i * 2) * 10, Math.cos(i * 2) * 10, i * 10 - 20))
  // }
  // const curve = new THREE.CatmullRomCurve3(points);
  // const geometry = new THREE.TubeGeometry(
  //   curve,
  //   64,//分段数
  //   2,//半径
  //   8,//径向分段数
  //   false,//是否闭合
  // );
  const geometry = new THREE.PlaneGeometry(10,10);

  material = new THREE.ShaderMaterial({

    transparent: true,
    uniforms: {
      iResolution: { value: new THREE.Vector2() },
      iTime: { value: 0 },
    },
    vertexShader: `
        varying vec2 vUv;
        void main() {
          vUv = uv;
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
      `,
    fragmentShader: `
        uniform vec2 iResolution;
        uniform float iTime;
        varying vec2 vUv;

        mat2 rotate2d(float angle) {
            return mat2(cos(angle), -sin(angle),
                        sin(angle), cos(angle));
        }

        float variation(vec2 v1, vec2 v2, float strength, float speed) {
            return sin(dot(normalize(v1), normalize(v2)) * strength + iTime * speed) / 100.0;
        }

        vec3 paintCircle(vec2 uv, vec2 center, float rad, float width) {
            vec2 diff = center - uv;
            float len = length(diff);
            len += variation(diff, vec2(0.0, 1.0), 5.0, 2.0);
            len -= variation(diff, vec2(1.0, 0.0), 5.0, 2.0);
            float circle = smoothstep(rad-width, rad, len) - smoothstep(rad, rad+width, len);
            return vec3(circle);
        }

        void main() {
            vec2 uv = vUv;
            uv.x *= 1.5;
            uv.x -= 0.25;
            
            vec3 color;
            float radius = 0.35;
            vec2 center = vec2(0.5);
            
            color = paintCircle(uv, center, radius, 0.1);
            vec2 v = rotate2d(iTime) * uv;
            color *= vec3(v.x, v.y, 0.7 - v.y * v.x);
            color += paintCircle(uv, center, radius, 0.01);
            
            gl_FragColor = vec4(color, 1.0);
        }
      `,
    
    side: THREE.DoubleSide
  });

  const tube = new THREE.Mesh(geometry, material);
  //设置网格的随机位置
  // sphere.position.set(
  //   (Math.random() - 0.5) * 2000,
  //   (Math.random() - 0.5) * 1000,
  //   (Math.random() - 0.5) * 1000
  // );
  return tube;
}

onMounted(() => {

  initData()

  //添加相机空间
  const controls = new OrbitControls(camera, renderer.domElement);
  // controls.enableDamping = false;
  controls.enableZoom = false;
  // 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
  controls.addEventListener('change', function () {
    renderer.render(scene, camera); //执行渲染操作
  });//监听鼠标、键盘事件
  renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px)
  //将innerHTML置空,避免append重复添加渲染
  leftRef.value.innerHTML = ''
  leftRef.value.append(renderer.domElement);

})
const initData = () => {
  createLight(scene);
  // for (let i = 1; i >= 0; i--) {
    const outSphere = createTube();
    tubes.push(outSphere);
    scene.add(outSphere);
  // }
  render();
}
function render() {
  requestAnimationFrame(render);
  // 旋转所有三角形
  // tubes.forEach(tube => {
  //   tube.rotation.x += 0.01;
  //   tube.rotation.y += 0.01;
  //   tube.rotation.z += 0.01;
  // });
  console.log( 'dfffff',material.uniforms.iResolution);
  material.uniforms.iResolution.value.set(
    window.innerWidth,
    window.innerHeight
  );
  material.uniforms.iTime.value = performance.now() / 1000;

  renderer.render(scene, camera);
}
onUnmounted(() => {
  //释放内存
  renderer.dispose();
})


</script>
<style scoped lang="less">
.pageBox {
  width: 100%;
  height: 100vh;
  padding: 0;
  margin: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;

  .rightBox {
    width: 100%;
    height: 100%;
  }
}
</style>

三、总结

       当前阶段,自己的目标是进行大量的练习,将一些项目在完成的基础上,能看懂的就看不懂,看不懂的先放着,等以后掌握的更多的,再回顾过来看;

都看到这里了,记得【点赞】+【关注】哟。

参考文章:

使用 Three.js 创建动态光效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值