> 文档中心 > 基于 three.js 的圣诞树

基于 three.js 的圣诞树

在这里插入图片描述

前言

快到圣诞节了,用当前所学的做个简易版圣诞树送给女朋友。

五角星

const top_corner_g = new THREE.ConeBufferGeometry(0.5, 1, 4)top_corner_g.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0.5, 0))const top_m = new THREE.MeshStandardMaterial({  color: 'rgb(255, 215, 0)',  roughness: 0.5,  metalness: 0.5})const top_corner = new THREE.Mesh(top_corner_g, top_m)top_corner.layers.enable(1) // 发光效果通道top_corner.castShadow = falsetop_corner.receiveShadow = falseconst top = new THREE.Group()const top_c1 = top_corner.clone()top.add(top_c1)const top_c2 = top_corner.clone()top_c2.rotation.set(1 * 2 * Math.PI / 5, 0, 0)top.add(top_c2)const top_c3 = top_corner.clone()top_c3.rotation.set(2 * 2 * Math.PI / 5, 0, 0)top.add(top_c3)const top_c4 = top_corner.clone()top_c4.rotation.set(3 * 2 * Math.PI / 5, 0, 0)top.add(top_c4)const top_c5 = top_corner.clone()top_c5.rotation.set(4 * 2 * Math.PI / 5, 0, 0)top.add(top_c5)top.position.set(0, 12, 0)tree.add(top)

雪花飘落

let fallSpeen = 0.04let amount = 500let sprite_m = new THREE.SpriteMaterial({ map: snow_map })for (let i = 0; i < amount; i ++){  let particle = new THREE.Sprite(sprite_m)  particle.position.x = randomRange(-20, 20)  particle.position.y = randomRange(-5, 40)  particle.position.z = randomRange(-20, 20)  particle.scale.x = particle.scale.y = particle.scale.z = 0.5  particle.v = new THREE.Vector3(0, -fallSpeen, 0)  particle.v.z = (randomRange(-fallSpeen, fallSpeen))  particle.v.x = (randomRange(-fallSpeen, fallSpeen))  particle.rotation.x = Math.PI / 2  particles.push(particle)  scene.add(particle)}
function animate() {...for (let i = 0; i < particles.length; i++) {  letparticle = particles[i]  let pp = particle.position  pp.add(particle.v)  if (pp.y < -5) pp.y = 40  if (pp.x > 20) pp.x = -20  else if (pp.x < -20) pp.x = 20  if (pp.z > 20) pp.z = -20  else if (pp.z < -20) pp.z = 20}...}

发光通道

<script type="x-shader/x-vertex" id="vertexshader">  varying vec2 vUv;  void main() {    vUv = uv;    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);  }</script><script type="x-shader/x-fragment" id="fragmentshader">  uniform sampler2D baseTexture;  uniform sampler2D bloomTexture;  varying vec2 vUv;  void main() {    gl_FragColor = (texture2D(baseTexture, vUv) + vec4(1.0) * texture2D(bloomTexture, vUv));  }</script>
const renderScene = new RenderPass(scene, camera)constbloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85)bloomPass.threshold = 0bloomPass.strength = 1.5bloomPass.radius = 0bloomComposer = new EffectComposer(renderer)bloomComposer.renderToScreen = falsebloomComposer.addPass(renderScene)bloomComposer.addPass(bloomPass)const finalPass = new ShaderPass(  new THREE.ShaderMaterial({    uniforms: {      baseTexture: { value: null },      bloomTexture: { value: bloomComposer.renderTarget2.texture },    },    vertexShader: document.getElementById('vertexshader').textContent,    fragmentShader: document.getElementById('fragmentshader').textContent,    defines: {},  }),  'baseTexture')finalPass.needsSwap = truefinalComposer = new EffectComposer(renderer)finalComposer.addPass(renderScene)finalComposer.addPass(finalPass)function darkenNonBloomed(obj) {  if (obj instanceof THREE.Scene) {    materials.scene = obj.background    obj.background = null    return  }  if (obj instanceof THREE.Sprite || (obj.isMesh && bloomLayer.test(obj.layers) === false)) {    materials[obj.uuid] = obj.material    obj.material = darkMaterial  }}function restoreMaterial(obj) {  if (obj instanceof THREE.Scene) {    obj.background = materials.scene    delete materials.background    return  }  if (materials[obj.uuid]) {    obj.material = materials[obj.uuid]    delete materials[obj.uuid]  }}function animate() {...scene.traverse(darkenNonBloomed)bloomComposer.render()scene.traverse(restoreMaterial)finalComposer.render()...}