A Fabric mod for Minecraft 1.21.1 that adds real-time voxel ray tracing with ReSTIR direct illumination, SVGF denoising, and hierarchical Morton-coded traversal. Designed as a companion to Iris shader packs such as Complementary Reimagined and Euphoria Patches.
Photonics currently ships three lighting modes: OFF, BASIC, and LIGHT_TREE. LIGHT_TREE is the active high-end path and now defaults to light binning when the shader pack does not explicitly override that behavior. The in-game settings screen also persists a local light-binning override, so local testing can force shader-pack default, enabled, or disabled behavior across reloads without relying on a hidden backend toggle.
Requires Java 21. Build and run unit tests with Gradle:
./gradlew build
./gradlew testThe project includes a runtime shader automation system that launches a Minecraft client, verifies the ray tracing pipeline is active with the expected shader pack, captures rendered attachment textures, and then shuts down the client automatically. This provides end-to-end validation that the mod initializes correctly, the raytracer produces visible lighting output, and no error patterns appear in the client log.
The shaderGameTest Gradle task orchestrates the full automation cycle. It requires a pre-existing singleplayer world save at run/saves/New World/ with the target shader pack already configured.
./gradlew shaderGameTestThis task performs the following steps in order:
- Cleans prior automation artifacts from
run/automation/. - Launches the
shaderGameTestClientrun configuration, which starts Minecraft with Quick Play pointing at the saved world and allphotonics.automation.*system properties enabled. - After the client exits, validates the generated report at
run/automation/shader-report.propertiesagainst pass/fail criteria.
The ShaderAutomation class writes its results to two locations under run/automation/:
shader-report.properties-- a Java properties file recording tick counts, capture counts, shader pack name, raytracer activity, lighting signal detection, per-attachment max luminance values, and the overall success/failure status with a reason string.captures/-- PNG images of rendered attachment textures (direct, direct_soft, handheld) captured at configurable intervals during the automation run.
All automation behavior is controlled through JVM system properties set in the shaderGameTestClient Loom run configuration in build.gradle. The default local and automation runs force LIGHT_TREE mode with light binning enabled so the smoke test exercises the same backend that production patches now use by default:
-Dphotonics.lightingMode=LIGHT_TREE
-Dphotonics.enableLightBinning=trueThe in-game settings screen persists the same photonics.enableLightBinning override in local storage, which makes it possible to cycle between shader-pack default, enabled, and disabled light binning across shader reloads.
| Property | Default | Purpose |
|---|---|---|
photonics.automation.enabled |
false |
Enables the automation system |
photonics.automation.worldName |
(empty) | World name recorded in the report |
photonics.automation.autoStartWorld |
false |
Whether to auto-start the world (Quick Play handles this) |
photonics.automation.startDelayTicks |
0 |
Ticks to wait after raytracer activation before capturing |
photonics.automation.timeoutTicks |
1200 |
Maximum ticks before the automation times out |
photonics.automation.expectedShaderPack |
(empty) | Expected shader pack name for validation |
photonics.automation.expectedPatchIdPrefix |
(empty) | Optional required prefix for the runtime patchId |
photonics.lightingMode |
shader pack/default | Overrides the effective Photonics lighting mode for automation or local testing |
photonics.enableLightBinning |
shader pack/default | Overrides the effective light-binning setting for automation or local testing |
photonics.automation.reportFile |
run/automation/shader-report.properties |
Path for the report output |
photonics.automation.captureDir |
run/automation/captures |
Directory for captured attachment images |
photonics.automation.captureEveryN |
60 |
Capture one frame every N rendered frames |
photonics.automation.captureCount |
1 |
Number of captures to take before finishing |
photonics.automation.autoStop |
false |
Shuts down the client after automation completes |
The shaderGameTest task reads the report and fails the build if any of the following conditions are not met:
- The report file exists and indicates
success=true. - The expected shader pack was matched (normalized comparison handles version suffixes and Euphoria/Complementary aliases).
- The raytracer was active during the run.
- A lighting signal was detected (at least one attachment had non-zero luminance).
- The required number of frame captures were taken.
- If
photonics.automation.expectedPatchIdPrefixis set, the runtimepatchIdbegins with that prefix. - The client log at
run/logs/latest.logcontains profiler evidence for both[Profiler] compileWorld:and[Profiler] upload:and does not contain forbidden error patterns such asNullPointerExceptionor shader option resolution failures.
The ShaderAutomationTest class covers the shader pack name matching logic (including normalization of version suffixes, punctuation, and the Euphoria/Complementary alias mapping) and the luminance computation against known pixel values.
| Task | Description |
|---|---|
test |
Runs all JUnit 5 unit tests |
patchValidationTest |
Runs shader patch validation tests only |
automationValidation |
Runs patch validation tests and a full build |
shaderGameTest |
Full shader runtime smoke test with report validation |
gameTest |
Alias for shaderGameTest |
renderdocPrepareClient |
Generates RenderDoc launch files for the default client |
renderdocPrepareShaderGameTest |
Generates RenderDoc launch files for the shader game test client |
renderdocClient |
Launches the default client through RenderDoc |
renderdocShaderGameTest |
Launches the shader game test client through RenderDoc |