mylingo3d
Version:
Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor
95 lines • 4 kB
JavaScript
import { Reactive } from "@lincode/reactivity";
import { mapRange } from "@tweakpane/core";
import { DirectionalLight as ThreeDirectionalLight } from "three";
import scene from "../../engine/scene";
import { onBeforeRender } from "../../events/onBeforeRender";
import { SHADOW_DISTANCE } from "../../globals";
import { directionalLightDefaults, directionalLightSchema } from "../../interface/IDirectionalLight";
import { getCameraRendered } from "../../states/useCameraRendered";
import { getShadowDistance } from "../../states/useShadowDistance";
import LightBase from "../core/LightBase";
import getWorldPosition from "../utils/getWorldPosition";
import { vec2Point } from "../utils/vec2Point";
export default class DirectionalLight extends LightBase {
static componentName = "directionalLight";
static defaults = directionalLightDefaults;
static schema = directionalLightSchema;
defaultShadowResolution = 1024;
constructor() {
super(ThreeDirectionalLight);
this.createEffect(() => {
const light = this.lightState.get();
if (!light)
return;
scene.add(light.target);
scene.attach(light);
return () => {
scene.remove(light.target);
scene.remove(light);
};
}, [this.lightState.get]);
this.createEffect(() => {
const light = this.lightState.get();
if (!light)
return;
const camManager = getCameraRendered().userData.manager;
const offset = camManager
? Math.max(mapRange(camManager.innerZ *
(camManager.fov / 75) *
(1 / camManager.zoom), 500, 1000, 1, 1.5), 1)
: 1;
const shadowDistance = this.shadowDistanceState.get() ??
getShadowDistance() ??
SHADOW_DISTANCE;
const shadowCamera = light.shadow.camera;
shadowCamera.zoom = 500 / offset / shadowDistance;
shadowCamera.updateProjectionMatrix();
const shadowBiasComputed = this.shadowBiasComputedState.get();
const shadowResolutionComputed = this.shadowResolutionComputedState.get();
if (!shadowBiasComputed || !shadowResolutionComputed)
return;
const shadowBias = shadowBiasComputed;
light.shadow.bias =
shadowBias *
offset *
(this.defaultShadowResolution / shadowResolutionComputed) *
0.5;
return () => {
light.shadow.bias = shadowBias;
};
}, [
this.lightState.get,
this.shadowDistanceState.get,
getShadowDistance,
getCameraRendered,
this.shadowBiasComputedState.get,
this.shadowResolutionComputedState.get
]);
this.createEffect(() => {
const light = this.lightState.get();
if (!light)
return;
const cam = getCameraRendered();
const handle = onBeforeRender(() => {
const camPos = getWorldPosition(cam);
const lightPos = getWorldPosition(this.outerObject3d);
light.position.copy(camPos).add(lightPos);
light.target.position.copy(camPos).sub(lightPos);
});
return () => {
handle.cancel();
};
}, [getCameraRendered, this.lightState.get]);
}
getWorldPosition() {
return vec2Point(getWorldPosition(this.outerObject3d));
}
shadowDistanceState = new Reactive(undefined);
get shadowDistance() {
return this.shadowDistanceState.get();
}
set shadowDistance(val) {
this.shadowDistanceState.set(val);
}
}
//# sourceMappingURL=DirectionalLight.js.map