mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-16 08:55:52 +00:00
Fix texture orientation. Add AO. Fix fog transition in sky
This commit is contained in:
parent
75750571de
commit
8ab6f63fee
10 changed files with 218 additions and 30 deletions
|
|
@ -7,8 +7,8 @@ import {
|
||||||
getRotation,
|
getRotation,
|
||||||
getScale,
|
getScale,
|
||||||
} from "@/src/mission";
|
} from "@/src/mission";
|
||||||
import { memo, Suspense, useEffect, useMemo } from "react";
|
import { memo, Suspense, useMemo } from "react";
|
||||||
import { Material, Mesh, MeshBasicMaterial } from "three";
|
import { Mesh } from "three";
|
||||||
import { setupColor } from "@/src/textureUtils";
|
import { setupColor } from "@/src/textureUtils";
|
||||||
|
|
||||||
const FALLBACK_URL = `${BASE_URL}/black.png`;
|
const FALLBACK_URL = `${BASE_URL}/black.png`;
|
||||||
|
|
@ -21,23 +21,17 @@ function useInterior(interiorFile: string) {
|
||||||
return useGLTF(url);
|
return useGLTF(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
function InteriorTexture({ material }: { material: Material }) {
|
function InteriorTexture({ materialName }: { materialName: string }) {
|
||||||
let url = FALLBACK_URL;
|
let url = FALLBACK_URL;
|
||||||
try {
|
try {
|
||||||
url = interiorTextureToUrl(material.name);
|
url = interiorTextureToUrl(materialName);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
const texture = useTexture(url, (texture) => setupColor(texture));
|
const texture = useTexture(url, (texture) => setupColor(texture));
|
||||||
|
|
||||||
useEffect(() => {
|
return <meshStandardMaterial map={texture} side={2} />;
|
||||||
const asBasicMaterial = material as MeshBasicMaterial;
|
|
||||||
asBasicMaterial.map = texture;
|
|
||||||
asBasicMaterial.needsUpdate = true;
|
|
||||||
}, [material, texture]);
|
|
||||||
|
|
||||||
return <primitive object={material} attach="material" />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function InteriorMesh({ node }: { node: Mesh }) {
|
function InteriorMesh({ node }: { node: Mesh }) {
|
||||||
|
|
@ -53,10 +47,10 @@ function InteriorMesh({ node }: { node: Mesh }) {
|
||||||
>
|
>
|
||||||
{Array.isArray(node.material) ? (
|
{Array.isArray(node.material) ? (
|
||||||
node.material.map((mat, index) => (
|
node.material.map((mat, index) => (
|
||||||
<InteriorTexture key={index} material={mat} />
|
<InteriorTexture key={index} materialName={mat.name} />
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<InteriorTexture material={node.material} />
|
<InteriorTexture materialName={node.material.name} />
|
||||||
)}
|
)}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,5 @@ export function Mission({ name }: { name: string }) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <>{mission.objects.map((object, i) => renderObject(object, i))}</>;
|
||||||
<>
|
|
||||||
<hemisphereLight
|
|
||||||
args={["rgba(209, 237, 255, 1)", "rgba(186, 200, 181, 1)", 2]}
|
|
||||||
/>
|
|
||||||
{mission.objects.map((object, i) => renderObject(object, i))}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
app/Sky.tsx
112
app/Sky.tsx
|
|
@ -1,10 +1,10 @@
|
||||||
import { ConsoleObject, getProperty } from "@/src/mission";
|
import { ConsoleObject, getProperty } from "@/src/mission";
|
||||||
import { useSettings } from "./SettingsProvider";
|
import { useSettings } from "./SettingsProvider";
|
||||||
import { Suspense, useMemo } from "react";
|
import { Suspense, useMemo, useEffect, useRef } from "react";
|
||||||
import { BASE_URL, getUrlForPath, loadDetailMapList } from "@/src/loaders";
|
import { BASE_URL, getUrlForPath, loadDetailMapList } from "@/src/loaders";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { useCubeTexture } from "@react-three/drei";
|
import { useCubeTexture } from "@react-three/drei";
|
||||||
import { Color } from "three";
|
import { Color, ShaderMaterial, BackSide } from "three";
|
||||||
|
|
||||||
const FALLBACK_URL = `${BASE_URL}/black.png`;
|
const FALLBACK_URL = `${BASE_URL}/black.png`;
|
||||||
|
|
||||||
|
|
@ -18,7 +18,15 @@ function useDetailMapList(name: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SkyBox({ materialList }: { materialList: string }) {
|
export function SkyBox({
|
||||||
|
materialList,
|
||||||
|
fogColor,
|
||||||
|
fogDistance,
|
||||||
|
}: {
|
||||||
|
materialList: string;
|
||||||
|
fogColor?: Color;
|
||||||
|
fogDistance?: number;
|
||||||
|
}) {
|
||||||
const { data: detailMapList } = useDetailMapList(materialList);
|
const { data: detailMapList } = useDetailMapList(materialList);
|
||||||
|
|
||||||
const skyBoxFiles = useMemo(
|
const skyBoxFiles = useMemo(
|
||||||
|
|
@ -45,7 +53,83 @@ export function SkyBox({ materialList }: { materialList: string }) {
|
||||||
|
|
||||||
const skyBox = useCubeTexture(skyBoxFiles, { path: "" });
|
const skyBox = useCubeTexture(skyBoxFiles, { path: "" });
|
||||||
|
|
||||||
return <primitive attach="background" object={skyBox} />;
|
// Create a shader material for the skybox with fog
|
||||||
|
const materialRef = useRef<ShaderMaterial>(null!);
|
||||||
|
|
||||||
|
const hasFog = !!fogColor && !!fogDistance;
|
||||||
|
|
||||||
|
const shaderMaterial = useMemo(() => {
|
||||||
|
if (!hasFog) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ShaderMaterial({
|
||||||
|
uniforms: {
|
||||||
|
skybox: { value: skyBox },
|
||||||
|
fogColor: { value: fogColor },
|
||||||
|
},
|
||||||
|
vertexShader: `
|
||||||
|
varying vec3 vDirection;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Use position directly as direction (no world transform needed)
|
||||||
|
vDirection = position;
|
||||||
|
|
||||||
|
// Transform position but ignore translation
|
||||||
|
vec4 pos = projectionMatrix * mat4(mat3(modelViewMatrix)) * vec4(position, 1.0);
|
||||||
|
gl_Position = pos.xyww; // Set depth to far plane
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
fragmentShader: `
|
||||||
|
uniform samplerCube skybox;
|
||||||
|
uniform vec3 fogColor;
|
||||||
|
|
||||||
|
varying vec3 vDirection;
|
||||||
|
|
||||||
|
// Convert linear to sRGB
|
||||||
|
vec3 linearToSRGB(vec3 color) {
|
||||||
|
return pow(color, vec3(1.0 / 2.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 direction = normalize(vDirection);
|
||||||
|
direction.x = -direction.x;
|
||||||
|
vec4 skyColor = textureCube(skybox, direction);
|
||||||
|
|
||||||
|
// Calculate fog factor based on vertical direction
|
||||||
|
// direction.y: -1 = straight down, 0 = horizon, 1 = straight up
|
||||||
|
// 100% fog from bottom to horizon, then fade from horizon (0) to 0.4
|
||||||
|
float fogFactor = smoothstep(0.0, 0.4, direction.y);
|
||||||
|
|
||||||
|
// Mix in sRGB space to match Three.js fog rendering
|
||||||
|
vec3 finalColor = mix(fogColor, skyColor.rgb, fogFactor);
|
||||||
|
gl_FragColor = vec4(finalColor, 1.0);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
side: BackSide,
|
||||||
|
depthWrite: false,
|
||||||
|
});
|
||||||
|
}, [skyBox, fogColor, hasFog]);
|
||||||
|
|
||||||
|
// Update uniforms when fog parameters change
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialRef.current && hasFog && shaderMaterial) {
|
||||||
|
materialRef.current.uniforms.skybox.value = skyBox;
|
||||||
|
materialRef.current.uniforms.fogColor.value = fogColor!;
|
||||||
|
}
|
||||||
|
}, [skyBox, fogColor, hasFog, shaderMaterial]);
|
||||||
|
|
||||||
|
// If fog is disabled, just use the skybox as background
|
||||||
|
if (!hasFog) {
|
||||||
|
return <primitive attach="background" object={skyBox} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<mesh scale={5000}>
|
||||||
|
<sphereGeometry args={[1, 60, 40]} />
|
||||||
|
<primitive ref={materialRef} object={shaderMaterial} attach="material" />
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Sky({ object }: { object: ConsoleObject }) {
|
export function Sky({ object }: { object: ConsoleObject }) {
|
||||||
|
|
@ -69,12 +153,15 @@ export function Sky({ object }: { object: ConsoleObject }) {
|
||||||
// `colorString` might specify an alpha value, but three.js doesn't
|
// `colorString` might specify an alpha value, but three.js doesn't
|
||||||
// support opacity on fog or scene backgrounds, so ignore it.
|
// support opacity on fog or scene backgrounds, so ignore it.
|
||||||
const [r, g, b] = colorString.split(" ").map((s) => parseFloat(s));
|
const [r, g, b] = colorString.split(" ").map((s) => parseFloat(s));
|
||||||
return new Color().setRGB(r, g, b);
|
return [
|
||||||
|
new Color().setRGB(r, g, b),
|
||||||
|
new Color().setRGB(r, g, b).convertSRGBToLinear(),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}, [object]);
|
}, [object]);
|
||||||
|
|
||||||
const backgroundColor = fogColor ? (
|
const backgroundColor = fogColor ? (
|
||||||
<color attach="background" args={[fogColor]} />
|
<color attach="background" args={[fogColor[0]]} />
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -83,14 +170,23 @@ export function Sky({ object }: { object: ConsoleObject }) {
|
||||||
// If there's a skybox, its textures will need to load. Render just the
|
// If there's a skybox, its textures will need to load. Render just the
|
||||||
// fog color as the background in the meantime.
|
// fog color as the background in the meantime.
|
||||||
<Suspense fallback={backgroundColor}>
|
<Suspense fallback={backgroundColor}>
|
||||||
<SkyBox materialList={materialList} />
|
<SkyBox
|
||||||
|
materialList={materialList}
|
||||||
|
fogColor={fogEnabled ? fogColor[1] : undefined}
|
||||||
|
fogDistance={fogEnabled ? fogDistance : undefined}
|
||||||
|
/>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
) : (
|
) : (
|
||||||
// If there's no skybox, just render the fog color as the background.
|
// If there's no skybox, just render the fog color as the background.
|
||||||
backgroundColor
|
backgroundColor
|
||||||
)}
|
)}
|
||||||
{fogEnabled && fogDistance && fogColor ? (
|
{fogEnabled && fogDistance && fogColor ? (
|
||||||
<fog attach="fog" color={fogColor} near={0} far={fogDistance * 2} />
|
<fog
|
||||||
|
attach="fog"
|
||||||
|
color={fogColor[1]}
|
||||||
|
near={fogDistance / 2}
|
||||||
|
far={fogDistance * 2}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
48
app/Sun.tsx
Normal file
48
app/Sun.tsx
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { ConsoleObject, getProperty } from "@/src/mission";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
import { Color } from "three";
|
||||||
|
|
||||||
|
export function Sun({ object }: { object: ConsoleObject }) {
|
||||||
|
const direction = useMemo(() => {
|
||||||
|
const directionStr = getProperty(object, "direction")?.value ?? "0 0 -1";
|
||||||
|
const [x, y, z] = directionStr.split(" ").map((s) => parseFloat(s));
|
||||||
|
// Scale the direction vector to position the light far from the scene
|
||||||
|
const scale = 5000;
|
||||||
|
return [x * scale, y * scale, z * scale] as [number, number, number];
|
||||||
|
}, [object]);
|
||||||
|
|
||||||
|
const color = useMemo(() => {
|
||||||
|
const colorStr = getProperty(object, "color")?.value ?? "1 1 1 1";
|
||||||
|
const [r, g, b] = colorStr.split(" ").map((s) => parseFloat(s));
|
||||||
|
return [r, g, b] as [number, number, number];
|
||||||
|
}, [object]);
|
||||||
|
|
||||||
|
const ambient = useMemo(() => {
|
||||||
|
const ambientStr = getProperty(object, "ambient")?.value ?? "0.5 0.5 0.5 1";
|
||||||
|
const [r, g, b] = ambientStr.split(" ").map((s) => parseFloat(s));
|
||||||
|
return [r, g, b] as [number, number, number];
|
||||||
|
}, [object]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Directional light for the sun */}
|
||||||
|
{/* <directionalLight
|
||||||
|
position={[500, 500, 500]}
|
||||||
|
target-position={direction}
|
||||||
|
color={color}
|
||||||
|
intensity={2}
|
||||||
|
castShadow
|
||||||
|
shadow-mapSize={[2048, 2048]}
|
||||||
|
shadow-camera-left={-2000}
|
||||||
|
shadow-camera-right={2000}
|
||||||
|
shadow-camera-top={2000}
|
||||||
|
shadow-camera-bottom={-2000}
|
||||||
|
shadow-camera-near={0.5}
|
||||||
|
shadow-camera-far={5000}
|
||||||
|
shadow-bias={-0.001}
|
||||||
|
/> */}
|
||||||
|
{/* Ambient light component */}
|
||||||
|
<hemisphereLight args={[new Color(...color), new Color(...ambient), 2]} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -209,6 +209,8 @@ export function TerrainBlock({ object }: { object: ConsoleObject }) {
|
||||||
position={position}
|
position={position}
|
||||||
scale={scale}
|
scale={scale}
|
||||||
geometry={planeGeometry}
|
geometry={planeGeometry}
|
||||||
|
receiveShadow
|
||||||
|
castShadow
|
||||||
>
|
>
|
||||||
{terrain ? (
|
{terrain ? (
|
||||||
<TerrainMaterial
|
<TerrainMaterial
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { ObserverControls } from "./ObserverControls";
|
||||||
import { InspectorControls } from "./InspectorControls";
|
import { InspectorControls } from "./InspectorControls";
|
||||||
import { SettingsProvider } from "./SettingsProvider";
|
import { SettingsProvider } from "./SettingsProvider";
|
||||||
import { PerspectiveCamera } from "@react-three/drei";
|
import { PerspectiveCamera } from "@react-three/drei";
|
||||||
|
import { EffectComposer, N8AO } from "@react-three/postprocessing";
|
||||||
|
|
||||||
// three.js has its own loaders for textures and models, but we need to load other
|
// three.js has its own loaders for textures and models, but we need to load other
|
||||||
// stuff too, e.g. missions, terrains, and more. This client is used for those.
|
// stuff too, e.g. missions, terrains, and more. This client is used for those.
|
||||||
|
|
@ -20,7 +21,7 @@ export default function HomePage() {
|
||||||
<SettingsProvider fogEnabled={fogEnabled}>
|
<SettingsProvider fogEnabled={fogEnabled}>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<main>
|
<main>
|
||||||
<Canvas>
|
<Canvas shadows>
|
||||||
<ObserverControls />
|
<ObserverControls />
|
||||||
<Mission key={missionName} name={missionName} />
|
<Mission key={missionName} name={missionName} />
|
||||||
<PerspectiveCamera
|
<PerspectiveCamera
|
||||||
|
|
@ -28,6 +29,9 @@ export default function HomePage() {
|
||||||
position={[-512, 256, -512]}
|
position={[-512, 256, -512]}
|
||||||
fov={90}
|
fov={90}
|
||||||
/>
|
/>
|
||||||
|
<EffectComposer>
|
||||||
|
<N8AO intensity={3} aoRadius={3} quality="performance" />
|
||||||
|
</EffectComposer>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
<InspectorControls
|
<InspectorControls
|
||||||
missionName={missionName}
|
missionName={missionName}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { WaterBlock } from "./WaterBlock";
|
||||||
import { SimGroup } from "./SimGroup";
|
import { SimGroup } from "./SimGroup";
|
||||||
import { InteriorInstance } from "./InteriorInstance";
|
import { InteriorInstance } from "./InteriorInstance";
|
||||||
import { Sky } from "./Sky";
|
import { Sky } from "./Sky";
|
||||||
|
import { Sun } from "./Sun";
|
||||||
|
|
||||||
const componentMap = {
|
const componentMap = {
|
||||||
SimGroup,
|
SimGroup,
|
||||||
|
|
@ -11,6 +12,7 @@ const componentMap = {
|
||||||
WaterBlock,
|
WaterBlock,
|
||||||
InteriorInstance,
|
InteriorInstance,
|
||||||
Sky,
|
Sky,
|
||||||
|
Sun,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function renderObject(object: ConsoleObject, key: string | number) {
|
export function renderObject(object: ConsoleObject, key: string | number) {
|
||||||
|
|
|
||||||
47
package-lock.json
generated
47
package-lock.json
generated
|
|
@ -11,6 +11,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-three/drei": "^10.7.6",
|
"@react-three/drei": "^10.7.6",
|
||||||
"@react-three/fiber": "^9.3.0",
|
"@react-three/fiber": "^9.3.0",
|
||||||
|
"@react-three/postprocessing": "^3.0.4",
|
||||||
"@tanstack/react-query": "^5.90.8",
|
"@tanstack/react-query": "^5.90.8",
|
||||||
"next": "^15.5.2",
|
"next": "^15.5.2",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
|
|
@ -1217,6 +1218,32 @@
|
||||||
"integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
|
"integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-three/postprocessing": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-three/postprocessing/-/postprocessing-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-e4+F5xtudDYvhxx3y0NtWXpZbwvQ0x1zdOXWTbXMK6fFLVDd4qucN90YaaStanZGS4Bd5siQm0lGL/5ogf8iDQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"maath": "^0.6.0",
|
||||||
|
"n8ao": "^1.9.4",
|
||||||
|
"postprocessing": "^6.36.6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@react-three/fiber": "^9.0.0",
|
||||||
|
"react": "^19.0",
|
||||||
|
"three": ">= 0.156.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@react-three/postprocessing/node_modules/maath": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/maath/-/maath-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-dSb2xQuP7vDnaYqfoKzlApeRcR2xtN8/f7WV/TMAkBC8552TwTLtOO0JTcSygkYMjNDPoo6V01jTw/aPi4JrMw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/three": ">=0.144.0",
|
||||||
|
"three": ">=0.144.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@swc/helpers": {
|
"node_modules/@swc/helpers": {
|
||||||
"version": "0.5.15",
|
"version": "0.5.15",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||||
|
|
@ -1967,6 +1994,16 @@
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/n8ao": {
|
||||||
|
"version": "1.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/n8ao/-/n8ao-1.10.1.tgz",
|
||||||
|
"integrity": "sha512-hhI1pC+BfOZBV1KMwynBrVlIm8wqLxj/abAWhF2nZ0qQKyzTSQa1QtLVS2veRiuoBQXojxobcnp0oe+PUoxf/w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"postprocessing": ">=6.30.0",
|
||||||
|
"three": ">=0.137"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.11",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
||||||
|
|
@ -2128,6 +2165,16 @@
|
||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/postprocessing": {
|
||||||
|
"version": "6.38.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postprocessing/-/postprocessing-6.38.0.tgz",
|
||||||
|
"integrity": "sha512-tisx8XN/PWTL3uXz2mt8bjlMS1wiOUSCK3ixi4zjwUCFmP8XW8hNhXwrxwd2zf2VmCyCQ3GUaLm7GLnkkBbDsQ==",
|
||||||
|
"license": "Zlib",
|
||||||
|
"peer": true,
|
||||||
|
"peerDependencies": {
|
||||||
|
"three": ">= 0.157.0 < 0.182.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/potpack": {
|
"node_modules/potpack": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-three/drei": "^10.7.6",
|
"@react-three/drei": "^10.7.6",
|
||||||
"@react-three/fiber": "^9.3.0",
|
"@react-three/fiber": "^9.3.0",
|
||||||
|
"@react-three/postprocessing": "^3.0.4",
|
||||||
"@tanstack/react-query": "^5.90.8",
|
"@tanstack/react-query": "^5.90.8",
|
||||||
"next": "^15.5.2",
|
"next": "^15.5.2",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ export function setupColor(tex, repeat = [1, 1]) {
|
||||||
tex.wrapS = tex.wrapT = RepeatWrapping;
|
tex.wrapS = tex.wrapT = RepeatWrapping;
|
||||||
tex.colorSpace = SRGBColorSpace;
|
tex.colorSpace = SRGBColorSpace;
|
||||||
tex.repeat.set(...repeat);
|
tex.repeat.set(...repeat);
|
||||||
|
tex.flipY = false; // DDS/DIF textures are already flipped
|
||||||
tex.anisotropy = 16;
|
tex.anisotropy = 16;
|
||||||
tex.generateMipmaps = true;
|
tex.generateMipmaps = true;
|
||||||
tex.minFilter = LinearMipmapLinearFilter;
|
tex.minFilter = LinearMipmapLinearFilter;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue