threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
339 lines (292 loc) • 10.5 kB
text/typescript
import {
BufferGeometry,
Camera,
Color,
IUniform,
Material,
MaterialEventMap,
MaterialParameters,
Object3D,
Scene,
WebGLProgramParametersWithUniforms,
WebGLRenderer,
} from 'three'
import type {IDisposable, IJSONSerializable} from 'ts-browser-helpers'
import type {MaterialExtension} from '../materials'
import type {ChangeEvent, IUiConfigContainer} from 'uiconfig.js'
import type {SerializationMetaType} from '../utils'
import type {IObject3D} from './IObject'
import {ISetDirtyCommonOptions} from './IObject'
import type {ITexture} from './ITexture'
import type {IImportResultUserData} from '../assetmanager'
import {AnimateTime} from '../utils'
export type IMaterialParameters = MaterialParameters & {customMaterialExtensions?: MaterialExtension[]}
// export type IMaterialEventTypes = 'dispose' | 'materialUpdate' | 'beforeRender' | 'beforeCompile' | 'afterRender' | 'textureUpdate' | 'beforeDeserialize'
// export type IMaterialEvent<T extends string = IMaterialEventTypes> = Event & {
// type: T
// bubbleToObject?: boolean
// bubbleToParent?: boolean
// material?: IMaterial
//
// texture?: ITexture
// oldTexture?: ITexture
//
// uiChangeEvent?: ChangeEvent
// }
export interface IMaterialEventMap extends MaterialEventMap{
beforeCompile: {
shader: WebGLProgramParametersWithUniforms
renderer: WebGLRenderer
}
beforeRender: {
renderer: WebGLRenderer
scene: Scene
camera: Camera
geometry: BufferGeometry
object: Object3D
}
afterRender: {
renderer: WebGLRenderer
scene: Scene
camera: Camera
geometry: BufferGeometry
object: Object3D
}
/**
* Fires when the material is set/added to a mesh
* This is applicable of all types of Object3D, like Line etc, not just Mesh
*/
addToMesh: {
object: Object3D
}
/**
* Fires when the material is changed/removed to a mesh
* This is applicable of all types of Object3D, like Line etc, not just Mesh
*/
removeFromMesh: {
object: Object3D
}
/**
* For internal use
*/
beforeDeserialize: {
data: unknown
meta?: SerializationMetaType
bubbleToObject: boolean
bubbleToParent: boolean
}
}
declare module 'three'{
export interface MaterialEventMap{
materialUpdate: {
// These are handled in dispatchEvent override in iMaterialCommons
bubbleToObject?: boolean
bubbleToParent?: boolean
uiChangeEvent?: ChangeEvent
} & IMaterialSetDirtyOptions
textureUpdate: {
texture: ITexture
bubbleToObject?: boolean
bubbleToParent?: boolean
uiChangeEvent?: ChangeEvent
}
select: { // todo remove?
ui?: boolean
// focusCamera?: boolean // todo ?
bubbleToObject?: boolean
bubbleToParent?: boolean
material: IMaterial
value?: /* IObject3D | */ IMaterial | null // todo is this required?
source?: string // who is triggering the event. so that recursive events can be prevented
} /* & IObjectSetDirtyOptions*/
}
}
export interface IMaterialSetDirtyOptions extends ISetDirtyCommonOptions{
/**
* @default true
*/
bubbleToObject?: boolean,
/**
* @default true
*/
needsUpdate?: boolean,
/**
* Change identifier that triggered the `setDirty` call.
* This is different from `key` in that it is used to identify the property/key that is changed. In many cases these could be same, but they could also be different eg, key might be x, with change being position.
*/
change?: string | keyof IMaterial
[key: string]: any
}
export interface IMaterialUserData extends IImportResultUserData{
uuid?: string // adding to userdata also, so that its saved in gltf
/**
* Automatically dispose material when not used by any object in the scene
* @default true
*/
disposeOnIdle?: boolean
renderToGBuffer?: boolean
/**
* Same as {@link renderToGBuffer} but for depth only, not normal or flags etc
*/
renderToDepth?: boolean
/**
* Flag to tell the scene to prefer `material.envMapIntensity` over `scene.envMapIntensity`
* only for materials that have envMapIntensity
*/
separateEnvMapIntensity?: boolean // default: false
/**
* The environment map to use in the `RootScene`. To use this, object with the material must be in the RootScene, and the key should exist in the `RootScene`'s `textureSlots`.
*
* only for materials that have envMap
*/
envMapSlotKey?: string
/**
* Automatically register this material in the {@link MaterialManager} when added to the scene.
* This provides hook to other plugins to extend the material, add uiconfig etc.
* @default true
*/
autoRegisterInManager?: boolean
cloneId?: string
cloneCount?: number
__envIntensity?: number // temp storage for envMapIntensity while rendering
__isVariation?: boolean
inverseAlphaMap?: boolean // only for physical material right now
/**
* See {@link MaterialManager.dispose} as {@link BaseGroundPlugin._refreshMaterial}
*/
runtimeMaterial?: boolean
/**
* See {@link GBufferPlugin}
*/
gBufferData?: {
materialId?: number
/**
* @default true
*/
tonemapEnabled?: boolean
[key: string]: any
}
/**
* Force a depth value in GBuffer.
* This is useful to force center values like 0 to the depth.
*/
forcedLinearDepth?: number // todo uiconfig for this in imaterial?
/**
* General flag to disable multiple plugins on the material at once, like SSAO, SSR, Bloom etc.
*/
pluginsDisabled?: boolean // todo uiconfig for this in imaterial?
// todo: move these to respective plugins
/**
* For SSCSPlugin
*/
sscsDisabled?: boolean
/**
* For SSRPlugin
*/
ssreflDisabled?: boolean
/**
* For SSRPlugin
*/
ssreflNonPhysical?: boolean
[key: string]: any
// legacy, to be removed
/**
* @deprecated
*/
setDirty?: (options?: IMaterialSetDirtyOptions) => void
/**
* @deprecated Use {@link postTonemap.tonemapEnabled} instead. This is kept because used in old files.
*/
postTonemap?: boolean
}
export interface AnimateTimeMaterial extends AnimateTime{from?: IMaterial}
export interface IMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends Material<TE>, IJSONSerializable, IDisposable, IUiConfigContainer {
constructor: {
TYPE: string
TypeSlug: string
MaterialProperties?: Record<string, any>
MapProperties?: string[]
InterpolateProperties?: string[]
MaterialTemplate?: IMaterialTemplate
}
assetType: 'material'
setDirty(options?: IMaterialSetDirtyOptions): void;
// clone?: ()=> any;
needsUpdate: boolean;
// toJSON same as three.js Material.toJSON
// toJSON(meta?: any): any;
// copyProps should be just setValues
setValues(parameters: Material|(MaterialParameters&{type?:string}), allowInvalidType?: boolean, clearCurrentUserData?: boolean, time?: AnimateTimeMaterial): this;
toJSON(meta?: SerializationMetaType, _internal?: boolean): any;
fromJSON(json: any, meta?: SerializationMetaType, _internal?: boolean): this | null;
extraUniformsToUpload: Record<string, IUniform>
materialExtensions: MaterialExtension[]
registerMaterialExtensions: (customMaterialExtensions: MaterialExtension[]) => void;
unregisterMaterialExtensions: (customMaterialExtensions: MaterialExtension[]) => void;
/**
* Managed internally, do not change manually
*/
generator?: IMaterialGenerator
/**
* Objects in the scene that are using this material.
* This is set in the {@link Object3DManager} when the objects are added/removed from the scene. Do not modify this set directly.
*/
appliedMeshes: Set<IObject3D>
lastShader?: WebGLProgramParametersWithUniforms
// Note: for userData: add _ in front of for private use, which is preserved while cloning but not serialisation, and __ for private use, which is not preserved while cloning and serialisation
userData: IMaterialUserData
/**
* Disposes the material from the GPU.
* Set force to false if not sure the material is used by any object in the scene.
* // todo add check for visible in scene also? or is that overkill
* @param force - when true, same as three.js dispose. when false, only disposes if disposeOnIdle not false and not used by any object in the scene. default: true
*/
dispose(force?: boolean): void
/**
* Clones the Material.
* This is a shallow clone, so the properties are copied by reference.
*
* @param track - if true, the clone id and count will be tracked in the userData and a suffix will be appended to the name. default - false
*/
clone(track?: boolean): this;
// optional from subclasses, added here for autocomplete
flatShading?: boolean
map?: ITexture | null
alphaMap?: ITexture | null
envMap?: ITexture | null
envMapIntensity?: number
aoMap?: ITexture | null
lightMap?: ITexture | null
normalMap?: ITexture | null
bumpMap?: ITexture | null
displacementMap?: ITexture | null
aoMapIntensity?: number
lightMapIntensity?: number
roughnessMap?: ITexture | null
metalnessMap?: ITexture | null
roughness?: number
metalness?: number
transmissionMap?: ITexture | null
transmission?: number
color?: Color
wireframe?: boolean
linewidth?: number
isRawShaderMaterial?: boolean
isPhysicalMaterial?: boolean
isLineMaterial?: boolean
isUnlitMaterial?: boolean
isGBufferMaterial?: boolean
isLineMaterial2?: boolean
isUnlitLineMaterial?: boolean
// [key: string]: any
}
export type IMaterialGenerator<T extends IMaterial = IMaterial> = (params: any)=>T
export interface IMaterialTemplate<T extends IMaterial = IMaterial, TP = any>{
templateUUID?: string,
name: string,
typeSlug?: string,
alias?: string[], // alternate names
materialType: string,
generator?: IMaterialGenerator<T>,
params?: TP
}