From ebb8350913722200e2e6cf782066a935fda18563 Mon Sep 17 00:00:00 2001 From: Jaime Torrealba Date: Sat, 13 Sep 2025 23:04:20 +0100 Subject: [PATCH 1/3] fix: Smoke component - Reactivity - Default values - Correct random an unpredictable behavior --- docs/guide/staging/smoke.md | 3 +- .../vue/src/pages/staging/SmokeDemo.vue | 84 ++++++++++++------- src/core/staging/Smoke.vue | 64 ++++++-------- 3 files changed, 78 insertions(+), 73 deletions(-) diff --git a/docs/guide/staging/smoke.md b/docs/guide/staging/smoke.md index a0a6d2254..918f55d16 100644 --- a/docs/guide/staging/smoke.md +++ b/docs/guide/staging/smoke.md @@ -49,8 +49,7 @@ Notice that you can pass a texture in combination with props, to personalize yo
NameTypeDescriptionDefaultRequired
colorTresColorThe color of the smoke.
'#ffffff'No
opacitynumberThe strength of the opacity.
0.5No
speednumberThe rotation speed of the smoke.
-
0.4No
widthnumberThe base width.
-
10No
depthnumberThe base depth.
+
0.4No
depthnumberThe base depth.
1.5No
segmentsnumberThe number of smoke to render.
20No
texturestringThe texture of the smoke.
default component textureNo
depthTestbooleanThe depthTest.
diff --git a/playground/vue/src/pages/staging/SmokeDemo.vue b/playground/vue/src/pages/staging/SmokeDemo.vue index 1d2379fcf..ffb40e236 100644 --- a/playground/vue/src/pages/staging/SmokeDemo.vue +++ b/playground/vue/src/pages/staging/SmokeDemo.vue @@ -2,6 +2,49 @@ import { Box, OrbitControls, Smoke } from '@tresjs/cientos' import { TresCanvas } from '@tresjs/core' import { NoToneMapping, SRGBColorSpace } from 'three' +import { TresLeches, useControls } from '@tresjs/leches' +import '@tresjs/leches/styles' + +const { segments, opacity, speed, depth, color, depthTest } = useControls({ + segments: { + label: 'Segments', + value: 5, + min: 1, + max: 20, + step: 1, + }, + opacity: { + label: 'Opacity', + value: 0.5, + min: 0, + max: 1, + step: 0.1, + }, + speed: { + label: 'Speed', + value: 0.4, + min: 0, + max: 1, + step: 0.1, + }, + depth: { + label: 'Depth', + value: 0.3, + min: 0, + max: 1, + step: 0.1, + }, + color: { + type: 'color', + label: 'Color', + value: '#f7f7f7', + }, + depthTest: { + type: 'boolean', + label: 'Depth Test', + value: false, + }, +}) const gl = { clearColor: '#333', @@ -12,46 +55,25 @@ const gl = { diff --git a/src/core/staging/Smoke.vue b/src/core/staging/Smoke.vue index f6b3d1849..270c246ae 100644 --- a/src/core/staging/Smoke.vue +++ b/src/core/staging/Smoke.vue @@ -29,14 +29,6 @@ export interface SmokeProps { * @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial */ speed?: number - /** - * The base width. - * @default 4 - * @type {number} - * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/materials/MeshBasicMaterial - */ - width?: number /** * The base depth. * @default 10 @@ -74,15 +66,17 @@ export interface SmokeProps { const props = withDefaults(defineProps(), { opacity: 0.5, speed: 0.4, - width: 10, - depth: 1.5, - segments: 20, - texture: 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/clouds/defaultCloud.png', - color: '#ffffff', - depthTest: true, + depth: 0.3, + segments: 10, + texture: + 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/clouds/defaultCloud.png', + color: '#f7f7f7', + depthTest: false, }) -const { width, depth, segments, texture, color, depthTest, opacity, speed } = toRefs(props) +const { depth, segments, texture, color, depthTest, opacity, speed } = toRefs( + props, +) const smokeRef = shallowRef() const groupRef = shallowRef() @@ -91,27 +85,26 @@ defineExpose({ instance: smokeRef, }) -const smoke = [...[segments]].map((_, index) => ({ - x: width.value / 2 - Math.random() * width.value, - y: width.value / 2 - Math.random() * width.value, - scale: 0.4 + Math.sin(((index + 1) / segments.value) * Math.PI) * ((0.2 + Math.random()) * 10), - density: Math.max(0.2, Math.random()), - rotation: Math.max(0.002, 0.005 * Math.random()) * speed.value, -})) - -const calculateOpacity = (scale: number, density: number): number => (scale / 6) * density * opacity.value +const smoke = computed(() => + Array.from({ length: segments.value }, (_, index) => ({ + x: (Math.random() - 0.5) * 0.5, + y: (Math.random() - 0.5) * 0.1, + scale: Math.sin((index + 1) / segments.value), + })), +) const { map } = (await useTexture({ map: texture.value })) as { map: Texture } const { renderer, camera } = useTresContext() + const colorSpace = computed(() => renderer.value?.outputColorSpace) const { onBeforeRender } = useLoop() onBeforeRender(({ invalidate }) => { if (smokeRef.value && camera.value && groupRef.value) { - groupRef.value?.children.forEach((child: Object3D, index: number) => { - child.rotation.z += smoke[index].rotation + groupRef.value?.children.forEach((child: Object3D) => { + child.rotation.z += Math.max(0.002, 0.005 * Math.random()) * speed.value }) smokeRef.value.lookAt(camera.value?.position) invalidate() @@ -120,23 +113,14 @@ onBeforeRender(({ invalidate }) => { ``` -Notice that you can pass a texture in combination with props, to personalize your effect - -```vue - -``` ## Props + + + +
NameTypeDescriptionDefaultRequired
colorTresColorThe color of the smoke.
@@ -51,6 +33,13 @@ Notice that you can pass a texture in combination with props, to personalize yo
0.5No
speednumberThe rotation speed of the smoke.
0.4No
depthnumberThe base depth.
1.5No
segmentsnumberThe number of smoke to render.
-
20No
texturestringThe texture of the smoke.
+
20No
SpreadXnumberSpread factor on the X axis.
+
20No
SpreadYnumberSpread factor on the Y axis.
+
20No
Scalenumbercontrols the overall size of the smoke segments
+
1No
texturestringThe texture of the smoke.
default component textureNo
depthTestbooleanThe depthTest.
trueNo
diff --git a/playground/vue/src/pages/staging/SmokeDemo.vue b/playground/vue/src/pages/staging/SmokeDemo.vue index ffb40e236..90e0f9b6c 100644 --- a/playground/vue/src/pages/staging/SmokeDemo.vue +++ b/playground/vue/src/pages/staging/SmokeDemo.vue @@ -5,7 +5,7 @@ import { NoToneMapping, SRGBColorSpace } from 'three' import { TresLeches, useControls } from '@tresjs/leches' import '@tresjs/leches/styles' -const { segments, opacity, speed, depth, color, depthTest } = useControls({ +const { segments, opacity, speed, depth, color, depthTest, spreadY, spreadX, scale } = useControls({ segments: { label: 'Segments', value: 5, @@ -44,6 +44,27 @@ const { segments, opacity, speed, depth, color, depthTest } = useControls({ label: 'Depth Test', value: false, }, + spreadY: { + label: 'Spread Y', + value: 0.1, + min: 0, + max: 4, + step: 0.1, + }, + spreadX: { + label: 'Spread X', + value: 0.5, + min: 0, + max: 4, + step: 0.1, + }, + scale: { + label: 'Scale', + value: 1, + min: 0.1, + max: 4, + step: 0.1, + }, }) const gl = { @@ -66,6 +87,9 @@ const gl = { :depth="depth.value" :color="color.value" :depth-test="depthTest.value" + :spreadY="spreadY.value" + :spreadX="spreadX.value" + :scale="scale.value" /> diff --git a/src/core/staging/Smoke.vue b/src/core/staging/Smoke.vue index 7ee2a2e38..ec87fe3d5 100644 --- a/src/core/staging/Smoke.vue +++ b/src/core/staging/Smoke.vue @@ -19,7 +19,6 @@ export interface SmokeProps { * @default 0.5 * @type {number} * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial */ opacity?: number /** @@ -27,7 +26,6 @@ export interface SmokeProps { * @default 0.4 * @type {number} * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial */ speed?: number /** @@ -35,7 +33,6 @@ export interface SmokeProps { * @default 10 * @type {number} * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/geometries/PlaneGeometry */ depth?: number /** @@ -43,7 +40,6 @@ export interface SmokeProps { * @default 10 * @type {number} * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial */ segments?: number /** @@ -51,7 +47,6 @@ export interface SmokeProps { * @default 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/clouds/defaultCloud.png' * @type {string} * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial */ texture?: string /** @@ -59,9 +54,29 @@ export interface SmokeProps { * @default true * @type {boolean} * @memberof SmokeProps - * @see https://threejs.org/docs/#api/en/materials/MeshStandardMaterial */ depthTest?: boolean + /** + * Spread on the Y axis. + * @default 0.1 + * @type {number} + * @memberof SmokeProps + */ + spreadY?: number + /** + * Spread on the X axis. + * @default 0.5 + * @type {number} + * @memberof SmokeProps + */ + spreadX?: number + /** + * Scale. + * @default 1 + * @type {number} + * @memberof SmokeProps + */ + scale?: number } const props = withDefaults(defineProps(), { @@ -73,9 +88,12 @@ const props = withDefaults(defineProps(), { 'https://raw.githubusercontent.com/Tresjs/assets/main/textures/clouds/defaultCloud.png', color: '#f7f7f7', depthTest: false, + spreadY: 0.1, + spreadX: 0.5, + scale: 1, }) -const { depth, segments, texture, color, depthTest, opacity, speed } = toRefs( +const { depth, segments, texture, color, depthTest, opacity, speed, spreadY, spreadX, scale } = toRefs( props, ) @@ -88,9 +106,9 @@ defineExpose({ const smoke = computed(() => Array.from({ length: segments.value }, (_, index) => ({ - x: (Math.random() - 0.5) * 0.5, - y: (Math.random() - 0.5) * 0.1, - scale: Math.sin((index + 1) / segments.value), + x: (Math.random() - 0.5) * spreadX.value, + y: (Math.random() - 0.5) * spreadY.value, + scale: Math.sin((index + 1) / segments.value) * scale.value, })), ) @@ -117,9 +135,10 @@ onBeforeRender(() => { Date: Sat, 27 Sep 2025 21:21:17 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=94=A5=20Remove=20unused=20imports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/theme/components/SmokeDemo.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/.vitepress/theme/components/SmokeDemo.vue b/docs/.vitepress/theme/components/SmokeDemo.vue index 5e6cdef64..10e580a5b 100644 --- a/docs/.vitepress/theme/components/SmokeDemo.vue +++ b/docs/.vitepress/theme/components/SmokeDemo.vue @@ -1,5 +1,5 @@