A C#/.NET 10 reproduction of Real-Time Polygonal-Light Shading with Linearly Transformed Cosines, built on top of Feather.
- .NET SDK 10.0.301, or a compatible .NET 10 SDK.
- A Feather-supported GPU/runtime.
- NuGet restore. FeatherCompute is referenced from
Directory.Packages.props.
The SDK version is pinned in global.json, so Rider and the CLI should pick the same SDK:
dotnet restore LTC.sln
dotnet build LTC.slnStandalone LTC viewer:
dotnet run --project src/Ltc.ViewerSponza viewer:
dotnet run --project src/Ltc.SponzaBy default, both viewers look for:
data/generated/ltc_fit_64x64.js
assets/lights/images.png
Ltc.Sponza also auto-loads:
assets/sponza
You can pass explicit paths when needed:
dotnet run --project src/Ltc.Viewer -- \
--lut data/generated/ltc_fit_64x64.js \
--light-texture assets/lights/images.png
dotnet run --project src/Ltc.Sponza -- \
--sponza assets/sponza \
--light-texture assets/lights/images.pngsrc/Ltc.Viewer:
- Left-drag: rotate the camera.
- Arrow keys: rotate the light.
Q/E: roughness down / up.A/D: light width down / up.W/S: light height up / down.Z/X: intensity down / up.R/F: texture LOD bias up / down.[/]: fewer / more ray-tracing comparison samples.Space: toggle two-sided lighting.T: toggle textured light.C: switch LTC / ray-traced ground truth / split / error view.G: toggle debug grid.Esc: exit.
src/Ltc.Sponza:
- Left-drag: rotate the camera.
W/A/S/D: move the camera.Q/E: roughness down / up.Z/X: intensity down / up.- Hold
Shift: move or adjust faster. Esc: exit.
The viewers can write .tga captures:
dotnet run --project src/Ltc.Viewer -- \
--capture data/generated/viewer.tga \
--width 1280 \
--height 720 \
--msaa 4dotnet run --project src/Ltc.Sponza -- \
--capture data/generated/sponza.tga \
--width 1280 \
--height 720 \
--msaa 4The standalone viewer also has a ray-traced comparison mode:
dotnet run --project src/Ltc.Viewer -- \
--compare-mode split \
--rt-grid 16Quick GPU/runtime check:
dotnet run --project src/Ltc.Fit -- --probe-gpuFit one preview cell:
dotnet run --project src/Ltc.Fit -- --fit-cell --previewFit a tiny preview table:
dotnet run --project src/Ltc.Fit -- \
--fit-table \
--preview \
--output data/generated/ltc_fit_4x4.jsFit the full 64x64 table:
dotnet run --project src/Ltc.Fit -- \
--fit-table \
--size 64 \
--output data/generated/ltc_fit_64x64.js \
--checkpoint-csv data/generated/ltc_fit_64x64.csvResume from a checkpoint:
dotnet run --project src/Ltc.Fit -- \
--fit-table \
--size 64 \
--resume-csv data/generated/ltc_fit_64x64.csv \
--output data/generated/ltc_fit_64x64.jsThe full table is slow enough that checkpointing is useful. It fits 4096 table cells, and each cell runs a small optimization problem with a multiple-importance-sampling L3 loss.
To evaluate a packed LUT:
dotnet run --project src/Ltc.Fit -- \
--eval-js-loss \
--lut data/generated/ltc_fit_64x64.jsassets/lights/ Default image used by textured polygonal lights.
assets/sponza/ Crytek Sponza OBJ scene and textures.
data/generated/ LUTs, checkpoints, captures, and local caches.
src/Ltc.Core/ Table configuration and shared core types.
src/Ltc.Feather/ Feather kernels, fitting code, LUT packing, LUT evaluation.
src/Ltc.Fit/ CLI for fitting and checking LUTs.
src/Ltc.Viewer/ Small LTC viewer.
src/Ltc.Sponza/ Sponza renderer.
tests/ Unit tests for core, fitting, packing, and viewer helpers.
Only these generated files are meant to be tracked:
data/generated/.gitkeep
data/generated/ltc_fit_64x64.js
These stay local:
data/generated/*.csv
data/generated/*.log
data/generated/*.tga
data/generated/light-texture-cache/
So the default viewer works after cloning, but training checkpoints, logs, captures, and cache files do not pollute the repository.
The Sponza scene is the fixed Crytek Sponza OBJ model. See assets/sponza/README.md and THIRD_PARTY_NOTICES.md.
The default light texture lives at assets/lights/images.png.
This project is licensed under the MIT License. See LICENSE.
Third-party assets keep their original attribution and license terms. See THIRD_PARTY_NOTICES.md.
