Skip to content

Commit

Permalink
fix: stage can configure envmap
Browse files Browse the repository at this point in the history
  • Loading branch information
drcmda committed Nov 21, 2022
1 parent 38a231e commit 2d2d2e8
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 26 deletions.
18 changes: 13 additions & 5 deletions README.md
Expand Up @@ -2643,25 +2643,33 @@ Creates a "stage" with proper studio lighting, 0/0/0 top-centred, model-shadows,

```tsx
type StageShadows = Partial<AccumulativeShadowsProps> &
Partial<RandomizedLightProps> &
Partial<ContactShadowsProps> & {
type: 'contact' | 'accumulative'
/** Shadow plane offset, default: 0 */
offset?: number
/** Shadow bias, default: -0.0001 */
bias?: number
/** Shadow normal bias, default: 0 */
normalBias?: number
/** Shadow map size, default: 1024 */
size?: number
}
type StageProps = JSX.IntrinsicElements['group'] & {
type StageProps = {
/** Lighting setup, default: "rembrandt" */
preset?: 'rembrandt' | 'portrait' | 'upfront' | 'soft'
preset?:
| 'rembrandt'
| 'portrait'
| 'upfront'
| 'soft'
| { main: [x: number, y: number, z: number]; fill: [x: number, y: number, z: number] }
/** Controls the ground shadows, default: "contact" */
shadows?: boolean | 'contact' | 'accumulative' | StageShadows
/** Optional zoom-to-fit using <Bounds>, can also be a margin, default: true */
/** Optionally wraps and thereby centers the models using <Bounds>, can also be a margin, default: true */
adjustCamera?: boolean | number
/** The default environment, default: "city" */
environment?: PresetsType | null
environment?: PresetsType | Partial<EnvironmentProps>
/** The lighting intensity, default: 0.5 */
intensity?: number
}
Expand All @@ -2670,7 +2678,7 @@ type StageProps = JSX.IntrinsicElements['group'] & {
By default it gives you contact shadows and auto-centering.

```jsx
<Stage>
<Stage adjustCamera intensity={0.5} shadows="contact" environment="city">
<mesh />
</Stage>
```
Expand Down
4 changes: 2 additions & 2 deletions src/core/AccumulativeShadows.tsx
Expand Up @@ -221,7 +221,7 @@ export const AccumulativeShadows = React.forwardRef(
}
)

type RandomizedLightProps = JSX.IntrinsicElements['group'] & {
export type RandomizedLightProps = {
/** How many frames it will jiggle the lights, 1.
* Frames is context aware, if a provider like AccumulativeShadows exists, frames will be taken from there! */
frames?: number
Expand Down Expand Up @@ -265,7 +265,7 @@ export const RandomizedLight = React.forwardRef(
intensity = 1,
ambient = 0.5,
...props
}: RandomizedLightProps,
}: JSX.IntrinsicElements['group'] & RandomizedLightProps,
forwardRef: React.ForwardedRef<AccumulativeLightContext>
) => {
const gLights = React.useRef<THREE.Group>(null!)
Expand Down
14 changes: 7 additions & 7 deletions src/core/Environment.tsx
Expand Up @@ -20,7 +20,7 @@ import { presetsObj, PresetsType } from '../helpers/environment-assets'

const CUBEMAP_ROOT = 'https://market-assets.fra1.cdn.digitaloceanspaces.com/market-assets/hdris/'

type Props = {
export type EnvironmentProps = {
children?: React.ReactNode
frames?: number
near?: number
Expand Down Expand Up @@ -72,7 +72,7 @@ function setEnvProps(
}
}

export function EnvironmentMap({ scene, background = false, blur, map }: Props) {
export function EnvironmentMap({ scene, background = false, blur, map }: EnvironmentProps) {
const defaultScene = useThree((state) => state.scene)
React.useLayoutEffect(() => {
if (map) return setEnvProps(background, scene, defaultScene, map, blur)
Expand All @@ -86,7 +86,7 @@ export function useEnvironment({
preset = undefined,
encoding = undefined,
extensions,
}: Partial<Props>) {
}: Partial<EnvironmentProps>) {
if (preset) {
if (!(preset in presetsObj)) throw new Error('Preset must be one of: ' + Object.keys(presetsObj).join(', '))
files = presetsObj[preset]
Expand Down Expand Up @@ -114,7 +114,7 @@ export function useEnvironment({
return texture
}

export function EnvironmentCube({ background = false, scene, blur, ...rest }: Props) {
export function EnvironmentCube({ background = false, scene, blur, ...rest }: EnvironmentProps) {
const texture = useEnvironment(rest)
const defaultScene = useThree((state) => state.scene)
React.useLayoutEffect(() => {
Expand All @@ -137,7 +137,7 @@ export function EnvironmentPortal({
path,
preset = undefined,
extensions,
}: Props) {
}: EnvironmentProps) {
const gl = useThree((state) => state.gl)
const defaultScene = useThree((state) => state.scene)
const camera = React.useRef<CubeCamera>(null!)
Expand Down Expand Up @@ -188,7 +188,7 @@ declare global {
}
}

function EnvironmentGround(props: Props) {
function EnvironmentGround(props: EnvironmentProps) {
const textureDefault = useEnvironment(props)
const texture = props.map || textureDefault

Expand All @@ -207,7 +207,7 @@ function EnvironmentGround(props: Props) {
)
}

export function Environment(props: Props) {
export function Environment(props: EnvironmentProps) {
return props.ground ? (
<EnvironmentGround {...props} />
) : props.map ? (
Expand Down
41 changes: 29 additions & 12 deletions src/core/Stage.tsx
@@ -1,8 +1,13 @@
import * as React from 'react'
import { Environment } from './Environment'
import { EnvironmentProps, Environment } from './Environment'
import { ContactShadowsProps, ContactShadows } from './ContactShadows'
import { Center } from './Center'
import { AccumulativeShadowsProps, AccumulativeShadows, RandomizedLight } from './AccumulativeShadows'
import {
AccumulativeShadowsProps,
RandomizedLightProps,
AccumulativeShadows,
RandomizedLight,
} from './AccumulativeShadows'
import { useBounds, Bounds } from './Bounds'
import { PresetsType } from '../helpers/environment-assets'

Expand All @@ -26,25 +31,33 @@ const presets = {
}

type StageShadows = Partial<AccumulativeShadowsProps> &
Partial<RandomizedLightProps> &
Partial<ContactShadowsProps> & {
type: 'contact' | 'accumulative'
/** Shadow plane offset, default: 0 */
offset?: number
/** Shadow bias, default: -0.0001 */
bias?: number
/** Shadow normal bias, default: 0 */
normalBias?: number
/** Shadow map size, default: 1024 */
size?: number
}

type StageProps = JSX.IntrinsicElements['group'] & {
type StageProps = {
/** Lighting setup, default: "rembrandt" */
preset?: 'rembrandt' | 'portrait' | 'upfront' | 'soft'
preset?:
| 'rembrandt'
| 'portrait'
| 'upfront'
| 'soft'
| { main: [x: number, y: number, z: number]; fill: [x: number, y: number, z: number] }
/** Controls the ground shadows, default: "contact" */
shadows?: boolean | 'contact' | 'accumulative' | StageShadows
/** Optionally wraps and thereby centers the models using <Bounds>, can also be a margin, default: true */
adjustCamera?: boolean | number
/** The default environment, default: "city" */
environment?: PresetsType | null
environment?: PresetsType | Partial<EnvironmentProps>
/** The lighting intensity, default: 0.5 */
intensity?: number
}
Expand All @@ -65,15 +78,18 @@ export function Stage({
environment = 'city',
preset = 'rembrandt',
...props
}: StageProps) {
const config = presets[preset]
}: JSX.IntrinsicElements['group'] & StageProps) {
const config = typeof preset === 'string' ? presets[preset] : preset
const [{ radius, height }, set] = React.useState({ radius: 0, width: 0, height: 0, depth: 0 })
const shadowBias = (shadows as StageShadows)?.bias ?? -0.0001
const normalBias = (shadows as StageShadows)?.normalBias ?? 0
const shadowSize = (shadows as StageShadows)?.size ?? 1024
const shadowOffset = (shadows as StageShadows)?.offset ?? 0
const contactShadow = shadows === 'contact' || (shadows as StageShadows)?.type === 'contact'
const accumulativeShadow = shadows === 'accumulative' || (shadows as StageShadows)?.type === 'accumulative'
const shadowSpread = { ...(typeof shadows === 'object' ? shadows : {}) }
const environmentProps = !environment ? null : typeof environment === 'string' ? { preset: environment } : environment

return (
<>
<ambientLight intensity={intensity / 3} />
Expand All @@ -83,6 +99,7 @@ export function Stage({
intensity={intensity * 2}
castShadow={!!shadows}
shadow-bias={shadowBias}
shadow-normalBias={normalBias}
shadow-mapSize={shadowSize}
/>
<pointLight
Expand Down Expand Up @@ -114,10 +131,10 @@ export function Stage({
{...(shadowSpread as AccumulativeShadowsProps)}
>
<RandomizedLight
amount={8}
radius={radius}
ambient={0.5}
intensity={1}
amount={(shadowSpread as RandomizedLightProps).amount ?? 8}
radius={(shadowSpread as RandomizedLightProps).radius ?? radius}
ambient={(shadowSpread as RandomizedLightProps).ambient ?? 0.5}
intensity={(shadowSpread as RandomizedLightProps).intensity ?? 1}
position={[config.main[0] * radius, config.main[1] * radius, config.main[2] * radius]}
size={radius * 4}
bias={-shadowBias}
Expand All @@ -126,7 +143,7 @@ export function Stage({
</AccumulativeShadows>
)}
</group>
{environment && <Environment preset={environment} />}
{environment && <Environment {...environmentProps} />}
</>
)
}

0 comments on commit 2d2d2e8

Please sign in to comment.