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

Commit

Permalink
IR 1900 ECS Plugin Parameters by Shader, Various Bugfixes (#10136)
Browse files Browse the repository at this point in the history
* move plugin parameters to the component level

* set plugin parameters by shader

* fake users

* remove entire shader references in favor of parameter array

* cleanup

* noise offset conversion

* ensmoothify the noise plugin and make the uniforms actually do stuff

* noise plugin refinements

* plugin import/export

* fix material editor texture switching

* material editor texture modification hotfixes

* cleanup

* physical box projected plugins

* nonphysical box projection plugin

* handle cases where materials don't have names

* cleanup
  • Loading branch information
AidanCaruso authored May 14, 2024
1 parent a381816 commit b965dcf
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 236 deletions.
5 changes: 3 additions & 2 deletions packages/editor/src/components/materials/MaterialEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export function MaterialEditor(props: { materialUUID: EntityUUID }) {
prototypeName.set(material.type)

const parameters = useHookstate(0)

return (
<div style={{ position: 'relative' }}>
<InputGroup name="Name" label={t('editor:properties.mesh.material.name')}>
Expand Down Expand Up @@ -186,7 +187,7 @@ export function MaterialEditor(props: { materialUUID: EntityUUID }) {
values={materialComponent.parameters.value!}
onChange={(k) => async (val) => {
let prop
if (prototype.prototypeArguments![k].type === 'texture' && typeof val === 'string') {
if (prototype.prototypeArguments[k].type.value === 'texture') {
if (val) {
const priorUnload = textureUnloadMap.get(NO_PROXY)[k]
if (priorUnload) {
Expand Down Expand Up @@ -232,7 +233,7 @@ export function MaterialEditor(props: { materialUUID: EntityUUID }) {
<Button
onClick={() => {
setComponent(entity, MaterialComponent[MaterialComponents.State], {
pluginEntities: [...(materialComponent.pluginEntities.value ?? []), pluginByName[selectedPlugin.value]!]
pluginEntities: [pluginByName[selectedPlugin.value]]
})
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { getMutableState } from '@etherealengine/hyperflux'
import MaterialComponentIcon from '@mui/icons-material/LocalFloristTwoTone'
import { Grid } from '@mui/material'

import { EntityUUID, UUIDComponent, getComponent } from '@etherealengine/ecs'
import { EntityUUID, UUIDComponent, getOptionalComponent } from '@etherealengine/ecs'
import { MaterialSelectionState } from '@etherealengine/engine/src/scene/materials/MaterialLibraryState'
import { MaterialComponent, MaterialComponents } from '@etherealengine/spatial/src/renderer/materials/MaterialComponent'
import { ItemTypes } from '../../constants/AssetTypes'
Expand All @@ -58,10 +58,12 @@ export type MaterialLibraryEntryProps = {
}

const nodeDisplayName = (node: MaterialLibraryEntryType) => {
return getComponent(
UUIDComponent.getEntityByUUID(node.uuid as EntityUUID),
MaterialComponent[MaterialComponents.State]
).material?.name
return (
getOptionalComponent(
UUIDComponent.getEntityByUUID(node.uuid as EntityUUID),
MaterialComponent[MaterialComponents.State]
)?.material?.name ?? ''
)
}

export default function MaterialLibraryEntry(props: MaterialLibraryEntryProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { getMutableState, getState, useHookstate, useState } from '@etherealengi
import { Stack } from '@mui/material'

import { pathJoin } from '@etherealengine/common/src/utils/miscUtils'
import { EntityUUID, UUIDComponent, getComponent, useQuery } from '@etherealengine/ecs'
import { EntityUUID, UUIDComponent, UndefinedEntity, getComponent, useQuery } from '@etherealengine/ecs'
import { SourceComponent } from '@etherealengine/engine/src/scene/components/SourceComponent'
import {
createMaterialEntity,
Expand Down Expand Up @@ -109,7 +109,7 @@ export default function MaterialLibraryPanel() {
<Button
onClick={() => {
const newMaterial = new MeshBasicMaterial({ name: 'New Material' })
createMaterialEntity(newMaterial, '')
createMaterialEntity(newMaterial, '', UndefinedEntity)
}}
>
New
Expand Down
5 changes: 0 additions & 5 deletions packages/editor/src/functions/EditorControlFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,6 @@ const addOrRemoveComponent = <C extends Component<any, any>>(
}
}

export const testst = {
setComponent: function () {}
}

const modifyName = (entities: Entity[], name: string) => {
const scenes = getSourcesForEntities(entities)

Expand Down Expand Up @@ -246,7 +242,6 @@ const modifyMaterial = (nodes: string[], materialId: EntityUUID, properties: { [
material[k] = v
}
})
material.needsUpdate = true
}
}

Expand Down
22 changes: 11 additions & 11 deletions packages/editor/src/functions/addMediaNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import { getComponent, getMutableComponent } from '@etherealengine/ecs/src/Compo
import { Engine } from '@etherealengine/ecs/src/Engine'
import { defineQuery } from '@etherealengine/ecs/src/QueryFunctions'
import { AssetLoaderState } from '@etherealengine/engine/src/assets/state/AssetLoaderState'
import { SourceComponent } from '@etherealengine/engine/src/scene/components/SourceComponent'
import { createMaterialEntity } from '@etherealengine/engine/src/scene/materials/functions/materialSourcingFunctions'
import { ComponentJsonType } from '@etherealengine/engine/src/scene/types/SceneTypes'
import { getState } from '@etherealengine/hyperflux'
Expand Down Expand Up @@ -94,20 +93,21 @@ export async function addMediaNode(
(mesh: Mesh) => mesh?.isMesh
)[0]
if (!material) return
if (!UUIDComponent.getEntityByUUID(material.uuid as EntityUUID)) createMaterialEntity(material, url)

const materialEntity = UUIDComponent.getEntityByUUID(material.uuid as EntityUUID)
if (materialEntity) material = getMaterial(material.uuid as EntityUUID)!
const materialStateComponent = getMutableComponent(materialEntity, MaterialComponent[MaterialComponents.State])

iterateObject3D(intersected.object, (mesh: Mesh) => {
if (!mesh?.isMesh) return
const src = getComponent(materialEntity, SourceComponent)
if (!src) return
if (!UUIDComponent.getEntityByUUID(material.uuid as EntityUUID)) createMaterialEntity(material, src)
const materialComponent = getMutableComponent(mesh.entity, MaterialComponent[MaterialComponents.State])
if (materialComponent.instances.value)
materialComponent.instances.set([...materialComponent.instances.value, mesh.entity])
//if (unregisterMaterialInstance(mesh.material as Material, mesh.entity) === 0) {
// unregisterMaterial(mesh.material as Material)
//}
mesh.material = material
const materialInstanceComponent = getMutableComponent(
mesh.entity,
MaterialComponent[MaterialComponents.Instance]
)
if (materialInstanceComponent.uuid.value) materialInstanceComponent.uuid.set([material.uuid as EntityUUID])
if (materialStateComponent.instances.value)
materialStateComponent.instances.set([...materialStateComponent.instances.value, mesh.entity])
})
})
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ Ethereal Engine. All Rights Reserved.
import { CubeTexture, Material, Texture } from 'three'

import { EntityUUID, UUIDComponent, getComponent } from '@etherealengine/ecs'
import { MaterialComponent, MaterialComponents } from '@etherealengine/spatial/src/renderer/materials/MaterialComponent'
import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
import {
MaterialComponent,
MaterialComponents,
materialByName
} from '@etherealengine/spatial/src/renderer/materials/MaterialComponent'
import matches from 'ts-matches'
import { injectMaterialDefaults } from '../../../../scene/materials/functions/materialSourcingFunctions'
import { GLTFWriter } from '../GLTFExporter'
Expand All @@ -52,6 +57,8 @@ export function isOldEEMaterial(extension: any) {
.test(argValues)
}

export type MaterialExtensionPluginType = { id: string; parameters: { [key: string]: any } }

export type EEMaterialExtensionType = {
uuid: EntityUUID
name: string
Expand All @@ -62,7 +69,7 @@ export type EEMaterialExtensionType = {
contents: any
}
}
plugins: string[]
plugins: MaterialExtensionPluginType[]
}

export default class EEMaterialExporterExtension extends ExporterExtension {
Expand All @@ -75,7 +82,9 @@ export default class EEMaterialExporterExtension extends ExporterExtension {
matCache: Map<any, any>

writeMaterial(material: Material, materialDef) {
const argData = injectMaterialDefaults(material.uuid as EntityUUID)
const materialEntityUUID = materialByName[material.name]
const materialEntity = UUIDComponent.getEntityByUUID(materialEntityUUID)
const argData = injectMaterialDefaults(materialEntityUUID)
if (!argData) return
const result: any = {}
Object.entries(argData).map(([k, v]) => {
Expand Down Expand Up @@ -106,17 +115,19 @@ export default class EEMaterialExporterExtension extends ExporterExtension {
delete materialDef.normalTexture
delete materialDef.emissiveTexture
delete materialDef.emissiveFactor
const materialComponent = getComponent(
UUIDComponent.getEntityByUUID(material.uuid as EntityUUID),
MaterialComponent[MaterialComponents.State]
)
const materialComponent = getComponent(materialEntity, MaterialComponent[MaterialComponents.State])
const prototype = getComponent(materialComponent.prototypeEntity!, MaterialComponent[MaterialComponents.Prototype])
const materialStates = getComponent(materialEntity, MaterialComponent[MaterialComponents.State])
const materialPlugins = materialStates.pluginEntities?.map((entity) => {
const plugin = getComponent(entity, MaterialComponent[MaterialComponents.Plugin])
return { id: plugin?.plugin?.id ?? '', name: plugin?.parameters ?? '' }
})
materialDef.extensions = materialDef.extensions ?? {}
materialDef.extensions[this.name] = {
uuid: material.uuid,
name: material.name,
prototype: material.userData.type ?? Object.keys(prototype.prototypeConstructor!)[0],
plugins: [] /**@TODO PLUGINS */,
uuid: getComponent(materialEntity, UUIDComponent),
name: getComponent(materialEntity, NameComponent),
prototype: Object.keys(prototype.prototypeConstructor!)[0],
plugins: materialPlugins,
args: result
}
this.writer.extensionsUsed[this.name] = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ All portions of the code written by the Ethereal Engine team are Copyright © 20
Ethereal Engine. All Rights Reserved.
*/

import { Entity, EntityUUID, defineComponent, getOptionalMutableComponent } from '@etherealengine/ecs'
import { Entity, defineComponent, getOptionalMutableComponent } from '@etherealengine/ecs'
import { defineState, matches } from '@etherealengine/hyperflux'
import { matchesVector3 } from '@etherealengine/spatial/src/common/functions/MatchesUtils'
import { PluginObjectType } from '@etherealengine/spatial/src/common/functions/OnBeforeCompilePlugin'
import { MaterialComponent, MaterialComponents } from '@etherealengine/spatial/src/renderer/materials/MaterialComponent'
import { getPluginByName } from '@etherealengine/spatial/src/renderer/materials/materialFunctions'
import {
MaterialComponent,
MaterialComponents,
pluginByName
} from '@etherealengine/spatial/src/renderer/materials/MaterialComponent'
import { applyPluginShaderParameters } from '@etherealengine/spatial/src/renderer/materials/materialFunctions'
import { Vector3 } from 'three'
import {
ditheringAlphatestChunk,
Expand Down Expand Up @@ -57,8 +61,7 @@ export const TransparencyDitheringComponent = Array.from({ length: maxDitherPoin
distance: 2,
exponent: 2,
calculationType: ditherCalculationType.worldTransformed,
//internal
materialUUIDs: [] as EntityUUID[]
shaders: [] as string[]
}
},

Expand All @@ -75,12 +78,10 @@ export const TransparencyDitheringPlugin: PluginObjectType = {
id: 'TransparencyDithering',
priority: 10,
compile: (shader, renderer) => {
const pluginEntity = getPluginByName(TransparencyDitheringPlugin.id)
const pluginEntity = pluginByName[TransparencyDitheringPlugin.id]
const plugin = getOptionalMutableComponent(pluginEntity, MaterialComponent[MaterialComponents.Plugin])
if (!plugin) return

plugin.shader[(shader as any).shaderName].set(shader)

if (!shader.vertexShader.startsWith('varying vec3 vWorldPosition')) {
shader.vertexShader = shader.vertexShader.replace(
/#include <common>/,
Expand All @@ -97,12 +98,12 @@ export const TransparencyDitheringPlugin: PluginObjectType = {
'#include <common>\n' + ditheringFragUniform
)
shader.fragmentShader = shader.fragmentShader.replace(/#include <alphatest_fragment>/, ditheringAlphatestChunk)
shader.uniforms.centers = {
value: Array.from({ length: maxDitherPoints }, () => new Vector3())
}
shader.uniforms.exponents = { value: Array.from({ length: maxDitherPoints }, () => 1) }
shader.uniforms.distances = { value: Array.from({ length: maxDitherPoints }, () => 1) }
shader.uniforms.useWorldCalculation = { value: Array.from({ length: maxDitherPoints }, () => 1) }
shader.uniforms.maxDitherPoints = { value: 1 }
applyPluginShaderParameters(pluginEntity, shader, {
centers: Array.from({ length: maxDitherPoints }, () => new Vector3()),
exponents: Array.from({ length: maxDitherPoints }, () => 2),
distances: Array.from({ length: maxDitherPoints }, () => 3),
useWorldCalculation: Array.from({ length: maxDitherPoints }, () => 1),
maxDitherPoints: 1
})
}
}
36 changes: 15 additions & 21 deletions packages/engine/src/avatar/systems/TransparencyDitheringSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
useOptionalComponent
} from '@etherealengine/ecs'
import { useHookstate } from '@etherealengine/hyperflux'
import { NameComponent } from '@etherealengine/spatial/src/common/NameComponent'
import {
MaterialComponent,
MaterialComponents,
Expand All @@ -61,23 +62,17 @@ const execute = () => {

for (const entity of TransparencyDitheringQuery()) {
const ditherComponent = getComponent(entity, TransparencyDitheringComponent[0])
for (const uuid of ditherComponent.materialUUIDs) {
const materialComponent = getComponent(
UUIDComponent.getEntityByUUID(uuid),
MaterialComponent[MaterialComponents.State]
)
const material = materialComponent.material
if (!material) continue
for (const shader of ditherComponent.shaders) {
for (let i = 0; i < maxDitherPoints; i++) {
const ditherComponent = getOptionalComponent(entity, TransparencyDitheringComponent[i])
if (!ditherComponent) break
if (!material.shader || !pluginComponent.shader) break
const shader = pluginComponent.shader[material.name]
if (!shader?.uniforms) break
shader.uniforms.centers.value[i] = ditherComponent.center
shader.uniforms.exponents.value[i] = ditherComponent.exponent
shader.uniforms.distances.value[i] = ditherComponent.distance
shader.uniforms.useWorldCalculation.value[i] = ditherComponent.calculationType
if (!pluginComponent.parameters) break
const parameters = pluginComponent.parameters[shader]
if (!parameters) break
parameters['centers'].value[i] = ditherComponent.center
parameters['exponents'].value[i] = ditherComponent.exponent
parameters['distances'].value[i] = ditherComponent.distance
parameters['useWorldCalculation'].value[i] = ditherComponent.calculationType
}
}
}
Expand All @@ -92,7 +87,7 @@ const DitherReactor = () => {

const modelComponent = useComponent(entity, ModelComponent)
useEffect(() => {
getMutableComponent(entity, TransparencyDitheringComponent[0]).materialUUIDs.set([])
//getMutableComponent(entity, TransparencyDitheringComponent[0]).materialUUIDs.set([])
}, [modelComponent.src])

const sceneInstanceID = useModelSceneID(entity)
Expand All @@ -110,22 +105,21 @@ const DitherReactor = () => {
const DitherChildReactor = (props: { entity: Entity; rootEntity: Entity }) => {
const { entity, rootEntity } = props

const materialUUIDs = useComponent(rootEntity, TransparencyDitheringComponent[0]).materialUUIDs
//const materialUUIDs = useComponent(rootEntity, TransparencyDitheringComponent[0]).materialUUIDs
const materialComponentUUID = useOptionalComponent(entity, MaterialComponent[MaterialComponents.Instance])?.uuid
useEffect(() => {
if (!materialComponentUUID?.value) return
for (const materialUUID of materialComponentUUID.value) {
const material = UUIDComponent.getEntityByUUID(materialUUID)
const materialComponent = getMutableComponent(material, MaterialComponent[MaterialComponents.State])
const materialName = getComponent(material, NameComponent)
if (materialComponent.pluginEntities.value)
materialComponent.pluginEntities.set([
...materialComponent.pluginEntities.value,
pluginByName[TransparencyDitheringPlugin.id]
])
materialComponent.pluginEntities.set([pluginByName[TransparencyDitheringPlugin.id]])
materialComponent.material.value!.alphaTest = 0.5
materialComponent.material.value!.side = FrontSide
const ditheringComponent = getMutableComponent(rootEntity, TransparencyDitheringComponent[0])
ditheringComponent.materialUUIDs.set([...ditheringComponent.materialUUIDs.value, materialUUID])
if (!ditheringComponent.shaders.value.includes(materialName))
ditheringComponent.shaders.set([...ditheringComponent.shaders.value, materialName])
}
}, [materialComponentUUID])

Expand Down
Loading

0 comments on commit b965dcf

Please sign in to comment.