more accurate InteriorInstance lightmap values

This commit is contained in:
Brian Beck 2025-12-09 17:31:37 -08:00
parent a4b7021acc
commit e37ece581b
10 changed files with 24 additions and 13 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,7 @@
2:I[39756,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"default"]
3:I[37457,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"default"]
4:I[47257,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"ClientPageRoot"]
5:I[31713,["/t2-mapper/_next/static/chunks/a99c02adf7563d85.js","/t2-mapper/_next/static/chunks/bce28defe6a29ff5.js","/t2-mapper/_next/static/chunks/32ef0c8650712240.js","/t2-mapper/_next/static/chunks/49f75d30e4f6ac74.js"],"default"]
5:I[31713,["/t2-mapper/_next/static/chunks/a99c02adf7563d85.js","/t2-mapper/_next/static/chunks/9df2d46c5eaa77d2.js","/t2-mapper/_next/static/chunks/32ef0c8650712240.js","/t2-mapper/_next/static/chunks/49f75d30e4f6ac74.js"],"default"]
8:I[97367,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"OutletBoundary"]
a:I[11533,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"AsyncMetadataOutlet"]
c:I[97367,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"ViewportBoundary"]
@ -10,7 +10,7 @@ e:I[97367,["/t2-mapper/_next/static/chunks/060f9a97930f3d04.js"],"MetadataBounda
f:"$Sreact.suspense"
11:I[68027,[],"default"]
:HL["/t2-mapper/_next/static/chunks/15b04c9d2ba2c4cf.css","style"]
0:{"P":null,"b":"Z2orC9Oxj30KOCL7Wakqt","p":"/t2-mapper","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/15b04c9d2ba2c4cf.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","searchParams":{},"params":{},"promises":["$@6","$@7"]}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/a99c02adf7563d85.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/bce28defe6a29ff5.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/32ef0c8650712240.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/49f75d30e4f6ac74.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$L9",["$","$La",null,{"promise":"$@b"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$Lc",null,{"children":"$Ld"}],null],["$","$Le",null,{"children":["$","div",null,{"hidden":true,"children":["$","$f",null,{"fallback":null,"children":"$L10"}]}]}]]}],false]],"m":"$undefined","G":["$11",[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/15b04c9d2ba2c4cf.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"s":false,"S":true}
0:{"P":null,"b":"nCiBD1gBZD0BBktWqKGDD","p":"/t2-mapper","c":["",""],"i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/15b04c9d2ba2c4cf.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","searchParams":{},"params":{},"promises":["$@6","$@7"]}],[["$","script","script-0",{"src":"/t2-mapper/_next/static/chunks/a99c02adf7563d85.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/t2-mapper/_next/static/chunks/9df2d46c5eaa77d2.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/t2-mapper/_next/static/chunks/32ef0c8650712240.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/t2-mapper/_next/static/chunks/49f75d30e4f6ac74.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$L9",["$","$La",null,{"promise":"$@b"}]]}]]}],{},null,false]},null,false],["$","$1","h",{"children":[null,[["$","$Lc",null,{"children":"$Ld"}],null],["$","$Le",null,{"children":["$","div",null,{"hidden":true,"children":["$","$f",null,{"fallback":null,"children":"$L10"}]}]}]]}],false]],"m":"$undefined","G":["$11",[["$","link","0",{"rel":"stylesheet","href":"/t2-mapper/_next/static/chunks/15b04c9d2ba2c4cf.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"s":false,"S":true}
6:{}
7:"$0:f:0:1:2:children:1:props:children:0:props:params"
d:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]

View file

@ -1,6 +1,12 @@
import { memo, Suspense, useMemo, useCallback } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { Mesh, Material, MeshStandardMaterial, Texture } from "three";
import {
Mesh,
Material,
MeshStandardMaterial,
Texture,
SRGBColorSpace,
} from "three";
import { useGLTF, useTexture } from "@react-three/drei";
import { textureToUrl, interiorToUrl } from "../loaders";
import type { TorqueObject } from "../torqueScript";
@ -16,8 +22,12 @@ import { injectInteriorLighting } from "../interiorMaterial";
* Lightmap intensity multiplier.
* Lightmaps contain baked lighting from interior-specific lights only
* (not scene sun/ambient - that's applied in real-time).
*
* Three.js's BRDF_Lambert divides by PI for energy conservation, but Torque
* (2001) used simple multiplication: base_texture * lightmap in gamma space.
* We multiply by PI to cancel out Three.js's division.
*/
const LIGHTMAP_INTENSITY = 2.5;
const LIGHTMAP_INTENSITY = Math.PI;
/**
* Load a .gltf file that was converted from a .dif, used for "interior" models.
@ -81,9 +91,10 @@ function InteriorTexture({
* Extract lightmap texture from a glTF material.
* The io_dif Blender addon stores lightmaps in the emissive channel for transport.
*
* Note: Torque used lightmaps directly as linear data (no gamma correction in
* the engine). The glTF loader preserves the original PNG data. We explicitly
* set colorSpace to linear to match Torque's behavior.
* Torque (2001) multiplied base_texture * lightmap directly in gamma/sRGB space
* with no gamma correction. The lightmap PNGs contain sRGB-encoded values.
* By setting colorSpace to SRGBColorSpace, Three.js correctly decodes the sRGB
* values to linear for its lighting calculations.
*/
function getLightMap(material: Material | null): Texture | null {
if (!material) return null;
@ -92,8 +103,8 @@ function getLightMap(material: Material | null): Texture | null {
// Lightmap is stored in emissiveMap with 0 strength (just for glTF transport)
const lightMap = stdMat.emissiveMap;
if (lightMap) {
// Use linear color space to match Torque's direct multiply behavior
lightMap.colorSpace = "srgb-linear";
// Lightmaps are sRGB-encoded PNGs - decode to linear for correct lighting
lightMap.colorSpace = SRGBColorSpace;
}
return lightMap ?? null;
}