mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
faster lighting
This commit is contained in:
1 parent
9b7aa13d61
commit
7739dbd0a3
4 files changed
+19
-23
No files matched your search
+13
-10
@@ -1,3 +1,4 @@
|
|||||||
|
import { ContactShadows } from "@react-three/drei";
|
||||||
import { useFrame } from "@react-three/fiber";
|
import { useFrame } from "@react-three/fiber";
|
||||||
import { clamp, times } from "lodash-es";
|
import { clamp, times } from "lodash-es";
|
||||||
import { Quicklime } from "quicklime";
|
import { Quicklime } from "quicklime";
|
||||||
@@ -12,25 +13,24 @@ import { HemisphereLight, SpotLight, type Group } from "three";
|
|||||||
import { degToRad, lerp } from "three/src/math/MathUtils.js";
|
import { degToRad, lerp } from "three/src/math/MathUtils.js";
|
||||||
import { Tankopedia } from "../../../../../../stores/tankopedia";
|
import { Tankopedia } from "../../../../../../stores/tankopedia";
|
||||||
import { TankopediaPersistent } from "../../../../../../stores/tankopediaPersistent";
|
import { TankopediaPersistent } from "../../../../../../stores/tankopediaPersistent";
|
||||||
import { HelpingSpotLight } from "../../../../../HelpingSpotLight";
|
|
||||||
|
|
||||||
const ANGLE = degToRad(12);
|
const ANGLE = degToRad(12);
|
||||||
const REVEAL_ANIMATION_TIME = 3;
|
const REVEAL_ANIMATION_TIME = 3;
|
||||||
const TRANSITION_ANIMATION_TIME = 0.5;
|
const TRANSITION_ANIMATION_TIME = 0.5;
|
||||||
|
|
||||||
const LIGHTS_COUNT = 4;
|
const LIGHTS_COUNT = 3;
|
||||||
const THETA_OFFSET = degToRad(180 - 45);
|
const THETA_OFFSET = degToRad(180 - 45);
|
||||||
const LIGHT_DISTANCE = 20;
|
const LIGHT_DISTANCE = 20;
|
||||||
const LIGHT_HEIGHT_0 = 4;
|
const LIGHT_HEIGHT_0 = 4;
|
||||||
const LIGHT_HEIGHT_1 = 6;
|
const LIGHT_HEIGHT_1 = 6;
|
||||||
const INTENSITY_0 = 6 * 9;
|
const INTENSITY_0 = 2 ** 6.5;
|
||||||
const INTENSITY_1 = 3 * 9;
|
const INTENSITY_1 = 2 ** 3.5;
|
||||||
const HEMISPHERE_INTENSITY = 2;
|
const HEMISPHERE_INTENSITY = 2 ** 1.2;
|
||||||
|
|
||||||
export const transitionEvent = new Quicklime<number>(0);
|
export const transitionEvent = new Quicklime<number>(0);
|
||||||
|
|
||||||
export function Lighting() {
|
export function Lighting() {
|
||||||
const wrapper = useRef<Group>(null!);
|
const wrapper = useRef<Group>(null);
|
||||||
|
|
||||||
const highGraphics = TankopediaPersistent.use((state) => state.highGraphics);
|
const highGraphics = TankopediaPersistent.use((state) => state.highGraphics);
|
||||||
const requestedDisplay = Tankopedia.use((state) => state.requestedDisplay);
|
const requestedDisplay = Tankopedia.use((state) => state.requestedDisplay);
|
||||||
@@ -61,6 +61,8 @@ export function Lighting() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<ContactShadows blur={2 ** 1} opacity={2 ** 1} />
|
||||||
|
|
||||||
{animate && (
|
{animate && (
|
||||||
<Animator
|
<Animator
|
||||||
t0={t0}
|
t0={t0}
|
||||||
@@ -73,7 +75,7 @@ export function Lighting() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<group ref={wrapper}>
|
<group ref={wrapper}>
|
||||||
<hemisphereLight intensity={0} color="#ffffff" groundColor="#afafaf" />
|
<hemisphereLight intensity={0} color="#d2e9ff" groundColor="#85490c" />
|
||||||
|
|
||||||
{times(LIGHTS_COUNT, (index) => {
|
{times(LIGHTS_COUNT, (index) => {
|
||||||
const x = index / (LIGHTS_COUNT - 1);
|
const x = index / (LIGHTS_COUNT - 1);
|
||||||
@@ -86,8 +88,7 @@ export function Lighting() {
|
|||||||
const intensity = lerp(INTENSITY_0, INTENSITY_1, x);
|
const intensity = lerp(INTENSITY_0, INTENSITY_1, x);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HelpingSpotLight
|
<spotLight
|
||||||
userData={{ index }}
|
|
||||||
key={index}
|
key={index}
|
||||||
position={position}
|
position={position}
|
||||||
intensity={intensity}
|
intensity={intensity}
|
||||||
@@ -109,13 +110,15 @@ interface AnimatorProps {
|
|||||||
|
|
||||||
t0: RefObject<number>;
|
t0: RefObject<number>;
|
||||||
animationTime: RefObject<number>;
|
animationTime: RefObject<number>;
|
||||||
wrapper: RefObject<Group>;
|
wrapper: RefObject<Group | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Animator({ stop, t0, animationTime, wrapper }: AnimatorProps) {
|
function Animator({ stop, t0, animationTime, wrapper }: AnimatorProps) {
|
||||||
const requestedDisplay = Tankopedia.use((state) => state.requestedDisplay);
|
const requestedDisplay = Tankopedia.use((state) => state.requestedDisplay);
|
||||||
|
|
||||||
const apply = useCallback((t: number) => {
|
const apply = useCallback((t: number) => {
|
||||||
|
if (wrapper.current === null) return;
|
||||||
|
|
||||||
for (const child of wrapper.current.children) {
|
for (const child of wrapper.current.children) {
|
||||||
if (child instanceof SpotLight) {
|
if (child instanceof SpotLight) {
|
||||||
child.angle = ANGLE * t;
|
child.angle = ANGLE * t;
|
||||||
|
|||||||
+3
-2
@@ -3,7 +3,7 @@ import { Quicklime, type QuicklimeEvent } from "quicklime";
|
|||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import { Mesh, MeshStandardMaterial } from "three";
|
import { Mesh, MeshStandardMaterial } from "three";
|
||||||
|
|
||||||
const SIZE = 2 ** 4;
|
const SIZE = 2 ** 5;
|
||||||
|
|
||||||
export const screenshotReadyEvent = new Quicklime(false);
|
export const screenshotReadyEvent = new Quicklime(false);
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ export function SceneProps() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<mesh
|
<mesh
|
||||||
|
position={[0, -(2 ** -8), 0]}
|
||||||
rotation={[-Math.PI / 2, 0, 0]}
|
rotation={[-Math.PI / 2, 0, 0]}
|
||||||
receiveShadow
|
receiveShadow
|
||||||
visible={!screenshotReadyEvent.last!}
|
visible={!screenshotReadyEvent.last!}
|
||||||
@@ -36,7 +37,7 @@ export function SceneProps() {
|
|||||||
ref={material}
|
ref={material}
|
||||||
color="black"
|
color="black"
|
||||||
roughness={1}
|
roughness={1}
|
||||||
metalness={0}
|
metalness={1}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
);
|
);
|
||||||
|
|||||||
-2
@@ -5,7 +5,6 @@ import {
|
|||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
useRef,
|
useRef,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Fog } from "three";
|
|
||||||
import { applyPitchYawLimits } from "../../../../../core/blitz/applyPitchYawLimits";
|
import { applyPitchYawLimits } from "../../../../../core/blitz/applyPitchYawLimits";
|
||||||
import { modelTransformEvent } from "../../../../../core/blitzkit/modelTransform";
|
import { modelTransformEvent } from "../../../../../core/blitzkit/modelTransform";
|
||||||
import { Pose, poseEvent } from "../../../../../core/blitzkit/pose";
|
import { Pose, poseEvent } from "../../../../../core/blitzkit/pose";
|
||||||
@@ -150,7 +149,6 @@ export const TankSandbox = forwardRef<HTMLCanvasElement, TankSandboxProps>(
|
|||||||
<SmartCanvas
|
<SmartCanvas
|
||||||
resize={{ debounce: 0 }}
|
resize={{ debounce: 0 }}
|
||||||
ref={canvas}
|
ref={canvas}
|
||||||
scene={{ fog: new Fog("black", 30, 50) }}
|
|
||||||
gl={{
|
gl={{
|
||||||
clippingPlanes: [],
|
clippingPlanes: [],
|
||||||
localClippingEnabled: true,
|
localClippingEnabled: true,
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ async function extractModel(vfs: AbstractVFS, path: string) {
|
|||||||
|
|
||||||
async function readBaseColor(path: string) {
|
async function readBaseColor(path: string) {
|
||||||
const raw = await readTexture(path);
|
const raw = await readTexture(path);
|
||||||
const image = await sharp(raw.data, { raw: raw }).webp().toBuffer();
|
const image = await sharp(raw.data, { raw }).webp().toBuffer();
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@@ -388,13 +388,7 @@ async function readBaseColor(path: string) {
|
|||||||
async function readOcclusion(path: string) {
|
async function readOcclusion(path: string) {
|
||||||
const raw = await readTexture(path);
|
const raw = await readTexture(path);
|
||||||
|
|
||||||
const image = await sharp(raw.data, {
|
const image = await sharp(raw.data, { raw })
|
||||||
raw: {
|
|
||||||
width: raw.width,
|
|
||||||
height: raw.height,
|
|
||||||
channels: raw.channels,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.extractChannel(3)
|
.extractChannel(3)
|
||||||
.webp()
|
.webp()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
@@ -404,7 +398,7 @@ async function readOcclusion(path: string) {
|
|||||||
|
|
||||||
async function readRoughnessMetallic(path: string) {
|
async function readRoughnessMetallic(path: string) {
|
||||||
const raw = await readTexture(path);
|
const raw = await readTexture(path);
|
||||||
const blitz = sharp(raw.data, { raw: raw });
|
const blitz = sharp(raw.data, { raw });
|
||||||
const metallicness = await blitz?.extractChannel(1).raw().toBuffer();
|
const metallicness = await blitz?.extractChannel(1).raw().toBuffer();
|
||||||
const roughness = await blitz?.extractChannel(3).raw().toBuffer();
|
const roughness = await blitz?.extractChannel(3).raw().toBuffer();
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user