threejs + react+hooks 创建一个基础的场景

简介

        使用 threejs + react 创建一个简单的 场景, 包括灯光,相机,阴影,以及一个简单的模型加载。


import React, {useEffect, useRef} from 'react'
import * as THREE from 'three' 
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

 function HelloShadow() {
  const canvasRef = useRef() 
  const scene = useRef(new THREE.Scene()).current
  const camera =useRef( new THREE.PerspectiveCamera()).current
  const renderer = useRef(new THREE.WebGLRenderer({alpha:true, antialias:true})).current
  let controls = new OrbitControls(camera, renderer.domElement)

  const meshList = []
  useEffect(() => {
    canvasRef.current.appendChild(renderer.domElement)
    init()
    initLight()
    initMesh()
  }, [])
 const init = () => {
    renderer.setSize(canvasRef.current.offsetWidth, canvasRef.current.offsetHeight)
    // renderer.setClearColor(0x111111)
    renderer.shadowMap.enabled = true

    camera.aspect = canvasRef.current.offsetWidth / canvasRef.current.offsetHeight 
    camera.fov = 45
    camera.near = 0.01
    camera.far = 2000
    camera.position.set(30, 20, 30)
    camera.lookAt(0, 0, 0)
    camera.updateProjectionMatrix()
    scene.add(camera)
    
    const axis = new THREE.AxesHelper(100)
    scene.add(axis) 

  }
 const initLight = () => {
    const light = new THREE.PointLight(0xFFFFFF, 1) 
    light.castShadow = true 
    light.position.set(0, 10, 0) 
    // light.target.position.set(-4, 0, -4) 
    scene.add(light)
    scene.add(light.target)

    const shadowCamera = light.shadow.camera 
    shadowCamera.left = -10 
    shadowCamera.right = 10 
    shadowCamera.top = 10 
    shadowCamera.bottom = -10 
    shadowCamera.updateProjectionMatrix()

    // const lightHelp = new THREE.DirectionalLightHelper(light)
    // scene.add(lightHelp)
    // const shadowHelper = new THREE.CameraHelper(shadowCamera)
    // scene.add(shadowHelper)
  }

 const initMesh = () => {
    const planeGeometry = new THREE.PlaneGeometry(40, 40) 
    const planeMaterial = new THREE.MeshPhongMaterial({color: 'gray'}) 
    const mesh = new THREE.Mesh(planeGeometry, planeMaterial)
    mesh.receiveShadow = true 
    mesh.rotation.x = Math.PI * -0.5
    scene.add(mesh) 

    const boxMaterial = new THREE.MeshPhongMaterial({color:0x88AACC}) 
    const boxGeometry = new THREE.BoxBufferGeometry(4, 4, 4)
    const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial) 
    boxMesh.castShadow = true 
    boxMesh.receiveShadow = true 
    boxMesh.position.set(5, 3, 0) 
    scene.add(boxMesh)

    const sphereGeometry = new THREE.SphereBufferGeometry(3, 32, 16)
    const sphereMaterial = new THREE.MeshPhongMaterial({color:0x88AACC})
    const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial) 
    sphereMesh.castShadow = true 
    sphereMesh.receiveShadow = true 
    sphereMesh.position.set(-4, 5, 0)
    scene.add(sphereMesh)
    meshList.push(boxMesh,sphereMesh)

    const loader = new GLTFLoader()
    let galaxy = "https://modelwarehouse.oss-cn-beijing.aliyuncs.com/Solaris%20bake%20pack%200601.glb"

    loader.load(galaxy,(glb) => {
      console.log(glb)
        let model = glb.scene
        model.scale.multiplyScalar(0.2) 
        scene.add(model) 
    },(e) => {
        const loaderProgress = Math.floor((e.loaded / e.total) * 100)
        console.log(loaderProgress)
      }
    )

    let geometry = new THREE.SphereBufferGeometry( 60, 320, 320 );
    let texture = new THREE.TextureLoader().load('https://img.alicdn.com/imgextra/i2/O1CN01uyMTm41zvuqddPG9A_!!6000000006777-0-tps-4096-2048.jpg');
    let material = new THREE.MeshBasicMaterial( {map: texture} );
    material.map.encoding = THREE.sRGBEncoding;
    let sphere = new THREE.Mesh( geometry, material );
    sphere.geometry.scale(1, 1, -1);
    scene.add( sphere );
  }

  const render = () => {
    // lightHelp.update() 
    meshList.forEach((item) => {
      item.rotation.y += 0.01
    })
    controls.update()
    controls.enableZoom = false  // 禁止缩放
    controls.minZoom = 0.1; // 缩放最小范围
    controls.maxZoom = 1;  // 最大
    renderer.render(scene, camera)
    window.requestAnimationFrame(render)
  }
  window.requestAnimationFrame(render)

  const handleResize = () => {
    camera.aspect = window.innerWidth / window.innerHeight 
    camera.updateProjectionMatrix() 
    renderer.setSize(window.innerWidth, window.innerHeight)
  }
  window.addEventListener('resize', handleResize)
  return (
    <div ref={canvasRef}></div>
  )
}

export default HelloShadow

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值