From 3823ad81681e0b0c04b7e17e46990968d12ceec7 Mon Sep 17 00:00:00 2001 From: Chau Tran Date: Mon, 15 Jul 2024 14:06:35 -0500 Subject: [PATCH] feat: introduce `MeshWobbleMaterial` (#63) This PR introduces `MeshWobbleMaterial` - Add `MeshWobbleMaterial` and its story - Adjust `MeshDistortMaterial` to expose a parameters interface --- .../stories/MeshDistortMaterial.stories.ts | 4 +- .../stories/MeshWobbleMaterial.stories.ts | 76 +++++++++++++++++++ README.md | 9 ++- src/materials/MeshDistortMaterial.ts | 19 ++++- src/materials/MeshWobbleMaterial.ts | 59 ++++++++++++++ src/materials/index.ts | 1 + 6 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 .storybook/stories/MeshWobbleMaterial.stories.ts create mode 100644 src/materials/MeshWobbleMaterial.ts diff --git a/.storybook/stories/MeshDistortMaterial.stories.ts b/.storybook/stories/MeshDistortMaterial.stories.ts index 55dab67..7e48d93 100644 --- a/.storybook/stories/MeshDistortMaterial.stories.ts +++ b/.storybook/stories/MeshDistortMaterial.stories.ts @@ -44,9 +44,7 @@ export const MDMStory = async () => { async function setupMeshDistortMaterial() { const geometry = new THREE.SphereGeometry(1, 32, 32) - meshDistortMaterial = new MeshDistortMaterial({ color: '#f25042' }) - - meshDistortMaterial._radius.value = 0.2 + meshDistortMaterial = new MeshDistortMaterial({ color: '#f25042', radius: 0.2 }) const mesh = new THREE.Mesh(geometry, meshDistortMaterial) mesh.scale.set(2, 4, 1) diff --git a/.storybook/stories/MeshWobbleMaterial.stories.ts b/.storybook/stories/MeshWobbleMaterial.stories.ts new file mode 100644 index 0000000..c346516 --- /dev/null +++ b/.storybook/stories/MeshWobbleMaterial.stories.ts @@ -0,0 +1,76 @@ +import * as THREE from 'three' +import { Setup } from '../Setup' +import GUI from 'lil-gui' +import { Meta } from '@storybook/html' +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' +import { MeshWobbleMaterial } from '../../src/materials/MeshWobbleMaterial' + +export default { + title: 'Shaders/MeshWobbleMaterial', +} as Meta // TODO: this should be `satisfies Meta` but commit hooks lag behind TS + +let gui: GUI, materialGuiFolder: GUI +let scene: THREE.Scene, + camera: THREE.PerspectiveCamera, + renderer: THREE.WebGLRenderer, + animateLoop: (arg0: (time: number) => void) => void, + meshWobbleMaterial: MeshWobbleMaterial + +export const MWMStory = async () => { + const setupResult = Setup() + scene = setupResult.scene + camera = setupResult.camera + renderer = setupResult.renderer + animateLoop = setupResult.render + + gui = new GUI({ title: MWMStory.storyName }) + camera.position.set(0, 0, 5) + + const controls = new OrbitControls(camera, renderer.domElement) + controls.update() + + const ambientLight = new THREE.AmbientLight() + scene.add(ambientLight) + + const dirLight = new THREE.DirectionalLight(0xabcdef, 10) + dirLight.position.set(1, 20, 1) + dirLight.castShadow = true + dirLight.shadow.mapSize.width = 1024 + dirLight.shadow.mapSize.height = 1024 + scene.add(dirLight) + + setupMeshWobbleMaterial() +} + +async function setupMeshWobbleMaterial() { + const geometry = new THREE.TorusGeometry(1, 0.25, 16, 100) + meshWobbleMaterial = new MeshWobbleMaterial({ color: '#f25042', factor: 0.75 }) + + const mesh = new THREE.Mesh(geometry, meshWobbleMaterial) + + scene.add(mesh) + + createMeshWobbleGUI() + + animateLoop((time) => { + meshWobbleMaterial.time = time * 0.0025 + }) +} + +/** + * Create gui for material properties + */ +function createMeshWobbleGUI() { + if (materialGuiFolder) { + materialGuiFolder.destroy() + } + + const matProps = gui.addFolder('MeshWobbleMaterial id: ' + meshWobbleMaterial.id) + + matProps.addColor(meshWobbleMaterial, 'color') + matProps.add(meshWobbleMaterial._factor, 'value').min(0.5).max(4).step(0.1).name('factor') + + materialGuiFolder = matProps +} + +MWMStory.storyName = 'Torus' diff --git a/README.md b/README.md index 3fe258f..b863b79 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ import { pcss, ... } from '@pmndrs/vanilla'
  • shaderMaterial
  • MeshDiscardMaterial
  • MeshDistortMaterial
  • +
  • MeshWobbleMaterial
  • MeshTransmissionMaterial
  • SpotLight
  • @@ -185,7 +186,7 @@ const mesh = new THREE.Mesh(geometry, new MeshDiscardMaterial()) #### MeshDistortMaterial -[![storybook](https://img.shields.io/badge/-storybook-%23ff69b4)](https://pmndrs.github.io/drei-vanilla/?path=/story/shaders-meshtransmissionmaterial--mdm-story) +[![storybook](https://img.shields.io/badge/-storybook-%23ff69b4)](https://pmndrs.github.io/drei-vanilla/?path=/story/shaders-meshdistortmaterial--mdm-story)

    Demo @@ -193,6 +194,12 @@ const mesh = new THREE.Mesh(geometry, new MeshDiscardMaterial()) This material makes your geometry distort following simplex noise. +#### MeshWobbleMaterial + +[![storybook](https://img.shields.io/badge/-storybook-%23ff69b4)](https://pmndrs.github.io/drei-vanilla/?path=/story/shaders-meshwobblematerial--mwm-story) + +This material makes your geometry wobble and wave around. It was taken from the [threejs-examples](https://threejs.org/examples/#webgl_materials_modified) and adapted into a self-contained material. + #### MeshTransmissionMaterial [![storybook](https://img.shields.io/badge/-storybook-%23ff69b4)](https://pmndrs.github.io/drei-vanilla/?path=/story/shaders-meshtransmissionmaterial--mtm-story) diff --git a/src/materials/MeshDistortMaterial.ts b/src/materials/MeshDistortMaterial.ts index 7ed5000..2ef97e4 100644 --- a/src/materials/MeshDistortMaterial.ts +++ b/src/materials/MeshDistortMaterial.ts @@ -2,17 +2,28 @@ import { IUniform, MeshPhysicalMaterial, MeshPhysicalMaterialParameters } from ' // @ts-ignore import distort from '../helpers/glsl/distort.vert.glsl' +export interface MeshDistortMaterialParameters { + time?: number + distort?: number + radius?: number +} + export class MeshDistortMaterial extends MeshPhysicalMaterial { _time: IUniform _distort: IUniform _radius: IUniform - constructor(parameters: MeshPhysicalMaterialParameters = {}) { + constructor({ + time = 0, + distort = 0.4, + radius = 1, + ...parameters + }: MeshDistortMaterialParameters & MeshPhysicalMaterialParameters = {}) { super(parameters) this.setValues(parameters) - this._time = { value: 0 } - this._distort = { value: 0.4 } - this._radius = { value: 1 } + this._time = { value: time } + this._distort = { value: distort } + this._radius = { value: radius } } // FIXME Use `THREE.WebGLProgramParametersWithUniforms` type when able to target @types/three@0.160.0 diff --git a/src/materials/MeshWobbleMaterial.ts b/src/materials/MeshWobbleMaterial.ts new file mode 100644 index 0000000..116a4c1 --- /dev/null +++ b/src/materials/MeshWobbleMaterial.ts @@ -0,0 +1,59 @@ +import { IUniform, MeshStandardMaterial, MeshStandardMaterialParameters } from 'three' + +export interface MeshWobbleMaterialParameters { + time?: number + factor?: number +} + +export class MeshWobbleMaterial extends MeshStandardMaterial { + _time: IUniform + _factor: IUniform + + constructor({ + time = 0, + factor = 1, + ...parameters + }: MeshStandardMaterialParameters & MeshWobbleMaterialParameters = {}) { + super(parameters) + this.setValues(parameters) + this._time = { value: time } + this._factor = { value: factor } + } + + // FIXME Use `THREE.WebGLProgramParametersWithUniforms` type when able to target @types/three@0.160.0 + override onBeforeCompile(shader: { vertexShader: string; uniforms: { [uniform: string]: IUniform } }) { + shader.uniforms['time'] = this._time + shader.uniforms['factor'] = this._factor + + shader.vertexShader = ` + uniform float time; + uniform float factor; + ${shader.vertexShader} + ` + shader.vertexShader = shader.vertexShader.replace( + '#include ', + `float theta = sin( time + position.y ) / 2.0 * factor; + float c = cos( theta ); + float s = sin( theta ); + mat3 m = mat3( c, 0, s, 0, 1, 0, -s, 0, c ); + vec3 transformed = vec3( position ) * m; + vNormal = vNormal * m;` + ) + } + + get time() { + return this._time.value + } + + set time(v) { + this._time.value = v + } + + get factor() { + return this._factor.value + } + + set factor(v) { + this._factor.value = v + } +} diff --git a/src/materials/index.ts b/src/materials/index.ts index 576164f..d9c55ac 100644 --- a/src/materials/index.ts +++ b/src/materials/index.ts @@ -5,3 +5,4 @@ export * from './BlurPass' export * from './ConvolutionMaterial' export * from './MeshReflectorMaterial' export * from './MeshDistortMaterial' +export * from './MeshWobbleMaterial'