Skip to content

Commit

Permalink
fix: shaderMaterial sync with drei
Browse files Browse the repository at this point in the history
  • Loading branch information
vis-prime committed Dec 5, 2023
1 parent 03cd182 commit dd7b867
Showing 1 changed file with 45 additions and 48 deletions.
93 changes: 45 additions & 48 deletions src/core/shaderMaterial.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,58 @@
import * as THREE from 'three'

type UniformValue =
| THREE.CubeTexture
| THREE.Texture
| Int32Array
| Float32Array
| THREE.Matrix4
| THREE.Matrix3
| THREE.Quaternion
| THREE.Vector4
| THREE.Vector3
| THREE.Vector2
| THREE.Color
| number
| boolean
| Array<any>
| null

type UniformProps = { [name: string]: UniformValue }

type ShaderMaterialInstance<TProps extends UniformProps> = THREE.ShaderMaterial & TProps

type ShaderMaterialParameters<TProps extends UniformProps> = THREE.ShaderMaterialParameters & Partial<TProps>

type ShaderMaterial<TProps extends UniformProps> = (new (
parameters?: ShaderMaterialParameters<TProps>
) => ShaderMaterialInstance<TProps>) & { key: string }

export function shaderMaterial<TProps extends UniformProps>(
uniforms: TProps,
export function shaderMaterial(
uniforms: {
[name: string]:
| THREE.CubeTexture
| THREE.Texture
| Int32Array
| Float32Array
| THREE.Matrix4
| THREE.Matrix3
| THREE.Quaternion
| THREE.Vector4
| THREE.Vector3
| THREE.Vector2
| THREE.Color
| number
| boolean
| Array<any>
| null
},
vertexShader: string,
fragmentShader: string,
onInit?: (material: ShaderMaterialInstance<TProps>) => void
onInit?: (material?: THREE.ShaderMaterial) => void
) {
const entries = Object.entries(uniforms)
const uniformDefs = Object.fromEntries(entries.map(([name, value]) => [name, { value }])) as {
[K in keyof TProps]: { value: TProps[K] }
}

class Material extends THREE.ShaderMaterial {
static key = THREE.MathUtils.generateUUID()

constructor(parameters?: ShaderMaterialParameters<TProps>) {
super({ uniforms: uniformDefs, vertexShader, fragmentShader })

for (const [name] of entries) {
const material = class extends THREE.ShaderMaterial {
public key: string = ''
constructor(parameters = {}) {
const entries = Object.entries(uniforms)
// Create uniforms and shaders
super({
uniforms: entries.reduce((acc, [name, value]) => {
const uniform = THREE.UniformsUtils.clone({ [name]: { value } })
return {
...acc,
...uniform,
}
}, {}),
vertexShader,
fragmentShader,
})
// Create getter/setters
entries.forEach(([name]) =>
Object.defineProperty(this, name, {
get: () => this.uniforms[name].value,
set: (v) => (this.uniforms[name].value = v),
})
}
)

// Assign parameters, this might include uniforms
Object.assign(this, parameters)

onInit?.(this as unknown as ShaderMaterialInstance<TProps>)
// Call onInit
if (onInit) onInit(this)
}
}

return Material as ShaderMaterial<TProps>
} as unknown as typeof THREE.ShaderMaterial & { key: string }
material.key = THREE.MathUtils.generateUUID()
return material
}

0 comments on commit dd7b867

Please sign in to comment.