Skip to content

Commit

Permalink
feat: introduce MeshWobbleMaterial (#63)
Browse files Browse the repository at this point in the history
This PR introduces `MeshWobbleMaterial`

- Add `MeshWobbleMaterial` and its story
- Adjust `MeshDistortMaterial` to expose a parameters interface
  • Loading branch information
nartc authored Jul 15, 2024
1 parent 1b08c0c commit 3823ad8
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 8 deletions.
4 changes: 1 addition & 3 deletions .storybook/stories/MeshDistortMaterial.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
76 changes: 76 additions & 0 deletions .storybook/stories/MeshWobbleMaterial.stories.ts
Original file line number Diff line number Diff line change
@@ -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'
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { pcss, ... } from '@pmndrs/vanilla'
<li><a href="#shadermaterial">shaderMaterial</a></li>
<li><a href="#discardmaterial">MeshDiscardMaterial</a></li>
<li><a href="#meshdistortmaterial">MeshDistortMaterial</a></li>
<li><a href="#meshwobblematerial">MeshWobbleMaterial</a></li>
<li><a href="#meshtransmissionmaterial">MeshTransmissionMaterial</a></li>
<li><a href="#spotlight">SpotLight</a></li>
</ul>
Expand Down Expand Up @@ -185,14 +186,20 @@ 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)

<p>
<a href="https://codesandbox.io/s/l03yb"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/l03yb/screenshot.png" alt="Demo"/></a>
</p>

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)
Expand Down
19 changes: 15 additions & 4 deletions src/materials/MeshDistortMaterial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<number>
_distort: IUniform<number>
_radius: IUniform<number>

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
Expand Down
59 changes: 59 additions & 0 deletions src/materials/MeshWobbleMaterial.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { IUniform, MeshStandardMaterial, MeshStandardMaterialParameters } from 'three'

export interface MeshWobbleMaterialParameters {
time?: number
factor?: number
}

export class MeshWobbleMaterial extends MeshStandardMaterial {
_time: IUniform<number>
_factor: IUniform<number>

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 <begin_vertex>',
`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
}
}
1 change: 1 addition & 0 deletions src/materials/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './BlurPass'
export * from './ConvolutionMaterial'
export * from './MeshReflectorMaterial'
export * from './MeshDistortMaterial'
export * from './MeshWobbleMaterial'

0 comments on commit 3823ad8

Please sign in to comment.