threejs 你是我心中最亮的星

threejs 你是我心中最亮的星

研究threejs,随便搞了个demo,稍微改了改默认代码就变成下面这样了。

效果图如下:

用到了一个素材,更像是陨石或者星星。中间有个小太阳,隐隐约约泛着洁白的光晕。

素材如下:

项目地址

参考地址

项目基于vue+threejs。

思路

大体思路如下:

  1. 在屏幕中间画一个球。
  2. 在球的后边在画一个球,这个球的颜色根据时间变化忽亮忽暗。
  3. 增加很多很多的陨石。
  4. 更新陨石的位置让他们动起来,整体再来一点点小旋转。
  5. 不行了,我有点头晕。

实践

增加一个太阳

在屏幕中间画一个球。

javascript 复制代码
<script setup>
import * as THREE from 'three';
import { onMounted } from 'vue';
import pointImage from './assets/point.png'

const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x4AB0F9, 0.015);
// scene.background = new THREE.Color(0xffffff);

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

// Create a sphere
var sphereGeometry = new THREE.SphereGeometry(3, 32, 32);
var sphereMaterial = new THREE.MeshBasicMaterial({color: 0xF3DC6B});
sphereMaterial.fog = false
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0, -80);
scene.add(sphere);

function animate() {
  requestAnimationFrame(animate);

  renderer.render(scene, camera);
}
animate();

onMounted(() => {
  let canvas = document.getElementById('can');
  renderer = new THREE.WebGLRenderer({canvas: canvas});
  renderer.setSize(window.innerWidth, window.innerHeight);
});

</script>

<template>
  <div id="content">
    <canvas id="can"></canvas>
  </div>
</template>

<style scoped>
#content {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#can {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
</style>

增加一个光晕效果

javascript 复制代码
// Create a halo
var haloGeometry = new THREE.SphereGeometry(6, 32, 32);
var haloMaterial = new THREE.ShaderMaterial({
    uniforms: {
        time: { value: 0.0 }
    },
    vertexShader: `
        varying vec3 vNormal;
        varying vec2 vUv;
        void main() {
            vUv = uv;
            vNormal = normalize(normalMatrix * normal);
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `,
    fragmentShader: `
        varying vec3 vNormal;
        varying vec2 vUv;
        uniform float time;
        void main() {
            float intensity = pow(0.1 + 0.3 * (sin(time * 4.0) + 1.0)/2.0 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * intensity;
        }
    `,
    side: THREE.BackSide,
    blending: THREE.AdditiveBlending,
    transparent: true
});
var halo = new THREE.Mesh(haloGeometry, haloMaterial);
halo.position.set(0, 0, -81);
scene.add(halo);

并在更新动画中更新时间。

javascript 复制代码
haloMaterial.uniforms.time.value += 0.005;

增加很多很多的陨石

其中这个材质需要设置成透明的,要不然总是有个小黑边不太好看。

javascript 复制代码
import pointImage from './assets/point.png'

var geometry = new THREE.BufferGeometry();
var positionVertices = [];

// Create particles
var particleCount = 5000;
for (var i = 0; i < particleCount; i++) {
    var x = THREE.MathUtils.randFloatSpread(200);
    var y = THREE.MathUtils.randFloatSpread(200);
    var z = THREE.MathUtils.randFloatSpread(200);
    positionVertices.push(x, y, z);
}

// Add positionVertices to the geometry
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positionVertices, 3));

// Create a material
var material = new THREE.PointsMaterial({ color: 0xefefef });
material.transparent = true

// Create a points object and add it to the scene
var points = new THREE.Points(geometry, material);
scene.add(points);

const loader = new THREE.TextureLoader();
loader.load(pointImage, function (texture) {
  material.map = texture;
  material.needsUpdate = true;
});

让陨石动起来

整体加个旋转就更晕了,非常好~

javascript 复制代码
var positions = points.geometry.attributes.position.array;
for (var i = 0; i < positions.length; i += 3) {
    positions[i+2] = positions[i+2] + 0.05;
    if (positions[i+2] > 100) {
        positions[i+2] = -100;
    }
}
points.rotation.z += 0.001;
points.geometry.attributes.position.needsUpdate = true;

完整代码

javascript 复制代码
<script setup>
import * as THREE from 'three';
import { onMounted } from 'vue';
import pointImage from './assets/point.png'

const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x4AB0F9, 0.015);
scene.background = new THREE.Color(0xffffff);

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

