Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce MeshDistortMaterial #61

Merged
merged 1 commit into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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": "yarn@1.22.22"
}
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/three@0.160.0
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==

glsl-resolve@0.0.1:
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 @@ raw-body@2.5.1:

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