Skip to content

Commit

Permalink
feat: introduce MeshDistortMaterial
Browse files Browse the repository at this point in the history
  • Loading branch information
ctran authored and ctran committed Jul 9, 2024
1 parent 6e3d7b4 commit 699bc1e
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 2 deletions.
80 changes: 80 additions & 0 deletions .storybook/stories/MeshDistortMaterial.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
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 { MeshDistortMaterial } from '../../src/materials/MeshDistortMaterial'

export default {
title: 'Shaders/MeshDistortMaterial',
} 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,
meshDistortMaterial: MeshDistortMaterial

export const MDMStory = async () => {
const setupResult = Setup()
scene = setupResult.scene
camera = setupResult.camera
renderer = setupResult.renderer
animateLoop = setupResult.render

gui = new GUI({ title: MDMStory.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)

setupMeshDistortMaterial()
}

async function setupMeshDistortMaterial() {
const geometry = new THREE.SphereGeometry(1, 32, 32)
meshDistortMaterial = new MeshDistortMaterial({ color: '#f25042' })

meshDistortMaterial._radius.value = 0.2

const mesh = new THREE.Mesh(geometry, meshDistortMaterial)
mesh.scale.set(2, 4, 1)

scene.add(mesh)

createMeshDistortGUI()

animateLoop((time) => {
meshDistortMaterial.time = time * 0.0025
meshDistortMaterial.distort = THREE.MathUtils.lerp(meshDistortMaterial.distort, 0.4, 0.05)
})
}

/**
* Create gui for material properties
*/
function createMeshDistortGUI() {
if (materialGuiFolder) {
materialGuiFolder.destroy()
}

const matProps = gui.addFolder('MeshDistortMaterial id: ' + meshDistortMaterial.id)

matProps.addColor(meshDistortMaterial, 'color')
matProps.add(meshDistortMaterial._radius, 'value').min(0.01).max(0.5).step(0.01).name('radius')

materialGuiFolder = matProps
}

MDMStory.storyName = 'Sphere'
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { pcss, ... } from '@pmndrs/vanilla'
<li><a href="#meshreflectormaterial">MeshReflectorMaterial</a></li>
<li><a href="#shadermaterial">shaderMaterial</a></li>
<li><a href="#discardmaterial">MeshDiscardMaterial</a></li>
<li><a href="#meshdistortmaterial">MeshDistortMaterial</a></li>
<li><a href="#meshtransmissionmaterial">MeshTransmissionMaterial</a></li>
<li><a href="#spotlight">SpotLight</a></li>
</ul>
Expand Down Expand Up @@ -182,6 +183,16 @@ A material that discards fragments. It can be used to render nothing efficiently
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)

<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.

#### MeshTransmissionMaterial

[![storybook](https://img.shields.io/badge/-storybook-%23ff69b4)](https://pmndrs.github.io/drei-vanilla/?path=/story/shaders-meshtransmissionmaterial--mtm-story)
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"build-storybook": "build-storybook"
},
"dependencies": {
"glsl-noise": "^0.0.0",
"troika-three-text": "0.47.2"
},
"devDependencies": {
Expand Down Expand Up @@ -102,6 +103,7 @@
"lil-gui": "^0.19.1",
"prettier": "^2.4.1",
"pretty-quick": "^3.1.0",
"raw-loader": "^4.0.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"rimraf": "^3.0.2",
Expand All @@ -118,5 +120,6 @@
},
"peerDependencies": {
"three": ">=0.137"
}
},
"packageManager": "[email protected]"
}
1 change: 1 addition & 0 deletions src/helpers/glsl/distort.vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#pragma glslify: snoise3 = require(glsl-noise/simplex/3d)
64 changes: 64 additions & 0 deletions src/materials/MeshDistortMaterial.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { IUniform, MeshPhysicalMaterial, MeshPhysicalMaterialParameters } from 'three'
// @ts-ignore
import distort from '../helpers/glsl/distort.vert.glsl'

export class MeshDistortMaterial extends MeshPhysicalMaterial {
_time: IUniform<number>
_distort: IUniform<number>
_radius: IUniform<number>

constructor(parameters: MeshPhysicalMaterialParameters = {}) {
super(parameters)
this.setValues(parameters)
this._time = { value: 0 }
this._distort = { value: 0.4 }
this._radius = { value: 1 }
}

// FIXME Use `THREE.WebGLProgramParametersWithUniforms` type when able to target @types/[email protected]
onBeforeCompile(shader: { vertexShader: string; uniforms: { [uniform: string]: IUniform } }) {
shader.uniforms.time = this._time
shader.uniforms.radius = this._radius
shader.uniforms.distort = this._distort

shader.vertexShader = `
uniform float time;
uniform float radius;
uniform float distort;
${distort}
${shader.vertexShader}
`
shader.vertexShader = shader.vertexShader.replace(
'#include <begin_vertex>',
`
float updateTime = time / 50.0;
float noise = snoise(vec3(position / 2.0 + updateTime * 5.0));
vec3 transformed = vec3(position * (noise * pow(distort, 2.0) + radius));
`
)
}

get time() {
return this._time.value
}

set time(v) {
this._time.value = v
}

get distort() {
return this._distort.value
}

set distort(v) {
this._distort.value = v
}

get radius() {
return this._radius.value
}

set radius(v) {
this._radius.value = v
}
}
1 change: 1 addition & 0 deletions src/materials/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './SpotLightMaterial'
export * from './BlurPass'
export * from './ConvolutionMaterial'
export * from './MeshReflectorMaterial'
export * from './MeshDistortMaterial'
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7606,6 +7606,11 @@ glsl-inject-defines@^1.0.1:
glsl-token-string "^1.0.1"
glsl-tokenizer "^2.0.2"

glsl-noise@^0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/glsl-noise/-/glsl-noise-0.0.0.tgz#367745f3a33382c0eeec4cb54b7e99cfc1d7670b"
integrity sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==

[email protected]:
version "0.0.1"
resolved "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz"
Expand Down Expand Up @@ -12115,7 +12120,7 @@ [email protected]:

raw-loader@^4.0.2:
version "4.0.2"
resolved "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6"
integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==
dependencies:
loader-utils "^2.0.0"
Expand Down

0 comments on commit 699bc1e

Please sign in to comment.