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

Commit

Permalink
IR-2080 CSM Fixes (#10213)
Browse files Browse the repository at this point in the history
* fixCSMandLightReactivity

* repair reactivity

* pr fixes

* fix davids issue

* improvements
  • Loading branch information
DanielBelmes authored May 25, 2024
1 parent 75d677f commit 3b1da4b
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 116 deletions.
141 changes: 70 additions & 71 deletions packages/engine/src/scene/systems/ShadowSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,7 @@ import { createEntity, removeEntity, useEntityContext } from '@etherealengine/ec
import { defineQuery, QueryReactor } from '@etherealengine/ecs/src/QueryFunctions'
import { defineSystem, useExecute } from '@etherealengine/ecs/src/SystemFunctions'
import { AnimationSystemGroup } from '@etherealengine/ecs/src/SystemGroups'
import {
defineState,
getMutableState,
getState,
hookstate,
NO_PROXY,
useHookstate,
useMutableState
} from '@etherealengine/hyperflux'
import { defineState, getMutableState, getState, hookstate, NO_PROXY, useHookstate } from '@etherealengine/hyperflux'
import { Vector3_Back } from '@etherealengine/spatial/src/common/constants/MathConstants'
import {
createPriorityQueue,
Expand All @@ -74,11 +66,10 @@ import { DirectionalLightComponent } from '@etherealengine/spatial/src/renderer/
import { addObjectToGroup, GroupComponent } from '@etherealengine/spatial/src/renderer/components/GroupComponent'
import { MeshComponent } from '@etherealengine/spatial/src/renderer/components/MeshComponent'
import { ObjectLayerComponents } from '@etherealengine/spatial/src/renderer/components/ObjectLayerComponent'
import { useScene } from '@etherealengine/spatial/src/renderer/components/SceneComponents'
import { VisibleComponent } from '@etherealengine/spatial/src/renderer/components/VisibleComponent'
import { ObjectLayers } from '@etherealengine/spatial/src/renderer/constants/ObjectLayers'
import { CSM } from '@etherealengine/spatial/src/renderer/csm/CSM'
import { CSMHelper } from '@etherealengine/spatial/src/renderer/csm/CSMHelper'
//import { CSMHelper } from '@etherealengine/spatial/src/renderer/csm/CSMHelper'
import {
getShadowsEnabled,
useShadowsEnabled
Expand All @@ -89,7 +80,7 @@ import { compareDistanceToCamera } from '@etherealengine/spatial/src/transform/c
import {
EntityTreeComponent,
iterateEntityNode,
useTreeQuery
useChildWithComponent
} from '@etherealengine/spatial/src/transform/components/EntityTree'
import { TransformComponent } from '@etherealengine/spatial/src/transform/components/TransformComponent'
import { XRLightProbeState } from '@etherealengine/spatial/src/xr/XRLightProbeSystem'
Expand Down Expand Up @@ -123,10 +114,10 @@ const raycaster = new Raycaster()
raycaster.firstHitOnly = true
const raycasterPosition = new Vector3()

const EntityCSMReactor = (props: { entity: Entity; rendererEntity: Entity }) => {
const { entity, rendererEntity } = props
const renderSettings = useComponent(entity, RenderSettingsComponent)
const EntityCSMReactor = (props: { entity: Entity; rendererEntity: Entity; renderSettingsEntity: Entity }) => {
const { entity, rendererEntity, renderSettingsEntity } = props
const rendererComponent = useComponent(rendererEntity, RendererComponent)
const renderSettingsComponent = useComponent(renderSettingsEntity, RenderSettingsComponent)

const directionalLightComponent = useComponent(entity, DirectionalLightComponent)
const shadowMapResolution = useHookstate(getMutableState(RendererState).shadowMapResolution)
Expand All @@ -137,12 +128,15 @@ const EntityCSMReactor = (props: { entity: Entity; rendererEntity: Entity }) =>

useEffect(() => {
if (!directionalLightComponent.value) return
if (!directionalLightComponent.castShadow.value) return
const csm = new CSM({
light: directionalLight as DirectionalLight,
shadowMapSize: shadowMapResolution.value,
shadowBias: directionalLightComponent.shadowBias.value,
maxFar: directionalLightComponent.cameraFar.value,
lightIntensity: directionalLightComponent.intensity.value,
cascades: renderSettings.cascades.value
lightColor: directionalLightComponent.color.value,
cascades: renderSettingsComponent?.cascades.value
})
rendererComponent.csm.set(csm)
return () => {
Expand All @@ -154,41 +148,51 @@ const EntityCSMReactor = (props: { entity: Entity; rendererEntity: Entity }) =>
/** Must run after scene object system to ensure source light is not lit */
useExecute(
() => {
if (!directionalLightComponent.castShadow.value) return
directionalLight.visible = false
},
{ after: SceneObjectSystem }
)

useEffect(() => {
if (!csm) return
if (!directionalLightComponent.castShadow.value) return

csm.shadowBias = directionalLight.shadow.bias
csm.maxFar = directionalLightComponent.cameraFar.value
csm.shadowMapSize = shadowMapResolution.value

for (const light of csm.lights) {
light.color.copy(directionalLightComponent.color.value)
light.intensity = directionalLightComponent.intensity.value
light.shadow.bias = directionalLightComponent.shadowBias.value
light.shadow.mapSize.setScalar(shadowMapResolution.value)
csm.needsUpdate = true
light.shadow.radius = directionalLightComponent.shadowRadius.value
}
csm.needsUpdate = true
}, [
csm,
rendererComponent.csm,
shadowMapResolution,
directionalLightComponent?.shadowBias,
directionalLightComponent?.intensity,
directionalLightComponent?.color,
directionalLightComponent?.castShadow,
directionalLightComponent?.shadowRadius,
directionalLightComponent?.cameraFar
directionalLightComponent.shadowBias,
directionalLightComponent.intensity,
directionalLightComponent.color,
directionalLightComponent.castShadow,
directionalLightComponent.shadowRadius,
directionalLightComponent.cameraFar
])

useEffect(() => {
if (!csm) return
csm.cascades = renderSettings.cascades.value
csm.cascades = renderSettingsComponent.cascades.value
csm.needsUpdate = true
}, [csm, renderSettings.cascades])
}, [csm, renderSettingsComponent.cascades])

return <ChildCSMReactor rendererEntity={rendererEntity} />
return (
<QueryReactor
Components={[ShadowComponent, GroupComponent]}
ChildEntityReactor={EntityChildCSMReactor}
props={{ rendererEntity: rendererEntity }}
/>
)
}

const PlainCSMReactor = (props: { rendererEntity: Entity }) => {
Expand Down Expand Up @@ -222,22 +226,18 @@ const PlainCSMReactor = (props: { rendererEntity: Entity }) => {
}
}, [rendererComponent.csm, shadowMapResolution])

return <ChildCSMReactor rendererEntity={rendererEntity} />
}

const ChildCSMReactor = (props: { rendererEntity: Entity }) => {
const entities = useTreeQuery(props.rendererEntity)
return (
<>
{entities.map((entity) => (
<EntityChildCSMReactor key={entity} entity={entity} rendererEntity={props.rendererEntity} />
))}
</>
<QueryReactor
Components={[ShadowComponent, GroupComponent]}
ChildEntityReactor={EntityChildCSMReactor}
props={{ rendererEntity: rendererEntity }}
/>
)
}

const EntityChildCSMReactor = (props: { entity: Entity; rendererEntity: Entity }) => {
const { entity, rendererEntity } = props
const EntityChildCSMReactor = (props: { rendererEntity: Entity }) => {
const entity = useEntityContext()
const { rendererEntity } = props

const shadowComponent = useComponent(entity, ShadowComponent)
const groupComponent = useComponent(entity, GroupComponent)
Expand All @@ -246,6 +246,8 @@ const EntityChildCSMReactor = (props: { entity: Entity; rendererEntity: Entity }
useEffect(() => {
if (!csm || !shadowComponent.receive.value) return

if (!groupComponent) return

const objs = [...groupComponent.value] as Mesh<any, Material>[]
for (const obj of objs) {
if (obj.material) {
Expand All @@ -266,58 +268,63 @@ const EntityChildCSMReactor = (props: { entity: Entity; rendererEntity: Entity }
}

function _CSMReactor() {
const renderSettingsEntity = useEntityContext()
const rendererEntity = useScene(renderSettingsEntity)
const rendererEntity = useEntityContext()
const renderSettingsEntity = useChildWithComponent(rendererEntity, RenderSettingsComponent)

if (!rendererEntity) return null
if (!renderSettingsEntity) return null

return <CSMReactor renderSettingsEntity={renderSettingsEntity} rendererEntity={rendererEntity} />
return <CSMReactor rendererEntity={rendererEntity} renderSettingsEntity={renderSettingsEntity} />
}

function CSMReactor(props: { renderSettingsEntity: Entity; rendererEntity: Entity }) {
const { renderSettingsEntity, rendererEntity } = props
const rendererComponent = useComponent(rendererEntity, RendererComponent)
function CSMReactor(props: { rendererEntity: Entity; renderSettingsEntity: Entity }) {
const { rendererEntity, renderSettingsEntity } = props
//const rendererComponent = useComponent(rendererEntity, RendererComponent)

const renderSettingsComponent = useComponent(renderSettingsEntity, RenderSettingsComponent)

const xrLightProbeEntity = useHookstate(getMutableState(XRLightProbeState).directionalLightEntity)

const activeLightEntity = useHookstate(UndefinedEntity)

const rendererState = useMutableState(RendererState)
//const rendererState = useMutableState(RendererState)

useEffect(() => {
if (!rendererComponent) return
if (!rendererComponent.csm.value || !rendererState.nodeHelperVisibility.value) return
// useEffect(() => {
// if (!rendererComponent) return
// if (!rendererComponent.csm.value || !rendererState.nodeHelperVisibility.value) return

const helper = new CSMHelper()
rendererComponent.csmHelper.set(helper)
return () => {
helper.remove()
rendererComponent.csmHelper.set(null)
}
}, [rendererComponent, renderSettingsComponent?.csm, rendererState.nodeHelperVisibility])
// const helper = new CSMHelper()
// rendererComponent.csmHelper.set(helper)
// return () => {
// helper.remove()
// rendererComponent.csmHelper.set(null)
// }
// }, [rendererComponent, renderSettingsComponent.csm, rendererState.nodeHelperVisibility])

useEffect(() => {
if (rendererEntity === Engine.instance.viewerEntity && xrLightProbeEntity.value) {
activeLightEntity.set(xrLightProbeEntity.value)
return
}

if (renderSettingsComponent?.primaryLight.value) {
if (renderSettingsComponent.primaryLight.value) {
activeLightEntity.set(UUIDComponent.getEntityByUUID(renderSettingsComponent.primaryLight.value))
return
}

activeLightEntity.set(UndefinedEntity)
}, [xrLightProbeEntity.value, renderSettingsComponent?.primaryLight?.value])
}, [xrLightProbeEntity.value, renderSettingsComponent.primaryLight.value])

if (!renderSettingsComponent?.csm.value) return null
if (!renderSettingsComponent.csm.value) return null

if (!activeLightEntity.value) return <PlainCSMReactor rendererEntity={rendererEntity} key={rendererEntity} />

return (
<EntityCSMReactor entity={activeLightEntity.value} rendererEntity={rendererEntity} key={activeLightEntity.value} />
<EntityCSMReactor
entity={activeLightEntity.value}
rendererEntity={rendererEntity}
renderSettingsEntity={renderSettingsEntity}
/>
)
}

Expand Down Expand Up @@ -432,7 +439,6 @@ const updateDropShadowTransforms = () => {
}
}

const groupQuery = defineQuery([GroupComponent, VisibleComponent, ShadowComponent])
const rendererQuery = defineQuery([RendererComponent])

const execute = () => {
Expand All @@ -448,14 +454,7 @@ const execute = () => {
const { csm, csmHelper } = getComponent(entity, RendererComponent)
if (csm) {
csm.update()
if (csmHelper) csmHelper.update(csm)

/** hack fix to ensure CSM material is applied to all materials (which are not set reactively) */
for (const entity of groupQuery()) {
for (const obj of getComponent(entity, GroupComponent) as any as Mesh[]) {
if (obj.material && obj.receiveShadow) csm.setupMaterial(obj)
}
}
//if (csmHelper) csmHelper.update(csm)
}
}
}
Expand Down Expand Up @@ -489,7 +488,7 @@ const reactor = () => {
return (
<>
{useShadows ? (
<QueryReactor Components={[RenderSettingsComponent]} ChildEntityReactor={_CSMReactor} />
<QueryReactor Components={[RendererComponent]} ChildEntityReactor={_CSMReactor} />
) : (
<QueryReactor Components={[VisibleComponent, ShadowComponent]} ChildEntityReactor={DropShadowReactor} />
)}
Expand Down
Loading

0 comments on commit 3b1da4b

Please sign in to comment.