flow: lights and normals

This commit is contained in:
cha0s 2024-07-18 04:18:06 -05:00
parent 82fd31802b
commit 2c2bfcbf0c
8 changed files with 96 additions and 26 deletions

View File

@ -10,6 +10,9 @@ const loading = {};
export function useAsset(source) {
const [assets, setAssets] = useContext(context);
useEffect(() => {
if (!source) {
return undefined;
}
if (!assets[source]) {
if (!loading[source]) {
(loading[source] = Assets.load(source)).then((asset) => {
@ -21,5 +24,5 @@ export function useAsset(source) {
}
}
}, [assets, setAssets, source]);
return assets[source];
return source ? assets[source] : undefined;
}

View File

@ -1,10 +1,12 @@
import {ExtensionType} from '@pixi/core';
import {Layer, Stage as LayerStage} from '@pixi/layers';
let AmbientLight, diffuseGroup, normalGroup, lightGroup;
if ('undefined' !== typeof window) {
({AmbientLight, diffuseGroup, normalGroup, lightGroup} = await import('@pixi/lights'));
}
import {
AmbientLight,
diffuseGroup,
normalGroup,
lightGroup,
} from './lights.js';
export const ApplicationStageLayers = {
type: ExtensionType.Application,
@ -26,6 +28,7 @@ export const ApplicationStageLights = {
stage.addChild(new Layer(diffuseGroup));
stage.addChild(new Layer(normalGroup));
stage.addChild(new Layer(lightGroup));
// stage.addChild(new AmbientLight(0x2244ff, 0.1));
stage.addChild(new AmbientLight(0xffffff, 1));
},
},

View File

@ -9,6 +9,11 @@ const LightInternal = PixiComponent('Light', {
create({x, y}) {
const light = new PointLight(0xffffff, 1);
light.position.set(x, y);
// light.shader.program.fragmentSrc = light.shader.program.fragmentSrc.replace(
// 'float D = length(lightVector)',
// 'float D = length(lightVector) / 2.0',
// );
// light.falloff = [1, 10, 100]
return light;
},
applyProps(light, oldProps, {x, y}) {

7
app/react-components/pixi/lights.js vendored Normal file
View File

@ -0,0 +1,7 @@
let AmbientLight, diffuseGroup, normalGroup, lightGroup;
if ('undefined' !== typeof window) {
({AmbientLight, diffuseGroup, normalGroup, lightGroup} = await import('@pixi/lights'));
}
export {AmbientLight, diffuseGroup, normalGroup, lightGroup};

View File

@ -1,27 +1,84 @@
import {Sprite as PixiSprite} from '@pixi/react';
import {useEffect, useState} from 'react';
import {useAsset} from '@/context/assets.js';
export default function Sprite({entity, ...rest}) {
const asset = useAsset(entity.Sprite.source);
import {diffuseGroup, normalGroup} from './lights.js';
function textureFromAsset(asset, animation, frame) {
if (!asset) {
return false;
return undefined;
}
let texture;
if (asset.data.animations) {
texture = asset.animations[entity.Sprite.animation][entity.Sprite.frame];
texture = asset.animations[animation][frame];
}
else {
texture = asset.textures[''];
}
return texture;
}
export default function Sprite({entity, ...rest}) {
const [mounted, setMounted] = useState();
const [normals, setNormals] = useState();
const [normalsMounted, setNormalsMounted] = useState();
const {anchor, animation, frame, scale, source} = entity.Sprite;
const asset = useAsset(source);
const normalsAsset = useAsset(normals);
useEffect(() => {
if (!asset) {
return;
}
const {normals} = asset.data.meta;
if (normals) {
const {pathname} = new URL(
source.split('/').slice(0, -1).concat(normals).join('/'),
'http://example.org',
);
setNormals(pathname);
}
}, [asset, source]);
const texture = textureFromAsset(
asset,
animation,
frame,
);
const normalsTexture = textureFromAsset(
normalsAsset,
animation,
frame,
);
if (mounted) {
mounted.parentGroup = diffuseGroup;
}
if (normalsMounted) {
normalsMounted.parentGroup = normalGroup;
}
return (
<PixiSprite
anchor={entity.Sprite.anchor}
scale={entity.Sprite.scale}
texture={texture}
x={Math.round(entity.Position.x)}
y={Math.round(entity.Position.y)}
{...rest}
/>
<>
{texture && (
<PixiSprite
anchor={anchor}
ref={setMounted}
scale={scale}
texture={texture}
x={Math.round(entity.Position.x)}
y={Math.round(entity.Position.y)}
{...rest}
/>
)}
{normalsTexture && (
<PixiSprite
anchor={anchor}
ref={setNormalsMounted}
scale={scale}
texture={normalsTexture}
x={Math.round(entity.Position.x)}
y={Math.round(entity.Position.y)}
{...rest}
/>
)}
</>
);
}

View File

@ -8,14 +8,10 @@ import {CompositeTilemap} from '@pixi/tilemap';
import {CHUNK_SIZE} from '@/constants.js';
import {useAsset} from '@/context/assets.js';
let diffuseGroup, normalGroup;
if ('undefined' !== typeof window) {
({diffuseGroup, normalGroup} = await import('@pixi/lights'));
}
import {diffuseGroup, normalGroup} from './lights.js';
const TileLayerInternal = PixiComponent('TileLayer', {
create: ({group, stage, tileLayer}) => {
create: ({group, tileLayer}) => {
const container = new Container();
const cy = Math.ceil(tileLayer.area.y / CHUNK_SIZE);
const cx = Math.ceil(tileLayer.area.x / CHUNK_SIZE);
@ -85,7 +81,7 @@ const TileLayerInternal = PixiComponent('TileLayer', {
});
export default function TileLayer(props) {
const {renderer, stage} = useApp();
const {renderer} = useApp();
const {tileLayer} = props;
const asset = useAsset(tileLayer.source);
const normalsAsset = useAsset([tileLayer.source.slice(0, -'.json'.length), 'normals.json'].join('.'));
@ -99,14 +95,12 @@ export default function TileLayer(props) {
asset={asset}
group={diffuseGroup}
renderer={renderer}
stage={stage}
/>
<TileLayerInternal
{...props}
asset={normalsAsset}
group={normalGroup}
renderer={renderer}
stage={stage}
/>
</>
);

View File

@ -0,0 +1 @@
{"frames":{"":{"frame":{"x":0,"y":0,"w":110,"h":102},"spriteSourceSize":{"x":0,"y":0,"w":110,"h":102},"sourceSize":{"w":110,"h":102}}},"meta":{"format":"RGBA8888","image":"./shit-shack.normals.png","scale":1,"size":{"w":110,"h":102}}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB