Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

fix csm and a bunch of other things #7924

Merged
merged 1 commit into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/editor/src/components/geometry/GeometryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ import { useHookstate } from '@etherealengine/hyperflux'
import DeleteIcon from '@mui/icons-material/DeleteForeverTwoTone'
import { Box, Grid, Stack, Typography } from '@mui/material'

import { Button } from '../inputs/Button'
import styles from '../layout/styles.module.scss'

const recalculateNormals = (geometry: BufferGeometry) => {
geometry.computeVertexNormals()
}

export default function GeometryEditor({ geometry }: { ['geometry']: BufferGeometry }) {
if (geometry === undefined) return <></>
const updateGeo = useHookstate(0)
Expand Down Expand Up @@ -46,6 +51,9 @@ export default function GeometryEditor({ geometry }: { ['geometry']: BufferGeome
<Typography variant={'h5'}>Geometry</Typography>
</Box>
<div className={styles.divider} />
<span>
<Button onClick={() => recalculateNormals(geometry)}>Recalculate Normals</Button>
</span>
<Box>
<Stack>
{geoData.attributes.map((attribData, idx) => {
Expand Down
4 changes: 1 addition & 3 deletions packages/editor/src/components/properties/NodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React, { PropsWithChildren } from 'react'
import { hasComponent, removeComponent } from '@etherealengine/engine/src/ecs/functions/ComponentFunctions'
import { dispatchAction } from '@etherealengine/hyperflux'

import { useEditorState } from '../../services/EditorServices'
import { SelectionAction } from '../../services/SelectionServices'
import PropertyGroup from './PropertyGroup'
import { EditorPropType } from './Util'
Expand Down Expand Up @@ -67,13 +66,12 @@ export const NodeEditor: React.FC<PropsWithChildren<NodeEditorProps>> = ({
entity,
component
}) => {
const editorState = useEditorState()
return (
<PropertyGroup
name={name}
description={description}
onClose={
editorState.advancedMode.value && component && hasComponent(entity, component)
component && hasComponent(entity, component)
? () => {
dispatchAction(SelectionAction.forceUpdate({}))
removeComponent(entity, component)
Expand Down
23 changes: 19 additions & 4 deletions packages/engine/src/assets/csm/CSM.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class CSM {
lights: DirectionalLight[]
lightSourcesCount: number
shaders: Map<Material, ShaderType> = new Map()
needsUpdate: boolean = false

constructor(data: CSMParams) {
this.camera = data.camera
Expand Down Expand Up @@ -126,13 +127,14 @@ export class CSM {
createLights(light?: DirectionalLight): void {
if (light) {
this.sourceLight = light
this.shadowBias = light.shadow.bias
for (let i = 0; i < this.cascades; i++) {
const lightClone = light.clone()
lightClone.castShadow = true
lightClone.visible = true
lightClone.matrixAutoUpdate = true
lightClone.matrixWorldAutoUpdate = true
this.parent.add(lightClone, lightClone.target)
this.parent.add(lightClone)
this.lights.push(lightClone)
lightClone.name = 'CSM_' + light.name
lightClone.target.name = 'CSM_' + light.target.name
Expand All @@ -153,7 +155,7 @@ export class CSM {
light.shadow.camera.far = this.lightFar
light.shadow.bias = this.shadowBias

this.parent.add(light, light.target)
this.parent.add(light)
this.lights.push(light)
light.name = 'CSM_' + light.name
light.target.name = 'CSM_' + light.target.name
Expand Down Expand Up @@ -261,6 +263,16 @@ export class CSM {
}

update(): void {
if (this.needsUpdate) {
for (const light of this.lights) {
this.updateFrustums()
light.shadow.map?.dispose()
light.shadow.map = null as any
light.shadow.camera.updateProjectionMatrix()
light.shadow.needsUpdate = true
}
this.needsUpdate = false
}
const camera = this.camera
const frustums = this.frustums
for (let i = 0; i < frustums.length; i++) {
Expand Down Expand Up @@ -290,6 +302,7 @@ export class CSM {

light.position.copy(_center)
light.target.position.copy(_center).add(this.lightDirection)
light.target.updateMatrixWorld(true)
}
this.parent.updateMatrixWorld(true)
}
Expand All @@ -312,6 +325,8 @@ export class CSM {
const breaksVec2 = []
const shaders = this.shaders

shaders.delete(material)

material.userData.CSMPlugin = {
id: 'CSM',
compile: (shader: ShaderType) => {
Expand All @@ -324,12 +339,11 @@ export class CSM {
shader.uniforms.shadowFar = { value: far }

shaders.set(material, shader)
this.needsUpdate = true
}
}

addOBCPlugin(material, material.userData.CSMPlugin)

shaders.delete(material)
}

updateUniforms(): void {
Expand Down Expand Up @@ -399,5 +413,6 @@ export class CSM {
material.needsUpdate = true
})
this.shaders.clear()
this.remove()
}
}
2 changes: 1 addition & 1 deletion packages/engine/src/assets/csm/Shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default {
getSpotLightInfo( spotLight, geometry, directLight );
#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )
spotLightShadow = spotLightShadows[ i ];
directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;
directLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;
#endif
RE_Direct( directLight, geometry, material, reflectedLight );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export class EEECSExporterExtension extends ExporterExtension implements GLTFExp
break
default:
const component = ComponentMap.get(field)!
if (!component?.toJSON) {
console.error(`[EEECSExporter]: Component ${field} does not have a toJSON method`)
continue
}
const compData = component.toJSON(entity, getMutableComponent(entity, component))
for (const [field, value] of Object.entries(compData)) {
data.push([`xrengine.${component.name}.${field}`, value])
Expand Down
2 changes: 2 additions & 0 deletions packages/engine/src/renderer/RendererState.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { defineState, syncStateWithLocalStorage } from '@etherealengine/hyperflux'

import { CSM } from '../assets/csm/CSM'
import { isMobile } from '../common/functions/isMobile'
import { RenderModes, RenderModesType } from './constants/RenderModes'

export const RendererState = defineState({
name: 'RendererState',
initial: () => ({
csm: null as CSM | null,
qualityLevel: isMobile ? 2 : 5, // range from 0 to 5
automatic: true,
// usePBR: true,
Expand Down
3 changes: 1 addition & 2 deletions packages/engine/src/renderer/WebGLRendererSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ export class EngineRenderer {
effectComposer: EffectComposerWithSchema = null!
/** @todo deprecate and replace with engine implementation */
xrManager: WebXRManager = null!
csm: CSM = null!
webGLLostContext: any = null

initialize() {
Expand Down Expand Up @@ -240,7 +239,7 @@ export class EngineRenderer {
cam.updateProjectionMatrix()
}

state.qualityLevel > 0 && this.csm?.updateFrustums()
state.qualityLevel > 0 && state.csm?.updateFrustums()
// Effect composer calls renderer.setSize internally
this.effectComposer.setSize(width, height, true)
this.needsResize = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,8 @@ import { RenderModes } from '../constants/RenderModes'
import { EngineRenderer, RenderSettingsState } from '../WebGLRendererSystem'

export const getShadowsEnabled = () => {
const rendererState = getMutableState(RendererState)
return (
!isMobileXRHeadset &&
!iOS &&
rendererState.useShadows.value &&
rendererState.renderMode.value === RenderModes.SHADOW
)
const rendererState = getState(RendererState)
return !isMobileXRHeadset && !iOS && rendererState.useShadows && rendererState.renderMode === RenderModes.SHADOW
}

export const useShadowsEnabled = () => {
Expand All @@ -28,9 +23,11 @@ export const useShadowsEnabled = () => {

export const updateShadowMap = () => {
const enabled = getShadowsEnabled()
const type = getState(RenderSettingsState).shadowMapType

EngineRenderer.instance.renderer.shadowMap.enabled = enabled
if (!enabled) return

const type = getState(RenderSettingsState).shadowMapType
EngineRenderer.instance.renderer.shadowMap.type = type
EngineRenderer.instance.renderer.shadowMap.needsUpdate = true

Expand Down
4 changes: 2 additions & 2 deletions packages/engine/src/renderer/functions/changeRenderMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { RenderPass } from 'postprocessing'
import { Light, MeshBasicMaterial, MeshNormalMaterial } from 'three'

import { Engine } from '@etherealengine/engine/src/ecs/classes/Engine'
import { getMutableState } from '@etherealengine/hyperflux'
import { getState } from '@etherealengine/hyperflux'

import { RenderModes } from '../constants/RenderModes'
import { RendererState } from '../RendererState'
Expand All @@ -14,7 +14,7 @@ import { updateShadowMap } from './RenderSettingsFunction'
* @param mode Mode which will be set to renderer
*/
export function changeRenderMode() {
const renderMode = getMutableState(RendererState).renderMode.value
const renderMode = getState(RendererState).renderMode

// revert any changes made by a render mode
switch (renderMode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ export const DirectionalLightComponent = defineComponent({
if (matches.number.test(json.shadowBias)) component.shadowBias.set(json.shadowBias)
if (matches.number.test(json.shadowRadius)) component.shadowRadius.set(json.shadowRadius)
if (matches.number.test(json.useInCSM)) component.useInCSM.set(json.useInCSM)

/**
* we need to put this here in case the CSM needs to grab the values, which can sometimes happen before the component reactor hooks
* @todo find a better way of doing this
*/
component.light.value.color.set(component.color.value)
component.light.value.intensity = component.intensity.value
component.light.value.castShadow = component.castShadow.value
component.light.value.shadow.camera.far = component.cameraFar.value
component.light.value.shadow.bias = component.shadowBias.value
component.light.value.shadow.radius = component.shadowRadius.value
component.light.value.shadow.mapSize.set(component.shadowMapResolution.value, component.shadowMapResolution.value)
},

toJSON: (entity, component) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/engine/src/scene/components/SkyboxComponent.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useEffect } from 'react'
import { Color, CubeTexture, sRGBEncoding } from 'three'

import { getMutableState, useHookstate } from '@etherealengine/hyperflux'
import { getMutableState, getState, useHookstate } from '@etherealengine/hyperflux'

import { AssetLoader } from '../../assets/classes/AssetLoader'
import { isClient } from '../../common/functions/isClient'
import { SceneState } from '../../ecs/classes/Scene'
import { defineComponent, useComponent } from '../../ecs/functions/ComponentFunctions'
import { RendererState } from '../../renderer/RendererState'
import { EngineRenderer } from '../../renderer/WebGLRendererSystem'
import { Sky } from '../classes/Sky'
import { SkyTypeEnum } from '../constants/SkyTypeEnum'
Expand Down Expand Up @@ -122,7 +123,7 @@ export const SkyboxComponent = defineComponent({
sky.turbidity = skyboxState.skyboxProps.value.turbidity
sky.luminance = skyboxState.skyboxProps.value.luminance

EngineRenderer.instance.csm?.lightDirection.copy(sky.sunPosition).multiplyScalar(-1)
getState(RendererState).csm?.lightDirection.copy(sky.sunPosition).multiplyScalar(-1)
background.set(
getPmremGenerator().fromCubemap(sky.generateSkyboxTextureCube(EngineRenderer.instance.renderer)).texture
)
Expand Down
2 changes: 1 addition & 1 deletion packages/engine/src/scene/functions/loadGLTFModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const parseECSData = (entity: Entity, data: [string, any][]): void => {
}

for (const [key, value] of Object.entries(prefabs)) {
const component = Array.from(ComponentJSONIDMap.keys()).find((jsonID) => jsonID === key)?.[0]
const component = Array.from(ComponentJSONIDMap.keys()).find((jsonID) => jsonID === key)
if (typeof component === 'undefined') {
console.warn(`Could not load component '${component}'`)
} else {
Expand Down
13 changes: 8 additions & 5 deletions packages/engine/src/scene/systems/SceneObjectSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
useOptionalComponent
} from '../../ecs/functions/ComponentFunctions'
import { defineSystem } from '../../ecs/functions/SystemFunctions'
import { updateShadowMap } from '../../renderer/functions/RenderSettingsFunction'
import { registerMaterial, unregisterMaterial } from '../../renderer/materials/functions/MaterialLibraryFunctions'
import { RendererState } from '../../renderer/RendererState'
import { EngineRenderer } from '../../renderer/WebGLRendererSystem'
Expand Down Expand Up @@ -95,7 +96,9 @@ function SceneObjectReactor(props: { entity: Entity; obj: Object3DWithEntity })
const { entity, obj } = props

const shadowComponent = useOptionalComponent(entity, ShadowComponent)
const forceBasicMaterials = useHookstate(getMutableState(RendererState).forceBasicMaterials)
const renderState = getMutableState(RendererState)
const forceBasicMaterials = useHookstate(renderState.forceBasicMaterials)
const csm = useHookstate(renderState.csm)

useEffect(() => {
return () => {
Expand All @@ -112,16 +115,16 @@ function SceneObjectReactor(props: { entity: Entity; obj: Object3DWithEntity })

useEffect(() => {
const shadow = shadowComponent?.value
const csm = getState(RendererState).csm
obj.traverse((child: Mesh<any, Material>) => {
if (!child.isMesh) return
child.castShadow = !!shadow?.cast
child.receiveShadow = !!shadow?.receive
if (child.material && child.receiveShadow) {
/** @todo store this somewhere such that if the CSM is destroyed and recreated it can set up the materials automatically */
EngineRenderer.instance.csm?.setupMaterial(child)
if (child.material && child.receiveShadow && csm) {
csm.setupMaterial(child)
}
})
}, [shadowComponent])
}, [shadowComponent?.cast, shadowComponent?.receive, csm])

return null
}
Expand Down
Loading