Skip to content

Commit

Permalink
feat: add Example effect
Browse files Browse the repository at this point in the history
  • Loading branch information
abernier committed Jul 25, 2023
1 parent 56e3687 commit 4925fc8
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 0 deletions.
48 changes: 48 additions & 0 deletions .storybook/stories/Example.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { memo } from 'react'
import * as THREE from 'three'
import type { Meta, StoryObj } from '@storybook/react'
import { Box, useTexture } from '@react-three/drei'

import { Setup } from '../Setup'
import { EffectComposer, Example } from '../../src'
import { BlendFunction } from 'postprocessing'

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
const meta = {
title: 'Effect/Example',
component: Example,
decorators: [(Story) => <Setup>{Story()}</Setup>],
tags: ['autodocs'],
argTypes: {
blendFunction: {
control: 'select',
options: Object.keys(BlendFunction),
mapping: Object.keys(BlendFunction).reduce((acc, k) => {
acc[k] = BlendFunction[k]
return acc
}, {}),
},
opacity: { control: { type: 'range', min: 0, max: 1, step: 0.001 } },
color: { control: { type: 'color' } },
},
} satisfies Meta<typeof Example>

export default meta
type Story = StoryObj<typeof meta>

// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Primary: Story = {
render: ({ color, ...args }) => (
<>
<Box />

<EffectComposer>
<Example color={color && new THREE.Color(color)} {...args} />
</EffectComposer>
</>
),
args: {
blendFunction: BlendFunction.ADD,
color: 'red' as unknown as THREE.Color,
},
}
77 changes: 77 additions & 0 deletions src/effects/Example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as THREE from 'three'
import { useRef } from 'react'
import { useFrame, useThree } from '@react-three/fiber'
import { BlendFunction, Effect } from 'postprocessing'

import { wrapEffect } from '../util'

//
// Effect
//

const ExampleShader = {
fragment: `
uniform vec3 color;
uniform float time;
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
outputColor = vec4(color, 0.5 + (cos(time) / 2.0 + 0.5));
}
`,
}

type ExampleEffectOptions = {
/** The color for this effect */
color: THREE.Color
/** The blend function of this effect */
blendFunction?: BlendFunction
}

export class ExampleEffect extends Effect {
constructor({ color, blendFunction }: ExampleEffectOptions) {
super('LensFlareEffect', ExampleShader.fragment, {
blendFunction,
uniforms: new Map<string, THREE.Uniform>([
['color', new THREE.Uniform(color)],
['time', new THREE.Uniform(0)],
]),
})
}

update(_renderer: any, _inputBuffer: any, deltaTime: number) {
const time = this.uniforms.get('time')
if (time) {
time.value += deltaTime
}
}
}

//
// Component
//

const ExampleWrapped = wrapEffect(ExampleEffect)

type ExampleProps = React.ComponentPropsWithoutRef<typeof ExampleWrapped> & {
/** mouse */
mouse?: boolean
}

export const Example = ({ mouse = false, ...props }: ExampleProps) => {
const pointer = useThree(({ pointer }) => pointer)

const ref = useRef<ExampleEffect>(null)

useFrame(() => {
if (!mouse) return
if (!ref?.current) return

const uColor = ref.current.uniforms.get('color')
if (!uColor) return

uColor.value.r = pointer.x / 2.0 + 0.5
uColor.value.g = pointer.y / 2.0 + 0.5
})

return <ExampleWrapped ref={ref} {...props} />
}
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './effects/ColorDepth'
export * from './effects/Depth'
export * from './effects/DepthOfField'
export * from './effects/DotScreen'
export * from './effects/Example'
export * from './effects/Glitch'
export * from './effects/GodRays'
export * from './effects/Grid'
Expand Down

0 comments on commit 4925fc8

Please sign in to comment.