UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

119 lines (102 loc) 4.11 kB
import { createEffect } from "@lincode/reactivity" import * as THREE from "three" //@ts-ignore import { ProgressiveLightMap } from "three/examples/jsm/misc/ProgressiveLightMap" import Octahedron from "../display/primitives/Octahedron" import Plane from "../display/primitives/Plane" import { onBeforeRender } from "../events/onBeforeRender" import { getCameraRendered } from "../states/useCameraRendered" import { getRenderer } from "../states/useRenderer" // ShadowMap + LightMap Res and Number of Directional Lights const shadowMapRes = 512, lightMapRes = 1024, lightCount = 8 let object: any = new THREE.Mesh(), lightOrigin: any = null const dirLights: any = [], lightmapObjects: any = [] const blurEdges = true const blendWindow = 200 const lightRadius = 50 const ambientWeight = 0.5 // directional lighting "origin" lightOrigin = new THREE.Group() lightOrigin.position.set(60, 150, 100) // create 8 directional lights to speed up the convergence for (let l = 0; l < lightCount; l++) { const dirLight = new THREE.DirectionalLight(0xffffff, 1.0 / lightCount) dirLight.name = "Dir. Light " + l dirLight.position.set(200, 200, 200) dirLight.castShadow = true // dirLight.shadow.camera.near = 100 // dirLight.shadow.camera.far = 5000 dirLight.shadow.camera.right = 150 dirLight.shadow.camera.left = -150 dirLight.shadow.camera.top = 150 dirLight.shadow.camera.bottom = -150 dirLight.shadow.mapSize.width = shadowMapRes dirLight.shadow.mapSize.height = shadowMapRes lightmapObjects.push(dirLight) dirLights.push(dirLight) } const ground = new Plane() ground.rotationX = -90 ground.scale = 100 ground.y = -50 const groundMesh = ground.object3d // const groundMesh = new THREE.Mesh( // new THREE.PlaneGeometry(999 * scaleDown, 999 * scaleDown), // new THREE.MeshStandardMaterial({ color: 0xffffff, depthWrite: true }) // ) lightmapObjects.push(groundMesh) object = new Octahedron().object3d object.traverse(function (child: any) { if (child.isMesh) { child.material = new THREE.MeshStandardMaterial() lightmapObjects.push(child) } }) const lightTarget = new THREE.Group() lightTarget.position.set(0, 20, 0) for (let l = 0; l < dirLights.length; l++) { dirLights[l].target = lightTarget } object.add(lightTarget) createEffect(() => { const renderer = getRenderer() if (!renderer) return const camera = getCameraRendered() const progressiveSurfacemap = new ProgressiveLightMap(renderer, lightMapRes) progressiveSurfacemap.addObjectsToLightMap(lightmapObjects) const handle = onBeforeRender(() => { progressiveSurfacemap.update(camera, blendWindow, blurEdges) if (!progressiveSurfacemap.firstUpdate) progressiveSurfacemap.showDebugLightmap(true) // Manually Update the Directional Lights for (let l = 0; l < dirLights.length; l++) { // Sometimes they will be sampled from the target direction // Sometimes they will be uniformly sampled from the upper hemisphere if (Math.random() > ambientWeight) { dirLights[l].position.set( lightOrigin.position.x + Math.random() * lightRadius, lightOrigin.position.y + Math.random() * lightRadius, lightOrigin.position.z + Math.random() * lightRadius ) } else { // Uniform Hemispherical Surface Distribution for Ambient Occlusion const lambda = Math.acos(2 * Math.random() - 1) - 3.14159 / 2.0 const phi = 2 * 3.14159 * Math.random() dirLights[l].position.set( Math.cos(lambda) * Math.cos(phi) * 300 + object.position.x, Math.abs(Math.cos(lambda) * Math.sin(phi) * 300) + object.position.y + 20, Math.sin(lambda) * 300 + object.position.z ) } } }) return () => { handle.cancel() } }, [getRenderer, getCameraRendered])