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>

最后

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

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

相关推荐
Mintopia9 小时前
Three.js 加载模型文件:从二进制到像素的奇幻漂流
前端·javascript·three.js
良辰未晚1 天前
基于全屏 Quad 的 Three.js 后处理全解析
three.js
Mintopia1 天前
Three.js 材质与灯光:一场像素级的光影华尔兹
前端·javascript·three.js
Mintopia1 天前
Three.js 3D 世界中的噪声运动:当数学与像素共舞
前端·javascript·three.js
阿怼丶11 天前
🔥Three.js轮廓线高亮神器来啦!自定义高亮选中效果只需一个类搞定!
前端·three.js
小桥风满袖11 天前
Three.js-硬要自学系列36之专项学习包围盒
前端·css·three.js
Mintopia11 天前
Three.js 模块化开发:代码界的乐高搭建指南
前端·javascript·three.js
刘皇叔code12 天前
Three.js中LightProbe的应用
three.js
小桥风满袖12 天前
Three.js-硬要自学系列35之专项学习盒子辅助器
前端·css·three.js
魂断蓝桥66613 天前
如何基于three.js(webgl)引擎架构,实现3D机房园区,数据中心消防系统
webgl·数字孪生·three.js·物联网3d·3d机房·、3d工厂、3d工业园区、智慧制造、智慧工业、智慧工厂·bim管理系·3d消防·消防演习模拟