【Three.js】雪花圣诞树

10 篇文章 1 订阅
9 篇文章 7 订阅

在这里插入图片描述
在这里插入图片描述

前言

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

五角星

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 = false
top_corner.receiveShadow = false
const 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.04
let amount = 500
let 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 = 0
bloomPass.strength = 1.5
bloomPass.radius = 0
bloomComposer = new EffectComposer(renderer)
bloomComposer.renderToScreen = false
bloomComposer.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 = true
finalComposer = 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()
	...
}

相关项目

🚩——坦克大战
📦—— 立体库房
🎄—— 圣诞树
✅—— 程序员升职记
🏀—— 投个篮吧
💖——粒子爱心

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饺子大魔王12138

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值