mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-03-26 07:39:31 +00:00
use renderer's max anisotropy, dispose of more resources
This commit is contained in:
parent
d31f3506a8
commit
409df9fcaa
68 changed files with 426 additions and 232 deletions
|
|
@ -20,6 +20,7 @@ import {
|
|||
import type { AnimationAction } from "three";
|
||||
import * as SkeletonUtils from "three/examples/jsm/utils/SkeletonUtils.js";
|
||||
import { setupTexture } from "../textureUtils";
|
||||
import { useAnisotropy } from "./useAnisotropy";
|
||||
import { useDebug, useSettings } from "./SettingsProvider";
|
||||
import { useShapeInfo, isOrganicShape } from "./ShapeInfoProvider";
|
||||
import { useEngineSelector, effectNow, engineStore } from "../state/engineStore";
|
||||
|
|
@ -37,6 +38,7 @@ import { injectShapeLighting } from "../shapeMaterial";
|
|||
import {
|
||||
processShapeScene,
|
||||
replaceWithShapeMaterial,
|
||||
disposeClonedScene,
|
||||
} from "../stream/playbackUtils";
|
||||
import type { ThreadState as StreamThreadState } from "../stream/types";
|
||||
|
||||
|
|
@ -198,7 +200,13 @@ const IflTexture = memo(function IflTexture({
|
|||
animated = false,
|
||||
}: TextureProps) {
|
||||
const resourcePath = material.userData.resource_path;
|
||||
const flagNames = new Set<string>(material.userData.flag_names ?? []);
|
||||
const flagNames = useMemo(
|
||||
() =>
|
||||
material.userData.flag_names
|
||||
? new Set<string>(material.userData.flag_names)
|
||||
: EMPTY_FLAG_NAMES,
|
||||
[material.userData.flag_names],
|
||||
);
|
||||
const iflPath = `textures/${resourcePath}.ifl`;
|
||||
|
||||
const texture = useIflTexture(iflPath);
|
||||
|
|
@ -217,6 +225,8 @@ const IflTexture = memo(function IflTexture({
|
|||
[material, texture, flagNames, isOrganic, vis, animated],
|
||||
);
|
||||
|
||||
useDisposeMaterial(customMaterial);
|
||||
|
||||
// Two-pass rendering for organic/translucent materials
|
||||
// Render BackSide first (with flipped normals), then FrontSide
|
||||
if (Array.isArray(customMaterial)) {
|
||||
|
|
@ -251,6 +261,18 @@ const IflTexture = memo(function IflTexture({
|
|||
);
|
||||
});
|
||||
|
||||
function useDisposeMaterial(material: MaterialResult) {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (Array.isArray(material)) {
|
||||
material.forEach((m) => m.dispose());
|
||||
} else {
|
||||
material.dispose();
|
||||
}
|
||||
};
|
||||
}, [material]);
|
||||
}
|
||||
|
||||
const EMPTY_FLAG_NAMES = new Set<string>();
|
||||
|
||||
const StaticTexture = memo(function StaticTexture({
|
||||
|
|
@ -281,14 +303,15 @@ const StaticTexture = memo(function StaticTexture({
|
|||
|
||||
const isOrganic = shapeName && isOrganicShape(shapeName);
|
||||
const isTranslucent = flagNames.has("Translucent");
|
||||
const anisotropy = useAnisotropy();
|
||||
|
||||
const texture = useTexture(url, (texture) => {
|
||||
// Organic/alpha-tested textures need special handling to avoid mipmap artifacts
|
||||
if (isOrganic || isTranslucent) {
|
||||
return setupTexture(texture, { disableMipmaps: true });
|
||||
return setupTexture(texture, { disableMipmaps: true, anisotropy });
|
||||
}
|
||||
// Standard color texture setup for diffuse-only materials
|
||||
return setupTexture(texture);
|
||||
return setupTexture(texture, { anisotropy });
|
||||
});
|
||||
|
||||
const customMaterial = useMemo(
|
||||
|
|
@ -304,6 +327,8 @@ const StaticTexture = memo(function StaticTexture({
|
|||
[material, texture, flagNames, isOrganic, vis, animated],
|
||||
);
|
||||
|
||||
useDisposeMaterial(customMaterial);
|
||||
|
||||
// Two-pass rendering for organic/translucent materials
|
||||
// Render BackSide first (with flipped normals), then FrontSide
|
||||
if (Array.isArray(customMaterial)) {
|
||||
|
|
@ -501,6 +526,7 @@ export const ShapeModel = memo(function ShapeModel({
|
|||
const { debugMode } = useDebug();
|
||||
const { animationEnabled } = useSettings();
|
||||
const runtime = useEngineSelector((state) => state.runtime.runtime);
|
||||
const anisotropy = useAnisotropy();
|
||||
|
||||
const { clonedScene, mixer, clipsByName, visNodesBySequence, iflMeshes } =
|
||||
useMemo(() => {
|
||||
|
|
@ -549,7 +575,7 @@ export const ShapeModel = memo(function ShapeModel({
|
|||
}
|
||||
});
|
||||
|
||||
processShapeScene(scene, shapeName ?? undefined);
|
||||
processShapeScene(scene, shapeName ?? undefined, { anisotropy });
|
||||
|
||||
// Un-hide IFL meshes that don't have a vis sequence — they should always
|
||||
// be visible. IFL meshes WITH vis sequences stay hidden until their
|
||||
|
|
@ -607,7 +633,16 @@ export const ShapeModel = memo(function ShapeModel({
|
|||
visNodesBySequence: visBySeq,
|
||||
iflMeshes: iflInfos,
|
||||
};
|
||||
}, [gltf]);
|
||||
}, [gltf, anisotropy]);
|
||||
|
||||
// Dispose cloned geometries and materials when the scene is replaced or
|
||||
// the component unmounts, to prevent GPU memory from accumulating.
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
disposeClonedScene(clonedScene);
|
||||
mixer?.uncacheRoot(clonedScene);
|
||||
};
|
||||
}, [clonedScene, mixer]);
|
||||
|
||||
const threadsRef = useRef(new Map<number, ThreadState>());
|
||||
const iflMeshAtlasRef = useRef(new Map<any, IflAtlas>());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue