Skip to content

Commit 5f044e1

Browse files
feat(cientos): add camera shake component with demo and docs
1 parent 89659bf commit 5f044e1

File tree

9 files changed

+444
-0
lines changed

9 files changed

+444
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<script setup lang="ts">
2+
import { Backdrop, CameraShake, ContactShadows, Environment, OrbitControls, useGLTF } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { SRGBColorSpace } from 'three'
5+
import { computed } from 'vue'
6+
7+
const gl = {
8+
clearColor: '#333',
9+
alpha: true,
10+
outputColorSpace: SRGBColorSpace,
11+
}
12+
13+
const { state } = useGLTF('https://raw.githubusercontent.com/Tresjs/assets/main/models/gltf/ugly-naked-bunny/ugly-naked-bunny-animated.gltf', { draco: true })
14+
15+
const model = computed(() => state?.value?.scene)
16+
</script>
17+
18+
<template>
19+
<div class="hud-overlay"></div>
20+
21+
<TresCanvas
22+
v-bind="gl"
23+
>
24+
<TresPerspectiveCamera :position="[0, 1.25, 3]" />
25+
26+
<TresGroup name="model" :position="[0, -0.5, 0]" :scale="[0.5, 0.5, 0.5]">
27+
<primitive v-if="model" :object="model" />
28+
</TresGroup>
29+
30+
<Backdrop
31+
:floor="5"
32+
:segments="10"
33+
receive-shadow
34+
:scale="[20, 8.5, 1]"
35+
:position="[0, -0.5, -2]"
36+
>
37+
<TresMeshPhysicalMaterial color="orange" />
38+
</Backdrop>
39+
40+
<ContactShadows
41+
:position="[0, -0.475, 0]"
42+
:scale="5"
43+
:blur="1"
44+
:opacity="0.5"
45+
/>
46+
47+
<TresAmbientLight :intensity="0.5" />
48+
49+
<Suspense>
50+
<Environment preset="dawn" :environment-intensity="0.5" />
51+
</Suspense>
52+
53+
<OrbitControls make-default :max-polar-angle="Math.PI / 2" />
54+
55+
<CameraShake
56+
:intensity="1"
57+
:maxYaw="0.1"
58+
:maxPitch="0.05"
59+
:maxRoll="0.05"
60+
:yawFrequency="0.05"
61+
:pitchFrequency="0.2"
62+
:rollFrequency="0.2"
63+
:decayRate="0.65"
64+
/>
65+
</TresCanvas>
66+
</template>
67+
68+
<style scoped>
69+
.hud-overlay {
70+
position: absolute;
71+
z-index: 2;
72+
width: 90%;
73+
height: 100%;
74+
background-image: url('/camera-shake/fake-hud.svg');
75+
background-repeat: no-repeat;
76+
background-position: center;
77+
background-size: contain;
78+
pointer-events: none;
79+
left: 50%;
80+
transform: translateX(-50%);
81+
aspect-ratio: 486 / 274;
82+
}
83+
</style>

apps/cientos-docs-vitepress/component-list/components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export default [
121121
{ text: 'Sky', link: '/guide/staging/sky' },
122122
{ text: 'Stars', link: '/guide/staging/stars' },
123123
{ text: 'Smoke', link: '/guide/staging/smoke' },
124+
{ text: 'CameraShake', link: '/guide/staging/camera-shake' },
124125
{ text: 'AccumulativeShadows', link: '/guide/staging/accumulative-shadows' },
125126
{ text: 'ContactShadows', link: '/guide/staging/contact-shadows' },
126127
{ text: 'Precipitation', link: '/guide/staging/precipitation' },
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Camera Shake
2+
3+
`<CameraShake />` is a component that adds **natural**, *noise-driven motion* to the **active camera**.
4+
It offers **per-axis control**, **adjustable intensity**, and *optional decay* — perfect for *handheld feel*, *footsteps*, *impacts*, or *engine rumble* — and is based on the [Drei `CameraShake` component](https://drei.docs.pmnd.rs/staging/camera-shake#camerashake).
5+
6+
<DocsDemo>
7+
<CameraShakeDemo />
8+
</DocsDemo>
9+
10+
<details>
11+
<summary>Demo code</summary>
12+
13+
<<< @/.vitepress/theme/components/CameraShakeDemo.vue{0}
14+
</details>
15+
16+
## Usage
17+
18+
You can use `<CameraShake />` component without passing any props, but still if you want you can tweak the props to find the best setup for you
19+
20+
```vue{8}
21+
<template>
22+
<TresCanvas>
23+
<TresPerspectiveCamera :position="[0, 2, 5]" />
24+
25+
<!-- YOUR SCENE -->
26+
27+
<OrbitControls make-default />
28+
<CameraShake :intensity="0.5" />
29+
</TresCanvas>
30+
</template>
31+
```
32+
33+
::: info
34+
`<CameraShake />` is fully compatible with **`<OrbitControls />`**.
35+
To ensure it works *as expected*, make sure to add the **`make-default`** prop:
36+
37+
```vue
38+
<OrbitControls make-default />
39+
```
40+
:::
41+
42+
## Understanding `Pitch`, `Yaw`, and `Roll`
43+
<img class="mx-auto w-90%" src="/camera-shake/schema.webp" />
44+
45+
## Props
46+
47+
| **Prop** | **Description** | **Default** |
48+
|---------------------|-------------------------------------------------------------------------------------------------------------------|-------------|
49+
| `intensity` | **Controls the overall strength** of the shake effect. | `1` |
50+
| `decay` | **Enables gradual reduction** of shake intensity over time. | `false` |
51+
| `decayRate` | **Sets the speed** at which intensity decays per second when `decay` is enabled. Multiplied by `delta` each frame.| `0.65` |
52+
| `maxYaw` | **Maximum amplitude** for yaw (horizontal rotation) in radians. | `0.01` |
53+
| `maxPitch` | **Maximum amplitude** for pitch (vertical rotation) in radians. | `0.01` |
54+
| `maxRoll` | **Maximum amplitude** for roll (tilt) in radians. | `0.01` |
55+
| `yawFrequency` | Frequency of **yaw oscillation**, used with elapsed time in Simplex noise calculations. | `0.1` |
56+
| `pitchFrequency` | Frequency of **pitch oscillation**. | `0.1` |
57+
| `rollFrequency` | Frequency of **roll oscillation**. | `0.1` |
Lines changed: 1 addition & 0 deletions
Loading
179 KB
Loading
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<script setup lang="ts">
2+
import { CameraShake, OrbitControls } from '@tresjs/cientos'
3+
import { TresCanvas } from '@tresjs/core'
4+
import { NoToneMapping, SRGBColorSpace } from 'three'
5+
import { TresLeches, useControls } from '@tresjs/leches'
6+
7+
const gl = {
8+
clearColor: '#333',
9+
alpha: true,
10+
outputColorSpace: SRGBColorSpace,
11+
toneMapping: NoToneMapping,
12+
}
13+
14+
const {
15+
intensity,
16+
decay,
17+
decayRate,
18+
maxYaw,
19+
maxPitch,
20+
maxRoll,
21+
yawFrequency,
22+
pitchFrequency,
23+
rollFrequency,
24+
} = useControls({
25+
intensity: {
26+
label: 'Intensity',
27+
value: 1,
28+
min: 0,
29+
max: 2,
30+
step: 0.01,
31+
},
32+
decay: false,
33+
decayRate: {
34+
label: 'Decay Rate',
35+
value: 0.65,
36+
min: 0,
37+
max: 1,
38+
step: 0.01,
39+
},
40+
maxYaw: {
41+
label: 'Max Yaw',
42+
value: 0.01,
43+
min: 0,
44+
max: 0.2,
45+
step: 0.001,
46+
},
47+
maxPitch: {
48+
label: 'Max Pitch',
49+
value: 0.01,
50+
min: 0,
51+
max: 0.2,
52+
step: 0.001,
53+
},
54+
maxRoll: {
55+
label: 'Max Roll',
56+
value: 0.01,
57+
min: 0,
58+
max: 0.2,
59+
step: 0.001,
60+
},
61+
yawFrequency: {
62+
label: 'Yaw Freq',
63+
value: 0.5,
64+
min: 0,
65+
max: 2,
66+
step: 0.01,
67+
},
68+
pitchFrequency: {
69+
label: 'Pitch Freq',
70+
value: 0.5,
71+
min: 0,
72+
max: 2,
73+
step: 0.01,
74+
},
75+
rollFrequency: {
76+
label: 'Roll Freq',
77+
value: 0.4,
78+
min: 0,
79+
max: 2,
80+
step: 0.01,
81+
},
82+
}, {
83+
uuid: 'camera-shake-demo',
84+
})
85+
</script>
86+
87+
<template>
88+
<TresLeches
89+
class="top-0 important-right-4"
90+
uuid="camera-shake-demo"
91+
/>
92+
93+
<TresCanvas
94+
v-bind="gl"
95+
>
96+
<TresPerspectiveCamera :position="[0, 2, 5]" />
97+
98+
<TresMesh>
99+
<TresBoxGeometry :args="[1, 1, 1]" />
100+
<TresMeshBasicMaterial color="orange" />
101+
</TresMesh>
102+
103+
<TresMesh :position-x="-2.5">
104+
<TresSphereGeometry :args="[.5, 32, 32]" />
105+
<TresMeshBasicMaterial color="hotpink" />
106+
</TresMesh>
107+
108+
<TresMesh :position-x="2.5">
109+
<TresConeGeometry :args="[.5, 1, 32]" />
110+
<TresMeshBasicMaterial color="lime" />
111+
</TresMesh>
112+
113+
<TresGridHelper :args="[10, 10]" />
114+
115+
<OrbitControls make-default />
116+
117+
<CameraShake
118+
:intensity="intensity"
119+
:decay="decay"
120+
:decayRate="decayRate"
121+
:maxYaw="maxYaw"
122+
:maxPitch="maxPitch"
123+
:maxRoll="maxRoll"
124+
:yawFrequency="yawFrequency"
125+
:pitchFrequency="pitchFrequency"
126+
:rollFrequency="rollFrequency"
127+
/>
128+
</TresCanvas>
129+
</template>

packages/cientos/playground/vue/src/router/routes/staging.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ export const stagingRoutes = [
4444
name: 'Ocean',
4545
component: () => import('../../pages/staging/OceanDemo.vue'),
4646
},
47+
{
48+
path: '/staging/camera-shake',
49+
name: 'CameraShake',
50+
component: () => import('../../pages/staging/CameraShakeDemo.vue'),
51+
},
4752
{
4853
path: '/staging/bounds',
4954
name: 'Bounds',

0 commit comments

Comments
 (0)