var geometry = new THREE.BufferGeometry();
var positionVertices = [];

// Create particles
var particleCount = 5000;
for (var i = 0; i < particleCount; i++) {
    var x = THREE.MathUtils.randFloatSpread(200);
    var y = THREE.MathUtils.randFloatSpread(200);
    var z = THREE.MathUtils.randFloatSpread(200);
    positionVertices.push(x, y, z);
}

// Add positionVertices to the geometry
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positionVertices, 3));

// Create a material
var material = new THREE.PointsMaterial({ color: 0xefefef });
material.transparent = true

// Create a points object and add it to the scene
var points = new THREE.Points(geometry, material);
scene.add(points);

const loader = new THREE.TextureLoader();
loader.load(pointImage, function (texture) {
  material.map = texture;
  material.needsUpdate = true;
});

// Create a sphere
var sphereGeometry = new THREE.SphereGeometry(3, 32, 32);
var sphereMaterial = new THREE.MeshBasicMaterial({color: 0xF3DC6B});
sphereMaterial.fog = false
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0, -80);
scene.add(sphere);

// Create a halo
var haloGeometry = new THREE.SphereGeometry(6, 32, 32);
var haloMaterial = new THREE.ShaderMaterial({
    uniforms: {
        time: { value: 0.0 }
    },
    vertexShader: `
        varying vec3 vNormal;
        varying vec2 vUv;
        void main() {
            vUv = uv;
            vNormal = normalize(normalMatrix * normal);
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `,
    fragmentShader: `
        varying vec3 vNormal;
        varying vec2 vUv;
        uniform float time;
        void main() {
            float intensity = pow(0.1 + 0.3 * (sin(time * 4.0) + 1.0)/2.0 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0) * intensity;
        }
    `,
    side: THREE.BackSide,
    blending: THREE.AdditiveBlending,
    transparent: true
});
var halo = new THREE.Mesh(haloGeometry, haloMaterial);
halo.position.set(0, 0, -81);
scene.add(halo);

function animate() {
  requestAnimationFrame(animate);

  haloMaterial.uniforms.time.value += 0.005;
  
  var positions = points.geometry.attributes.position.array;
  for (var i = 0; i < positions.length; i += 3) {
      positions[i+2] = positions[i+2] + 0.05;
      if (positions[i+2] > 100) {
          positions[i+2] = -100;
      }
  }
  points.rotation.z += 0.001;
  points.geometry.attributes.position.needsUpdate = true;

  renderer.render(scene, camera);
}
animate();

onMounted(() => {
  let canvas = document.getElementById('can');
  renderer = new THREE.WebGLRenderer({canvas: canvas});
  renderer.setSize(window.innerWidth, window.innerHeight);
});

</script>

<template>
  <div id="content">
    <canvas id="can"></canvas>
  </div>
</template>

<style scoped>
#content {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
#can {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
</style>

最后

也是在学习过程中,如果有什么问题,欢迎在评论区留言。

如果有什么比较好的想法想做出更加晕眩的效果,也欢迎提出来,共同研究一下。

相关推荐
用户789377339085319 小时前
Vue3 + Three.js 仓储数字孪生:按需渲染架构与五大核心功能复盘
vue.js·three.js
孙凯亮5 天前
Three.js VR 模拟器(Immersive Web Emulator)踩坑全记录:从报错到可用,避坑指南一次性奉上
前端·three.js
苏武难飞8 天前
THREE.JS实现一个魔法镜子!
前端·css·three.js
郝学胜-神的一滴8 天前
[简化版 Games 101] 计算机图形学 05:二维变换下
c++·unity·图形渲染·three.js·opengl·unreal
qq_120840937110 天前
Three.js 场景性能优化实战:首屏、帧率与内存的工程化治理
开发语言·javascript·性能优化·three.js
qq_120840937111 天前
Three.js 模型加载稳定性实战:从资源失败到可用发布的工程化方案
前端·javascript·vue.js·vue3·three.js
烛阴15 天前
Three.js 材质完全入门指南:让你的 3D 物体「活」起来
webgl·three.js
三维搬砖者21 天前
AI 解密大厂 Three.js 三维引擎开发 03|从经纬度到三维世界的坐标解码
webgl·three.js
一马平川的大草原1 个月前
基于Vue+Three.js实现三维油藏模型解析与可视化交互切割操作
vue.js·three.js·三维油藏模型
RulerMike1 个月前
three 实现简单机械臂逆运动
前端·ai编程·three.js