feat: optimize rendering

This commit is contained in:
TrèsAbhi committed 2025-08-11 11:25:25 -05:00
1 parent b2ee97b3d4
commit 9f15ded0c9
6 files changed
+40 -50

No files matched your search

@@ -1,6 +1,6 @@
import { Canvas } from '@react-three/fiber';
import { GuessEphemeral } from '../stores/guessEphemeral';
import { TankopediaDisplay } from '../stores/tankopediaPersistent/constants';
import { SmartCanvas } from './SmartCanvas';
import { Controls } from './Tankopedia/HeroSection/components/TankSandbox/components/Control';
import { Lighting } from './Tankopedia/HeroSection/components/TankSandbox/components/Lighting';
import { TankModel } from './Tankopedia/HeroSection/components/TankSandbox/components/TankModel';
@@ -13,7 +13,7 @@ export function GuessRenderer() {
const isRevealed = guessState !== null;
return (
<Canvas
<SmartCanvas
style={{
filter: `grayscale(${isRevealed ? 0 : 1}) contrast(${isRevealed ? 1 : CONTRAST}) brightness(${isRevealed ? 1 : BRIGHTNESS})`,
// filter: `drop-shadow(0 0 1rem ${Var('black-a11')})`,
@@ -25,6 +25,6 @@ export function GuessRenderer() {
<Controls distanceScale={2} zoomable={false} />
<Lighting display={TankopediaDisplay.Model} />
<TankModel />
</Canvas>
</SmartCanvas>
);
}
@@ -0,0 +1,20 @@
import { Canvas, type CanvasProps } from '@react-three/fiber';
import { forwardRef, useImperativeHandle, useRef } from 'react';
import { useOnScreen } from '../hooks/useOnScreen';
export const SmartCanvas = forwardRef<HTMLCanvasElement, CanvasProps>(
(props, ref) => {
const canvas = useRef<HTMLCanvasElement>(null);
const onScreen = useOnScreen(canvas);
useImperativeHandle(ref, () => canvas.current!, []);
return (
<Canvas
frameloop={onScreen ? 'demand' : 'never'}
ref={canvas}
{...props}
/>
);
},
);
@@ -1,4 +1,3 @@
import { invalidate } from '@react-three/fiber';
import type { QuicklimeEvent } from 'quicklime';
import { useEffect, useRef } from 'react';
import type { Group } from 'three';
@@ -19,8 +18,6 @@ export function CanvasContent() {
if (!gun.current) return;
gun.current.rotation.x = event.data.pitch;
invalidate();
}
modelTransformEvent.on(handleModelTransformEvent);
@@ -1,19 +1,12 @@
import { Canvas } from '@react-three/fiber';
import { SmartCanvas } from '../../../../../../../SmartCanvas';
import { CameraPositioner, zoom } from './CameraPositioner';
import { CanvasContent } from './CanvasContent';
export function FlexibilityCanvas() {
return (
<Canvas
frameloop="demand"
orthographic
camera={{
zoom,
rotation: [0, Math.PI / 2, 0],
}}
>
<SmartCanvas orthographic camera={{ zoom, rotation: [0, Math.PI / 2, 0] }}>
<CanvasContent />
<CameraPositioner />
</Canvas>
</SmartCanvas>
);
}
@@ -1,6 +1,6 @@
import { I_HAT, J_HAT } from '@blitzkit/core';
import { OrbitControls } from '@react-three/drei';
import { invalidate, useThree } from '@react-three/fiber';
import { invalidate, useFrame, useThree } from '@react-three/fiber';
import { useEffect, useRef } from 'react';
import { PerspectiveCamera, Vector3 } from 'three';
import { OrbitControls as OrbitControlsClass } from 'three-stdlib';
@@ -90,32 +90,16 @@ export function Controls({
-13,
).multiplyScalar(distanceScale);
useEffect(() => {
if (!orbitControls.current || !doAutoRotate) return;
const t0 = useRef(Date.now() / 1000);
useFrame(() => {
const now = Date.now() / 1000;
const t = now - t0.current;
const t0 = Date.now() / 1000;
let cancel = false;
function frame() {
if (!cancel) requestAnimationFrame(frame);
const now = Date.now() / 1000;
const t = now - t0;
camera.position
.copy(inspectModeInitialPosition)
.applyAxisAngle(I_HAT, (Math.PI / 32) * Math.sin(t / 9))
.applyAxisAngle(J_HAT, (-Math.PI / 16) * Math.sin(t / 7));
invalidate();
}
frame();
return () => {
cancel = true;
};
}, [doAutoRotate, camera]);
camera.position
.copy(inspectModeInitialPosition)
.applyAxisAngle(I_HAT, (Math.PI / 32) * Math.sin(t / 9))
.applyAxisAngle(J_HAT, (-Math.PI / 16) * Math.sin(t / 7));
});
useEffect(() => {
const unsubscribeTankopediaEphemeral = tankopediaEphemeralStore.subscribe(
@@ -229,8 +213,6 @@ export function Controls({
}, [camera, protagonistTank.id, antagonistTank.id]);
useEffect(() => {
let isInitialIteration = true;
function handleWheel(event: WheelEvent) {
event.preventDefault();
}
@@ -1,5 +1,5 @@
import { BLITZKIT_TANK_ICON_SIZE } from '@blitzkit/core';
import { Canvas, invalidate } from '@react-three/fiber';
import { invalidate } from '@react-three/fiber';
import {
forwardRef,
Suspense,
@@ -13,7 +13,6 @@ import { applyPitchYawLimits } from '../../../../../core/blitz/applyPitchYawLimi
import { modelTransformEvent } from '../../../../../core/blitzkit/modelTransform';
import { Pose, poseEvent } from '../../../../../core/blitzkit/pose';
import { useEquipment } from '../../../../../hooks/useEquipment';
import { useOnScreen } from '../../../../../hooks/useOnScreen';
import { useTankModelDefinition } from '../../../../../hooks/useTankModelDefinition';
import { Duel } from '../../../../../stores/duel';
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
@@ -26,6 +25,7 @@ import {
StaticArmor,
type ThicknessRange,
} from '../../../../Armor/components/StaticArmor';
import { SmartCanvas } from '../../../../SmartCanvas';
import { AutoClear } from './components/AutoClear';
import { Controls } from './components/Control';
import { InitialFogReveal } from './components/InitialFogReveal';
@@ -65,7 +65,6 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
const hideTankModelUnderArmor = TankopediaPersistent.use(
(state) => state.hideTankModelUnderArmor,
);
const onScreen = useOnScreen(canvas);
useEffect(() => {
if (rawDisplay === display) return;
@@ -204,10 +203,9 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
}, [display]);
return (
<Canvas
<SmartCanvas
ref={canvas}
scene={{ fog: naked ? undefined : fog.current }}
frameloop={onScreen ? 'demand' : 'never'}
gl={{
clippingPlanes: [],
localClippingEnabled: true,
@@ -248,7 +246,7 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
)}
<Lighting display={display} />
</Suspense>
</Canvas>
</SmartCanvas>
);
},
);