Initial commit: Minecraft 光追着色器包(从零实现的 path tracing)
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
# MinecraftPT — Path Traced Shader Pack
|
||||
## Design & Architecture Documentation
|
||||
|
||||
MinecraftPT is an original, from-scratch implementation of a high-quality
|
||||
path-traced Minecraft shader pack, designed by studying the architecture of the
|
||||
IterationRP shader pack (see `study/architecture.md`). It targets OptiFine and
|
||||
Iris (OpenGL 4.30 compute required; `iris.features.required=CUSTOM_IMAGES`).
|
||||
|
||||
All code in this pack is original work. The architecture follows the same
|
||||
deferred + voxelized path-tracing class of techniques, implemented with our own
|
||||
algorithms and data layouts.
|
||||
|
||||
---
|
||||
|
||||
## 1. Frame pipeline (program chain)
|
||||
|
||||
```
|
||||
begin1.csh CausticsTex_CS -> generate caustics normal field (pixelData2D)shadow.vsh/gsh/fsh Shadow+Voxelizer -> render shadow map AND voxel atlas into shadowcolor0/1
|
||||
composite3.csh VoxelData_Copy_CS -> 2D atlas -> 3D voxelData3D (RGBA16) + sparse markers
|
||||
composite3_a.csh SkyImage_CS -> precompute sky panorama (skyBox2D)
|
||||
composite4.csh IRC_CS -> update 3D irradiance cache (RGBA16F)
|
||||
composite4_a.csh SH_TRACING_CS -> SH sky tracing for ambient
|
||||
composite5.fsh DiffuseTracing_FS -> 1 diffuse path ray/pixel @ half res (colortex6+10)
|
||||
composite10.fsh DiffuseTemporal_FS -> temporal accumulation -> colortex7
|
||||
composite11.fsh DiffuseVariance_FS -> luminance moments -> colortex8
|
||||
composite12..15.fsh DiffuseSpatial x4 -> edge-avoiding a-trous @ steps 1,2,4,8
|
||||
composite20.fsh Sky_Overworld_FS -> sky into HDR background (colortex12)
|
||||
composite25.fsh Soild_FS -> MAIN lighting: gbuffer + PT diffuse/spec + sun/held/emissive
|
||||
composite40.fsh WaterRefraction_FS -> water refraction pass
|
||||
composite42.fsh SpecularTracing_FS -> GGX reflection ray @ half res (colortex9)
|
||||
composite44.fsh SpecularTemporal_FS -> temporal accumulation -> colortex11
|
||||
composite46..47.fsh SpecularSpatial x2 -> edge-avoiding filter
|
||||
composite50.fsh Translucent_FS -> glass/water/particle composite
|
||||
composite51.fsh Volumetric_FS -> volumetric fog + water fog
|
||||
composite53.fsh Dof_FS -> depth of field (option)
|
||||
composite65.fsh TAA -> temporal AA (writes colortex12 + 13 history)
|
||||
composite67.fsh MotionBlur_FS -> camera motion blur (option)
|
||||
composite70..73.csh Bloom compute -> downsample x2 + axial blur X/Y
|
||||
composite72_a..75.csh RTWSM compute -> importance analysis/blur/collapse/warp build
|
||||
composite74.csh Exposure_CS -> auto exposure (SSBO)
|
||||
composite76.fsh Bloom_FS -> bloom composite
|
||||
composite79.csh DepthCopy_CS -> depthtex0 -> prevDepth2D (for next frame)
|
||||
composite80.fsh Final_FS -> tonemap + color grade -> colortex0
|
||||
final.vsh/fsh -> present colortex0 to screen
|
||||
```
|
||||
|
||||
Dimension variants: `world1/` (Nether) and `world-1/` (End) override the entry
|
||||
points with `DIMENSION_NETHER` / `DIMENSION_END`; the loader falls back to the
|
||||
root programs for anything not overridden.
|
||||
|
||||
## 2. Buffer layout
|
||||
|
||||
| Buffer | Format | Res | Content |
|
||||
|---|---|---|---|
|
||||
| colortex0 | RGBA16 | full | solid albedo.rgb + emissive.a |
|
||||
| colortex1 | RGBA16 | full | world normal (oct, xy) + vertex normal (oct, zw) |
|
||||
| colortex2 | RGBA16 | full | spec.r (roughness) .g (metalness) .b (sss) .a (matID/255) |
|
||||
| colortex3 | RGBA16 | full | lightmap.rg + parallaxShadow.b + spare |
|
||||
| colortex4 | RGBA16 | full | translucent albedo.rgb + alpha.a |
|
||||
| colortex5 | RGBA16 | full | translucent normal.xy + matID.a + rough.b |
|
||||
| colortex6 | RGBA16F | half | noisy diffuse PT (current) |
|
||||
| colortex7 | RGBA16F | half | diffuse PT history (temporal output) |
|
||||
| colortex8 | RGBA16F | half | diffuse variance |
|
||||
| colortex9 | RGBA16F | half | noisy specular PT (current) |
|
||||
| colortex10 | RG16F | half | motion vectors (half-res pixels) |
|
||||
| colortex11 | RGBA16F | half | specular PT history |
|
||||
| colortex12 | RGBA16F | full | HDR scene (composite output) |
|
||||
| colortex13 | RGBA16F | full | TAA history |
|
||||
| colortex14 | R16F | 1x1 | exposure |
|
||||
| colortex15 | RGBA16F | 1/4 | bloom pyramid |
|
||||
| depthtex0 | R32F | full | scene depth |
|
||||
| shadowcolor0 | RGBA16 | SxS | shadow map (right region) |
|
||||
| shadowcolor1 | RGBA16 | SxS | voxel atlas (left region) |
|
||||
|
||||
Images: voxelData3D (RGBA16 3D), irradianceCache3D/Alt (RGBA16F 3D),
|
||||
skyBox2D (RGBA16F panorama), prevDepth2D (R32F half), rtwImportance2D (R32F),
|
||||
rtwWarp1D (RG16), pixelData2D (RG16F caustics field).
|
||||
|
||||
Custom textures: atlas2D (block atlas), atlasSpecular2D (LAB PBR spec atlas),
|
||||
CloudNoise3D (128³ RGBA8), CloudDetailedNoise3D (32³ RGB8), noise.png
|
||||
(blue-noise dither), ripple.png.
|
||||
|
||||
## 3. Voxelization (shadow pass)
|
||||
|
||||
The world is rendered once from the shadow camera into a square S×S framebuffer
|
||||
(S = 2·W, W = voxelWidth per resolution, e.g. 4096/8192/12288/16384):
|
||||
|
||||
- **Voxel atlas** (bottom-left, [0,W)² texels): the geometry shader emits, per
|
||||
triangle, an extra triangle positioned at the voxel's atlas texel
|
||||
(`VoxelTexel_From_VoxelCoord` linear packing
|
||||
`n = x + y·Rx + z·Rx·Ry; texel = (n mod W, floor(n/W))`), with z encoding
|
||||
block-shape info. The fragment shader writes shadowcolor1 =
|
||||
`(midTexCoord, voxelID, pack(textureRes, skylight))`.
|
||||
- **Shadow map** (right square [W,2W)×[0,W)): the same triangle is re-emitted
|
||||
after `ShiftShadowNdcPos` (maps shadow NDC square into the right region,
|
||||
aspect-preserving) plus the RTWSM warp offset. The FS writes
|
||||
shadowcolor0 = (albedo.rgb, depth.a).
|
||||
|
||||
Block ID encoding: full blocks `id+1000`, cutout shapes `1000-id`, empty
|
||||
markers in .z (0.91/0.71/0.61 for 8³/4³/2³ empty cells) computed by
|
||||
VoxelData_Copy_CS via shared-memory atomic occupancy reduction (sparse tracing).
|
||||
|
||||
## 4. Path tracing
|
||||
|
||||
All rays march the 3D voxel grid with Amanatides–Woo DDA
|
||||
(`PackRay`, per-axis `totalStep`, sparse-skip on empty markers):
|
||||
|
||||
- **Shadow rays** (ShadowTracing): up to 64 steps; penumbra from
|
||||
distance-to-occluder weighting; used for sun direct light.
|
||||
- **Diffuse** (DiffuseTracing_FS): cosine-weighted hemisphere sample per pixel,
|
||||
bounce: light spheres (torches etc.) + full-block/cutout hit shading
|
||||
(albedo from atlas, direct sun via shadow ray, skylight from voxel.w,
|
||||
one IRC bounce).
|
||||
- **Specular** (SpecularTracer): GGX importance-sampled reflection direction,
|
||||
traced; hit shading + sky sampling on miss/escape (`SampleSkyBox` from the
|
||||
precomputed panorama); light spheres contribute.
|
||||
- **IRC** (IRC_CS / SH_TRACING_CS / SampleIRC): 3D irradiance cache grid
|
||||
(PT_IRC_RESOLUTION³), updated by tracing few rays per cell toward the sky
|
||||
with SH-weighted accumulation, trilinearly sampled with normal bias as cheap
|
||||
indirect diffuse.
|
||||
|
||||
## 5. Denoiser
|
||||
|
||||
- **Temporal**: reproject previous frame by motion vectors (+jitter), validate
|
||||
with prevDepth2D, neighborhood clamp (min/max 3×3), blend by accumulation
|
||||
count (`PT_DIFFUSE_TEMPORAL_MAX_ACCUM`), history-fix option.
|
||||
- **Variance**: luminance moments over 3×3 to steer firefly handling.
|
||||
- **Spatial**: edge-avoiding A-trous passes; weights combine luminance, depth
|
||||
and normal similarity; diffuse 4 levels (steps 1,2,4,8), specular 2 levels.
|
||||
|
||||
## 6. Lighting composite (Soild_FS)
|
||||
|
||||
Per pixel: gbuffer decode -> direct sun (GetSunlight: voxel shadow tracing,
|
||||
optionally warped shadow map) + block light (lightmap, colored) + IRC ambient
|
||||
+ held light (torch/flashlight with short shadow ray) + emission (gbuffer.a) +
|
||||
denoised PT diffuse (colortex7) + denoised PT specular (colortex11) with
|
||||
reflection strength, plus analytic GGX direct specular (NDF/geometry/Fresnel).
|
||||
Transparent pass (Translucent_FS) handles water (fresnel + refraction color),
|
||||
glass (fresnel tint), particles.
|
||||
|
||||
## 7. Sky / atmosphere / clouds / volumetrics
|
||||
|
||||
- Analytic Rayleigh/Mie atmosphere (`PrecomputedAtmosphere.glsl`): sun/sky
|
||||
irradiance from camera altitude + sun elevation; sky radiance per direction
|
||||
with sun disk, sunset tint, horizon haze, night sky. Sky panorama
|
||||
(SkyImage_CS) renders a 3:2 cubemap cross into skyBox2D for PT sky sampling.
|
||||
- End sky: stars, planet, accretion disc (EndSky).
|
||||
- Planar clouds: FBM 2D density, coverage/density by weather, sun+sky lighting.
|
||||
- Volumetric fog (Volumetric_FS): height-based two-layer density + 3D noise,
|
||||
ray marched with jitter, sun phase in-scattering, cloud shadow modulation;
|
||||
underwater fog variant.
|
||||
- Water: Gerstner-ish multi-octave waves (WaterWaves), caustics field
|
||||
(CausticsTex_CS analytic wave normal field), refraction pass, deep-water tint.
|
||||
|
||||
## 8. Post-processing
|
||||
|
||||
Auto exposure (log-average luminance, temporal smoothing, EV), bloom (2-level
|
||||
downsample + axial blur X/Y + composite), TAA (jittered accumulation with
|
||||
neighborhood clamp and subpixel sharpening), motion blur (per-pixel velocity,
|
||||
shutter angle), DOF (CoC + bokeh gather, cat's eye option), final tonemap
|
||||
(ACES/AGX/filmic/vanilla), color grading (white/black point, saturation, gamma,
|
||||
tone hue shifts), blue-noise dithering, gamma output.
|
||||
|
||||
## 9. RTWSM (warped shadow map)
|
||||
|
||||
BackwardAnalysis computes per-texel importance from shadow depth proximity and
|
||||
gradient; BlurImportance smooths it; CollapseImportance + BuildingWarp build a
|
||||
1D cumulative warp curve per row (rtwWarp1D); SampleWarp redistributes shadow
|
||||
map coordinates toward high-importance texels, applied both when rendering the
|
||||
shadow map (GS) and when sampling it.
|
||||
|
||||
## 10. Per-frame lighting constants\r?\n\r?\nNo shared SSBO is used (for maximum loader compatibility). Per-frame lighting\r?\nvalues (sun direction, sun/moon/sky irradiances, cloud irradiances, fog factors)\r?\nare computed inline by `Lib/BasicFunctions/LightingConstants.glsl` — cheap\r?\nfunctions of the sun angle and camera altitude using the analytic atmosphere\r?\nmodel. Auto-exposure is computed by Exposure_CS into a 1x1 R16F image\r?\n(exposureTex) that the final pass samples.\r?\n
|
||||
## 11. File map
|
||||
|
||||
```
|
||||
shaders/
|
||||
shaders.properties program chain, buffers, images, GUI
|
||||
block.properties block -> ID mapping (material system)
|
||||
entity.properties entity -> ID mapping
|
||||
item.properties held item light levels
|
||||
begin1.csh shadow.* final.* gbuffers_*.vsh/fsh composite*.fsh/csh
|
||||
world1/ world-1/ Nether/End overrides
|
||||
Lib/ all implementation code (see tree above)
|
||||
texture/ noise.png, CloudNoise bins, ripple.png
|
||||
lang/ en_us / zh_cn
|
||||
scripts/ generate_textures.js (regenerates textures)
|
||||
```
|
||||
|
||||
## 12. Tuning notes
|
||||
|
||||
- Default: PT_VOXEL_RESOLUTION 8006 (256×192×256, 128-block radius, S=8192),
|
||||
half-res tracing, 8-frame temporal accumulation, IRC 32³.
|
||||
- For weaker GPUs: 8004 (S=4096), PT_HALF_RES stays on, reduce
|
||||
PT_DIFFUSE_TEMPORAL_MAX_ACCUM, VFOG_QUALITY.
|
||||
- For high end: 12006/16008, SKYBOX_RESOLUTION 128, DOF on, motion blur on.
|
||||
@@ -0,0 +1,205 @@
|
||||
// MinecraftPT texture generator
|
||||
// Generates noise.png (blue noise), CloudNoise 3D bins, and ripple.png
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const zlib = require('zlib');
|
||||
|
||||
const outDir = path.join(__dirname, 'texture');
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
|
||||
// ---------- PNG encoder (minimal, non-interlaced RGBA8) ----------
|
||||
function crc32(buf) {
|
||||
let table = crc32.table;
|
||||
if (!table) {
|
||||
table = crc32.table = new Int32Array(256);
|
||||
for (let n = 0; n < 256; n++) {
|
||||
let c = n;
|
||||
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
||||
table[n] = c;
|
||||
}
|
||||
}
|
||||
let crc = -1;
|
||||
for (let i = 0; i < buf.length; i++) crc = (crc >>> 8) ^ table[(crc ^ buf[i]) & 0xff];
|
||||
return (crc ^ -1) >>> 0;
|
||||
}
|
||||
|
||||
function chunk(type, data) {
|
||||
const len = Buffer.alloc(4);
|
||||
len.writeUInt32BE(data.length);
|
||||
const typeBuf = Buffer.from(type, 'ascii');
|
||||
const crc = Buffer.alloc(4);
|
||||
crc.writeUInt32BE(crc32(Buffer.concat([typeBuf, data])));
|
||||
return Buffer.concat([len, typeBuf, data, crc]);
|
||||
}
|
||||
|
||||
function encodePNG(width, height, rgba) {
|
||||
const sig = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
||||
const ihdr = Buffer.alloc(13);
|
||||
ihdr.writeUInt32BE(width, 0);
|
||||
ihdr.writeUInt32BE(height, 4);
|
||||
ihdr[8] = 8; // bit depth
|
||||
ihdr[9] = 6; // color type RGBA
|
||||
const raw = Buffer.alloc((width * 4 + 1) * height);
|
||||
for (let y = 0; y < height; y++) {
|
||||
raw[y * (width * 4 + 1)] = 0; // filter none
|
||||
rgba.copy(raw, y * (width * 4 + 1) + 1, y * width * 4, (y + 1) * width * 4);
|
||||
}
|
||||
const idat = zlib.deflateSync(raw, { level: 9 });
|
||||
return Buffer.concat([sig, chunk('IHDR', ihdr), chunk('IDAT', idat), chunk('IEND', Buffer.alloc(0))]);
|
||||
}
|
||||
|
||||
// ---------- Hashing ----------
|
||||
function hash1(x, y, z, seed) {
|
||||
let h = (x * 374761393 + y * 668265263 + z * 2246822519 + seed * 3266489917) | 0;
|
||||
h = (h ^ (h >>> 13)) | 0;
|
||||
h = Math.imul(h, 1274126177);
|
||||
h = (h ^ (h >>> 16)) >>> 0;
|
||||
return h / 4294967296;
|
||||
}
|
||||
|
||||
// ---------- 1. Blue noise 128x128 ----------
|
||||
{
|
||||
const S = 128;
|
||||
const buf = Buffer.alloc(S * S * 4);
|
||||
const noise = new Float32Array(S * S);
|
||||
|
||||
// white noise
|
||||
for (let y = 0; y < S; y++)
|
||||
for (let x = 0; x < S; x++)
|
||||
noise[y * S + x] = hash1(x, y, 7, 12345);
|
||||
|
||||
// high-pass: n - blur(n), renormalize -> bluish
|
||||
const blurred = new Float32Array(S * S);
|
||||
for (let y = 0; y < S; y++) {
|
||||
for (let x = 0; x < S; x++) {
|
||||
let sum = 0;
|
||||
for (let dy = -1; dy <= 1; dy++)
|
||||
for (let dx = -1; dx <= 1; dx++) {
|
||||
const xx = (x + dx + S) % S;
|
||||
const yy = (y + dy + S) % S;
|
||||
sum += noise[yy * S + xx];
|
||||
}
|
||||
blurred[y * S + x] = sum / 9;
|
||||
}
|
||||
}
|
||||
let min = 1e9, max = -1e9;
|
||||
for (let i = 0; i < S * S; i++) {
|
||||
const v = noise[i] - blurred[i];
|
||||
noise[i] = v;
|
||||
if (v < min) min = v;
|
||||
if (v > max) max = v;
|
||||
}
|
||||
for (let y = 0; y < S; y++) {
|
||||
for (let x = 0; x < S; x++) {
|
||||
const v = (noise[y * S + x] - min) / (max - min);
|
||||
const p = y * S * 4 + x * 4;
|
||||
buf[p] = Math.round(v * 255);
|
||||
buf[p + 1] = Math.round(v * 255);
|
||||
buf[p + 2] = Math.round(v * 255);
|
||||
buf[p + 3] = 255;
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(path.join(outDir, 'noise.png'), encodePNG(S, S, buf));
|
||||
console.log('noise.png generated');
|
||||
}
|
||||
|
||||
// ---------- 2. 3D value noise (128^3 RGBA8) ----------
|
||||
function make3DNoise(W, H, D, seed) {
|
||||
const data = Buffer.alloc(W * H * D * 4);
|
||||
|
||||
// Generate 3 octaves of value noise at lattice 8, 4, 2
|
||||
const octaves = [
|
||||
{ lat: 8, amp: 0.6 },
|
||||
{ lat: 4, amp: 0.3 },
|
||||
{ lat: 2, amp: 0.1 },
|
||||
];
|
||||
|
||||
for (let z = 0; z < D; z++) {
|
||||
for (let y = 0; y < H; y++) {
|
||||
for (let x = 0; x < W; x++) {
|
||||
let v = 0;
|
||||
for (const o of octaves) {
|
||||
const L = o.lat;
|
||||
const fx = (x / W) * L;
|
||||
const fy = (y / H) * L;
|
||||
const fz = (z / D) * L;
|
||||
const x0 = Math.floor(fx), y0 = Math.floor(fy), z0 = Math.floor(fz);
|
||||
const x1 = x0 + 1, y1 = y0 + 1, z1 = z0 + 1;
|
||||
const tx = fx - x0, ty = fy - y0, tz = fz - z0;
|
||||
const sx = tx * tx * (3 - 2 * tx);
|
||||
const sy = ty * ty * (3 - 2 * ty);
|
||||
const sz = tz * tz * (3 - 2 * tz);
|
||||
|
||||
const c000 = hash1(x0, y0, z0, seed + o.lat);
|
||||
const c100 = hash1(x1, y0, z0, seed + o.lat);
|
||||
const c010 = hash1(x0, y1, z0, seed + o.lat);
|
||||
const c110 = hash1(x1, y1, z0, seed + o.lat);
|
||||
const c001 = hash1(x0, y0, z1, seed + o.lat);
|
||||
const c101 = hash1(x1, y0, z1, seed + o.lat);
|
||||
const c011 = hash1(x0, y1, z1, seed + o.lat);
|
||||
const c111 = hash1(x1, y1, z1, seed + o.lat);
|
||||
|
||||
const x00 = c000 + (c100 - c000) * sx;
|
||||
const x10 = c010 + (c110 - c010) * sx;
|
||||
const x01 = c001 + (c101 - c001) * sx;
|
||||
const x11 = c011 + (c111 - c011) * sx;
|
||||
const y0v = x00 + (x10 - x00) * sy;
|
||||
const y1v = x01 + (x11 - x01) * sy;
|
||||
v += (y0v + (y1v - y0v) * sz) * o.amp;
|
||||
}
|
||||
const idx = (z * H + y) * W * 4 + x * 4;
|
||||
data[idx] = Math.round(v * 255);
|
||||
data[idx + 1] = Math.round(v * 255);
|
||||
data[idx + 2] = Math.round(v * 255);
|
||||
data[idx + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
{
|
||||
const W = 128, H = 128, D = 128;
|
||||
const data = make3DNoise(W, H, D, 4242);
|
||||
fs.writeFileSync(path.join(outDir, 'CloudNoise_128_128_128.bin'), data);
|
||||
console.log('CloudNoise_128_128_128.bin generated');
|
||||
}
|
||||
|
||||
{
|
||||
const W = 32, H = 32, D = 32;
|
||||
const data = make3DNoise(W, H, D, 7777);
|
||||
// RGB8 only
|
||||
const rgb = Buffer.alloc(W * H * D * 3);
|
||||
for (let i = 0; i < W * H * D; i++) {
|
||||
rgb[i * 3] = data[i * 4];
|
||||
rgb[i * 3 + 1] = data[i * 4 + 1];
|
||||
rgb[i * 3 + 2] = data[i * 4 + 2];
|
||||
}
|
||||
fs.writeFileSync(path.join(outDir, 'CloudNoise2_32_32_32.bin'), rgb);
|
||||
console.log('CloudNoise2_32_32_32.bin generated');
|
||||
}
|
||||
|
||||
// ---------- 3. Ripple 128x128 ----------
|
||||
{
|
||||
const S = 128;
|
||||
const buf = Buffer.alloc(S * S * 4);
|
||||
for (let y = 0; y < S; y++) {
|
||||
for (let x = 0; x < S; x++) {
|
||||
const dx = (x - S / 2) / S;
|
||||
const dy = (y - S / 2) / S;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
// concentric ripple
|
||||
const n = hash1(x, y, 11, 999);
|
||||
const ripple = 0.5 + 0.5 * Math.sin(dist * 40 + n * 6.28);
|
||||
const p = (y * S + x) * 4;
|
||||
buf[p] = Math.round(ripple * 255);
|
||||
buf[p + 1] = Math.round(ripple * 255);
|
||||
buf[p + 2] = 128;
|
||||
buf[p + 3] = 255;
|
||||
}
|
||||
}
|
||||
fs.writeFileSync(path.join(outDir, 'ripple.png'), encodePNG(S, S, buf));
|
||||
console.log('ripple.png generated');
|
||||
}
|
||||
|
||||
console.log('All textures generated in', outDir);
|
||||
@@ -0,0 +1,37 @@
|
||||
// MinecraftPT — Block Light
|
||||
// Maps vanilla block light level to physical light, with per-block colors.
|
||||
|
||||
#ifndef BLOCKLIGHT_GLSL
|
||||
#define BLOCKLIGHT_GLSL
|
||||
|
||||
// Convert lightmap blocklight (0-1) to physical light intensity
|
||||
float BlocklightFromLightmap(float blocklight){
|
||||
return pow(blocklight, 2.0) * BLOCKLIGHT_BRIGHTNESS;
|
||||
}
|
||||
|
||||
// Get the block light color for a material
|
||||
vec3 BlocklightColor(float materialID){
|
||||
// Warm torch color by default
|
||||
vec3 color = pow(vec3(COLOR_TORCH_R, COLOR_TORCH_G, COLOR_TORCH_B), vec3(2.2));
|
||||
|
||||
if (materialID == MATID_SOULTORCH || materialID == MATID_COPPER_LANTERN){
|
||||
color = pow(vec3(COLOR_SOULTORCH_R, COLOR_SOULTORCH_G, COLOR_SOULTORCH_B), vec3(2.2));
|
||||
}else if (materialID == MATID_AMETHYST){
|
||||
color = pow(vec3(COLOR_AMETHYST_R, COLOR_AMETHYST_G, COLOR_AMETHYST_B), vec3(2.2));
|
||||
}else if (materialID == MATID_FIRE){
|
||||
color = pow(vec3(COLOR_FIRE_R, COLOR_FIRE_G, COLOR_FIRE_B), vec3(2.2));
|
||||
}else if (materialID == MATID_ENDROD){
|
||||
color = pow(vec3(COLOR_ENDROD_R, COLOR_ENDROD_G, COLOR_ENDROD_B), vec3(2.2));
|
||||
}
|
||||
|
||||
return color * BlocklightFromLightmap(0.5);
|
||||
}
|
||||
|
||||
// Physical block light for a lightmap value
|
||||
vec3 Blocklight(vec2 lightmap){
|
||||
// Blocklight color temperature
|
||||
vec3 warmColor = pow(vec3(COLOR_TORCH_R, COLOR_TORCH_G, COLOR_TORCH_B), vec3(2.2));
|
||||
return warmColor * pow(lightmap.x, 2.0) * BLOCKLIGHT_BRIGHTNESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// MinecraftPT — Held Light
|
||||
// Torch in hand / flashlight illumination.
|
||||
|
||||
#ifndef HELDLIGHT_GLSL
|
||||
#define HELDLIGHT_GLSL
|
||||
|
||||
// Physical held light: torches held in hand or flashlight
|
||||
vec3 GetHeldLight(vec3 worldPos, vec3 worldNormal, out float heldLightShadow){
|
||||
vec3 result = vec3(0.0);
|
||||
heldLightShadow = 1.0;
|
||||
|
||||
#ifdef HELDLIGHT_MODE
|
||||
#if HELDLIGHT_MODE >= 1
|
||||
// Torch in hand position (roughly 0.4, -0.4, 0.6 relative to camera)
|
||||
vec3 heldPos = gbufferModelViewInverse[3].xyz + cameraPosition;
|
||||
vec3 toLight = heldPos - worldPos;
|
||||
float dist = length(toLight);
|
||||
vec3 dir = toLight / max(dist, 1e-4);
|
||||
|
||||
float intensity = exp(-dist * dist * HELDLIGHT_FALLOFF) * HELDLIGHT_BRIGHTNESS;
|
||||
float NdotL = max(dot(worldNormal, dir), 0.0);
|
||||
|
||||
vec3 color = pow(vec3(COLOR_TORCH_R, COLOR_TORCH_G, COLOR_TORCH_B), vec3(2.2));
|
||||
|
||||
result = color * intensity * NdotL;
|
||||
|
||||
#ifdef HELDLIGHT_SHADOW
|
||||
// Simple ray shadow for held light (short distance)
|
||||
heldLightShadow = SimpleShadowTracing(WorldToVoxel(worldPos + worldNormal * 0.1), dir);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Lighting Constants
|
||||
// Per-frame lighting values computed inline (no SSBO dependency).
|
||||
// These are cheap functions of the sun angle and camera position; computed
|
||||
// per-pass instead of via a shared buffer for maximum loader compatibility.
|
||||
|
||||
#ifndef LIGHTING_CONSTANTS_GLSL
|
||||
#define LIGHTING_CONSTANTS_GLSL
|
||||
|
||||
#include "/Lib/BasicFunctions/PrecomputedAtmosphere.glsl"
|
||||
|
||||
// Sun direction in world space (matches the shadow camera direction)
|
||||
vec3 GetSunDirWorld(){
|
||||
#ifndef DIMENSION_NETHER
|
||||
#ifndef DIMENSION_END
|
||||
return normalize(shadowModelViewInverse2);
|
||||
#else
|
||||
return normalize(shadowModelViewInverse2) * fsign(0.5 - sunAngle);
|
||||
#endif
|
||||
#else
|
||||
return normalize(shadowModelViewInverse2) * fsign(0.5 - sunAngle);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Atmosphere camera position (scaled Earth radius + camera altitude)
|
||||
vec3 GetAtmoCamera(){
|
||||
return vec3(0.0, max(cameraPosition.y, 63.0) * 0.001 + atmosphereModel_bottom_radius, 0.0);
|
||||
}
|
||||
|
||||
// Sun irradiance (direct light color/intensity)
|
||||
vec3 GetSunIrradiance(){
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
vec3 moon, sunSky, moonSky;
|
||||
return GetSunAndSkyIrradiance(GetAtmoCamera(), sunDir, -sunDir, moon, sunSky, moonSky);
|
||||
}
|
||||
|
||||
vec3 GetMoonIrradiance(){
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
vec3 moon, sunSky, moonSky;
|
||||
GetSunAndSkyIrradiance(GetAtmoCamera(), sunDir, -sunDir, moon, sunSky, moonSky);
|
||||
return moon;
|
||||
}
|
||||
|
||||
vec3 GetCelestialIrradiance(){
|
||||
return GetSunIrradiance() + GetMoonIrradiance();
|
||||
}
|
||||
|
||||
vec3 GetAtmoIrradiance(){
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
vec3 moon, sunSky, moonSky;
|
||||
GetSunAndSkyIrradiance(GetAtmoCamera(), sunDir, -sunDir, moon, sunSky, moonSky);
|
||||
return sunSky + moonSky;
|
||||
}
|
||||
|
||||
// Cloud-altitude irradiances
|
||||
vec3 GetCloudSunIrradiance(){
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
vec3 atmoCamera = vec3(0.0, mix(CLOUD_CLEAR_ALTITUDE, CLOUD_RAIN_ALTITUDE, wetness) * 0.001 + atmosphereModel_bottom_radius, 0.0);
|
||||
vec3 moon, sunSky, moonSky;
|
||||
return GetSunAndSkyIrradiance(atmoCamera, sunDir, -sunDir, moon, sunSky, moonSky);
|
||||
}
|
||||
|
||||
vec3 GetCloudAtmoIrradiance(){
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
vec3 atmoCamera = vec3(0.0, mix(CLOUD_CLEAR_ALTITUDE, CLOUD_RAIN_ALTITUDE, wetness) * 0.001 + atmosphereModel_bottom_radius, 0.0);
|
||||
vec3 moon, sunSky, moonSky;
|
||||
GetSunAndSkyIrradiance(atmoCamera, sunDir, -sunDir, moon, sunSky, moonSky);
|
||||
return sunSky + moonSky;
|
||||
}
|
||||
|
||||
// Moon/sun phase for fog time factor
|
||||
vec2 GetFogTimeFactor(){
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
float timeNoon = pow(1.0 - (clamp(sunDir.y, 0.2, 0.99) - 0.2) / 0.8, 6.0);
|
||||
float moonlightStrength = curve(saturate(sunDir.y * -5.0));
|
||||
return vec2(timeNoon, moonlightStrength);
|
||||
}
|
||||
|
||||
// Dimension-aware irradiance override
|
||||
vec3 GetDimensionAmbient(){
|
||||
#ifdef DIMENSION_NETHER
|
||||
return vec3(0.08, 0.02, 0.01) * NETHER_BRIGHTNESS;
|
||||
#elif defined DIMENSION_END
|
||||
return vec3(0.02, 0.02, 0.04);
|
||||
#else
|
||||
return GetAtmoIrradiance();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
// MinecraftPT — Nether Color
|
||||
// Dimension-specific color and lighting adjustments.
|
||||
|
||||
#ifndef NETHER_COLOR_GLSL
|
||||
#define NETHER_COLOR_GLSL
|
||||
|
||||
vec3 GetDimensionSkylight(vec3 skyColor){
|
||||
#ifdef DIMENSION_NETHER
|
||||
return skyColor * 0.4;
|
||||
#elif defined DIMENSION_END
|
||||
return skyColor * 0.2;
|
||||
#else
|
||||
return skyColor;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Precomputed Atmosphere (analytic)
|
||||
// A compact analytic Rayleigh/Mie sky model with precomputed transmittance.
|
||||
// Provides sun/sky irradiance for the scene and sky radiance for the panorama.
|
||||
|
||||
#ifndef PRECOMPUTED_ATMOSPHERE_GLSL
|
||||
#define PRECOMPUTED_ATMOSPHERE_GLSL
|
||||
|
||||
// Earth-like atmosphere constants (scaled)
|
||||
const float atmosphereModel_bottom_radius = 6360.0;
|
||||
const float atmosphereModel_top_radius = 6420.0;
|
||||
|
||||
const vec3 wavelengths = vec3(680.0, 550.0, 440.0); // nm
|
||||
const vec3 betaRayleigh = vec3(5.802, 13.558, 33.1) * 1e-6;
|
||||
const float betaMie = 3.996e-6;
|
||||
const float mieG = 0.8;
|
||||
|
||||
vec3 RayleighPhase(float cosTheta){
|
||||
return 3.0 / (16.0 * 3.14159265) * (1.0 + cosTheta * cosTheta);
|
||||
}
|
||||
|
||||
vec3 MiePhase(float cosTheta){
|
||||
float g = mieG;
|
||||
float g2 = g * g;
|
||||
return 3.0 / (8.0 * 3.14159265) * ((1.0 - g2) * (1.0 + cosTheta * cosTheta)) /
|
||||
((2.0 + g2) * pow(1.0 + g2 - 2.0 * g * cosTheta, 1.5));
|
||||
}
|
||||
|
||||
// Ground intersection for ray from camera
|
||||
float GroundIntersection(vec3 pos, vec3 dir){
|
||||
float b = dot(pos, dir);
|
||||
float c = dot(pos, pos) - atmosphereModel_bottom_radius * atmosphereModel_bottom_radius;
|
||||
float h = b * b - c;
|
||||
if (h > 0.0){
|
||||
float t = -b - sqrt(h);
|
||||
if (t > 0.0) return t;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
float AtmosphereIntersection(vec3 pos, vec3 dir){
|
||||
float b = dot(pos, dir);
|
||||
float c = dot(pos, pos) - atmosphereModel_top_radius * atmosphereModel_top_radius;
|
||||
float h = b * b - c;
|
||||
if (h > 0.0){
|
||||
float t = -b + sqrt(h);
|
||||
if (t > 0.0) return t;
|
||||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
// Optical depth to space (transmittance approximation)
|
||||
vec3 OpticalDepthToSpace(vec3 pos, vec3 dir){
|
||||
float tMax = AtmosphereIntersection(pos, dir);
|
||||
if (tMax < 0.0) return vec3(1e10);
|
||||
|
||||
const int steps = 16;
|
||||
float dt = tMax / float(steps);
|
||||
vec3 opticalDepth = vec3(0.0);
|
||||
|
||||
vec3 p = pos;
|
||||
for (int i = 0; i < steps; i++){
|
||||
float h = length(p) - atmosphereModel_bottom_radius;
|
||||
vec3 density = exp(-h / 8.0) * betaRayleigh + exp(-h / 1.2) * betaMie;
|
||||
opticalDepth += density * dt;
|
||||
p += dir * dt;
|
||||
}
|
||||
|
||||
return opticalDepth;
|
||||
}
|
||||
|
||||
// Sun/sky irradiance at a camera position (simplified single scattering)
|
||||
void GetSunAndSkyIrradiance(vec3 camera, vec3 sunDir, vec3 moonDir,
|
||||
out vec3 colorSunlight, out vec3 colorMoonlight,
|
||||
out vec3 colorSunSkylight, out vec3 colorMoonSkylight){
|
||||
|
||||
vec3 sunColor = vec3(1.0, 0.98, 0.92);
|
||||
vec3 moonColor = vec3(0.5, 0.6, 0.8) * 0.1;
|
||||
|
||||
float sunElevation = sunDir.y;
|
||||
float moonElevation = moonDir.y;
|
||||
|
||||
float sunStrength = curve(saturate(sunElevation * 15.0 + 0.5));
|
||||
float moonStrength = curve(saturate(-sunElevation * 5.0 + 0.5));
|
||||
|
||||
// Sun disk color by elevation (sunset tint)
|
||||
vec3 sunsetTint = mix(vec3(1.0, 0.3, 0.1), vec3(1.0), curve(saturate(sunElevation * 3.0)));
|
||||
sunColor *= sunsetTint;
|
||||
|
||||
colorSunlight = sunColor * sunStrength * SUNLIGHT_INTENSITY;
|
||||
colorMoonlight = moonColor * moonStrength;
|
||||
|
||||
// Sky irradiance: ambient hemisphere light
|
||||
vec3 skyColorDay = vec3(0.55, 0.75, 1.0) * sunStrength * 0.8;
|
||||
vec3 skyColorNight = vec3(0.05, 0.08, 0.15) * 0.3;
|
||||
vec3 skyColorSunset = vec3(1.0, 0.5, 0.3) * curve(saturate(1.0 - abs(sunElevation) * 4.0)) * 0.3;
|
||||
|
||||
colorSunSkylight = skyColorDay + skyColorSunset;
|
||||
colorMoonSkylight = skyColorNight;
|
||||
}
|
||||
|
||||
// Sky radiance for a direction (used for the sky panorama and reflections)
|
||||
vec3 GetSkyRadiance(vec3 dir, vec3 sunDir){
|
||||
dir = normalize(dir);
|
||||
sunDir = normalize(sunDir);
|
||||
|
||||
float cosTheta = dot(dir, sunDir);
|
||||
|
||||
// Horizon / elevation response
|
||||
float elevation = dir.y;
|
||||
|
||||
// Day sky
|
||||
vec3 skyDay = vec3(0.4, 0.62, 0.9) * 0.6;
|
||||
skyDay = mix(skyDay, vec3(0.9, 0.95, 1.0), pow(saturate(elevation), 0.6));
|
||||
skyDay *= 1.0 - exp(-max(elevation, 0.0) * 3.0);
|
||||
|
||||
// Rayleigh scattering glow around sun
|
||||
vec3 rayleigh = RayleighPhase(cosTheta) * betaRayleigh * 1.2;
|
||||
|
||||
// Mie scattering (sun disk)
|
||||
float mie = MiePhase(cosTheta) * betaMie * 20.0;
|
||||
|
||||
// Sun disk itself
|
||||
float sunDisk = exp(-(1.0 - cosTheta) / (2.0 * SUN_ANGULAR_RADIUS * SUN_ANGULAR_RADIUS));
|
||||
|
||||
vec3 sunColor = vec3(1.0, 0.97, 0.9) * SUNLIGHT_INTENSITY;
|
||||
|
||||
// Sunset tint
|
||||
float sunElevation = sunDir.y;
|
||||
sunColor *= mix(vec3(1.0, 0.3, 0.1), vec3(1.0), curve(saturate(sunElevation * 3.0)));
|
||||
|
||||
float sunVisible = curve(saturate(sunElevation * 15.0 + 0.5));
|
||||
|
||||
vec3 radiance = skyDay;
|
||||
radiance += sunColor * (rayleigh + mie) * sunVisible;
|
||||
radiance += sunColor * sunDisk * sunVisible * 80.0;
|
||||
|
||||
// Night sky
|
||||
float night = 1.0 - curve(saturate(sunElevation * 10.0 + 0.5));
|
||||
radiance += vec3(0.02, 0.03, 0.06) * night;
|
||||
|
||||
// Horizon haze
|
||||
float horizon = exp(-abs(elevation) * 4.0);
|
||||
radiance += vec3(0.9, 0.7, 0.5) * horizon * sunVisible * 0.1;
|
||||
|
||||
return radiance;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
// MinecraftPT — Sunlight & Shadow
|
||||
// Direct sunlight with RTWSM warped shadow map sampling and voxel shadow tracing.
|
||||
|
||||
#ifndef SUNLIGHT_SHADOW_GLSL
|
||||
#define SUNLIGHT_SHADOW_GLSL
|
||||
|
||||
#include "/Lib/RTWSM/SampleWarp.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
|
||||
// Sample the warped shadow map
|
||||
float SampleShadowMap(vec3 shadowPos){
|
||||
vec2 shadowCoord = shadowPos.xy * 0.5 + 0.5;
|
||||
vec3 shadowUv = vec3(UnshiftShadowScreenPos(shadowCoord), shadowPos.z * 0.5 + 0.5);
|
||||
|
||||
float shadow = 0.0;
|
||||
float depth = shadowUv.z;
|
||||
|
||||
#ifdef SHADOW_QUALITY
|
||||
#if SHADOW_QUALITY >= 2
|
||||
// 3x3 PCF
|
||||
for (int i = -1; i <= 1; i++){
|
||||
for (int j = -1; j <= 1; j++){
|
||||
vec2 sampleCoord = shadowUv.xy + vec2(i, j) * shadowPixelSize;
|
||||
shadow += step(texelFetch(shadowcolor0, ivec2(sampleCoord * shadowSize), 0).a, depth) * (1.0 / 9.0);
|
||||
}}
|
||||
#else
|
||||
shadow = step(texelFetch(shadowcolor0, ivec2(shadowUv.xy * shadowSize), 0).a, depth);
|
||||
#endif
|
||||
#else
|
||||
shadow = step(texelFetch(shadowcolor0, ivec2(shadowUv.xy * shadowSize), 0).a, depth);
|
||||
#endif
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
// Full sunlight evaluation: shadow map + optional voxel shadow tracing
|
||||
float GetSunShadow(vec3 viewPos, vec3 worldPos, vec3 vertexNormal, float lightmap){
|
||||
float shadow = 1.0;
|
||||
|
||||
#ifdef PT_SHADOW
|
||||
vec3 shadowDir = normalize(shadowModelViewInverse2);
|
||||
shadow = ShadowTracing(viewPos, worldPos, vertexNormal, shadowDir, lightmap);
|
||||
#else
|
||||
// Shadow map path
|
||||
vec4 shadowPos = shadowProjection * shadowModelView * vec4(worldPos, 1.0);
|
||||
if (shadowPos.w > 0.0){
|
||||
vec3 shadowNdc = shadowPos.xyz / shadowPos.w;
|
||||
if (all(lessThan(abs(shadowNdc.xy), vec2(1.0)))){
|
||||
shadow = SampleShadowMap(shadowNdc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
// Direct sun light for a surface
|
||||
vec3 GetSunlight(vec3 viewPos, vec3 worldPos, vec3 vertexNormal, vec3 worldNormal, float lightmap){
|
||||
float shadow = GetSunShadow(viewPos, worldPos, vertexNormal, lightmap);
|
||||
float NdotL = max(dot(worldNormal, GetSunDirWorld()), 0.0);
|
||||
|
||||
vec3 sunColor = GetSunIrradiance();
|
||||
#ifdef COLORED_SHADOWS
|
||||
// Sample shadow albedo for colored shadows (subtle)
|
||||
vec3 shadowAlbedo = vec3(0.0);
|
||||
sunColor *= 1.0 - shadowAlbedo * 0.3;
|
||||
#endif
|
||||
|
||||
return sunColor * shadow * NdotL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
// MinecraftPT — Temporal Noise
|
||||
// Blue noise sampling with temporal interleaving, used for dithering and ray offsets.
|
||||
|
||||
#ifndef TEMPORAL_NOISE_GLSL
|
||||
#define TEMPORAL_NOISE_GLSL
|
||||
|
||||
float BlueNoiseTemporal(){
|
||||
vec2 coord = (gl_FragCoord.xy + 0.5) / screenSize;
|
||||
coord = fract(coord * vec2(128.0, 128.0) + 0.5);
|
||||
vec2 texel = coord * vec2(127.0 / 128.0) + vec2(0.5 / 128.0);
|
||||
float noise = textureLod(noisetex, texel, 0.0).r;
|
||||
return fract(noise + frameCounter * 0.03125);
|
||||
}
|
||||
|
||||
vec2 BlueNoiseTemporal2(){
|
||||
vec2 coord = (gl_FragCoord.xy + 0.5) / screenSize;
|
||||
coord = fract(coord * vec2(128.0, 128.0) + 0.5);
|
||||
vec2 texel = coord * vec2(127.0 / 128.0) + vec2(0.5 / 128.0);
|
||||
vec2 noise = textureLod(noisetex, texel, 0.0).rg;
|
||||
return fract(noise + frameCounter * 0.03125);
|
||||
}
|
||||
|
||||
// Interleaved gradient noise
|
||||
float InterleavedNoise(vec2 pos){
|
||||
vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
|
||||
return fract(magic.z * fract(dot(pos, magic.xy)));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
// MinecraftPT — Vanilla Composite helpers
|
||||
// Sky/cloud colors approximating vanilla for transitions and fog.
|
||||
|
||||
#ifndef VANILLA_COMPOSITE_GLSL
|
||||
#define VANILLA_COMPOSITE_GLSL
|
||||
|
||||
vec3 GetVanillaSkyColor(vec3 dir){
|
||||
vec3 skyColor = vec3(0.6, 0.8, 1.0);
|
||||
float horizon = exp(-max(dir.y, 0.0) * 3.0);
|
||||
return mix(skyColor * 0.3, skyColor, 1.0 - horizon);
|
||||
}
|
||||
|
||||
vec3 GetVanillaFogColor(vec3 skyColor, float nightFactor){
|
||||
return mix(skyColor, skyColor * vec3(0.2, 0.25, 0.4), nightFactor);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,221 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — GbufferData structures
|
||||
|
||||
#ifndef GBUFFER_DATA_GLSL
|
||||
#define GBUFFER_DATA_GLSL
|
||||
|
||||
struct Material{
|
||||
float roughness;
|
||||
float metalness;
|
||||
float emissiveness;
|
||||
float scattering;
|
||||
float reflectionStrength;
|
||||
};
|
||||
|
||||
struct GbufferData{
|
||||
vec3 albedo;
|
||||
float albedoAlpha;
|
||||
vec3 worldNormal;
|
||||
vec3 vertexNormal;
|
||||
vec2 lightmap;
|
||||
float materialID;
|
||||
float parallaxShadow;
|
||||
Material material;
|
||||
};
|
||||
|
||||
// Standard material defaults
|
||||
#define material_air Material(1.0, 0.0, 0.0, 0.0, 0.0);
|
||||
#define material_water Material(0.0, 0.018, 0.0, 0.0, 1.0);
|
||||
#define material_glass Material(0.0, 0.04, 0.0, 0.0, 1.0);
|
||||
|
||||
// Material IDs (written to GBuffer)
|
||||
#define MATID_DEFAULT 0.0
|
||||
#define MATID_WATER 1.0
|
||||
#define MATID_STAINEDGLASS 2.0
|
||||
#define MATID_LEAVES 3.0
|
||||
#define MATID_GRASS 4.0 // cross plant
|
||||
#define MATID_HAND 5.0
|
||||
#define MATID_ENTITIES 6.0
|
||||
#define MATID_ENTITIES_PLAYER 7.0
|
||||
#define MATID_ENTITIES_SNOW 8.0
|
||||
#define MATID_LIGHTNING 9.0
|
||||
#define MATID_SKY 10.0
|
||||
#define MATID_TORCH 11.0
|
||||
#define MATID_FIRE 12.0
|
||||
#define MATID_ENDROD 13.0
|
||||
#define MATID_AMETHYST 14.0
|
||||
#define MATID_SOULTORCH 15.0
|
||||
#define MATID_REDSTONE_TORCH 16.0
|
||||
#define MATID_PARTICLE 17.0
|
||||
#define MATID_END_PORTAL 18.0
|
||||
#define MATID_SELECTION 19.0
|
||||
#define MATID_COPPER_LANTERN 20.0
|
||||
#define MATID_BEACON_BEAM 21.0
|
||||
|
||||
// Material from specular texture (LAB PBR)
|
||||
Material MaterialFromTex(vec4 specTex){
|
||||
Material material;
|
||||
|
||||
material.roughness = 1.0 - specTex.r;
|
||||
material.roughness = material.roughness * material.roughness;
|
||||
|
||||
material.metalness = specTex.g;
|
||||
|
||||
material.reflectionStrength = saturate(material.roughness < 0.1 ? 1.0 : pow(specTex.r, 0.2));
|
||||
material.reflectionStrength = saturate(material.reflectionStrength + material.metalness);
|
||||
material.metalness = max(material.metalness, 0.04);
|
||||
|
||||
material.emissiveness = specTex.a;
|
||||
material.scattering = 0.0;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
// Predefined metal F0 values (from LAB PBR spec)
|
||||
vec3 PredefinedMetalF0(float index){
|
||||
vec3 f0 = vec3(0.0);
|
||||
|
||||
if (abs(index - 230.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.56, 0.58, 0.58); // Iron
|
||||
}else if (abs(index - 231.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(1.00, 0.69, 0.28); // Gold
|
||||
}else if (abs(index - 232.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.81, 0.82, 0.83); // Aluminum
|
||||
}else if (abs(index - 233.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.50, 0.49, 0.49); // Chromium
|
||||
}else if (abs(index - 234.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.95, 0.52, 0.35); // Copper
|
||||
}else if (abs(index - 235.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.81, 0.83, 0.87); // Lead
|
||||
}else if (abs(index - 236.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.66, 0.63, 0.58); // Platinum
|
||||
}else if (abs(index - 237.0 / 255.0) < 2e-4){
|
||||
f0 = vec3(0.95, 0.91, 0.81); // Silver
|
||||
}
|
||||
|
||||
return f0;
|
||||
}
|
||||
|
||||
// Read solid GBuffer data
|
||||
GbufferData GetGbufferDataSoild(ivec2 texelCoord){
|
||||
GbufferData data;
|
||||
|
||||
vec4 gbuffer2 = texelFetch(colortex2, texelCoord, 0);
|
||||
vec4 gbuffer3 = texelFetch(colortex3, texelCoord, 0);
|
||||
|
||||
data.albedo = GammaToLinear(texelFetch(colortex0, texelCoord, 0).rgb);
|
||||
data.albedoAlpha = 1.0;
|
||||
data.worldNormal = DecodeNormal(texelFetch(colortex1, texelCoord, 0).xy);
|
||||
data.vertexNormal = DecodeNormal(texelFetch(colortex1, texelCoord, 0).zw);
|
||||
data.lightmap = gbuffer3.xy;
|
||||
data.materialID = gbuffer2.a;
|
||||
data.parallaxShadow = gbuffer3.b;
|
||||
|
||||
vec4 specTex = vec4(gbuffer2.r, gbuffer2.g, gbuffer2.b, 0.0);
|
||||
data.material = MaterialFromTex(specTex);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Read translucent GBuffer data
|
||||
GbufferData GetGbufferDataTranslucent(ivec2 texelCoord, out bool isSmooth){
|
||||
GbufferData data;
|
||||
|
||||
vec4 gbuffer5 = texelFetch(colortex5, texelCoord, 0);
|
||||
vec4 gbuffer6 = texelFetch(colortex6, texelCoord, 0);
|
||||
|
||||
data.worldNormal = DecodeNormal(gbuffer6.xy);
|
||||
data.vertexNormal = DecodeNormal(gbuffer6.zw);
|
||||
data.lightmap = texelFetch(colortex7, texelCoord, 0).xy;
|
||||
data.materialID = gbuffer6.a;
|
||||
data.parallaxShadow = 1.0;
|
||||
|
||||
isSmooth = false;
|
||||
|
||||
if (data.materialID == MATID_WATER){
|
||||
data.albedo = GammaToLinear(gbuffer5.rgb);
|
||||
data.albedoAlpha = gbuffer5.a;
|
||||
data.material = material_water;
|
||||
isSmooth = true;
|
||||
|
||||
}else if (data.materialID == MATID_STAINEDGLASS){
|
||||
data.albedo = GammaToLinear(gbuffer5.rgb);
|
||||
data.albedoAlpha = gbuffer5.a;
|
||||
data.material = material_glass;
|
||||
isSmooth = true;
|
||||
|
||||
}else if (data.materialID == MATID_PARTICLE){
|
||||
data.albedo = GammaToLinear(gbuffer5.rgb);
|
||||
data.albedoAlpha = gbuffer5.a;
|
||||
data.material = material_air;
|
||||
|
||||
}else{
|
||||
data.albedo = GammaToLinear(texelFetch(colortex0, texelCoord, 0).rgb);
|
||||
data.albedoAlpha = 1.0;
|
||||
vec4 specTex = vec4(gbuffer2.r, gbuffer2.g, gbuffer2.b, 0.0);
|
||||
data.material = MaterialFromTex(specTex);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Material mask utilities
|
||||
struct MaterialMask{
|
||||
float sky;
|
||||
float grass;
|
||||
float leaves;
|
||||
float hand;
|
||||
float entityPlayer;
|
||||
float water;
|
||||
float stainedGlass;
|
||||
float lightning;
|
||||
float entitiesSnow;
|
||||
float endrod;
|
||||
float fire;
|
||||
float torch;
|
||||
float lightSource;
|
||||
float redstoneTorch;
|
||||
float soulTorch;
|
||||
float amethyst;
|
||||
float particle;
|
||||
float endPortal;
|
||||
float selection;
|
||||
};
|
||||
|
||||
MaterialMask CalculateMasks(float materialIDs){
|
||||
MaterialMask mask;
|
||||
|
||||
mask.sky = float(materialIDs == MATID_SKY);
|
||||
mask.grass = float(materialIDs == MATID_GRASS || materialIDs == MATID_BEACON_BEAM);
|
||||
mask.leaves = float(materialIDs == MATID_LEAVES);
|
||||
mask.hand = float(materialIDs == MATID_HAND);
|
||||
mask.water = float(materialIDs == MATID_WATER);
|
||||
mask.stainedGlass = float(materialIDs == MATID_STAINEDGLASS);
|
||||
mask.entityPlayer = float(materialIDs == MATID_ENTITIES_PLAYER);
|
||||
mask.entitiesSnow = float(materialIDs == MATID_ENTITIES_SNOW || materialIDs == MATID_BEACON_BEAM);
|
||||
mask.lightning = float(materialIDs == MATID_LIGHTNING);
|
||||
mask.endrod = float(materialIDs == MATID_ENDROD);
|
||||
mask.fire = float(materialIDs == MATID_FIRE);
|
||||
mask.torch = float(materialIDs == MATID_TORCH);
|
||||
mask.redstoneTorch = float(materialIDs == MATID_REDSTONE_TORCH);
|
||||
mask.amethyst = float(materialIDs == MATID_AMETHYST);
|
||||
mask.soulTorch = float(materialIDs == MATID_SOULTORCH || materialIDs == MATID_COPPER_LANTERN);
|
||||
mask.particle = float(materialIDs == MATID_PARTICLE);
|
||||
mask.endPortal = float(materialIDs == MATID_END_PORTAL);
|
||||
mask.selection = float(materialIDs == MATID_SELECTION);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void ApplyMaterial(inout Material material, in MaterialMask materialMask, inout bool isSmooth){
|
||||
if (materialMask.water > 0.5){
|
||||
material = material_water;
|
||||
isSmooth = true;
|
||||
}else if (materialMask.stainedGlass > 0.5){
|
||||
material = material_glass;
|
||||
isSmooth = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
// MinecraftPT — Bloom CS (SIG)
|
||||
// Bloom sprite / glare generation (compute shader utility).
|
||||
|
||||
#ifndef BLOOM_CS_SIG_GLSL
|
||||
#define BLOOM_CS_SIG_GLSL
|
||||
|
||||
// Bloom glare from bright pixels
|
||||
void EmitBloomGlare(ivec2 texel, vec3 color, float intensity){
|
||||
// Simple bloom spike (cross pattern)
|
||||
// This is a placeholder — actual implementation samples and adds to bloom buffer
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
// MinecraftPT — Cloud Shadow
|
||||
// Cloud shadow projection onto the ground from the cloud layer.
|
||||
|
||||
#ifndef CLOUD_SHADOW_GLSL
|
||||
uniform sampler3D CloudNoise3D;
|
||||
#define CLOUD_SHADOW_GLSL
|
||||
|
||||
float GetCloudShadow(vec3 worldPos){
|
||||
float cloudAlt = mix(CLOUD_CLEAR_ALTITUDE, CLOUD_RAIN_ALTITUDE, wetness);
|
||||
float cloudDensity = mix(CLOUD_CLEAR_DENSITY, CLOUD_RAIN_DENSITY, wetness);
|
||||
|
||||
// Project ground position onto cloud layer
|
||||
vec3 shadowDir = normalize(GetSunDirWorld());
|
||||
vec3 cloudPos = worldPos + shadowDir * (cloudAlt - worldPos.y) / shadowDir.y;
|
||||
|
||||
// Sample cloud density at that position
|
||||
vec2 p = cloudPos.xz * CLOUD_BASE_NOISE_SCALE + frameTimeCounter * 0.001 * CLOUD_SPEED;
|
||||
float n = textureLod(CloudNoise3D, vec3(p, 0.2), 0.0).r;
|
||||
|
||||
float shadow = 1.0 - saturate((n - 0.5) * cloudDensity * 2.0 * CLOUD_SHADOW);
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// MinecraftPT — Depth of Field
|
||||
// Circle of confusion computation and bokeh blur.
|
||||
|
||||
#ifndef DOF_GLSL
|
||||
#define DOF_GLSL
|
||||
|
||||
// Compute CoC (circle of confusion) for a fragment
|
||||
float GetCoC(float depth, float focalDepth){
|
||||
float focus = focalDepth;
|
||||
float aperture = DOF_BLUR;
|
||||
float coc = abs(depth - focus) / focus * aperture * DOF_MAX_COC;
|
||||
return clamp(coc, 0.0, DOF_MAX_COC);
|
||||
}
|
||||
|
||||
// Simple bokeh blur (gather)
|
||||
vec3 DofBlur(vec2 texelCoord, float coc){
|
||||
vec3 color = vec3(0.0);
|
||||
float weight = 0.0;
|
||||
|
||||
int radius = int(min(coc, 8.0)) + 1;
|
||||
for (int i = -radius; i <= radius; i++){
|
||||
for (int j = -radius; j <= radius; j++){
|
||||
float dist = length(vec2(i, j));
|
||||
if (dist > coc) continue;
|
||||
|
||||
vec2 coord = texelCoord + vec2(i, j);
|
||||
vec3 sampleColor = texelFetch(colortex12, ivec2(coord), 0).rgb;
|
||||
float w = max(0.0, 1.0 - dist / coc);
|
||||
|
||||
color += sampleColor * w;
|
||||
weight += w;
|
||||
}}
|
||||
|
||||
return weight > 0.0 ? color / weight : color;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — End Sky
|
||||
// End dimension sky: stars, planet, accretion disc around black hole.
|
||||
|
||||
#ifndef END_SKY_GLSL
|
||||
#define END_SKY_GLSL
|
||||
|
||||
vec3 GetEndSky(vec3 dir, vec3 sunDir){
|
||||
dir = normalize(dir);
|
||||
|
||||
// Dark base
|
||||
vec3 color = vec3(0.01, 0.01, 0.02);
|
||||
|
||||
// Stars (hash-based)
|
||||
float stars = 0.0;
|
||||
vec3 starDir = dir;
|
||||
for (int i = 0; i < 32; i++){
|
||||
vec3 seed = vec3(i * 0.1, 0.5, 0.7);
|
||||
vec3 starPos = normalize(hash3(seed.xy) - 0.5);
|
||||
float star = exp(-(1.0 - dot(dir, starPos)) * 1000.0);
|
||||
stars += star * hash1(seed.xy);
|
||||
}
|
||||
color += stars * 0.5;
|
||||
|
||||
// Planet (distant body)
|
||||
vec3 planetDir = normalize(vec3(0.5, 0.3, 0.0));
|
||||
float planet = exp(-(1.0 - dot(dir, planetDir)) * 200.0);
|
||||
color += vec3(0.3, 0.4, 0.6) * planet * 0.8;
|
||||
|
||||
// Accretion disc (around planet)
|
||||
float disc = exp(-abs(dot(normalize(dir.xz), normalize(planetDir.xz))) * 50.0);
|
||||
disc *= step(abs(dir.y), 0.1);
|
||||
color += vec3(1.0, 0.6, 0.2) * disc * 0.5;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// MinecraftPT — Parallax Occlusion Mapping
|
||||
// Steep parallax mapping with PCF soft shadows.
|
||||
|
||||
#ifndef PARALLAX_GLSL
|
||||
#define PARALLAX_GLSL
|
||||
|
||||
// Steep parallax mapping
|
||||
vec2 ParallaxMapping(vec2 texcoord, vec3 viewDir){
|
||||
float height = texture(tex, texcoord).a;
|
||||
vec2 delta = viewDir.xy / viewDir.z * PARALLAX_DEPTH;
|
||||
|
||||
int numLayers = max(1, int(PARALLAX_QUALITY));
|
||||
float layerDepth = 1.0 / float(numLayers);
|
||||
float currentDepth = 0.0;
|
||||
vec2 currentCoord = texcoord;
|
||||
|
||||
for (int i = 0; i < numLayers; i++){
|
||||
currentCoord -= delta * layerDepth;
|
||||
height = texture(tex, currentCoord).a;
|
||||
currentDepth += layerDepth;
|
||||
if (height < currentDepth) break;
|
||||
}
|
||||
|
||||
// Parallax shadow
|
||||
float shadow = 1.0;
|
||||
#ifdef PARALLAX_SHADOW
|
||||
// PCF shadow
|
||||
for (int i = 0; i < PARALLAX_SHADOW_QUALITY; i++){
|
||||
vec2 shadowCoord = currentCoord + delta * float(i) / float(PARALLAX_SHADOW_QUALITY);
|
||||
shadow *= step(currentDepth - layerDepth * float(i) / float(PARALLAX_SHADOW_QUALITY), texture(tex, shadowCoord).a);
|
||||
}
|
||||
#endif
|
||||
|
||||
return currentCoord;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
// MinecraftPT — Planar Clouds
|
||||
// Simple 2D cloud layer rendered as a plane at altitude.
|
||||
|
||||
#ifndef PLANAR_CLOUDS_GLSL
|
||||
#define PLANAR_CLOUDS_GLSL
|
||||
|
||||
// Sample cloud density at a world XZ position (2D noise + coverage)
|
||||
float GetPlanarCloudDensity(vec2 xz, float time, out vec3 cloudColor){
|
||||
// Coverage by weather
|
||||
float coverage = mix(PC_CLEAR_COVERAGE, PC_RAIN_COVERAGE, wetness);
|
||||
float density = mix(PC_CLEAR_DENSITY, PC_RAIN_DENSITY, wetness);
|
||||
float sunlighting = mix(PC_CLEAR_SUNLIGHTING, PC_RAIN_SUNLIGHTING, wetness);
|
||||
float skylighting = mix(PC_CLEAR_SKYLIGHTING, PC_RAIN_SKYLIGHTING, wetness);
|
||||
|
||||
// FBM noise
|
||||
vec2 p = xz * PC_NOISE_SCALE + vec2(time * 0.01, 0.0);
|
||||
float n = 0.0;
|
||||
float amp = 0.5;
|
||||
for (int i = 0; i < 3; i++){
|
||||
n += textureLod(CloudNoise3D, vec3(p, 0.5), 0.0).r * amp;
|
||||
p *= 2.0;
|
||||
amp *= 0.5;
|
||||
}
|
||||
|
||||
float clouds = saturate((n - (1.0 - coverage)) * (1.0 / max(coverage, 0.01)));
|
||||
|
||||
// Cloud color: lit by sun and sky
|
||||
float sunFactor = sunlighting;
|
||||
cloudColor = mix(GetCloudAtmoIrradiance(), GetCloudSunIrradiance(), sunFactor) * clouds
|
||||
+ vec3(1.0) * skylighting * clouds;
|
||||
|
||||
return clouds * density;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
// MinecraftPT — Ripple
|
||||
// Rain-induced ripple normal map for water surfaces.
|
||||
|
||||
#ifndef RIPPLE_GLSL
|
||||
uniform sampler2D ripple2D;
|
||||
#define RIPPLE_GLSL
|
||||
|
||||
vec2 GetRippleNormal(vec3 worldPos, float time){
|
||||
vec2 coord = worldPos.xz * 0.1;
|
||||
vec2 ripple = textureLod(ripple2D, fract(coord + time * 0.02), 0.0).rg;
|
||||
return ripple * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
// MinecraftPT — Volumetric Fog
|
||||
// Height-based volumetric fog with 3D noise, ray marched in the volumetric pass.
|
||||
|
||||
#ifndef VOLUMETRIC_FOG_GLSL
|
||||
uniform sampler3D CloudNoise3D;
|
||||
#define VOLUMETRIC_FOG_GLSL
|
||||
|
||||
// Fog density at a world position (height + noise)
|
||||
float GetVolumetricFogDensity(vec3 worldPos, float time){
|
||||
float height = worldPos.y;
|
||||
|
||||
// Two-layer height fog
|
||||
float density = VFOG_DENSITY_BASE;
|
||||
density += exp(-(height - VFOG_HEIGHT) * VFOG_FALLOFF) * VFOG_DENSITY;
|
||||
density += exp(-(height - VFOG_HEIGHT_2) * VFOG_FALLOFF * 2.0) * VFOG_DENSITY * 0.5;
|
||||
|
||||
// Noise variation
|
||||
#ifdef VFOG_NOISE_TYPE
|
||||
if (VFOG_NOISE_TYPE > 0){
|
||||
vec3 p = worldPos * vec3(VFOG_NOISE_HORIZONTAL_SCALE, VFOG_NOISE_VERTICAL_SCALE, VFOG_NOISE_HORIZONTAL_SCALE) + vec3(time * 0.01, 0.0, time * 0.008);
|
||||
float n = 0.0;
|
||||
float amp = 0.5;
|
||||
for (int i = 0; i < VFOG_NOISE_OCTAVE; i++){
|
||||
n += textureLod(CloudNoise3D, fract(p), 0.0).r * amp;
|
||||
p *= 2.0;
|
||||
amp *= 0.5;
|
||||
}
|
||||
density *= 1.0 + (n - 0.5) * VFOG_NOISE_COVERAGE * 2.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Rain fog boost
|
||||
density *= 1.0 + wetness * VFOG_RAIN_DENSITY_MUL;
|
||||
|
||||
return max(density, 0.0);
|
||||
}
|
||||
|
||||
// In-scattering color for fog (sun + sky)
|
||||
vec3 GetFogColor(vec3 worldPos, vec3 sunDir){
|
||||
vec3 sunColor = GetSunIrradiance() * VFOG_SUNLIGHT_DENSITY;
|
||||
vec3 skyColor = GetAtmoIrradiance();
|
||||
|
||||
return skyColor + sunColor * 0.5;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
// MinecraftPT — Water Fog
|
||||
// Underwater volumetric fog with scattering colors.
|
||||
|
||||
#ifndef WATER_FOG_GLSL
|
||||
#define WATER_FOG_GLSL
|
||||
|
||||
vec3 GetWaterFogColor(vec3 worldPos){
|
||||
return vec3(WATER_SCATTERING_R, WATER_SCATTERING_G, WATER_SCATTERING_B) * WATER_SCATTERING_DENSITY;
|
||||
}
|
||||
|
||||
float GetWaterFogDensity(vec3 worldPos){
|
||||
return WATER_SCATTERING_DENSITY;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// MinecraftPT — Water Waves
|
||||
// Gerstner-style water wave normals with multi-octave detail.
|
||||
|
||||
#ifndef WATER_WAVES_GLSL
|
||||
#define WATER_WAVES_GLSL
|
||||
|
||||
vec3 GetWaveNormal(vec3 worldPos, float lightmap){
|
||||
vec2 pos = worldPos.xz;
|
||||
|
||||
float time = frameTimeCounter * 0.05 * WAVE_SPEED;
|
||||
|
||||
// Multi-octave sine waves
|
||||
float wave1 = sin(pos.x * 0.1 * WAVE_SCALE + time) * cos(pos.y * 0.08 * WAVE_SCALE + time * 0.7);
|
||||
float wave2 = sin(pos.x * 0.2 * WAVE_SCALE + time * 1.3) * cos(pos.y * 0.15 * WAVE_SCALE - time * 0.9);
|
||||
float wave3 = sin((pos.x + pos.y) * 0.35 * WAVE_SCALE + time * 1.7) * 0.5;
|
||||
|
||||
// Height field derivatives for normal
|
||||
float dx = cos(pos.x * 0.1 * WAVE_SCALE + time) * 0.1 * WAVE_SCALE * 0.5 * 0.05
|
||||
+ cos(pos.x * 0.2 * WAVE_SCALE + time * 1.3) * 0.2 * WAVE_SCALE * 0.5 * 0.04;
|
||||
float dz = -sin(pos.x * 0.1 * WAVE_SCALE + time) * sin(pos.y * 0.08 * WAVE_SCALE + time * 0.7) * 0.08 * WAVE_SCALE * 0.5 * 0.05
|
||||
- sin(pos.x * 0.2 * WAVE_SCALE + time * 1.3) * sin(pos.y * 0.15 * WAVE_SCALE - time * 0.9) * 0.15 * WAVE_SCALE * 0.5 * 0.04;
|
||||
|
||||
vec3 normal = normalize(vec3(-dx, 1.0, -dz) * WAVE_NORMAL_STRENGTH + vec3(0.0, 1.0 - WAVE_NORMAL_STRENGTH, 0.0));
|
||||
|
||||
return normal;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Waving Plants
|
||||
// Wind animation for grass, plants, leaves.
|
||||
|
||||
#ifndef WAVING_PLANTS_GLSL
|
||||
#define WAVING_PLANTS_GLSL
|
||||
|
||||
void WavingPlants(inout vec4 worldPos, float lightLevel){
|
||||
float time = frameTimeCounter * 0.05 * WAVING_SPEED;
|
||||
|
||||
// Wind direction
|
||||
vec2 wind = vec2(0.5, 0.3) * sin(time) + vec2(0.2);
|
||||
|
||||
// Amplitude by plant type
|
||||
float amplitude = GRASS_AMPLITUDE;
|
||||
#ifdef IS_LEAVES
|
||||
amplitude = LEAVES_AMPLITUDE;
|
||||
#endif
|
||||
|
||||
float dist = length(worldPos.xyz - gbufferModelViewInverse[3].xyz);
|
||||
float fade = 1.0 - saturate(dist / WAVING_RANGE);
|
||||
|
||||
vec3 vertexPos = worldPos.xyz;
|
||||
|
||||
// Vertex-based wave
|
||||
vec3 offset = vec3(wind * sin(vertexPos.x * 0.3 + vertexPos.z * 0.2 + time * 2.0), 0.0);
|
||||
offset *= vertexPos.y * amplitude * fade;
|
||||
|
||||
// Random per-vertex jitter (height-based)
|
||||
float heightFactor = vertexPos.y;
|
||||
float noise = sin(vertexPos.x * 12.9898 + vertexPos.z * 78.233 + time) * 0.5 + 0.5;
|
||||
offset.x += noise * amplitude * 0.5 * heightFactor * fade;
|
||||
offset.z += noise * amplitude * 0.3 * heightFactor * fade;
|
||||
|
||||
worldPos.xyz += offset;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Diffuse Spatial Filter
|
||||
// Edge-avoiding A-trous wavelet spatial filter. Multi-pass (detail levels).
|
||||
|
||||
#ifndef DIFFUSE_SPATIAL_FILTER_GLSL
|
||||
#define DIFFUSE_SPATIAL_FILTER_GLSL
|
||||
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
// Single A-trous pass at the given step size
|
||||
vec3 DiffuseSpatialPass(vec3 center, vec2 texelCoord, int step){
|
||||
vec3 result = center * 0.25;
|
||||
|
||||
// Center depth and normal for edge detection
|
||||
float depth = texelFetch(depthtex0, texelCoord * 2.0, 0).r;
|
||||
vec3 normal = DecodeNormal(texelFetch(colortex1, texelCoord * 2.0, 0).xy);
|
||||
vec3 centerAlbedo = texelFetch(colortex0, texelCoord * 2.0, 0).rgb;
|
||||
|
||||
// Reconstruct view position for depth edge weight
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(texelCoord * 2.0 / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
|
||||
float weightSum = 0.25;
|
||||
|
||||
vec2 offsets[4] = vec2[4](vec2(1.0, 0.0), vec2(-1.0, 0.0), vec2(0.0, 1.0), vec2(0.0, -1.0));
|
||||
|
||||
for (int i = 0; i < 4; i++){
|
||||
vec2 coord = texelCoord + offsets[i] * float(step);
|
||||
vec3 sampleColor = texelFetch(colortex7, ivec2(coord), 0).rgb;
|
||||
|
||||
float sampleDepth = texelFetch(depthtex0, coord * 2.0, 0).r;
|
||||
vec3 sampleNormal = DecodeNormal(texelFetch(colortex1, coord * 2.0, 0).xy);
|
||||
|
||||
// Edge-avoiding weights
|
||||
float depthWeight = exp(-abs(depth - sampleDepth) * PT_DIFFUSE_SPATIAL_FILTER_DEPTH_WEIGHT * 100.0);
|
||||
float normalWeight = pow(max(dot(normal, sampleNormal), 0.0), 8.0 * PT_DIFFUSE_SPATIAL_FILTER_NORMAL_WEIGHT + 1.0);
|
||||
float luminanceWeight = exp(-abs(luminance(center) - luminance(sampleColor)) * PT_DIFFUSE_SPATIAL_FILTER_LUMINANCE_WEIGHT * 10.0);
|
||||
|
||||
float weight = depthWeight * normalWeight * luminanceWeight;
|
||||
|
||||
result += sampleColor * weight;
|
||||
weightSum += weight;
|
||||
}
|
||||
|
||||
return result / weightSum;
|
||||
}
|
||||
|
||||
// Run the spatial filter chain (detail levels)
|
||||
vec3 DiffuseSpatialFilter(vec2 texelCoord){
|
||||
vec3 color = texelFetch(colortex7, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
int levels = 1 + int(PT_DIFFUSE_SPATIAL_FILTER_DETAIL);
|
||||
|
||||
int step = 1;
|
||||
for (int i = 0; i < levels; i++){
|
||||
color = DiffuseSpatialPass(color, texelCoord, step);
|
||||
step *= 2;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// MinecraftPT — Diffuse Temporal Filter
|
||||
// Reprojects the previous frame's denoised diffuse result using motion vectors
|
||||
// and accumulates with the current noisy frame.
|
||||
|
||||
#ifndef DIFFUSE_TEMPORAL_FILTER_GLSL
|
||||
#define DIFFUSE_TEMPORAL_FILTER_GLSL
|
||||
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
vec3 DiffuseTemporalAccumulate(vec3 current, vec2 texelCoord, vec3 prevColor){
|
||||
vec2 motionVec = texelFetch(colortex10, ivec2(texelCoord), 0).xy;
|
||||
vec2 prevCoord = (texelCoord + 0.5) - motionVec;
|
||||
|
||||
// Validate reprojection: depth comparison
|
||||
float depth = texelFetch(depthtex0, texelCoord * 2.0, 0).r;
|
||||
float prevDepth = textureLod(prevDepth2D, prevCoord / (screenSize * 0.5), 0.0).r;
|
||||
|
||||
float depthValid = step(abs(depth - prevDepth), 0.05 * depth + 0.001);
|
||||
|
||||
// History confidence based on accumulation count
|
||||
float accum = 1.0 / float(PT_DIFFUSE_TEMPORAL_MAX_ACCUM);
|
||||
|
||||
// Sample previous
|
||||
vec3 history = textureLod(colortex7, prevCoord / (screenSize * 0.5), 0.0).rgb;
|
||||
|
||||
// Neighborhood clamp to reduce ghosting
|
||||
vec3 minColor = history;
|
||||
vec3 maxColor = history;
|
||||
for (int i = -1; i <= 1; i++){
|
||||
for (int j = -1; j <= 1; j++){
|
||||
vec3 c = textureLod(colortex7, (prevCoord + vec2(i, j)) / (screenSize * 0.5), 0.0).rgb;
|
||||
minColor = min(minColor, c);
|
||||
maxColor = max(maxColor, c);
|
||||
}}
|
||||
history = clamp(history, minColor, maxColor);
|
||||
|
||||
float blend = mix(accum, 1.0, depthValid * PT_DIFFUSE_TEMPORAL_HISTORY_FIX * 0.5);
|
||||
|
||||
return mix(current, history, blend * (1.0 - accum));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Diffuse Variance Estimation
|
||||
// Computes luminance moments to drive temporal accumulation and firefly rejection.
|
||||
|
||||
#ifndef DIFFUSE_VARIANCE_ESTIMATION_GLSL
|
||||
#define DIFFUSE_VARIANCE_ESTIMATION_GLSL
|
||||
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
vec2 DiffuseEstimateVariance(vec3 color, vec2 texelCoord){
|
||||
float lum = luminance(color);
|
||||
float lum2 = lum * lum;
|
||||
|
||||
// Local variance from neighbors (5-tap)
|
||||
float variance = 0.0;
|
||||
for (int i = -1; i <= 1; i++){
|
||||
for (int j = -1; j <= 1; j++){
|
||||
if (i == 0 && j == 0) continue;
|
||||
vec3 c = texelFetch(colortex7, ivec2(texelCoord) + ivec2(i, j), 0).rgb;
|
||||
float l = luminance(c);
|
||||
variance += (l - lum) * (l - lum);
|
||||
}}
|
||||
variance /= 8.0;
|
||||
|
||||
// Clamp fireflies
|
||||
float firefly = step(1.0, lum / max(variance * 4.0, 0.001));
|
||||
|
||||
return vec2(lum, firefly);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Specular Spatial Filter
|
||||
// Edge-avoiding spatial filter for specular reflections (fewer passes than diffuse).
|
||||
|
||||
#ifndef SPECULAR_SPATIAL_FILTER_GLSL
|
||||
#define SPECULAR_SPATIAL_FILTER_GLSL
|
||||
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
vec3 SpecularSpatialPass(vec3 center, vec2 texelCoord, int step){
|
||||
vec3 result = center * 0.25;
|
||||
|
||||
float depth = texelFetch(depthtex0, texelCoord * 2.0, 0).r;
|
||||
vec3 normal = DecodeNormal(texelFetch(colortex1, texelCoord * 2.0, 0).xy);
|
||||
|
||||
float weightSum = 0.25;
|
||||
|
||||
vec2 offsets[4] = vec2[4](vec2(1.0, 0.0), vec2(-1.0, 0.0), vec2(0.0, 1.0), vec2(0.0, -1.0));
|
||||
|
||||
for (int i = 0; i < 4; i++){
|
||||
vec2 coord = texelCoord + offsets[i] * float(step);
|
||||
vec3 sampleColor = texelFetch(colortex11, ivec2(coord), 0).rgb;
|
||||
|
||||
float sampleDepth = texelFetch(depthtex0, coord * 2.0, 0).r;
|
||||
vec3 sampleNormal = DecodeNormal(texelFetch(colortex1, coord * 2.0, 0).xy);
|
||||
|
||||
float depthWeight = exp(-abs(depth - sampleDepth) * PT_DIFFUSE_SPATIAL_FILTER_DEPTH_WEIGHT * 100.0);
|
||||
float normalWeight = pow(max(dot(normal, sampleNormal), 0.0), 8.0 * PT_DIFFUSE_SPATIAL_FILTER_NORMAL_WEIGHT + 1.0);
|
||||
float luminanceWeight = exp(-abs(luminance(center) - luminance(sampleColor)) * PT_DIFFUSE_SPATIAL_FILTER_LUMINANCE_WEIGHT * 10.0);
|
||||
|
||||
float weight = depthWeight * normalWeight * luminanceWeight;
|
||||
|
||||
result += sampleColor * weight;
|
||||
weightSum += weight;
|
||||
}
|
||||
|
||||
return result / weightSum;
|
||||
}
|
||||
|
||||
vec3 SpecularSpatialFilter(vec2 texelCoord){
|
||||
vec3 color = texelFetch(colortex11, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
int levels = 1 + int(PT_DIFFUSE_SPATIAL_FILTER_DETAIL) / 2;
|
||||
|
||||
int step = 1;
|
||||
for (int i = 0; i < levels; i++){
|
||||
color = SpecularSpatialPass(color, texelCoord, step);
|
||||
step *= 2;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
// MinecraftPT — Specular Temporal Filter
|
||||
// Temporal accumulation for specular reflections with reprojection.
|
||||
|
||||
#ifndef SPECULAR_TEMPORAL_FILTER_GLSL
|
||||
#define SPECULAR_TEMPORAL_FILTER_GLSL
|
||||
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
vec3 SpecularTemporalAccumulate(vec3 current, vec2 texelCoord){
|
||||
vec2 motionVec = texelFetch(colortex10, ivec2(texelCoord), 0).xy;
|
||||
vec2 prevCoord = (texelCoord + 0.5) - motionVec;
|
||||
|
||||
float depth = texelFetch(depthtex0, texelCoord * 2.0, 0).r;
|
||||
float prevDepth = textureLod(prevDepth2D, prevCoord / (screenSize * 0.5), 0.0).r;
|
||||
|
||||
float depthValid = step(abs(depth - prevDepth), 0.05 * depth + 0.001);
|
||||
|
||||
float accum = 1.0 / float(PT_DIFFUSE_TEMPORAL_MAX_ACCUM);
|
||||
|
||||
vec3 history = textureLod(colortex11, prevCoord / (screenSize * 0.5), 0.0).rgb;
|
||||
|
||||
// Neighborhood clamp
|
||||
vec3 minColor = history;
|
||||
vec3 maxColor = history;
|
||||
for (int i = -1; i <= 1; i++){
|
||||
for (int j = -1; j <= 1; j++){
|
||||
vec3 c = textureLod(colortex11, (prevCoord + vec2(i, j)) / (screenSize * 0.5), 0.0).rgb;
|
||||
minColor = min(minColor, c);
|
||||
maxColor = max(maxColor, c);
|
||||
}}
|
||||
history = clamp(history, minColor, maxColor);
|
||||
|
||||
float blend = mix(accum, 1.0, depthValid * PT_DIFFUSE_TEMPORAL_HISTORY_FIX * 0.5);
|
||||
|
||||
return mix(current, history, blend * (1.0 - accum));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
// MinecraftPT — SampleIRC
|
||||
// Sampling the irradiance cache: a 3D grid of pre-computed diffuse irradiance
|
||||
// used to cheaply evaluate indirect diffuse light.
|
||||
|
||||
#ifndef SAMPLE_IRC_GLSL
|
||||
#define SAMPLE_IRC_GLSL
|
||||
|
||||
// Sample irradiance cache at a world position (trilinear)
|
||||
vec3 SampleIRC(vec3 worldPos){
|
||||
vec3 voxelPos = WorldToVoxel(worldPos);
|
||||
|
||||
vec3 coord = voxelPos / float(ircResolution);
|
||||
|
||||
if (clamp(coord, vec3(0.0), vec3(1.0)) == coord){
|
||||
coord *= float(ircResolution) - 1.0;
|
||||
|
||||
vec3 base = floor(coord);
|
||||
vec3 frac = coord - base;
|
||||
ivec3 i0 = ivec3(base);
|
||||
ivec3 i1 = min(i0 + 1, ivec3(ircResolution - 1));
|
||||
|
||||
vec3 c000 = texelFetch(irradianceCache3D, i0, 0).rgb;
|
||||
vec3 c100 = texelFetch(irradianceCache3D, ivec3(i1.x, i0.y, i0.z), 0).rgb;
|
||||
vec3 c010 = texelFetch(irradianceCache3D, ivec3(i0.x, i1.y, i0.z), 0).rgb;
|
||||
vec3 c110 = texelFetch(irradianceCache3D, ivec3(i1.x, i1.y, i0.z), 0).rgb;
|
||||
vec3 c001 = texelFetch(irradianceCache3D, ivec3(i0.x, i0.y, i1.z), 0).rgb;
|
||||
vec3 c101 = texelFetch(irradianceCache3D, ivec3(i1.x, i0.y, i1.z), 0).rgb;
|
||||
vec3 c011 = texelFetch(irradianceCache3D, ivec3(i0.x, i1.y, i1.z), 0).rgb;
|
||||
vec3 c111 = texelFetch(irradianceCache3D, i1, 0).rgb;
|
||||
|
||||
vec3 x00 = mix(c000, c100, frac.x);
|
||||
vec3 x10 = mix(c010, c110, frac.x);
|
||||
vec3 x01 = mix(c001, c101, frac.x);
|
||||
vec3 x11 = mix(c011, c111, frac.x);
|
||||
vec3 y0 = mix(x00, x10, frac.y);
|
||||
vec3 y1 = mix(x01, x11, frac.y);
|
||||
|
||||
return mix(y0, y1, frac.z);
|
||||
}
|
||||
|
||||
// Outside the cache — fall back to sky ambient
|
||||
return GetCelestialIrradiance() + GetAtmoIrradiance();
|
||||
}
|
||||
|
||||
// Normal-aware IRC sampling (bias by surface normal facing)
|
||||
vec3 SampleIRCNormal(vec3 worldPos, vec3 normal){
|
||||
vec3 irc = SampleIRC(worldPos);
|
||||
// Simple hemisphere shading via normal alignment with up
|
||||
float upFactor = normal.y * 0.5 + 0.5;
|
||||
return irc * (0.5 + 0.5 * upFactor);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Shadow Tracing
|
||||
// Direct sunlight shadow rays: march from surface toward the sun through the
|
||||
// voxel grid. Soft penumbra via distance-weighted ray length.
|
||||
|
||||
#ifndef SHADOW_TRACING_GLSL
|
||||
#define SHADOW_TRACING_GLSL
|
||||
|
||||
#include "/Lib/PathTracing/Tracer/TracingUtilities.glsl"
|
||||
|
||||
float ShadowTracing(vec3 viewPos, vec3 worldPos, vec3 vertexNormal, vec3 lightVector, float lightMap){
|
||||
float shadow = 1.0;
|
||||
|
||||
vec3 voxelPos = WorldToVoxel(worldPos);
|
||||
voxelPos += vertexNormal * (-viewPos.z * 0.0003);
|
||||
|
||||
if (clamp(voxelPos, vec3(0.0), vec3(voxelResolution)) == voxelPos){
|
||||
lightMap = saturate(1.0 - lightMap * 2.0);
|
||||
vec2 shadowWeight = vec2(
|
||||
4.0 - 2.0 * saturate(lightMap - viewPos.z * 0.01),
|
||||
0.2 + 0.5 * saturate(lightMap - viewPos.z * 0.01)
|
||||
);
|
||||
|
||||
Ray ray = PackRay(voxelPos, lightVector);
|
||||
|
||||
vec3 voxelCoord = floor(ray.ori);
|
||||
vec3 totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
float rayLength = 0.0;
|
||||
vec3 tracingNext;
|
||||
|
||||
bool hit = false;
|
||||
|
||||
for (int i = 0; i < 64; i++){
|
||||
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord) break;
|
||||
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
|
||||
// Full block or cutout shape
|
||||
if (voxelID >= 999.0){
|
||||
hit = rayLength > 0.0;
|
||||
}else if (voxelID < 1000.0 && voxelID > 1.0){
|
||||
float rawID = 1000.0 - voxelID;
|
||||
rayLength = minVec3(totalStep);
|
||||
hit = HitShape_Lite(ray, voxelCoord, rawID, rayLength);
|
||||
}
|
||||
|
||||
if (hit){
|
||||
shadow = saturate((rayLength - shadowWeight.y) * shadowWeight.x);
|
||||
break;
|
||||
}
|
||||
|
||||
// Sparse skip
|
||||
float marker = voxelData.z;
|
||||
if (marker > 0.60 && marker < 0.92){
|
||||
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
||||
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
||||
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
||||
float tSkip = minVec3(distToBoundary) + 1e-4;
|
||||
rayLength += tSkip;
|
||||
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
||||
ray.ori += stepVec;
|
||||
voxelCoord = floor(ray.ori);
|
||||
totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
continue;
|
||||
}
|
||||
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
}
|
||||
}
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
// Simplified version for IRC / light sampling (no soft penumbra)
|
||||
float SimpleShadowTracing(vec3 voxelPos, vec3 lightVector){
|
||||
Ray ray = PackRay(voxelPos, lightVector);
|
||||
|
||||
vec3 voxelCoord = floor(ray.ori);
|
||||
vec3 totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
float rayLength = 0.0;
|
||||
vec3 tracingNext;
|
||||
|
||||
bool hit = false;
|
||||
|
||||
for (int i = 0; i < 64; i++){
|
||||
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord) break;
|
||||
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
|
||||
if (voxelID >= 999.0){
|
||||
hit = rayLength > 0.0;
|
||||
}else if (voxelID < 1000.0 && voxelID > 1.0){
|
||||
float rawID = 1000.0 - voxelID;
|
||||
rayLength = minVec3(totalStep);
|
||||
hit = HitShape_Lite(ray, voxelCoord, rawID, rayLength);
|
||||
}
|
||||
|
||||
if (hit) break;
|
||||
|
||||
// Sparse skip
|
||||
float marker = voxelData.z;
|
||||
if (marker > 0.60 && marker < 0.92){
|
||||
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
||||
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
||||
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
||||
float tSkip = minVec3(distToBoundary) + 1e-4;
|
||||
rayLength += tSkip;
|
||||
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
||||
ray.ori += stepVec;
|
||||
voxelCoord = floor(ray.ori);
|
||||
totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
continue;
|
||||
}
|
||||
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
}
|
||||
|
||||
return float(!hit);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Specular Tracer
|
||||
// Traces GGX-sampled reflection/refraction rays through the voxel grid and
|
||||
// accumulates the reflected radiance (incl. light sphere contributions).
|
||||
|
||||
#ifndef SPECULAR_TRACER_GLSL
|
||||
#define SPECULAR_TRACER_GLSL
|
||||
|
||||
#include "/Lib/PathTracing/Tracer/TracingUtilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/ShadowTracing.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/SampleIRC.glsl"
|
||||
|
||||
// Panorama: 3:2 cubemap cross. Map direction to face UV.
|
||||
float absX = abs(dir.x), absY = abs(dir.y), absZ = abs(dir.z);
|
||||
float maxAxis = max(absX, max(absY, absZ));
|
||||
|
||||
vec2 uv;
|
||||
vec3 tdir = dir / maxAxis;
|
||||
|
||||
if (maxAxis == absX){
|
||||
uv = vec2(tdir.y * 0.5 + 0.5, tdir.z * 0.5 + 0.5) / vec2(3.0, 2.0) + vec2(0.0, 0.5) * vec2(1.0/3.0, 1.0/2.0);
|
||||
if (tdir.x > 0.0){
|
||||
uv = vec2(tdir.y * 0.5 + 0.5, tdir.z * 0.5 + 0.5) / vec2(3.0, 2.0) + vec2(1.0/3.0, 0.5/2.0);
|
||||
}
|
||||
}else if (maxAxis == absY){
|
||||
uv = vec2(tdir.x * 0.5 + 0.5, tdir.z * 0.5 + 0.5) / vec2(3.0, 2.0) + vec2(2.0/3.0, 0.5/2.0);
|
||||
if (tdir.y > 0.0){
|
||||
uv = vec2(tdir.x * 0.5 + 0.5, tdir.z * 0.5 + 0.5) / vec2(3.0, 2.0) + vec2(1.0/3.0, 0.5/2.0);
|
||||
}
|
||||
}else{
|
||||
uv = vec2(tdir.x * 0.5 + 0.5, tdir.y * 0.5 + 0.5) / vec2(3.0, 2.0) + vec2(2.0/3.0, 1.5/2.0);
|
||||
if (tdir.z > 0.0){
|
||||
uv = vec2(tdir.x * 0.5 + 0.5, tdir.y * 0.5 + 0.5) / vec2(3.0, 2.0) + vec2(1.0/3.0, 1.5/2.0);
|
||||
}
|
||||
}
|
||||
|
||||
return textureLod(skyBox2D, uv, 0.0).rgb;
|
||||
}
|
||||
|
||||
// Trace a single specular ray and accumulate radiance.
|
||||
// origin: world pos (voxel space handled inside), dir: normalized direction
|
||||
vec3 SpecularTrace(vec3 voxelPos, vec3 dir, float maxDist, vec2 noise){
|
||||
vec3 result = vec3(0.0);
|
||||
|
||||
Ray ray = PackRay(voxelPos, dir);
|
||||
|
||||
vec3 voxelCoord = floor(ray.ori);
|
||||
vec3 totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
float rayLength = 0.0;
|
||||
vec3 tracingNext;
|
||||
|
||||
bool hit = false;
|
||||
|
||||
for (int i = 0; i < 128; i++){
|
||||
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord){
|
||||
// Escaped the voxel grid — sample sky
|
||||
result = SampleSkyBox(dir);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rayLength > maxDist){
|
||||
result = SampleSkyBox(dir);
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
|
||||
// Light source: accumulate sphere light
|
||||
if (IsLightSphere(voxelID)){
|
||||
result += HitLightShpereReflection(ray, voxelCoord, voxelID, rayLength);
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (voxelID >= 999.0){ // Full block
|
||||
// Shade the hit point: sample albedo from atlas, apply lighting
|
||||
vec3 hitPos = ray.ori + ray.dir * rayLength;
|
||||
vec3 hitNormal = -step(vec3(rayLength), totalStep - abs(ray.rdir)) * ray.sdir;
|
||||
vec2 midCoord = voxelData.xy;
|
||||
vec3 albedo = SampleVoxelAlbedo(midCoord, hitPos, hitNormal);
|
||||
|
||||
// Direct light from sun
|
||||
vec3 sunColor = GetSunIrradiance();
|
||||
float sunShadow = SimpleShadowTracing(hitPos + hitNormal * 0.01, GetSunDirWorld());
|
||||
vec3 direct = albedo * sunColor * sunShadow * max(dot(hitNormal, GetSunDirWorld()), 0.0);
|
||||
|
||||
// Sky ambient from IRC
|
||||
vec3 irc = SampleIRC(hitPos);
|
||||
result += direct + irc * albedo * 0.5;
|
||||
|
||||
hit = true;
|
||||
break;
|
||||
}else if (voxelID < 1000.0 && voxelID > 1.0){
|
||||
// Cutout shape
|
||||
float rawID = 1000.0 - voxelID;
|
||||
rayLength = minVec3(totalStep);
|
||||
vec3 n;
|
||||
if (HitShape(ray, voxelCoord, rawID, rayLength, n)){
|
||||
vec3 hitPos = ray.ori + ray.dir * rayLength;
|
||||
vec2 midCoord = voxelData.xy;
|
||||
vec3 albedo = SampleVoxelAlbedo(midCoord, hitPos, n);
|
||||
|
||||
vec3 sunColor = GetSunIrradiance();
|
||||
float sunShadow = SimpleShadowTracing(hitPos + n * 0.01, GetSunDirWorld());
|
||||
vec3 direct = albedo * sunColor * sunShadow * max(dot(n, GetSunDirWorld()), 0.0);
|
||||
|
||||
vec3 irc = SampleIRC(hitPos);
|
||||
result += direct + irc * albedo * 0.5;
|
||||
|
||||
hit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Sparse skip
|
||||
float marker = voxelData.z;
|
||||
if (marker > 0.60 && marker < 0.92){
|
||||
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
||||
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
||||
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
||||
float tSkip = minVec3(distToBoundary) + 1e-4;
|
||||
rayLength += tSkip;
|
||||
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
||||
ray.ori += stepVec;
|
||||
voxelCoord = floor(ray.ori);
|
||||
totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
continue;
|
||||
}
|
||||
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
}
|
||||
|
||||
if (!hit){
|
||||
result = SampleSkyBox(dir);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
// MinecraftPT — Tracing Noise
|
||||
// Noise functions for ray tracing (hash-based, temporally stable).
|
||||
|
||||
#ifndef TRACING_NOISE_GLSL
|
||||
#define TRACING_NOISE_GLSL
|
||||
|
||||
// Per-pixel temporal noise, stable across frames
|
||||
float GetTracingNoise(vec2 screenPos, int frame, int offset){
|
||||
// Blue noise from texture + temporal interleave
|
||||
vec2 coord = (screenPos + 0.5) / screenSize;
|
||||
coord = fract(coord * vec2(128.0, 128.0) + 0.5);
|
||||
vec2 texel = coord * vec2(127.0 / 128.0) + vec2(0.5 / 128.0);
|
||||
float noise = textureLod(noisetex, texel, 0.0).r;
|
||||
return fract(noise + (frame + offset) * 0.03125);
|
||||
}
|
||||
|
||||
vec2 GetTracingNoise2(vec2 screenPos, int frame, int offset){
|
||||
// 2D noise for ray directions
|
||||
vec2 coord = (screenPos + 0.5) / screenSize;
|
||||
coord = fract(coord * vec2(128.0, 128.0) + 0.5);
|
||||
vec2 texel = coord * vec2(127.0 / 128.0) + vec2(0.5 / 128.0);
|
||||
vec2 noise = textureLod(noisetex, texel, 0.0).rg;
|
||||
return fract(noise + (frame + offset) * 0.03125);
|
||||
}
|
||||
|
||||
// Golden-ratio based sample rotation (for progressive sampling)
|
||||
vec2 RotateNoise(vec2 uv, int sampleIndex, int totalSamples){
|
||||
float angle = 6.28318 * float(sampleIndex) / float(totalSamples);
|
||||
mat2 rot = mat2(cos(angle), sin(angle), -sin(angle), cos(angle));
|
||||
return rot * uv;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Tracing Utilities
|
||||
// Core voxel ray marching helpers used by all tracers.
|
||||
|
||||
// Custom resource declarations (bound via shaders.properties)
|
||||
uniform sampler2D atlas2D;
|
||||
uniform sampler3D voxelData3D;
|
||||
uniform sampler2D skyBox2D;
|
||||
|
||||
// Sample the sky box panorama for a direction (for reflections / sky miss).
|
||||
// Layout must match SkyImage_CS: 3x2 tiles:
|
||||
// row 0: +X -X +Y row 1: -Y +Z -Z
|
||||
vec3 SampleSkyBox(vec3 dir){
|
||||
dir = normalize(dir);
|
||||
|
||||
float absX = abs(dir.x), absY = abs(dir.y), absZ = abs(dir.z);
|
||||
float maxAxis = max(absX, max(absY, absZ));
|
||||
|
||||
vec3 tdir = dir / maxAxis;
|
||||
|
||||
vec2 uv;
|
||||
vec2 tileOrigin;
|
||||
vec2 tile = vec2(1.0 / 3.0, 1.0 / 2.0);
|
||||
|
||||
if (maxAxis == absX){
|
||||
// +X (col 0) or -X (col 1), row 0
|
||||
tileOrigin = vec2(dir.x > 0.0 ? 0.0 : 1.0, 0.0);
|
||||
uv = vec2(tdir.y * 0.5 + 0.5, tdir.z * 0.5 + 0.5);
|
||||
}else if (maxAxis == absY){
|
||||
// +Y (col 2, row 0) or -Y (col 0, row 1)
|
||||
tileOrigin = dir.y > 0.0 ? vec2(2.0, 0.0) : vec2(0.0, 1.0);
|
||||
uv = vec2(tdir.x * 0.5 + 0.5, tdir.z * 0.5 + 0.5);
|
||||
}else{
|
||||
// +Z (col 1, row 1) or -Z (col 2, row 1)
|
||||
tileOrigin = vec2(dir.z > 0.0 ? 1.0 : 2.0, 1.0);
|
||||
uv = vec2(tdir.x * 0.5 + 0.5, tdir.y * 0.5 + 0.5);
|
||||
}
|
||||
|
||||
uv = uv * tile + tileOrigin * tile;
|
||||
|
||||
return textureLod(skyBox2D, uv, 0.0).rgb;
|
||||
}
|
||||
|
||||
|
||||
#ifndef TRACING_UTILITIES_GLSL
|
||||
#define TRACING_UTILITIES_GLSL
|
||||
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
#include "/Lib/PathTracing/Voxelizer/BlockShape.glsl"
|
||||
|
||||
// Convert world position to voxel grid coordinates
|
||||
vec3 WorldToVoxel(vec3 worldPos){
|
||||
return worldPos + cameraPositionFract + (voxelResolution * 0.5);
|
||||
}
|
||||
|
||||
// Sample the atlas for a hit voxel, returns albedo
|
||||
vec3 SampleVoxelAlbedo(vec2 midCoord, vec3 hitVoxelPos, vec3 hitNormal){
|
||||
// Reconstruct the face UV from hit position within voxel
|
||||
vec3 local = fract(hitVoxelPos);
|
||||
vec2 uv;
|
||||
if (abs(hitNormal.x) > 0.5){
|
||||
uv = vec2(local.z, local.y);
|
||||
}else if (abs(hitNormal.y) > 0.5){
|
||||
uv = vec2(local.x, local.z);
|
||||
}else{
|
||||
uv = vec2(local.x, local.y);
|
||||
}
|
||||
|
||||
// midCoord is the tile-aligned center UV; reconstruct pixel within tile
|
||||
vec2 tileCoord = midCoord;
|
||||
vec2 atlasSizeF = vec2(atlasSize);
|
||||
float tileW = 1.0 / atlasSizeF.x; // approximate; resolved via textureResolution
|
||||
vec2 pixelUV = tileCoord + (uv - 0.5) * tileW * 4.0;
|
||||
|
||||
return textureLod(atlas2D, pixelUV, 0.0).rgb;
|
||||
}
|
||||
|
||||
// Read a voxel's data
|
||||
vec4 ReadVoxel(ivec3 voxelCoord){
|
||||
return texelFetch(voxelData3D, voxelCoord, 0);
|
||||
}
|
||||
|
||||
// Test whether a voxel is empty (air or empty marker)
|
||||
bool IsVoxelEmpty(vec4 voxelData){
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
return voxelID <= 1.0;
|
||||
}
|
||||
|
||||
// Test whether a voxel is a light source (sphere light)
|
||||
bool IsLightSphere(float voxelID){
|
||||
return voxelID >= 239.0 && voxelID <= 290.0;
|
||||
}
|
||||
|
||||
// Core 3D-DDA march. Calls the callback-style inline logic via return.
|
||||
// Returns: 0 = no hit, 1 = hit, 2 = hit light
|
||||
int TraceRay(Ray ray, float maxDist, out float rayLength, out ivec3 hitVoxel, out float voxelID, out vec3 hitNormal){
|
||||
vec3 voxelPos = ray.ori;
|
||||
vec3 voxelCoord = floor(voxelPos);
|
||||
vec3 totalStep = (ray.sdir * (voxelCoord - voxelPos + 0.5) + 0.5) * abs(ray.rdir);
|
||||
rayLength = 0.0;
|
||||
vec3 tracingNext;
|
||||
hitNormal = vec3(0.0);
|
||||
|
||||
int result = 0;
|
||||
vec3 prevCoord = voxelCoord;
|
||||
|
||||
for (int i = 0; i < 128; i++){
|
||||
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord) break;
|
||||
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
||||
float id = DecodeVoxelID(voxelData.z);
|
||||
|
||||
if (id <= 1.0){
|
||||
// empty or full-block marker
|
||||
if (id >= 0.99 && id <= 1.0){
|
||||
// Full block
|
||||
if (rayLength > 0.0){
|
||||
hitVoxel = ivec3(voxelCoord);
|
||||
voxelID = 1.0;
|
||||
hitNormal = -step(vec3(rayLength), totalStep - abs(ray.rdir)) * ray.sdir;
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else if (id >= 1000.0){
|
||||
// Encoded as full block: id = rawID + 1000
|
||||
float rawID = id - 1000.0;
|
||||
if (rawID <= 1.0){
|
||||
hitVoxel = ivec3(voxelCoord);
|
||||
voxelID = rawID;
|
||||
hitNormal = -step(vec3(rayLength), totalStep - abs(ray.rdir)) * ray.sdir;
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}else if (id > 1.0 && id < 1000.0){
|
||||
// Cutout shape: id = 1000 - rawID
|
||||
float rawID = 1000.0 - id;
|
||||
float t = minVec3(totalStep);
|
||||
rayLength = t;
|
||||
vec3 n;
|
||||
if (HitShape(ray, voxelCoord, rawID, rayLength, n)){
|
||||
hitVoxel = ivec3(voxelCoord);
|
||||
voxelID = rawID;
|
||||
hitNormal = n;
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}else if (id >= 200.0 && id <= 290.0){
|
||||
// Light source — contribute and continue
|
||||
// (handled by caller; here just note it)
|
||||
hitVoxel = ivec3(voxelCoord);
|
||||
voxelID = id;
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// Sparse tracing: skip empty markers
|
||||
float marker = voxelData.z;
|
||||
if (marker > 0.60 && marker < 0.92){
|
||||
// Hierarchical skip — approximate by stepping over the block size
|
||||
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
||||
// find next boundary
|
||||
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
||||
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
||||
float tSkip = minVec3(distToBoundary) + 1e-4;
|
||||
rayLength += tSkip;
|
||||
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
||||
voxelPos += stepVec;
|
||||
voxelCoord = floor(voxelPos);
|
||||
totalStep = (ray.sdir * (voxelCoord - voxelPos + 0.5) + 0.5) * abs(ray.rdir);
|
||||
if (rayLength > maxDist) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
|
||||
if (rayLength > maxDist) break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,223 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Block Shape reconstruction
|
||||
// Exact AABB-based shapes for non-full-block voxel IDs, used during ray marching.
|
||||
|
||||
#ifndef BLOCK_SHAPE_GLSL
|
||||
#define BLOCK_SHAPE_GLSL
|
||||
|
||||
float SphereIntersectionLength(Ray ray, vec3 blockOrigin, vec3 sphereOrigin, float sphereRadius){
|
||||
sphereOrigin = -blockOrigin - sphereOrigin;
|
||||
|
||||
float b = dot(ray.dir, sphereOrigin);
|
||||
float c = dot(sphereOrigin, sphereOrigin) - sphereRadius * sphereRadius;
|
||||
float d = b * b - c;
|
||||
|
||||
float intersectionLength = 0.0;
|
||||
|
||||
if (d > 0.0){
|
||||
d = sqrt(d);
|
||||
intersectionLength = saturate(min(-b + d, d * 2.0));
|
||||
}
|
||||
|
||||
return intersectionLength;
|
||||
}
|
||||
|
||||
float BoxIntersectionLength(Ray ray, vec3 blockOrigin){
|
||||
vec3 boxMax = blockOrigin + 1.0;
|
||||
|
||||
vec3 t1 = ray.rdir * blockOrigin;
|
||||
vec3 t2 = ray.rdir * boxMax;
|
||||
|
||||
vec3 tMin = min(t1, t2);
|
||||
vec3 tMax = max(t1, t2);
|
||||
|
||||
float tEnter = maxVec3(tMin);
|
||||
float tExit = minVec3(tMax);
|
||||
|
||||
return max(tExit - tEnter, 0.0);
|
||||
}
|
||||
|
||||
// Light sphere colors for emissive blocks (IDs 200-270 range)
|
||||
vec3 LightShpereColor(float voxelID){
|
||||
const vec3 torchColor = pow(vec3(COLOR_TORCH_R, COLOR_TORCH_G, COLOR_TORCH_B), vec3(2.2)) * BRIGHTNESS_TORCH * SPHERELIGHT_BRIGHTNESS;
|
||||
const vec3 fireColor = pow(vec3(COLOR_FIRE_R, COLOR_FIRE_G, COLOR_FIRE_B), vec3(2.2)) * BRIGHTNESS_FIRE * SPHERELIGHT_BRIGHTNESS;
|
||||
const vec3 redstoneTorchColor = pow(vec3(COLOR_REDSTONETORCH_R, COLOR_REDSTONETORCH_G, COLOR_REDSTONETORCH_B), vec3(2.2)) * BRIGHTNESS_REDSTONETORCH * SPHERELIGHT_BRIGHTNESS;
|
||||
const vec3 amethystColor = pow(vec3(COLOR_AMETHYST_R, COLOR_AMETHYST_G, COLOR_AMETHYST_B), vec3(2.2)) * BRIGHTNESS_AMETHYST * SPHERELIGHT_BRIGHTNESS;
|
||||
const vec3 soultorchColor = pow(vec3(COLOR_SOULTORCH_R, COLOR_SOULTORCH_G, COLOR_SOULTORCH_B), vec3(2.2)) * BRIGHTNESS_SOULTORCH * SPHERELIGHT_BRIGHTNESS;
|
||||
const vec3 lightblockColor = pow(vec3(COLOR_LIGHTBLOCK_R, COLOR_LIGHTBLOCK_G, COLOR_LIGHTBLOCK_B), vec3(2.2)) * BRIGHTNESS_LIGHTBLOCK * SPHERELIGHT_BRIGHTNESS;
|
||||
const vec3 endrodColor = pow(vec3(COLOR_ENDROD_R, COLOR_ENDROD_G, COLOR_ENDROD_B), vec3(2.2)) * BRIGHTNESS_ENDROD * SPHERELIGHT_BRIGHTNESS;
|
||||
|
||||
vec3 shpereColor = vec3(0.0);
|
||||
|
||||
if (voxelID <= 244.0){
|
||||
if (voxelID == 242.0){ // Torch
|
||||
shpereColor = torchColor;
|
||||
}else if (voxelID == 243.0){ // Redstone Torch
|
||||
shpereColor = redstoneTorchColor;
|
||||
}else if (abs(voxelID - 240.0) < 1.5){ // Campfire 239 240
|
||||
shpereColor = fireColor;
|
||||
}else{
|
||||
shpereColor = soultorchColor;
|
||||
}
|
||||
|
||||
}else{
|
||||
if (voxelID == 245.0){ // Amethyst Cluster
|
||||
shpereColor = amethystColor;
|
||||
}else if (voxelID == 246.0){ // Soul Torch
|
||||
shpereColor = soultorchColor;
|
||||
}else if (voxelID == 247.0){ // Copper Lantern
|
||||
shpereColor = torchColor;
|
||||
}else if (abs(voxelID - 250.5) < 2.0){ // Candle & Sea Pickle
|
||||
shpereColor = torchColor * 0.8;
|
||||
}else if (abs(voxelID - 263.0) < 7.5){ // Light Block
|
||||
shpereColor = lightblockColor * (voxelID * (1.0 / 15.0) - (255.0 / 15.0));
|
||||
}else if (abs(voxelID - 280.0) < 1.5){ // End Rod
|
||||
shpereColor = endrodColor;
|
||||
}else{
|
||||
// Generic emissive (from vanilla light level blocks)
|
||||
shpereColor = torchColor * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
return shpereColor;
|
||||
}
|
||||
|
||||
vec3 HitLightShpere(Ray ray, vec3 voxelCoord, float voxelID, float rayLength){
|
||||
vec3 shpereLighting = vec3(0.0);
|
||||
|
||||
vec3 blockOrigin = voxelCoord - ray.ori;
|
||||
float intersectionLength = SphereIntersectionLength(ray, blockOrigin, vec3(0.5), 0.5);
|
||||
|
||||
if (intersectionLength > 0.0)
|
||||
intersectionLength = intersectionLength * intersectionLength;
|
||||
shpereLighting = LightShpereColor(voxelID) * (intersectionLength * BLOCKLIGHT_BRIGHTNESS);
|
||||
|
||||
return shpereLighting;
|
||||
}
|
||||
|
||||
vec3 HitLightShpereReflection(Ray ray, vec3 voxelCoord, float voxelID, float rayLength){
|
||||
vec3 shpereLighting = vec3(0.0);
|
||||
|
||||
vec3 blockOrigin = voxelCoord - ray.ori;
|
||||
float intersectionLength = SphereIntersectionLength(ray, blockOrigin, vec3(0.5), 0.25);
|
||||
|
||||
if (intersectionLength > 0.0)
|
||||
intersectionLength = intersectionLength * intersectionLength;
|
||||
intersectionLength = intersectionLength * intersectionLength * 50.0;
|
||||
shpereLighting = LightShpereColor(voxelID) * (intersectionLength * BLOCKLIGHT_BRIGHTNESS);
|
||||
|
||||
return shpereLighting;
|
||||
}
|
||||
|
||||
bool IsHitBox(Ray ray, vec3 blockOrigin, vec3 boxOrigin, vec3 boxSize, inout float rayLength, inout vec3 hitNormal){
|
||||
vec3 boxMin = blockOrigin + boxOrigin;
|
||||
vec3 boxMax = boxMin + boxSize;
|
||||
|
||||
vec3 t1 = ray.rdir * boxMin;
|
||||
vec3 t2 = ray.rdir * boxMax;
|
||||
|
||||
vec3 tMin = min(t1, t2);
|
||||
vec3 tMax = max(t1, t2);
|
||||
|
||||
float tEnter = maxVec3(tMin);
|
||||
float tExit = minVec3(tMax);
|
||||
|
||||
bool hit = min(rayLength, tExit) >= tEnter && tExit >= 0.0;
|
||||
|
||||
if (hit){
|
||||
hitNormal = -step(vec3(tEnter), tMin) * ray.sdir;
|
||||
rayLength = tEnter;
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
// Full shape reconstruction for cutout blocks. voxelID here is the raw block ID
|
||||
// from block.properties (0-100 range).
|
||||
bool HitShape(Ray ray, vec3 voxelCoord, float voxelID, inout float rayLength, out vec3 hitNormal){
|
||||
vec3 blockOrigin = voxelCoord - ray.ori;
|
||||
hitNormal = vec3(0.0);
|
||||
|
||||
bool hit = false;
|
||||
|
||||
const float rotIndex[8] = float[8](1.0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, -1.0);
|
||||
|
||||
if (voxelID == 2.0){ // Leaves — full block
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0), vec3(1.0), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 4.0){ // Cross plant (X shape)
|
||||
vec3 ori0 = vec3(0.5);
|
||||
vec3 size0 = vec3(-1.0, 1.0, 0.25 / 16.0);
|
||||
vec3 ori1 = vec3(0.5);
|
||||
vec3 size1 = vec3(0.25 / 16.0, 1.0, -1.0);
|
||||
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(ori0.x, 0.0, ori0.z), vec3(size0.x, 1.0, size0.z), rayLength, hitNormal);
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(ori1.x, 0.0, ori1.z), vec3(size1.x, 1.0, size1.z), rayLength, hitNormal) || hit;
|
||||
|
||||
}else if (voxelID == 5.0){ // Torch
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.4375, 0.0, 0.4375), vec3(0.125, 0.5625, 0.125), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 6.0){ // Lantern
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.25, 0.1875, 0.25), vec3(0.5, 0.5625, 0.5), rayLength, hitNormal);
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.4375, 0.0, 0.4375), vec3(0.125, 0.1875, 0.125), rayLength, hitNormal) || hit;
|
||||
|
||||
}else if (voxelID == 10.0 || voxelID == 11.0){ // Glass pane / Iron bars
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(7.0 / 16.0, 0.0, 7.0 / 16.0), vec3(2.0 / 16.0, 1.0, 2.0 / 16.0), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID >= 12.0 && voxelID <= 13.0){ // Stairs & slabs simplified as full-ish
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0), vec3(1.0), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID >= 14.0 && voxelID <= 16.0){ // Walls, fences, fence gates
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.25, 0.0, 0.25), vec3(0.5, 1.0, 0.5), rayLength, hitNormal);
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0, 0.375, 0.0), vec3(1.0, 0.25, 1.0), rayLength, hitNormal) || hit;
|
||||
|
||||
}else if (voxelID == 17.0){ // Door
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0, 0.0, 13.0 / 16.0), vec3(1.0, 1.0, 3.0 / 16.0), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 20.0){ // End rod
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.4375, 0.0, 0.4375), vec3(0.125, 1.0, 0.125), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 21.0){ // Chain
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.4375, 0.0, 0.4375), vec3(0.125, 1.0, 0.125), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 22.0){ // Amethyst cluster
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.25, 0.0, 0.25), vec3(0.5, 0.5, 0.5), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 27.0){ // Ladder
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 28.0 || voxelID == 29.0 || voxelID == 31.0){ // Sugar cane / Bamboo / Chorus
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.375, 0.0, 0.375), vec3(0.25, 1.0, 0.25), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 32.0){ // Coral
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.25, 0.0, 0.25), vec3(0.5, 0.625, 0.5), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 33.0){ // Pointed dripstone
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.375, 0.0, 0.375), vec3(0.25, 1.0, 0.25), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 35.0){ // Lightning rod
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.375, 0.0, 0.375), vec3(0.25, 1.0, 0.25), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 37.0){ // Snow layers
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0, 0.0, 0.0), vec3(1.0, 0.125, 1.0), rayLength, hitNormal);
|
||||
|
||||
}else if (voxelID == 80.0){ // Cobweb
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0), vec3(1.0), rayLength, hitNormal);
|
||||
|
||||
}else{
|
||||
// Default: full block
|
||||
hit = IsHitBox(ray, blockOrigin, vec3(0.0), vec3(1.0), rayLength, hitNormal);
|
||||
}
|
||||
|
||||
return hit;
|
||||
}
|
||||
|
||||
// Lightweight hit test (no normal) for shadow rays
|
||||
bool HitShape_Lite(Ray ray, vec3 voxelCoord, float voxelID, float rayLength){
|
||||
vec3 blockOrigin = voxelCoord - ray.ori;
|
||||
vec3 unused = vec3(0.0);
|
||||
return HitShape(ray, voxelCoord, voxelID, rayLength, unused);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,338 @@
|
||||
// MinecraftPT — Shadow + Voxelization pass
|
||||
// Renders the RTWSM shadow map (shadowcolor0) AND the voxel atlas (shadowcolor1),
|
||||
// which is then copied into the 3D voxel texture by VoxelData_Copy_CS.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
#include "/Lib/RTWSM/SampleWarp.glsl"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Vertex Shader
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef PROGRAM_VSH
|
||||
|
||||
uniform mat4 shadowModelViewInverse;
|
||||
uniform mat4 shadowProjection;
|
||||
uniform vec3 cameraPositionFract;
|
||||
uniform float frameTimeCounter;
|
||||
uniform float wetness;
|
||||
|
||||
uniform sampler2D noisetex;
|
||||
|
||||
in vec4 mc_Entity;
|
||||
in vec4 at_midBlock;
|
||||
in vec2 mc_midTexCoord;
|
||||
|
||||
out vec3 g_color;
|
||||
out vec3 g_worldPos;
|
||||
out vec2 g_texcoord;
|
||||
|
||||
#ifdef PROGRAM_VOXEL
|
||||
flat out float g_voxelID;
|
||||
out float g_mcLightLevel;
|
||||
out vec3 g_voxelCoord;
|
||||
out float g_notInVoxel;
|
||||
out float g_normalInvalid;
|
||||
#endif
|
||||
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
#include "/Lib/RTWSM/SampleWarp.glsl"
|
||||
|
||||
#ifdef WAVING_PLANTS
|
||||
#include "/Lib/IndividualFunctions/WavingPlants.glsl"
|
||||
#endif
|
||||
|
||||
void main(){
|
||||
vec4 worldPos = shadowModelViewInverse * gl_ModelViewMatrix * gl_Vertex;
|
||||
|
||||
float skylightmap = saturate(float(gl_MultiTexCoord1.y - 8) / 232.0);
|
||||
|
||||
#ifdef WAVING_PLANTS
|
||||
#ifdef SHADOW_WAVING_PLANTS
|
||||
WavingPlants(worldPos, skylightmap);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
g_worldPos = worldPos.xyz;
|
||||
g_color = gl_Color.rgb;
|
||||
g_texcoord.xy = mat2(gl_TextureMatrix[0]) * gl_MultiTexCoord0.xy + gl_TextureMatrix[0][3].xy;
|
||||
|
||||
#ifdef PROGRAM_VOXEL
|
||||
vec3 worldNormal = mat3(shadowModelViewInverse) * normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
g_voxelID = mc_Entity.x;
|
||||
g_mcLightLevel = skylightmap;
|
||||
g_notInVoxel = step(5999.5, g_voxelID);
|
||||
g_notInVoxel += step(g_voxelID, 0.5);
|
||||
g_notInVoxel *= float(abs(g_voxelID - 8400.0) > 400.5);
|
||||
g_normalInvalid = step(maxVec3(abs(worldNormal)), 0.99);
|
||||
|
||||
g_voxelCoord = vec3(-2.0);
|
||||
|
||||
if (g_notInVoxel < 0.5){
|
||||
// Full block detection: verify vertices are on the block grid
|
||||
if (g_voxelID <= 1.0){
|
||||
vec3 vertexPos = gl_Vertex.xyz + cameraPositionFract;
|
||||
vertexPos = abs(vertexPos - round(vertexPos));
|
||||
float posInvalid = vertexPos.x + vertexPos.y + vertexPos.z;
|
||||
posInvalid = step(0.001, posInvalid);
|
||||
g_notInVoxel = posInvalid + g_normalInvalid;
|
||||
}
|
||||
|
||||
#ifdef PT_MIDBLOCK_TEMPFIX
|
||||
g_voxelCoord = g_worldPos + cameraPositionFract + (voxelResolution * 0.5) - worldNormal * 0.01;
|
||||
#else
|
||||
g_voxelCoord = g_worldPos + cameraPositionFract + (voxelResolution * 0.5) + at_midBlock.xyz * 0.015625;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
gl_Position = vec4(1.0); // set by geometry shader
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Geometry Shader
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef PROGRAM_GSH
|
||||
|
||||
layout(triangles) in;
|
||||
layout(triangle_strip, max_vertices = 6) out;
|
||||
|
||||
uniform mat4 shadowProjection;
|
||||
uniform ivec2 atlasSize;
|
||||
uniform int renderStage;
|
||||
|
||||
in vec3 g_color[];
|
||||
in vec3 g_worldPos[];
|
||||
in vec2 g_texcoord[];
|
||||
|
||||
#ifdef PROGRAM_VOXEL
|
||||
flat in float g_voxelID[];
|
||||
in float g_mcLightLevel[];
|
||||
in vec3 g_voxelCoord[];
|
||||
in float g_notInVoxel[];
|
||||
in float g_normalInvalid[];
|
||||
#endif
|
||||
|
||||
out vec3 v_color;
|
||||
out vec4 v_worldPos_voxelData_isWater_isVoxel;
|
||||
out vec2 v_texcoord_mcLightLevel;
|
||||
flat out vec2 v_midTexCoord;
|
||||
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
|
||||
void main(){
|
||||
v_midTexCoord = vec2(0.0);
|
||||
|
||||
vec3 posDiff = vec3(
|
||||
distance(g_worldPos[0], g_worldPos[1]),
|
||||
distance(g_worldPos[1], g_worldPos[2]),
|
||||
distance(g_worldPos[2], g_worldPos[0])
|
||||
);
|
||||
|
||||
// Emit the shadow map triangle (for RTWSM shadow sampling)
|
||||
{
|
||||
float bias = saturate(maxVec3(posDiff) * 0.5 - 1.0) * shadowProjection[0][0] * 0.3;
|
||||
|
||||
for (int i = 0; i < 3; i++){
|
||||
vec4 worldPos = shadowModelViewInverse * gl_in[i].gl_Position;
|
||||
gl_Position = gl_in[i].gl_Position;
|
||||
gl_Position.z += bias;
|
||||
|
||||
// Shift into the right square shadow region, then apply warp
|
||||
ShiftShadowNdcPos(gl_Position.xy);
|
||||
gl_Position.xy += SampleRTWWarpSmooth(gl_Position.xy * 0.5 + 0.5) * 2.0;
|
||||
|
||||
v_color = g_color[i];
|
||||
v_worldPos_voxelData_isWater_isVoxel = vec4(g_worldPos[i], 0.0);
|
||||
v_texcoord_mcLightLevel = g_texcoord[i];
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#ifdef PROGRAM_VOXEL
|
||||
|
||||
vec3 voxelCoord = floor(g_voxelCoord[0] * 0.33333333 + g_voxelCoord[1] * 0.33333333 + g_voxelCoord[2] * 0.33333333);
|
||||
|
||||
if (all(bvec3(
|
||||
clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 1.0)) == voxelCoord,
|
||||
g_notInVoxel[0] + g_notInVoxel[1] + g_notInVoxel[2] < 0.5,
|
||||
renderStage == MC_RENDER_STAGE_TERRAIN_SOLID || renderStage == MC_RENDER_STAGE_TERRAIN_TRANSLUCENT
|
||||
))){
|
||||
|
||||
vec2 atlasResolution = vec2(atlasSize);
|
||||
|
||||
vec2 maxTexCoord = max(g_texcoord[0].xy, max(g_texcoord[1].xy, g_texcoord[2].xy));
|
||||
vec2 minTexCoord = min(g_texcoord[0].xy, min(g_texcoord[1].xy, g_texcoord[2].xy));
|
||||
|
||||
v_midTexCoord = (maxTexCoord + minTexCoord) * 0.5;
|
||||
|
||||
vec2 coordSize = (maxTexCoord - minTexCoord) * atlasResolution;
|
||||
|
||||
#if TEXTURE_RESOLUTION == 0
|
||||
float coordMaxSize = maxVec3(vec3(
|
||||
maxVec2(abs(g_texcoord[0].xy - g_texcoord[1].xy) * atlasResolution) / max(posDiff.x, 1e-4),
|
||||
maxVec2(abs(g_texcoord[1].xy - g_texcoord[2].xy) * atlasResolution) / max(posDiff.y, 1e-4),
|
||||
maxVec2(abs(g_texcoord[0].xy - g_texcoord[2].xy) * atlasResolution) / max(posDiff.z, 1e-4)
|
||||
));
|
||||
|
||||
float textureResolution = floor(coordMaxSize + 0.5);
|
||||
#else
|
||||
float textureResolution = TEXTURE_RESOLUTION;
|
||||
#endif
|
||||
|
||||
float voxelID = g_voxelID[0];
|
||||
|
||||
float roundedResolution = round(log2(textureResolution));
|
||||
|
||||
vec2 atlasTiles = vec2(atlasSize) * exp2(-roundedResolution);
|
||||
|
||||
// Tile-aligned texel sampling for accurate atlas UV
|
||||
v_midTexCoord = (floor(v_midTexCoord * atlasTiles) + 0.5) / atlasTiles;
|
||||
|
||||
float skylight = saturate(SkyLightmapCurve(g_mcLightLevel[0] * 0.33333333 + g_mcLightLevel[1] * 0.33333333 + g_mcLightLevel[2] * 0.33333333));
|
||||
|
||||
float zOffset = g_normalInvalid[0] + g_normalInvalid[1] + g_normalInvalid[2];
|
||||
|
||||
coordSize /= textureResolution;
|
||||
|
||||
zOffset += saturate(coordSize.x * coordSize.y) * -0.2;
|
||||
|
||||
bool isCutout = voxelID == 2.0;
|
||||
|
||||
// Light blocks (8000-8400): encode block light level
|
||||
if (abs(voxelID - 8400.0) < 400.5){
|
||||
voxelID -= 8000.0;
|
||||
|
||||
if (voxelID > 499.5){
|
||||
// hardcoded light level block
|
||||
voxelID = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Encode: cutout shapes get 1000 - id, full blocks get id + 1000
|
||||
bool isShape = bool(
|
||||
uint(voxelID == 2.0) | // leaves
|
||||
uint(voxelID == 4.0) | // cross plants
|
||||
uint(voxelID == 5.0) | // torch
|
||||
uint(voxelID == 6.0) | // lantern
|
||||
uint(voxelID == 10.0) | // glass pane
|
||||
uint(voxelID == 11.0) | // iron bars
|
||||
uint(voxelID == 12.0) | // stairs
|
||||
uint(voxelID == 13.0) | // slabs
|
||||
uint(voxelID == 14.0) | // walls
|
||||
uint(voxelID == 15.0) | // fences
|
||||
uint(voxelID == 16.0) | // fence gates
|
||||
uint(voxelID == 17.0) | // doors
|
||||
uint(voxelID == 20.0) | // end rod
|
||||
uint(voxelID == 21.0) | // chain
|
||||
uint(voxelID == 22.0) | // amethyst
|
||||
uint(voxelID == 27.0) | // ladder
|
||||
uint(voxelID == 28.0) | // sugar cane
|
||||
uint(voxelID == 29.0) | // bamboo
|
||||
uint(voxelID == 31.0) | // chorus
|
||||
uint(voxelID == 32.0) | // coral
|
||||
uint(voxelID == 33.0) | // dripstone
|
||||
uint(voxelID == 35.0) | // lightning rod
|
||||
uint(voxelID == 36.0) | // pot
|
||||
uint(voxelID == 37.0) | // snow layers
|
||||
uint(voxelID == 80.0) // cobweb
|
||||
);
|
||||
|
||||
voxelID = isShape ? 1000.0 - voxelID : voxelID + 1000.0;
|
||||
|
||||
#ifdef PT_FULLBLOCK_VERIFICATION
|
||||
if (voxelID == 1001.0){
|
||||
if (abs(posDiff.x + posDiff.y + posDiff.z - 3.41421356) > 0.001){
|
||||
voxelID = 65536.0;
|
||||
zOffset = -0.49;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 voxelTexel = VoxelTexel_From_VoxelCoord(voxelCoord);
|
||||
const vec2[3] vertexOffset = vec2[3](vec2(0.0, 0.0), vec2(1.0, 0.0), vec2(0.5, 1.0));
|
||||
|
||||
for (int i = 0; i < 3; i++){
|
||||
gl_Position = vec4((voxelTexel + vertexOffset[i]) * shadowPixelSize * 2.0 - 1.0, zOffset * 0.5 - 0.75, 1.0);
|
||||
|
||||
v_color = g_color[i];
|
||||
v_worldPos_voxelData_isWater_isVoxel = vec4(voxelID, roundedResolution, 0.0, 1.0);
|
||||
v_texcoord_mcLightLevel = vec2(skylight, 0.0);
|
||||
|
||||
EmitVertex();
|
||||
}
|
||||
|
||||
EndPrimitive();
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Fragment Shader
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef PROGRAM_FSH
|
||||
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
|
||||
layout(location = 0) out vec4 shadowbuffer0;
|
||||
layout(location = 1) out vec4 shadowbuffer1;
|
||||
|
||||
uniform mat4 shadowModelViewInverse;
|
||||
uniform vec3 cameraPosition;
|
||||
uniform ivec2 atlasSize;
|
||||
uniform int isEyeInWater;
|
||||
uniform vec2 screenSize;
|
||||
uniform vec2 pixelSize;
|
||||
uniform int frameCounter;
|
||||
uniform int renderStage;
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D noisetex;
|
||||
uniform sampler2D pixelData2D;
|
||||
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
#include "/Lib/RTWSM/SampleWarp.glsl"
|
||||
|
||||
in vec3 v_color;
|
||||
in vec4 v_worldPos_voxelData_isWater_isVoxel;
|
||||
in vec2 v_texcoord_mcLightLevel;
|
||||
flat in vec2 v_midTexCoord;
|
||||
|
||||
void main(){
|
||||
// Shadow map fragment
|
||||
if (v_worldPos_voxelData_isWater_isVoxel.w < 0.5){
|
||||
vec4 albedoTex = textureLod(tex, v_texcoord_mcLightLevel.xy, 0.0);
|
||||
|
||||
// Keep shadow fragments only in the right square region [W, 2W] x [0, W]
|
||||
if (gl_FragCoord.x < float(voxelWidth) || gl_FragCoord.x >= shadowSize || gl_FragCoord.y >= float(voxelWidth)
|
||||
|| albedoTex.a < 0.004) discard;
|
||||
|
||||
albedoTex.rgb *= v_color;
|
||||
|
||||
shadowbuffer0 = vec4(albedoTex);
|
||||
shadowbuffer1 = vec4(0.0);
|
||||
}
|
||||
|
||||
// Voxel atlas fragment
|
||||
if (v_worldPos_voxelData_isWater_isVoxel.w > 0.2){
|
||||
shadowbuffer0 = vec4(v_color.rgb, v_texcoord_mcLightLevel.x);
|
||||
|
||||
vec2 midCoord = saturate(v_midTexCoord * (65536.0 / 65535.0));
|
||||
float voxelID = saturate(v_worldPos_voxelData_isWater_isVoxel.x / 65535.0);
|
||||
float textureResolution = saturate(v_worldPos_voxelData_isWater_isVoxel.y / 255.0);
|
||||
float skylight = saturate(SkyLightmapCurve(v_texcoord_mcLightLevel.x * 1.07));
|
||||
|
||||
shadowbuffer1 = vec4(midCoord, voxelID, Pack2xU8_to_U16(vec2(textureResolution, skylight)));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — Voxel Profile
|
||||
// Voxel grid parameters derived from settings.
|
||||
//
|
||||
// The shadow framebuffer (shadowcolor0/1) is square, size S x S, and holds:
|
||||
// - the VOXEL ATLAS in the bottom-left region: texels [0, W) x [0, H)
|
||||
// where W = voxelWidth and H = ceil(N / W), N = Rx*Ry*Rz voxels.
|
||||
// Each voxel is one texel; linear packing: n = x + y*Rx + z*Rx*Ry.
|
||||
// - the SHADOW MAP in the right square region: texels [W, 2W) x [0, W).
|
||||
// The shadow camera NDC is shifted into this region (square -> square,
|
||||
// no aspect distortion). Effective shadow resolution = W.
|
||||
|
||||
#ifndef VOXEL_PROFILE_GLSL
|
||||
#define VOXEL_PROFILE_GLSL
|
||||
|
||||
// Shadow render distance -> shadow coverage
|
||||
#if SHADOW_RENDER_DISTANCE == 4
|
||||
const float shadowDistance = 64.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 6
|
||||
const float shadowDistance = 96.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 8
|
||||
const float shadowDistance = 128.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 12
|
||||
const float shadowDistance = 192.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 16
|
||||
const float shadowDistance = 256.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 24
|
||||
const float shadowDistance = 384.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 32
|
||||
const float shadowDistance = 512.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 48
|
||||
const float shadowDistance = 768.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 64
|
||||
const float shadowDistance = 1024.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 96
|
||||
const float shadowDistance = 1536.1;
|
||||
#elif SHADOW_RENDER_DISTANCE == 128
|
||||
const float shadowDistance = 2048.1;
|
||||
#else
|
||||
const float shadowDistance = 256.1;
|
||||
#endif
|
||||
|
||||
// Voxel grid resolution and coverage (blocks)
|
||||
#if PT_VOXEL_RESOLUTION == 4004
|
||||
const ivec3 voxelResolutionInt = ivec3(128);
|
||||
const float voxelDistance = 64.0;
|
||||
const int voxelWidth = 2048;
|
||||
#elif PT_VOXEL_RESOLUTION == 6004
|
||||
const ivec3 voxelResolutionInt = ivec3(192, 128, 192);
|
||||
const float voxelDistance = 96.0;
|
||||
const int voxelWidth = 2048;
|
||||
#elif PT_VOXEL_RESOLUTION == 8004
|
||||
const ivec3 voxelResolutionInt = ivec3(256, 128, 256);
|
||||
const float voxelDistance = 128.0;
|
||||
const int voxelWidth = 2048;
|
||||
#elif PT_VOXEL_RESOLUTION == 8006
|
||||
const ivec3 voxelResolutionInt = ivec3(256, 192, 256);
|
||||
const float voxelDistance = 128.0;
|
||||
const int voxelWidth = 4096;
|
||||
#elif PT_VOXEL_RESOLUTION == 8008
|
||||
const ivec3 voxelResolutionInt = ivec3(256);
|
||||
const float voxelDistance = 128.0;
|
||||
const int voxelWidth = 4096;
|
||||
#elif PT_VOXEL_RESOLUTION == 12004
|
||||
const ivec3 voxelResolutionInt = ivec3(384, 128, 384);
|
||||
const float voxelDistance = 192.0;
|
||||
const int voxelWidth = 4096;
|
||||
#elif PT_VOXEL_RESOLUTION == 12006
|
||||
const ivec3 voxelResolutionInt = ivec3(384, 192, 384);
|
||||
const float voxelDistance = 192.0;
|
||||
const int voxelWidth = 4096;
|
||||
#elif PT_VOXEL_RESOLUTION == 12008
|
||||
const ivec3 voxelResolutionInt = ivec3(384, 256, 384);
|
||||
const float voxelDistance = 192.0;
|
||||
const int voxelWidth = 6144;
|
||||
#elif PT_VOXEL_RESOLUTION == 16004
|
||||
const ivec3 voxelResolutionInt = ivec3(512, 128, 512);
|
||||
const float voxelDistance = 256.0;
|
||||
const int voxelWidth = 6144;
|
||||
#elif PT_VOXEL_RESOLUTION == 16008
|
||||
const ivec3 voxelResolutionInt = ivec3(512, 256, 512);
|
||||
const float voxelDistance = 256.0;
|
||||
const int voxelWidth = 6144;
|
||||
#elif PT_VOXEL_RESOLUTION == 16016
|
||||
const ivec3 voxelResolutionInt = ivec3(512);
|
||||
const float voxelDistance = 256.0;
|
||||
const int voxelWidth = 8192;
|
||||
#else
|
||||
const ivec3 voxelResolutionInt = ivec3(256, 192, 256);
|
||||
const float voxelDistance = 128.0;
|
||||
const int voxelWidth = 4096;
|
||||
#endif
|
||||
|
||||
const vec3 voxelResolution = vec3(voxelResolutionInt);
|
||||
|
||||
// Irradiance cache resolution (clamped to voxel grid)
|
||||
const int ircResolution = min(PT_IRC_RESOLUTION, voxelResolutionInt.x);
|
||||
|
||||
// Shadow framebuffer size (square)
|
||||
const int shadowMapResolution = voxelWidth * 2;
|
||||
const float shadowSize = float(shadowMapResolution);
|
||||
const float shadowPixelSize = 1.0 / shadowSize;
|
||||
const float shadowRatio = 0.5; // W / S
|
||||
|
||||
// Map 3D voxel coordinate to 2D atlas texel (linear packing)
|
||||
vec2 VoxelTexel_From_VoxelCoord(vec3 voxelCoord){
|
||||
float n = voxelCoord.x + voxelCoord.y * voxelResolution.x + voxelCoord.z * voxelResolution.x * voxelResolution.y;
|
||||
return vec2(mod(n, float(voxelWidth)), floor(n / float(voxelWidth)));
|
||||
}
|
||||
|
||||
// Shift shadow map NDC into the right square region [W, 2W] x [0, W]
|
||||
void ShiftShadowNdcPos(inout vec2 coord){
|
||||
coord = coord * shadowRatio + vec2(1.0 - shadowRatio, shadowRatio - 1.0);
|
||||
}
|
||||
|
||||
// Shift shadow map screen uv into the right square region
|
||||
void ShiftShadowScreenPos(inout vec2 coord){
|
||||
coord = coord * shadowRatio + vec2(1.0 - shadowRatio, 0.0);
|
||||
}
|
||||
|
||||
// Shift back from shadow region uv to standard shadow uv
|
||||
vec2 UnshiftShadowScreenPos(vec2 coord){
|
||||
return (coord - vec2(1.0 - shadowRatio, 0.0)) / shadowRatio;
|
||||
}
|
||||
|
||||
// Block ID encoding (16-bit range)
|
||||
// Full block: voxelID + 1000
|
||||
// Cutout shape: 1000 - voxelID
|
||||
// Empty markers: 0.91 (8^3), 0.71 (4^3), 0.61 (2^3)
|
||||
float EncodeVoxelID(float voxelID){
|
||||
return saturate((voxelID + 1000.0) / 65535.0);
|
||||
}
|
||||
|
||||
float DecodeVoxelID(float encoded){
|
||||
return abs(floor(encoded * 65535.0 - 999.9));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// MinecraftPT — CausticsTex_CS
|
||||
// Generates a caustics normal field texture (pixelData2D) used by water voxels.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(16, 16, 1);
|
||||
layout (local_size_x = 32, local_size_y = 32) in;
|
||||
|
||||
layout (rg16f) uniform writeonly image2D img_pixelData2D;
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
vec2 uv = (vec2(texel) + 0.5) / vec2(512.0, 513.0);
|
||||
|
||||
float time = frameTimeCounter * 0.05;
|
||||
|
||||
// Analytic caustics field (sum of moving sine waves)
|
||||
vec2 coord = uv * 32.0;
|
||||
float n1 = sin(coord.x * 2.0 + time * 3.0) * cos(coord.y * 1.7 - time * 2.0);
|
||||
float n2 = sin(coord.x * 1.3 - time * 1.5) * cos(coord.y * 2.4 + time * 2.5);
|
||||
float n3 = sin((coord.x + coord.y) * 3.1 + time * 4.0) * 0.5;
|
||||
|
||||
float field = n1 * 0.5 + n2 * 0.3 + n3 * 0.2;
|
||||
|
||||
// Normal from field gradient
|
||||
float eps = 0.01;
|
||||
float fx = sin((coord.x + eps) * 2.0 + time * 3.0) * cos(coord.y * 1.7 - time * 2.0);
|
||||
float fxx = sin((coord.x - eps) * 2.0 + time * 3.0) * cos(coord.y * 1.7 - time * 2.0);
|
||||
float fy = sin(coord.x * 2.0 + time * 3.0) * cos((coord.y + eps) * 1.7 - time * 2.0);
|
||||
float fyy = sin(coord.x * 2.0 + time * 3.0) * cos((coord.y - eps) * 1.7 - time * 2.0);
|
||||
|
||||
vec2 normal = vec2((fx - fxx) * 0.5 / eps, (fy - fyy) * 0.5 / eps) * 0.2;
|
||||
normal = tanh(normal);
|
||||
|
||||
imageStore(img_pixelData2D, texel, vec4(normal * 0.5 + 0.5, 0.0, 0.0));
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// MinecraftPT — Bloom_CS
|
||||
// Bloom compute passes: two downsample levels + axial blur X/Y.
|
||||
// Uses two alternating images (bloomA/bloomB) to avoid read-write conflicts.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(int(ceil(viewWidth * 0.03125)), int(ceil(viewHeight * 0.03125)), 1);
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
layout (rgba16f) uniform writeonly image2D img_bloomA;
|
||||
layout (rgba16f) uniform writeonly image2D img_bloomB;
|
||||
|
||||
uniform sampler2D colortex12;
|
||||
uniform sampler2D bloomA;
|
||||
uniform sampler2D bloomB;
|
||||
|
||||
// Downsample pass
|
||||
#ifdef PROGRAM_BLOOM_DOWNSAMPLE
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
|
||||
#if PROGRAM_BLOOM_DOWNSAMPLE_LEVEL == 1
|
||||
// Level 1: 2x2 box from the HDR scene -> bloomA
|
||||
for (int i = 0; i < 2; i++){
|
||||
for (int j = 0; j < 2; j++){
|
||||
color += texelFetch(colortex12, texel * 2 + ivec2(i, j), 0).rgb;
|
||||
}}
|
||||
color *= 0.25;
|
||||
|
||||
float brightness = luminance(color);
|
||||
color *= saturate(brightness * BLOOM_CLAMP_STRENGTH);
|
||||
|
||||
ivec2 imgSize = imageSize(img_bloomA);
|
||||
if (all(lessThan(texel, imgSize))){
|
||||
imageStore(img_bloomA, texel, vec4(color, 1.0));
|
||||
}
|
||||
|
||||
#else
|
||||
// Level 2: 2x2 box from bloomA -> bloomB
|
||||
for (int i = 0; i < 2; i++){
|
||||
for (int j = 0; j < 2; j++){
|
||||
color += texelFetch(bloomA, texel * 2 + ivec2(i, j), 0).rgb;
|
||||
}}
|
||||
color *= 0.25;
|
||||
|
||||
float brightness = luminance(color);
|
||||
color *= saturate(brightness * BLOOM_CLAMP_STRENGTH);
|
||||
|
||||
ivec2 imgSize = imageSize(img_bloomB);
|
||||
if (all(lessThan(texel, imgSize))){
|
||||
imageStore(img_bloomB, texel, vec4(color, 1.0));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Axial blur pass (X or Y depending on defines)
|
||||
#ifdef PROGRAM_BLOOM_AXIALBLUR
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 imgSize = imageSize(img_bloomA);
|
||||
if (any(greaterThanEqual(texel, imgSize))) return;
|
||||
|
||||
vec2 uv = (vec2(texel) + 0.5) / vec2(imgSize);
|
||||
|
||||
// Which buffer to read (BLOOM_AXIAL_READ_A defined for the pass reading bloomA)
|
||||
#ifdef BLOOM_AXIAL_READ_A
|
||||
sampler2D src = bloomA;
|
||||
#else
|
||||
sampler2D src = bloomB;
|
||||
#endif
|
||||
|
||||
#ifdef PROGRAM_BLOOM_AXIALBLUR_X
|
||||
vec2 axis = vec2(1.0, 0.0);
|
||||
#else
|
||||
vec2 axis = vec2(0.0, 1.0);
|
||||
#endif
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
float weightSum = 0.0;
|
||||
|
||||
for (int i = -8; i <= 8; i++){
|
||||
vec2 coord = uv + axis * float(i) / vec2(imgSize);
|
||||
float w = exp(-float(i * i) * 0.05);
|
||||
color += textureLod(src, coord, 0.0).rgb * w;
|
||||
weightSum += w;
|
||||
}
|
||||
|
||||
// Write to the opposite buffer of the read source
|
||||
#ifdef BLOOM_AXIAL_READ_A
|
||||
imageStore(img_bloomB, texel, vec4(color / weightSum, 1.0));
|
||||
#else
|
||||
imageStore(img_bloomA, texel, vec4(color / weightSum, 1.0));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
// MinecraftPT — Bloom_FS
|
||||
// Final bloom composite onto the scene.
|
||||
// bloomB is a fixed 1024x1024 image; the valid bloom region for this screen
|
||||
// is its top-left (viewWidth/4 x viewHeight/4) texels, so UV = screen / 4096.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
uniform sampler2D colortex12;
|
||||
uniform sampler2D bloomB;
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
|
||||
vec3 scene = texelFetch(colortex12, ivec2(texelCoord), 0).rgb;
|
||||
vec3 bloom = textureLod(bloomB, clamp(texelCoord / 4096.0, vec2(0.0), vec2(1.0)), 0.0).rgb;
|
||||
|
||||
vec3 color = scene + bloom * BLOOM_AMOUNT;
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// MinecraftPT — DepthCopy_CS
|
||||
// Copies the current frame depth to prevDepth2D at the end of the frame,
|
||||
// so temporal filters in the next frame have the previous depth for
|
||||
// reprojection validation.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(int(ceil(viewWidth * 0.0625)), int(ceil(viewHeight * 0.0625)), 1);
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
layout (r32f) uniform writeonly image2D img_prevDepth2D;
|
||||
|
||||
uniform sampler2D depthtex0;
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
imageStore(img_prevDepth2D, texel, vec4(texelFetch(depthtex0, texel * 2, 0).r));
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// MinecraftPT — DiffuseSpatial (single pass, step parameterized by composite index)
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Denoiser/DiffuseSpatialFilter.glsl"
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
vec3 color = texelFetch(colortex7, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
// Step size determined by whic composite pass we are
|
||||
int step = 1;
|
||||
#ifdef SPATIAL_STEP_2
|
||||
step = 2;
|
||||
#elif defined SPATIAL_STEP_4
|
||||
step = 4;
|
||||
#elif defined SPATIAL_STEP_8
|
||||
step = 8;
|
||||
#endif
|
||||
|
||||
color = DiffuseSpatialPass(color, texelCoord, step);
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// MinecraftPT — DiffuseTemporal_FS
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Denoiser/DiffuseTemporalFilter.glsl"
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
vec3 current = texelFetch(colortex6, ivec2(texelCoord), 0).rgb;
|
||||
vec3 prev = texelFetch(colortex7, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
vec3 result = DiffuseTemporalAccumulate(current, texelCoord, prev);
|
||||
|
||||
colorOut = vec4(result, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// MinecraftPT — DiffuseTracing_FS
|
||||
// One diffuse path-tracing ray per pixel at half resolution.
|
||||
// Output: colortex6 = noisy diffuse irradiance, colortex10 = motion vectors.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/GbufferData.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/TracingNoise.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/TracingUtilities.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/ShadowTracing.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/SampleIRC.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/SpecularTracer.glsl"
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
|
||||
uniform sampler2D colortex0; // albedo
|
||||
uniform sampler2D colortex1; // normals
|
||||
uniform sampler2D colortex3; // lightmap
|
||||
|
||||
layout(location = 0) out vec4 diffuseOut; // colortex6
|
||||
layout(location = 1) out vec4 motionOut; // colortex10
|
||||
|
||||
vec3 TraceDiffuseRay(vec3 origin, vec3 dir, float maxDist){
|
||||
vec3 result = vec3(0.0);
|
||||
|
||||
Ray ray = PackRay(origin, dir);
|
||||
vec3 voxelCoord = floor(ray.ori);
|
||||
vec3 totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
float rayLength = 0.0;
|
||||
vec3 tracingNext;
|
||||
|
||||
for (int i = 0; i < 128; i++){
|
||||
if (clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 0.5)) != voxelCoord){
|
||||
// Miss: sample sky
|
||||
result += SampleSkyBox(dir) * (1.0 / 3.14159265);
|
||||
break;
|
||||
}
|
||||
|
||||
if (rayLength > maxDist){
|
||||
result += SampleSkyBox(dir) * (1.0 / 3.14159265);
|
||||
break;
|
||||
}
|
||||
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(voxelCoord), 0);
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
|
||||
// Light sphere contribution
|
||||
if (IsLightSphere(voxelID)){
|
||||
result += HitLightShpere(ray, voxelCoord, voxelID, rayLength);
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hit = false;
|
||||
vec3 hitNormal = vec3(0.0);
|
||||
|
||||
if (voxelID >= 999.0){
|
||||
hit = rayLength > 0.0;
|
||||
hitNormal = -step(vec3(rayLength), totalStep - abs(ray.rdir)) * ray.sdir;
|
||||
}else if (voxelID < 1000.0 && voxelID > 1.0){
|
||||
float rawID = 1000.0 - voxelID;
|
||||
rayLength = minVec3(totalStep);
|
||||
hit = HitShape(ray, voxelCoord, rawID, rayLength, hitNormal);
|
||||
}
|
||||
|
||||
if (hit){
|
||||
vec3 hitPos = ray.ori + ray.dir * rayLength;
|
||||
vec2 midCoord = voxelData.xy;
|
||||
vec3 albedo = SampleVoxelAlbedo(midCoord, hitPos, hitNormal);
|
||||
float skylight = Unpack2xU8_Y_from_U16(voxelData.w);
|
||||
|
||||
// Direct sun at hit point
|
||||
vec3 sun = GetSunIrradiance();
|
||||
float shadow = SimpleShadowTracing(hitPos + hitNormal * 0.01, GetSunDirWorld());
|
||||
float NdotL = max(dot(hitNormal, GetSunDirWorld()), 0.0);
|
||||
|
||||
result += albedo * sun * shadow * NdotL;
|
||||
|
||||
// Sky light at hit point (from voxel skylight)
|
||||
result += albedo * GetAtmoIrradiance() * skylight * 0.5;
|
||||
|
||||
// One-bounce: sample IRC
|
||||
result += albedo * SampleIRC(hitPos) * 0.5;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Sparse skip
|
||||
float marker = voxelData.z;
|
||||
if (marker > 0.60 && marker < 0.92){
|
||||
float skipSize = marker > 0.90 ? 8.0 : (marker > 0.70 ? 4.0 : 2.0);
|
||||
vec3 nextBoundary = floor((voxelCoord + 1.0) / skipSize) * skipSize;
|
||||
vec3 distToBoundary = (nextBoundary - voxelCoord) * abs(ray.rdir);
|
||||
float tSkip = minVec3(distToBoundary) + 1e-4;
|
||||
rayLength += tSkip;
|
||||
vec3 stepVec = ray.sdir * abs(ray.rdir) * tSkip;
|
||||
ray.ori += stepVec;
|
||||
voxelCoord = floor(ray.ori);
|
||||
totalStep = (ray.sdir * (voxelCoord - ray.ori + 0.5) + 0.5) * abs(ray.rdir);
|
||||
continue;
|
||||
}
|
||||
|
||||
rayLength = minVec3(totalStep);
|
||||
tracingNext = step(totalStep, vec3(rayLength));
|
||||
voxelCoord += tracingNext * ray.sdir;
|
||||
totalStep += tracingNext * abs(ray.rdir);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void main(){
|
||||
// Half resolution texel
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
ivec2 fullCoord = texelCoord * 2;
|
||||
|
||||
// Skip sky
|
||||
float depth = texelFetch(depthtex0, fullCoord, 0).r;
|
||||
if (depth >= 1.0){
|
||||
diffuseOut = vec4(0.0);
|
||||
motionOut = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 albedoData = texelFetch(colortex0, fullCoord, 0);
|
||||
vec4 normalData = texelFetch(colortex1, fullCoord, 0);
|
||||
|
||||
vec3 worldNormal = DecodeNormal(normalData.xy);
|
||||
vec3 viewNormal = mat3(gbufferModelView) * worldNormal;
|
||||
|
||||
// Reconstruct view position
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(fullCoord) / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
|
||||
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
|
||||
|
||||
vec2 noise = GetTracingNoise2(vec2(texelCoord), frameCounter, 0);
|
||||
|
||||
// Cosine-weighted hemisphere sampling
|
||||
vec3 dir = SampleHemisphere(noise, worldNormal);
|
||||
|
||||
// Only trace if there's anything to bounce (skip pure black)
|
||||
vec3 traceResult = TraceDiffuseRay(WorldToVoxel(worldPos + worldNormal * 0.05), dir, PT_DIFFUSE_TRACING_DISTANCE);
|
||||
|
||||
diffuseOut = vec4(traceResult, 1.0);
|
||||
|
||||
// Motion vectors (full res reprojection)
|
||||
vec4 prevViewPos = gbufferPreviousProjection * gbufferPreviousModelView * vec4(worldPos, 1.0);
|
||||
prevViewPos.xyz /= prevViewPos.w;
|
||||
vec2 prevScreen = (prevViewPos.xy * 0.5 + 0.5) * screenSize;
|
||||
|
||||
vec2 motion = vec2(texelCoord) - prevScreen * 0.5;
|
||||
|
||||
motionOut = vec4(motion, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// MinecraftPT — DiffuseVariance_FS
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Denoiser/DiffuseVarianceEstimation.glsl"
|
||||
|
||||
layout(location = 0) out vec4 varOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
vec3 color = texelFetch(colortex7, ivec2(texelCoord), 0).rgb;
|
||||
vec2 variance = DiffuseEstimateVariance(color, texelCoord);
|
||||
|
||||
varOut = vec4(variance, 0.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// MinecraftPT — Dof_FS
|
||||
// Depth of field with circle of confusion bokeh.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/IndividualFunctions/DOF.glsl"
|
||||
|
||||
uniform sampler2D colortex12;
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
|
||||
vec3 color = texelFetch(colortex12, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
#ifdef DOF
|
||||
if (DOF > 0){
|
||||
float depth = texelFetch(depthtex0, ivec2(texelCoord), 0).r;
|
||||
|
||||
// Focal distance (from center depth or manual)
|
||||
float focalDepth = CAMERA_FOCAL_POINT;
|
||||
#ifdef CAMERA_FOCUS_MODE
|
||||
if (CAMERA_FOCUS_MODE == 1){
|
||||
vec2 center = screenSize * 0.5;
|
||||
focalDepth = texelFetch(depthtex0, ivec2(center), 0).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
float coc = GetCoC(depth, focalDepth);
|
||||
|
||||
#ifdef DISABLE_HAND_DOF
|
||||
// Skip hand (close depth)
|
||||
if (depth < 0.1) coc = 0.0;
|
||||
#endif
|
||||
|
||||
if (coc > 0.5){
|
||||
color = DofBlur(texelCoord, coc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// MinecraftPT — Exposure_CS
|
||||
// Computes the average scene luminance and smooths the exposure over time.
|
||||
// Writes the result into a 1x1 R16F image (exposureTex) read by the final pass.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(8, 8, 1);
|
||||
layout (local_size_x = 16, local_size_y = 16) in;
|
||||
|
||||
layout (r16f) uniform writeonly image2D img_exposureTex;
|
||||
|
||||
uniform sampler2D colortex12;
|
||||
|
||||
shared float luminanceSum[256];
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
// Downsample luminance from the HDR scene
|
||||
float lum = 0.0;
|
||||
vec2 base = vec2(texel * 4);
|
||||
for (int i = 0; i < 4; i++){
|
||||
for (int j = 0; j < 4; j++){
|
||||
vec3 color = texelFetch(colortex12, ivec2(base + vec2(i, j)), 0).rgb;
|
||||
lum += luminance(color);
|
||||
}}
|
||||
lum /= 16.0;
|
||||
|
||||
// Shared reduction
|
||||
uint local = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 16u;
|
||||
luminanceSum[local] = lum;
|
||||
barrier();
|
||||
|
||||
if (local == 0u){
|
||||
float avg = 0.0;
|
||||
for (uint i = 0u; i < 256u; i++){
|
||||
avg += luminanceSum[i];
|
||||
}
|
||||
avg /= 256.0;
|
||||
|
||||
// Target exposure (inverse of average luminance)
|
||||
float targetExposure = 1.0 / max(avg, 0.001);
|
||||
|
||||
// Read previous exposure for temporal smoothing (single thread)
|
||||
float prevExposure = imageLoad(img_exposureTex, ivec2(0, 0)).r;
|
||||
if (prevExposure <= 0.0) prevExposure = 1.0;
|
||||
|
||||
float adapted = mix(prevExposure, targetExposure, SMOOTH_EXPOSURE);
|
||||
adapted = clamp(adapted, 0.01, 100.0);
|
||||
|
||||
imageStore(img_exposureTex, ivec2(0, 0), vec4(adapted));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// MinecraftPT — IRC_CS (Irradiance Cache Update)
|
||||
// Updates the 3D irradiance cache: traces a few rays per cell toward the sky,
|
||||
// stores ambient + direct light contributions, blends over time.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/ShadowTracing.glsl"
|
||||
#include "/Lib/BasicFunctions/PrecomputedAtmosphere.glsl"
|
||||
|
||||
#ifdef PT_IRC
|
||||
|
||||
|
||||
const ivec3 workGroups = ivec3(int(ceil(float(ircResolution) / 4.0)));
|
||||
layout (local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
|
||||
|
||||
layout (rgba16f) uniform writeonly image3D img_irradianceCache3D;
|
||||
layout (rgba16f) uniform readonly image3D img_irradianceCache3D_Alt;
|
||||
|
||||
uniform sampler3D voxelData3D;
|
||||
|
||||
void main(){
|
||||
ivec3 texel = ivec3(gl_GlobalInvocationID.xyz);
|
||||
|
||||
if (any(greaterThanEqual(texel, ivec3(ircResolution)))){
|
||||
return;
|
||||
}
|
||||
|
||||
// World position of this cache cell
|
||||
vec3 cellPos = (vec3(texel) + 0.5) / float(ircResolution);
|
||||
vec3 worldPos = (cellPos - 0.5) * voxelDistance + cameraPosition;
|
||||
|
||||
// Voxel occupancy check — don't cache inside solid blocks
|
||||
vec3 voxelCoord = cellPos * voxelResolution;
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 1.0))), 0);
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
|
||||
if (voxelID > 1.0 && voxelID < 999.0){
|
||||
// Solid — keep old value
|
||||
return;
|
||||
}
|
||||
|
||||
// Sample sky irradiance from multiple directions (hemisphere)
|
||||
vec3 irradiance = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < PT_IRC_SPP; i++){
|
||||
// Deterministic sample directions over hemisphere
|
||||
float phi = 6.28318 * hash1(vec3(texel) + float(i) * 1.7);
|
||||
float cosTheta = hash1(vec3(texel) * 2.0 + float(i) * 3.1);
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
|
||||
vec3 dir = vec3(cos(phi) * sinTheta, cosTheta, sin(phi) * sinTheta);
|
||||
|
||||
// Trace toward sky — if not blocked, add sky light
|
||||
vec3 voxelPos = WorldToVoxel(worldPos) + dir * 0.5;
|
||||
float visibility = SimpleShadowTracing(voxelPos, dir);
|
||||
|
||||
// Sky radiance in this direction (analytic)
|
||||
vec3 skyRadiance = GetSkyRadiance(dir, GetSunDirWorld());
|
||||
|
||||
irradiance += skyRadiance * visibility;
|
||||
}
|
||||
|
||||
irradiance /= float(PT_IRC_SPP);
|
||||
|
||||
// Sun contribution (direct)
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
float sunVis = SimpleShadowTracing(WorldToVoxel(worldPos), sunDir);
|
||||
irradiance += GetSunIrradiance() * sunVis * max(sunDir.y, 0.0);
|
||||
|
||||
// Blend with previous (temporal smoothing), ping-pong by frame parity
|
||||
bool evenFrame = (frameCounter % 2) == 0;
|
||||
vec3 prev = evenFrame
|
||||
? texelFetch(img_irradianceCache3D_Alt, texel, 0).rgb
|
||||
: texelFetch(img_irradianceCache3D, texel, 0).rgb;
|
||||
irradiance = mix(prev, irradiance, PT_IRC_BLENDWEIGHT);
|
||||
|
||||
if (evenFrame){
|
||||
imageStore(img_irradianceCache3D, texel, vec4(irradiance, 1.0));
|
||||
}else{
|
||||
imageStore(img_irradianceCache3D_Alt, texel, vec4(irradiance, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
// MinecraftPT — MotionBlur_FS
|
||||
// Per-pixel camera motion blur using motion vectors.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
|
||||
uniform sampler2D colortex12;
|
||||
uniform sampler2D colortex10;
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
|
||||
vec3 color = texelFetch(colortex12, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
#ifdef MOTION_BLUR
|
||||
if (MOTION_BLUR > 0){
|
||||
vec2 motion = texelFetch(colortex10, ivec2(texelCoord * 0.5), 0).xy * 2.0;
|
||||
float speed = length(motion);
|
||||
|
||||
if (speed > 0.5){
|
||||
// Shutter angle sampling
|
||||
float shutterAngle = mix(90.0, 360.0, MOTION_BLUR_SUTTER_SPEED);
|
||||
float samples = float(MOTION_BLUR_QUALITY);
|
||||
float dither = BlueNoiseTemporal();
|
||||
|
||||
vec2 dir = normalize(motion);
|
||||
float length = min(speed, 32.0) * 0.5;
|
||||
|
||||
vec3 acc = vec3(0.0);
|
||||
for (int i = 0; i < MOTION_BLUR_QUALITY; i++){
|
||||
float t = (float(i) + dither) / samples - 0.5;
|
||||
vec2 sampleCoord = texelCoord + dir * length * t;
|
||||
acc += textureLod(colortex12, sampleCoord / screenSize, 0.0).rgb;
|
||||
}
|
||||
|
||||
color = acc / samples;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// MinecraftPT — SH_Tracing_CS
|
||||
// Low-order spherical-harmonics sky tracing: evaluates sky radiance on a small
|
||||
// SH basis and stores it for ambient light estimation (used by IRC seeding).
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/BasicFunctions/PrecomputedAtmosphere.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/ShadowTracing.glsl"
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
|
||||
#ifdef PT_IRC
|
||||
|
||||
|
||||
const ivec3 workGroups = ivec3(int(ceil(float(ircResolution) / 4.0)));
|
||||
layout (local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
|
||||
|
||||
layout (rgba16f) uniform writeonly image3D img_irradianceCache3D;
|
||||
layout (rgba16f) uniform readonly image3D img_irradianceCache3D_Alt;
|
||||
|
||||
uniform sampler3D voxelData3D;
|
||||
|
||||
// SH basis Y1 (linear, 3 components) coefficients for sky radiance at a cell
|
||||
void main(){
|
||||
ivec3 texel = ivec3(gl_GlobalInvocationID.xyz);
|
||||
|
||||
if (any(greaterThanEqual(texel, ivec3(ircResolution)))){
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 cellPos = (vec3(texel) + 0.5) / float(ircResolution);
|
||||
vec3 worldPos = (cellPos - 0.5) * voxelDistance + cameraPosition;
|
||||
|
||||
vec3 voxelCoord = cellPos * voxelResolution;
|
||||
vec4 voxelData = texelFetch(voxelData3D, ivec3(clamp(voxelCoord, vec3(0.0), vec3(voxelResolution - 1.0))), 0);
|
||||
float voxelID = DecodeVoxelID(voxelData.z);
|
||||
|
||||
if (voxelID > 1.0 && voxelID < 999.0){
|
||||
return;
|
||||
}
|
||||
|
||||
// Trace N directions, accumulate SH coefficients
|
||||
vec3 sh = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < 6; i++){
|
||||
float phi = 6.28318 * hash1(vec3(texel) * 1.3 + float(i) * 0.7);
|
||||
float cosTheta = hash1(vec3(texel) * 0.7 + float(i) * 1.9);
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
|
||||
vec3 dir = vec3(cos(phi) * sinTheta, cosTheta, sin(phi) * sinTheta);
|
||||
|
||||
float visibility = SimpleShadowTracing(WorldToVoxel(worldPos) + dir * 0.5, dir);
|
||||
|
||||
vec3 radiance = GetSkyRadiance(dir, GetSunDirWorld());
|
||||
|
||||
sh += radiance * visibility * cosTheta; // cos-weighted
|
||||
}
|
||||
|
||||
sh /= 6.0;
|
||||
|
||||
imageStore(img_irradianceCache3D, texel, vec4(sh, 1.0));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
// MinecraftPT — SkyImage_CS
|
||||
// Precomputes the sky panorama (skyBox2D, 3:2 cubemap cross) using the analytic
|
||||
// atmosphere model, for sampling by the path tracer and reflections.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/BasicFunctions/PrecomputedAtmosphere.glsl"
|
||||
#include "/Lib/IndividualFunctions/EndSky.glsl"
|
||||
#include "/Lib/IndividualFunctions/PlanarClouds.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(int(ceil(float(SKYBOX_RESOLUTION_X) / 8.0)), int(ceil(float(SKYBOX_RESOLUTION_Y) / 8.0)), 1);
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
layout (rgba16f) uniform writeonly image2D img_skyBox2D;
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
// Panorama layout: 3:2 cross (like a cubemap cross folded)
|
||||
vec2 resolution = vec2(SKYBOX_RESOLUTION_X, SKYBOX_RESOLUTION_Y);
|
||||
vec2 uv = (vec2(texel) + 0.5) / resolution;
|
||||
|
||||
// Determine face and local UV
|
||||
float tileX = SKYBOX_RESOLUTION / resolution.x; // 1/3
|
||||
float tileY = SKYBOX_RESOLUTION / resolution.y; // 1/2
|
||||
|
||||
int face = int(floor(uv.x / tileX));
|
||||
vec2 faceUV = vec2(
|
||||
(uv.x - float(face) * tileX) / tileX,
|
||||
(uv.y - float(face < 3 ? 0 : 1) * tileY) / tileY
|
||||
);
|
||||
faceUV = faceUV * 2.0 - 1.0;
|
||||
|
||||
// Cubemap cross mapping (Standard OpenGL cross layout, 4x3 grid):
|
||||
// faces: 0=+X, 1=-X, 2=+Y, 3=-Y, 4=+Z, 5=-Z (top row: +X -X +Y; bottom row: -Y +Z -Z)
|
||||
// This panorama is a 3x2 layout, so: top row = +X, -X, +Y; bottom row = -Y, +Z, -Z
|
||||
vec3 dir;
|
||||
if (face == 0){ // +X
|
||||
dir = vec3(1.0, -faceUV.y, -faceUV.x);
|
||||
}else if (face == 1){ // -X
|
||||
dir = vec3(-1.0, -faceUV.y, faceUV.x);
|
||||
}else if (face == 2){ // +Y
|
||||
dir = vec3(faceUV.x, 1.0, -faceUV.y);
|
||||
}else if (face == 3){ // -Y
|
||||
dir = vec3(faceUV.x, -1.0, faceUV.y);
|
||||
}else if (face == 4){ // +Z
|
||||
dir = vec3(faceUV.x, -faceUV.y, 1.0);
|
||||
}else{ // -Z
|
||||
dir = vec3(-faceUV.x, -faceUV.y, -1.0);
|
||||
}
|
||||
|
||||
dir = normalize(dir);
|
||||
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
|
||||
// Sky radiance from analytic atmosphere
|
||||
vec3 color = GetSkyRadiance(dir, sunDir);
|
||||
|
||||
// Stars at night
|
||||
float night = 1.0 - curve(saturate(sunDir.y * 10.0 + 0.5));
|
||||
if (night > 0.5){
|
||||
float stars = 0.0;
|
||||
vec3 starSeed = floor(dir * 64.0);
|
||||
float star = hash1(starSeed);
|
||||
stars = step(0.998, star) * 2.0;
|
||||
color += vec3(1.0, 1.0, 1.0) * stars * night;
|
||||
}
|
||||
|
||||
// End dimension sky
|
||||
#ifdef DIMENSION_END
|
||||
color = GetEndSky(dir, sunDir);
|
||||
#endif
|
||||
|
||||
imageStore(img_skyBox2D, texel, vec4(color, 0.0));
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// MinecraftPT — Sky_End_FS
|
||||
// End dimension sky rendering pass.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/IndividualFunctions/EndSky.glsl"
|
||||
|
||||
uniform sampler2D depthtex0;
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float depth = texelFetch(depthtex0, texelCoord, 0).r;
|
||||
if (depth < 1.0){
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(texelCoord) / screenSize * 2.0 - 1.0, 1.0, 1.0);
|
||||
vec3 viewDir = normalize(viewPos.xyz / viewPos.w);
|
||||
vec3 worldDir = normalize(mat3(gbufferModelViewInverse) * viewDir);
|
||||
|
||||
vec3 color = GetEndSky(worldDir, GetSunDirWorld());
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// MinecraftPT — Sky_Overworld_FS
|
||||
// Renders the sky into the background (colortex12) where no geometry was drawn.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/BasicFunctions/PrecomputedAtmosphere.glsl"
|
||||
#include "/Lib/IndividualFunctions/EndSky.glsl"
|
||||
#include "/Lib/IndividualFunctions/PlanarClouds.glsl"
|
||||
#include "/Lib/IndividualFunctions/CloudShadow.glsl"
|
||||
|
||||
uniform sampler2D depthtex0;
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float depth = texelFetch(depthtex0, texelCoord, 0).r;
|
||||
if (depth < 1.0){
|
||||
// Not sky — preserve scene
|
||||
discard;
|
||||
}
|
||||
|
||||
// Reconstruct view ray
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(texelCoord) / screenSize * 2.0 - 1.0, 1.0, 1.0);
|
||||
vec3 viewDir = normalize(viewPos.xyz / viewPos.w);
|
||||
vec3 worldDir = normalize(mat3(gbufferModelViewInverse) * viewDir);
|
||||
|
||||
vec3 sunDir = GetSunDirWorld();
|
||||
|
||||
// Sky radiance
|
||||
vec3 color = GetSkyRadiance(worldDir, sunDir);
|
||||
|
||||
#ifdef DIMENSION_END
|
||||
color = GetEndSky(worldDir, sunDir);
|
||||
#elif defined DIMENSION_NETHER
|
||||
// Nether: dark smoky red-brown atmosphere
|
||||
color = vec3(0.18, 0.06, 0.03) * 1.2;
|
||||
color += vec3(0.5, 0.2, 0.1) * 0.3 * (1.0 - abs(worldDir.y) * 0.5);
|
||||
#endif
|
||||
|
||||
// Planar clouds
|
||||
#ifdef PLANAR_CLOUDS
|
||||
if (PLANAR_CLOUDS > 0){
|
||||
// Ray-plane intersection with cloud layer
|
||||
float cloudAlt = mix(PC_ALTITUDE, CLOUD_CLEAR_ALTITUDE, wetness * 0.5);
|
||||
if (worldDir.y > 0.001){
|
||||
float t = (cloudAlt - cameraPosition.y) / worldDir.y;
|
||||
if (t > 0.0){
|
||||
vec3 cloudPos = cameraPosition + worldDir * t;
|
||||
vec3 cloudColor;
|
||||
float cloudDensity = GetPlanarCloudDensity(cloudPos.xz, frameTimeCounter * CLOUD_SPEED, cloudColor);
|
||||
|
||||
if (cloudDensity > 0.01){
|
||||
// Soft cloud edge
|
||||
vec3 cloudLight = mix(GetCloudAtmoIrradiance(), GetCloudSunIrradiance(), 0.8);
|
||||
color = mix(color, cloudLight, cloudDensity * 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
// MinecraftPT — Soild_FS (Main Lighting Composite)
|
||||
// Combines GBuffer data with path-traced diffuse + specular, direct sun,
|
||||
// held light, emission, and ambient to produce the final HDR scene.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/GbufferData.glsl"
|
||||
#include "/Lib/BasicFunctions/Blocklight.glsl"
|
||||
#include "/Lib/BasicFunctions/HeldLight.glsl"
|
||||
#include "/Lib/BasicFunctions/Sunlight_Shadow.glsl"
|
||||
#include "/Lib/BasicFunctions/NetherColor.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/SampleIRC.glsl"
|
||||
|
||||
uniform sampler2D colortex7; // diffuse PT (denoised)
|
||||
uniform sampler2D colortex11; // specular PT (denoised)
|
||||
uniform sampler2D colortex8; // previous diffuse (for blending)
|
||||
uniform sampler2D colortex12; // combined HDR (for historical blend)
|
||||
|
||||
layout(location = 0) out vec4 colorOut; // colortex12
|
||||
|
||||
void main(){
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
// Skip sky — sky was written by composite20 (Sky_Overworld_FS) into colortex12
|
||||
float depth = texelFetch(depthtex0, texelCoord, 0).r;
|
||||
if (depth >= 1.0){
|
||||
discard;
|
||||
}
|
||||
|
||||
// Read GBuffer
|
||||
GbufferData gbuffer = GetGbufferDataSoild(texelCoord);
|
||||
MaterialMask mask = CalculateMasks(gbuffer.materialID);
|
||||
|
||||
vec3 worldNormal = gbuffer.worldNormal;
|
||||
vec3 vertexNormal = gbuffer.vertexNormal;
|
||||
vec3 albedo = gbuffer.albedo;
|
||||
vec2 lightmap = gbuffer.lightmap;
|
||||
|
||||
// Reconstruct world position
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(texelCoord) / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
|
||||
|
||||
// Path-traced diffuse (from half-res colortex6, sampled at full res)
|
||||
vec2 halfCoord = vec2(texelCoord) * 0.5;
|
||||
vec3 diffusePT = textureLod(colortex7, halfCoord / (screenSize * 0.5), 0.0).rgb;
|
||||
|
||||
// Path-traced specular
|
||||
vec3 specularPT = textureLod(colortex11, halfCoord / (screenSize * 0.5), 0.0).rgb;
|
||||
|
||||
// Direct sunlight
|
||||
vec3 sunLight = GetSunlight(viewPos.xyz, worldPos, vertexNormal, worldNormal, lightmap.x);
|
||||
|
||||
// Block light
|
||||
vec3 blockLight = Blocklight(lightmap) * gbuffer.material.emissiveness;
|
||||
|
||||
// Emission from GBuffer
|
||||
vec3 emission = vec3(0.0);
|
||||
emission = texelFetch(colortex0, texelCoord, 0).a * 2.0;
|
||||
|
||||
// Held light
|
||||
float heldShadow = 1.0;
|
||||
vec3 heldLight = GetHeldLight(worldPos, worldNormal, heldShadow);
|
||||
|
||||
// IRC ambient
|
||||
vec3 irc = SampleIRC(worldPos) * 0.3;
|
||||
|
||||
// Combine:
|
||||
// diffuse = albedo * (sun + block + irc + held) + diffusePT
|
||||
// specular = specularPT
|
||||
// emission = emission
|
||||
// HDR output
|
||||
|
||||
vec3 color = vec3(0.0);
|
||||
|
||||
// Diffuse
|
||||
color += albedo * (sunLight + blockLight + irc) * (1.0 - gbuffer.material.metalness);
|
||||
color += albedo * heldLight * heldShadow * gbuffer.material.roughness;
|
||||
|
||||
// Path-traced diffuse contribution (indirect GI)
|
||||
color += diffusePT * albedo * 0.5;
|
||||
|
||||
// Specular
|
||||
color += specularPT * gbuffer.material.reflectionStrength;
|
||||
|
||||
// Emission
|
||||
color += emission;
|
||||
|
||||
// Fresnel-based specular from direct light
|
||||
float NdotV = max(dot(worldNormal, normalize(-viewPos.xyz)), 0.0);
|
||||
float F0 = gbuffer.material.metalness;
|
||||
vec3 fresnel = FresnelSchlick(NdotV, vec3(F0));
|
||||
|
||||
// Direct specular (sun)
|
||||
float NdotL = max(dot(worldNormal, GetSunDirWorld()), 0.0);
|
||||
if (NdotL > 0.0){
|
||||
float roughness = gbuffer.material.roughness;
|
||||
vec3 halfVec = normalize(GetSunDirWorld() + normalize(-viewPos.xyz));
|
||||
float NdotH = max(dot(worldNormal, halfVec), 0.0);
|
||||
float D = GGX_D(NdotH, roughness);
|
||||
float G = Smith_G(NdotV, NdotL, roughness);
|
||||
vec3 specular = fresnel * D * G / (4.0 * NdotV * NdotL + 0.0001);
|
||||
color += GetSunIrradiance() * specular * NdotL * 0.5;
|
||||
}
|
||||
|
||||
// Apply parallax shadow
|
||||
color *= gbuffer.parallaxShadow;
|
||||
|
||||
// Sky mask: if sky, output 0
|
||||
if (mask.sky > 0.5) color = vec3(0.0);
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// MinecraftPT — SpecularSpatial_FS
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Denoiser/SpecularSpatialFilter.glsl"
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
vec3 color = texelFetch(colortex11, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
int step = 1;
|
||||
#ifdef SPATIAL_STEP_2
|
||||
step = 2;
|
||||
#elif defined SPATIAL_STEP_4
|
||||
step = 4;
|
||||
#endif
|
||||
|
||||
color = SpecularSpatialPass(color, texelCoord, step);
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// MinecraftPT — SpecularTemporal_FS
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Denoiser/SpecularTemporalFilter.glsl"
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
vec3 current = texelFetch(colortex9, ivec2(texelCoord), 0).rgb;
|
||||
vec3 prev = texelFetch(colortex11, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
vec3 result = SpecularTemporalAccumulate(current, texelCoord);
|
||||
|
||||
colorOut = vec4(result, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// MinecraftPT — SpecularTracing_FS
|
||||
// Specular reflection path tracing at half resolution.
|
||||
// Output: colortex9 = noisy specular, colortex11 = history (ping-pong)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/GbufferData.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/TracingNoise.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/TracingUtilities.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/SpecularTracer.glsl"
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
|
||||
layout(location = 0) out vec4 specularOut;
|
||||
|
||||
void main(){
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
ivec2 fullCoord = texelCoord * 2;
|
||||
|
||||
float depth = texelFetch(depthtex0, fullCoord, 0).r;
|
||||
if (depth >= 1.0){
|
||||
specularOut = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 normalData = texelFetch(colortex1, fullCoord, 0);
|
||||
vec3 worldNormal = DecodeNormal(normalData.xy);
|
||||
vec4 materialData = texelFetch(colortex2, fullCoord, 0);
|
||||
|
||||
float roughness = 1.0 - materialData.r;
|
||||
roughness = roughness * roughness;
|
||||
float metalness = materialData.g;
|
||||
|
||||
// Skip rough non-metal surfaces when rough specular is disabled
|
||||
#if ENABLE_ROUGH_SPECULAR == 0
|
||||
if (roughness > 0.5 && metalness < 0.04){
|
||||
specularOut = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reconstruct view position
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(fullCoord) / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
|
||||
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
|
||||
vec3 viewDir = normalize(-viewPos.xyz);
|
||||
|
||||
vec2 noise = GetTracingNoise2(vec2(texelCoord), frameCounter, 1);
|
||||
|
||||
// Importance-sample GGX reflection direction
|
||||
vec3 reflDir = ImportanceSampleGGX(noise, worldNormal, roughness);
|
||||
|
||||
// Or use pure reflection for smooth surfaces
|
||||
if (roughness < 0.05){
|
||||
reflDir = reflect(-viewDir, worldNormal);
|
||||
}
|
||||
|
||||
// Trace the specular ray
|
||||
vec3 result = SpecularTrace(WorldToVoxel(worldPos + worldNormal * 0.02), reflDir, PT_SPECULAR_TRACING_DISTANCE, noise);
|
||||
|
||||
specularOut = vec4(result, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// MinecraftPT — TAA
|
||||
// Temporal anti-aliasing with jittered accumulation and neighborhood clamping.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
|
||||
uniform sampler2D colortex12; // HDR scene (current)
|
||||
uniform sampler2D colortex13; // previous frame HDR
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
layout(location = 1) out vec4 historyOut; // same result, stored for next frame
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
|
||||
vec3 current = texelFetch(colortex12, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
// Motion vector
|
||||
vec2 motion = texelFetch(colortex10, ivec2(texelCoord * 0.5), 0).xy * 2.0;
|
||||
vec2 prevCoord = texelCoord + motion;
|
||||
|
||||
// Sample previous
|
||||
vec3 history = textureLod(colortex13, prevCoord / screenSize, 0.0).rgb;
|
||||
|
||||
// Neighborhood clamp
|
||||
vec3 minColor = history;
|
||||
vec3 maxColor = history;
|
||||
for (int i = -1; i <= 1; i++){
|
||||
for (int j = -1; j <= 1; j++){
|
||||
vec3 c = textureLod(colortex13, (prevCoord + vec2(i, j)) / screenSize, 0.0).rgb;
|
||||
minColor = min(minColor, c);
|
||||
maxColor = max(maxColor, c);
|
||||
}}
|
||||
history = clamp(history, minColor, maxColor);
|
||||
|
||||
// Subpixel sharpening
|
||||
float sharpening = TAA_SUBPIXEL_SHARPNING;
|
||||
current = current + (current - history) * sharpening * TAA_AGGRESSION;
|
||||
|
||||
float blend = TAA_BLENDWEIGHT;
|
||||
vec3 color = mix(current, history, blend);
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
historyOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
// MinecraftPT — Translucent_FS
|
||||
// Composites translucent geometry (water, glass, particles) on top of solid.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/GbufferData.glsl"
|
||||
#include "/Lib/BasicFunctions/Sunlight_Shadow.glsl"
|
||||
#include "/Lib/BasicFunctions/Blocklight.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/SampleIRC.glsl"
|
||||
#include "/Lib/PathTracing/Tracer/ShadowTracing.glsl"
|
||||
|
||||
uniform sampler2D colortex12; // combined HDR solid scene
|
||||
uniform sampler2D colortex4; // translucent albedo
|
||||
uniform sampler2D colortex5; // translucent normal
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float depth = texelFetch(depthtex0, texelCoord, 0).r;
|
||||
if (depth >= 1.0){
|
||||
colorOut = texelFetch(colortex12, texelCoord, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there is translucent data
|
||||
vec4 gbuffer5 = texelFetch(colortex5, texelCoord, 0);
|
||||
float matID = gbuffer5.a * 255.0;
|
||||
|
||||
if (matID < 0.5){
|
||||
colorOut = texelFetch(colortex12, texelCoord, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
bool isSmooth;
|
||||
GbufferData gbuffer = GetGbufferDataTranslucent(texelCoord, isSmooth);
|
||||
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(texelCoord) / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
|
||||
|
||||
vec3 solidColor = texelFetch(colortex12, texelCoord, 0).rgb;
|
||||
|
||||
// Water: blend with refraction
|
||||
vec3 color = solidColor;
|
||||
|
||||
if (matID == MATID_WATER){
|
||||
vec3 waterColor = gbuffer.albedo;
|
||||
float alpha = gbuffer.albedoAlpha;
|
||||
|
||||
// Fresnel
|
||||
vec3 viewDir = normalize(-viewPos.xyz);
|
||||
float NdotV = max(dot(gbuffer.worldNormal, viewDir), 0.0);
|
||||
float fresnel = 0.02 + 0.98 * pow(1.0 - NdotV, 5.0);
|
||||
|
||||
// Light contribution (sun + sky) on water
|
||||
vec3 sunLight = GetSunlight(viewPos.xyz, worldPos, gbuffer.vertexNormal, gbuffer.worldNormal, gbuffer.lightmap.x);
|
||||
vec3 waterLight = waterColor * (sunLight + Blocklight(gbuffer.lightmap) * 0.5);
|
||||
|
||||
// Water tint / depth color
|
||||
vec3 deepColor = waterColor * 0.3;
|
||||
|
||||
color = mix(solidColor, waterLight + deepColor, fresnel * 0.8 + 0.2);
|
||||
|
||||
}else if (matID == MATID_STAINEDGLASS){
|
||||
vec3 glassColor = gbuffer.albedo;
|
||||
float alpha = gbuffer.albedoAlpha;
|
||||
|
||||
vec3 viewDir = normalize(-viewPos.xyz);
|
||||
float NdotV = max(dot(gbuffer.worldNormal, viewDir), 0.0);
|
||||
float fresnel = 0.04 + 0.96 * pow(1.0 - NdotV, 5.0);
|
||||
|
||||
color = mix(solidColor, solidColor * glassColor, fresnel);
|
||||
color += glassColor * 0.1;
|
||||
|
||||
}else{
|
||||
// Particles etc — additively blend
|
||||
color = solidColor + gbuffer.albedo * gbuffer.albedoAlpha * 0.5;
|
||||
}
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// MinecraftPT — Volumetric_FS
|
||||
// Volumetric fog + volumetric clouds ray marched per-pixel and composited.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/LightingConstants.glsl"
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
#include "/Lib/IndividualFunctions/VolumetricFog.glsl"
|
||||
#include "/Lib/IndividualFunctions/WaterFog.glsl"
|
||||
#include "/Lib/IndividualFunctions/PlanarClouds.glsl"
|
||||
#include "/Lib/IndividualFunctions/CloudShadow.glsl"
|
||||
|
||||
uniform sampler2D colortex12; // HDR scene
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
vec2 texelCoord = gl_FragCoord.xy;
|
||||
vec3 sceneColor = texelFetch(colortex12, ivec2(texelCoord), 0).rgb;
|
||||
|
||||
float depth = texelFetch(depthtex0, ivec2(texelCoord), 0).r;
|
||||
|
||||
// Reconstruct view position
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(texelCoord / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
|
||||
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
|
||||
|
||||
// Dithering for the ray march
|
||||
float dither = BlueNoiseTemporal();
|
||||
|
||||
// Volumetric fog accumulation
|
||||
vec3 fogColor = vec3(0.0);
|
||||
float transmittance = 1.0;
|
||||
|
||||
// Ray march toward the surface
|
||||
int steps = VFOG_QUALITY;
|
||||
float dist = length(viewPos.xyz);
|
||||
float stepSize = dist / float(steps);
|
||||
|
||||
vec3 rayDir = normalize(viewPos.xyz);
|
||||
vec3 marchPos = worldPos;
|
||||
|
||||
float time = frameTimeCounter * 0.05;
|
||||
|
||||
for (int i = 0; i < steps; i++){
|
||||
float t = (float(i) + dither) * stepSize;
|
||||
vec3 samplePos = marchPos - rayDir * t;
|
||||
|
||||
float density = GetVolumetricFogDensity(samplePos, time);
|
||||
density *= stepSize;
|
||||
|
||||
// Sun scattering
|
||||
float phase = 0.5 + 0.5 * dot(normalize(GetSunDirWorld()), -rayDir);
|
||||
|
||||
vec3 inscatter = GetFogColor(samplePos, GetSunDirWorld()) * density * phase;
|
||||
|
||||
fogColor += transmittance * inscatter;
|
||||
transmittance *= exp(-density);
|
||||
}
|
||||
|
||||
// Cloud shadow on fog
|
||||
#ifdef VFOG_CLOUD_SHADOW
|
||||
float cloudShadow = GetCloudShadow(worldPos);
|
||||
fogColor *= cloudShadow;
|
||||
#endif
|
||||
|
||||
// Combine
|
||||
vec3 finalColor = sceneColor * transmittance + fogColor;
|
||||
|
||||
// Water fog (underwater)
|
||||
#ifdef UNDERWATER_VFOG
|
||||
if (isEyeInWater > 0){
|
||||
vec3 waterColor = GetWaterFogColor(worldPos);
|
||||
float waterFog = 1.0 - exp(-dist * GetWaterFogDensity(worldPos) * UNDERWATER_VFOG_DENSITY);
|
||||
finalColor = mix(finalColor, waterColor * 3.0, waterFog);
|
||||
}
|
||||
#endif
|
||||
|
||||
colorOut = vec4(finalColor, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// MinecraftPT — VoxelData_Copy compute shader
|
||||
// Copies the 2D voxel atlas (shadowcolor1) into the 3D voxel texture,
|
||||
// computing sparse-tracing empty markers for hierarchical ray skipping.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
|
||||
#if PT_VOXEL_RESOLUTION == 4004
|
||||
const ivec3 workGroups = ivec3(16, 16, 16);
|
||||
#elif PT_VOXEL_RESOLUTION == 6004
|
||||
const ivec3 workGroups = ivec3(24, 16, 24);
|
||||
#elif PT_VOXEL_RESOLUTION == 8004
|
||||
const ivec3 workGroups = ivec3(32, 16, 32);
|
||||
#elif PT_VOXEL_RESOLUTION == 8006
|
||||
const ivec3 workGroups = ivec3(32, 24, 32);
|
||||
#elif PT_VOXEL_RESOLUTION == 8008
|
||||
const ivec3 workGroups = ivec3(32, 32, 32);
|
||||
#elif PT_VOXEL_RESOLUTION == 12004
|
||||
const ivec3 workGroups = ivec3(48, 16, 48);
|
||||
#elif PT_VOXEL_RESOLUTION == 12006
|
||||
const ivec3 workGroups = ivec3(48, 24, 48);
|
||||
#elif PT_VOXEL_RESOLUTION == 12008
|
||||
const ivec3 workGroups = ivec3(48, 32, 48);
|
||||
#elif PT_VOXEL_RESOLUTION == 16004
|
||||
const ivec3 workGroups = ivec3(64, 16, 64);
|
||||
#elif PT_VOXEL_RESOLUTION == 16008
|
||||
const ivec3 workGroups = ivec3(64, 32, 64);
|
||||
#elif PT_VOXEL_RESOLUTION == 16016
|
||||
const ivec3 workGroups = ivec3(64, 64, 64);
|
||||
#else
|
||||
const ivec3 workGroups = ivec3(32, 24, 32);
|
||||
#endif
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
|
||||
|
||||
layout (rgba16) uniform writeonly image3D img_voxelData3D;
|
||||
|
||||
#ifdef PT_SPARE_TRACING
|
||||
shared uint isOccupied_8;
|
||||
shared uint isOccupied_4[8];
|
||||
shared uint isOccupied_2[64];
|
||||
#endif
|
||||
|
||||
uniform sampler2D shadowcolor1;
|
||||
|
||||
void main(){
|
||||
#ifdef PT_SPARE_TRACING
|
||||
int id_4 = int((gl_LocalInvocationID.x >> 2u) + (gl_LocalInvocationID.y >> 2u) * 2u + (gl_LocalInvocationID.z >> 2u) * 4u);
|
||||
int id_2 = int((gl_LocalInvocationID.x >> 1u) + (gl_LocalInvocationID.y >> 1u) * 4u + (gl_LocalInvocationID.z >> 2u) * 16u);
|
||||
|
||||
isOccupied_8 = 0u;
|
||||
isOccupied_4[id_4] = 0u;
|
||||
isOccupied_2[id_2] = 0u;
|
||||
|
||||
barrier();
|
||||
#endif
|
||||
|
||||
ivec3 drawTexel = ivec3(gl_GlobalInvocationID.xyz);
|
||||
ivec2 voxelTexel = ivec2(VoxelTexel_From_VoxelCoord(vec3(drawTexel)));
|
||||
|
||||
vec4 voxelData = texelFetch(shadowcolor1, voxelTexel, 0);
|
||||
|
||||
// A texel with z >= 1.0 is empty (clear color)
|
||||
if (voxelData.z >= 1.0){
|
||||
voxelData = vec4(0.0, 0.0, 1.0, 1.0); // empty voxel: encoded ID = 1.0 (air)
|
||||
}
|
||||
|
||||
#ifdef PT_SPARE_TRACING
|
||||
uint occupied = uint(voxelData.z < 0.999);
|
||||
|
||||
atomicMax(isOccupied_8, occupied);
|
||||
barrier();
|
||||
|
||||
if (isOccupied_8 == 0u){
|
||||
voxelData.z = 0.91; // 8^3 empty marker
|
||||
}else{
|
||||
atomicMax(isOccupied_4[id_4], occupied);
|
||||
barrier();
|
||||
if (isOccupied_4[id_4] == 0u){
|
||||
voxelData.z = 0.71; // 4^3 empty marker
|
||||
}else{
|
||||
atomicMax(isOccupied_2[id_2], occupied);
|
||||
barrier();
|
||||
if (isOccupied_2[id_2] == 0u)
|
||||
voxelData.z = 0.61; // 2^3 empty marker
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
imageStore(img_voxelData3D, drawTexel, voxelData);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// MinecraftPT — WaterRefraction_FS
|
||||
// Water refraction pass: sample the solid scene with wave-based offset.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/GbufferData.glsl"
|
||||
#include "/Lib/IndividualFunctions/WaterWaves.glsl"
|
||||
|
||||
uniform sampler2D colortex12; // solid scene
|
||||
uniform sampler2D colortex4; // translucent albedo
|
||||
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
|
||||
void main(){
|
||||
ivec2 texelCoord = ivec2(gl_FragCoord.xy);
|
||||
|
||||
float depth = texelFetch(depthtex0, texelCoord, 0).r;
|
||||
if (depth >= 1.0){
|
||||
colorOut = texelFetch(colortex12, texelCoord, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 gbuffer5 = texelFetch(colortex5, texelCoord, 0);
|
||||
float matID = gbuffer5.a * 255.0;
|
||||
|
||||
if (matID != MATID_WATER){
|
||||
colorOut = texelFetch(colortex12, texelCoord, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reconstruct world position
|
||||
vec4 viewPos = gbufferProjectionInverse * vec4(vec2(texelCoord) / screenSize * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
|
||||
viewPos.xyz /= viewPos.w;
|
||||
vec3 worldPos = gbufferModelViewInverse[3].xyz + viewPos.xyz;
|
||||
|
||||
// Wave normal-based refraction offset
|
||||
vec3 waveNormal = GetWaveNormal(worldPos, 0.5);
|
||||
vec3 viewDir = normalize(-viewPos.xyz);
|
||||
vec3 refracted = refract(viewDir, waveNormal, 0.75);
|
||||
|
||||
// Sample the solid scene with the refraction offset
|
||||
vec3 refractedDir = mat3(gbufferModelView) * refracted;
|
||||
vec2 refractedCoord = viewPos.xy / viewPos.z * refractedDir.xy / refractedDir.z * 0.5 + 0.5;
|
||||
vec2 sampleCoord = refractedCoord * screenSize;
|
||||
|
||||
vec3 color = textureLod(colortex12, sampleCoord / screenSize, 0.0).rgb;
|
||||
|
||||
// Water depth color fade
|
||||
vec3 waterColor = texelFetch(colortex4, texelCoord, 0).rgb;
|
||||
color = mix(color, waterColor, 0.3);
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// MinecraftPT — Final_FS
|
||||
// HDR tonemapping, color grading, dithering, and output to screen.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
||||
|
||||
uniform sampler2D exposureTex;
|
||||
|
||||
#if defined PROGRAM_FINAL_0
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
#elif defined PROGRAM_FINAL_1
|
||||
layout(location = 0) out vec4 colorOut;
|
||||
#endif
|
||||
|
||||
// Tonemapping operators
|
||||
vec3 TonemapACES(vec3 color){
|
||||
// ACES filmic
|
||||
float a = 2.51;
|
||||
float b = 0.03;
|
||||
float c = 2.43;
|
||||
float d = 0.59;
|
||||
float e = 0.14;
|
||||
return saturate((color * (a * color + b)) / (color * (c * color + d) + e));
|
||||
}
|
||||
|
||||
vec3 TonemapAGX(vec3 color){
|
||||
// AGX-inspired: log-shaping curve
|
||||
vec3 logColor = log2(max(color, 1e-6));
|
||||
vec3 mid = vec3(AGX_HDR_MIDGREY);
|
||||
vec3 shaped = logColor - mid;
|
||||
shaped = tanh(shaped * 0.5) * 0.5 + 0.5;
|
||||
vec3 result = exp2(shaped + mid);
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3 TonemapFilmic(vec3 color){
|
||||
// Uncharted 2 filmic
|
||||
vec3 x = max(color, 0.0);
|
||||
return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);
|
||||
}
|
||||
|
||||
// Color grading
|
||||
vec3 ApplyColorGrading(vec3 color){
|
||||
// White/black point
|
||||
color = (color - BLACK_POINT) / (WHITE_POINT - BLACK_POINT + 1e-6);
|
||||
|
||||
// Saturation
|
||||
float lum = luminance(color);
|
||||
color = mix(vec3(lum), color, SATURATION);
|
||||
|
||||
// Gamma
|
||||
color = pow(color, vec3(GAMMA));
|
||||
|
||||
// Hue shifts (simplified)
|
||||
#ifdef ADVANCED_COLOR
|
||||
vec3 midtone = color * MIDTONE_HUE * MIDTONE_STRENGTH;
|
||||
vec3 highlight = color * HIGHLIGHT_HUE * HIGHLIGHT_STRENGTH;
|
||||
vec3 shadow = color * SHADOW_HUE * SHADOW_STRENGTH;
|
||||
color += midtone + highlight + shadow;
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void main(){
|
||||
vec3 color = texelFetch(colortex12, ivec2(gl_FragCoord.xy), 0).rgb;
|
||||
|
||||
// Exposure
|
||||
#ifdef MANUAL_EXPOSURE
|
||||
float exposure = MANUAL_EXPOSURE * pow(2.0, EV_VALUE);
|
||||
#else
|
||||
float exposure = textureLod(exposureTex, vec2(0.5), 0.0).r;
|
||||
#endif
|
||||
color *= exposure;
|
||||
|
||||
// Bloom composite
|
||||
#ifdef BLOOM
|
||||
vec3 bloom = vec3(0.0);
|
||||
// Simple bloom: sample from bloom buffer
|
||||
bloom = textureLod(colortex15, gl_FragCoord.xy / screenSize, 0.0).rgb;
|
||||
color += bloom * BLOOM_AMOUNT;
|
||||
#endif
|
||||
|
||||
// Tonemapping
|
||||
#if TONEMAP_OPERATOR == 0
|
||||
color = TonemapACES(color);
|
||||
#elif TONEMAP_OPERATOR == 1
|
||||
color = TonemapAGX(color);
|
||||
#elif TONEMAP_OPERATOR == 2
|
||||
color = TonemapFilmic(color);
|
||||
#else
|
||||
// Vanilla-like: Reinhard
|
||||
color = color / (color + 1.0);
|
||||
#endif
|
||||
|
||||
// Color grading
|
||||
color = ApplyColorGrading(color);
|
||||
|
||||
// Dithering
|
||||
vec2 noise = BlueNoiseTemporal2();
|
||||
color += (noise - 0.5) / 255.0;
|
||||
|
||||
// Gamma correction
|
||||
color = LinearToGamma(color);
|
||||
|
||||
colorOut = vec4(color, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// MinecraftPT — Armor Glint Fragment Shader (enchanted armor shimmer)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
// Glint is additive-ish; store with high specular
|
||||
colortex0Out = vec4(albedo.rgb, 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 6.0 / 255.0);
|
||||
colortex3Out = vec4(lightmap, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// MinecraftPT — Basic Fragment Shader (untextured geometry, e.g. clouds, selection)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
flat in int blockId;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = color;
|
||||
|
||||
#ifdef IS_SELECTION
|
||||
float matID = 19.0 / 255.0; // MATID_SELECTION
|
||||
#else
|
||||
float matID = 0.0;
|
||||
#endif
|
||||
|
||||
colortex0Out = vec4(albedo.rgb, 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, matID);
|
||||
colortex3Out = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// MinecraftPT — Beacon Beam Fragment Shader (emissive beam)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
colortex0Out = vec4(albedo.rgb, 1.0); // fully emissive
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
colortex3Out = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// MinecraftPT — Composite_Copy_CS
|
||||
// Copies the full-res GBuffer into the half-res working buffers used by the
|
||||
// path tracing passes (simplified: keeps full-res, pass-through for layout parity).
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
uniform sampler2D colortex0;
|
||||
uniform sampler2D colortex1;
|
||||
uniform sampler2D colortex3;
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
// Pass-through (identity copy for pipeline parity)
|
||||
// In a full implementation this would downsample to half-res buffers.
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// MinecraftPT — Damaged Block Fragment Shader
|
||||
// Handles block damage cracks — same as terrain but with damage texture overlay
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/Programs/Gbuffers/Terrain_FS.glsl"
|
||||
@@ -0,0 +1,60 @@
|
||||
// MinecraftPT — Entities Fragment Shader
|
||||
// Handles entities (players, mobs), hands are in Hand_FS
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
flat in int blockId;
|
||||
flat in float blockLightLevel;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
uniform bool isPlayer;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
// Entity material ID — default entity
|
||||
float matID = 6.0; // MATID_ENTITIES
|
||||
|
||||
// Player special handling (OptiFine provides isPlayer uniform in entities pass)
|
||||
if (isPlayer){
|
||||
matID = 7.0; // MATID_ENTITIES_PLAYER
|
||||
}
|
||||
|
||||
vec4 specTex = vec4(0.0);
|
||||
#ifdef TEXTURE_PBR_FORMAT
|
||||
if (TEXTURE_PBR_FORMAT >= 1){
|
||||
specTex = texture(atlasSpecular2D, texcoord);
|
||||
}
|
||||
#endif
|
||||
|
||||
vec2 lm = lightmap;
|
||||
lm.y = SkyLightmapCurve(lightmap.y);
|
||||
|
||||
float emissive = 0.0;
|
||||
#ifdef VANILLA_EMISSIVE
|
||||
emissive = step(13.5, blockLightLevel) * blockLightLevel / 15.0;
|
||||
#endif
|
||||
|
||||
colortex0Out = vec4(albedo.rgb, emissive);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(specTex.r, specTex.g, specTex.b, matID / 255.0);
|
||||
colortex3Out = vec4(lm, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// MinecraftPT — Entities Vertex Shader
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
out vec2 texcoord;
|
||||
out vec3 worldPos;
|
||||
out vec3 worldNormal;
|
||||
out vec3 vertexNormal;
|
||||
out vec4 color;
|
||||
out vec2 lightmap;
|
||||
flat out int blockId;
|
||||
flat out float blockLightLevel;
|
||||
|
||||
void main(){
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 wPos = gbufferModelViewInverse * viewPos;
|
||||
worldPos = wPos.xyz;
|
||||
|
||||
vertexNormal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
worldNormal = normalize(mat3(gbufferModelViewInverse) * vertexNormal);
|
||||
|
||||
lightmap = gl_MultiTexCoord1.xy / 240.0;
|
||||
lightmap = saturate(lightmap);
|
||||
|
||||
blockId = int(mc_Entity.x + 0.5);
|
||||
blockLightLevel = at_midBlock.w;
|
||||
|
||||
texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
color = gl_Color;
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
gl_Position.xy += taaJitter * gl_Position.w;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// MinecraftPT — Generic Vertex Shader (entities, textured, line, weather, glints)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
out vec2 texcoord;
|
||||
out vec3 worldPos;
|
||||
out vec3 worldNormal;
|
||||
out vec3 vertexNormal;
|
||||
out vec4 color;
|
||||
out vec2 lightmap;
|
||||
flat out int blockId;
|
||||
flat out float blockLightLevel;
|
||||
|
||||
void main(){
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 wPos = gbufferModelViewInverse * viewPos;
|
||||
worldPos = wPos.xyz;
|
||||
|
||||
vertexNormal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
worldNormal = normalize(mat3(gbufferModelViewInverse) * vertexNormal);
|
||||
|
||||
lightmap = gl_MultiTexCoord1.xy / 240.0;
|
||||
lightmap = saturate(lightmap);
|
||||
|
||||
blockId = int(mc_Entity.x + 0.5);
|
||||
blockLightLevel = at_midBlock.w;
|
||||
|
||||
texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
color = gl_Color;
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
gl_Position.xy += taaJitter * gl_Position.w;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// MinecraftPT — Water Hand Vertex Shader (hand when submerged)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
out vec2 texcoord;
|
||||
out vec3 worldPos;
|
||||
out vec3 worldNormal;
|
||||
out vec3 vertexNormal;
|
||||
out vec4 color;
|
||||
out vec2 lightmap;
|
||||
|
||||
void main(){
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 wPos = gbufferModelViewInverse * viewPos;
|
||||
worldPos = wPos.xyz;
|
||||
|
||||
vertexNormal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
worldNormal = normalize(mat3(gbufferModelViewInverse) * vertexNormal);
|
||||
|
||||
lightmap = gl_MultiTexCoord1.xy / 240.0;
|
||||
lightmap = saturate(lightmap);
|
||||
|
||||
texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
color = gl_Color;
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
gl_Position.xy += taaJitter * gl_Position.w;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// MinecraftPT — Line Fragment Shader (debug lines, selection box)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
flat in int blockId;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
colortex0Out = vec4(color.rgb, 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 19.0 / 255.0); // MATID_SELECTION
|
||||
colortex3Out = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// MinecraftPT — Sky Vertex Shader
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
out vec2 texcoord;
|
||||
out vec3 worldPos;
|
||||
out vec4 color;
|
||||
|
||||
void main(){
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 wPos = gbufferModelViewInverse * viewPos;
|
||||
worldPos = wPos.xyz;
|
||||
|
||||
texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
color = gl_Color;
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// MinecraftPT — Sky Fragment Shader
|
||||
// Writes sky color into GBuffer with MATID_SKY so composite can identify it.
|
||||
// Custom sky is drawn in composite20 (Sky_Overworld_FS) over this.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec4 color;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
// Sky: mark with MATID_SKY
|
||||
colortex0Out = vec4(albedo.rgb, 0.0);
|
||||
colortex1Out = vec4(0.5);
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 10.0 / 255.0); // MATID_SKY
|
||||
colortex3Out = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// MinecraftPT — Spider Eyes Fragment Shader (emissive eyes)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
colortex0Out = vec4(albedo.rgb, albedo.r > 0.5 ? 1.0 : 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 6.0 / 255.0);
|
||||
colortex3Out = vec4(lightmap, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
// MinecraftPT — Terrain Fragment Shader
|
||||
// Writes the solid and translucent GBuffer
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
flat in int blockId;
|
||||
flat in float blockLightLevel;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out; // albedo + emissive
|
||||
layout(location = 1) out vec4 colortex1Out; // normals
|
||||
layout(location = 2) out vec4 colortex2Out; // spec + matID
|
||||
layout(location = 3) out vec4 colortex3Out; // lightmap
|
||||
layout(location = 4) out vec4 colortex4Out; // translucent albedo + alpha
|
||||
layout(location = 5) out vec4 colortex5Out; // translucent normal + matID
|
||||
|
||||
// Material IDs from block.properties
|
||||
#define BLOCK_LEAVES 1
|
||||
#define BLOCK_TRANSLUCENT 2
|
||||
#define BLOCK_WATER 3
|
||||
#define BLOCK_CROSS 4
|
||||
#define BLOCK_TORCH 5
|
||||
#define BLOCK_LANTERN 6
|
||||
#define BLOCK_FIRE 7
|
||||
#define BLOCK_CAMPFIRE 8
|
||||
#define BLOCK_LAVA 9
|
||||
#define BLOCK_GLASS_PANE 10
|
||||
#define BLOCK_IRON_BARS 11
|
||||
#define BLOCK_STAIRS 12
|
||||
#define BLOCK_SLAB 13
|
||||
#define BLOCK_WALL 14
|
||||
#define BLOCK_FENCE 15
|
||||
#define BLOCK_FENCE_GATE 16
|
||||
#define BLOCK_DOOR 17
|
||||
#define BLOCK_RAIL 18
|
||||
#define BLOCK_REDSTONE 19
|
||||
#define BLOCK_ENDROD 20
|
||||
#define BLOCK_CHAIN 21
|
||||
#define BLOCK_AMETHYST 22
|
||||
#define BLOCK_CANDLE 23
|
||||
#define BLOCK_GLOWSTONE 24
|
||||
#define BLOCK_LIGHT 25
|
||||
#define BLOCK_PORTAL 26
|
||||
#define BLOCK_LADDER 27
|
||||
#define BLOCK_SUGARCANE 28
|
||||
#define BLOCK_BAMBOO 29
|
||||
#define BLOCK_CACTUS 30
|
||||
#define BLOCK_CHORUS 31
|
||||
#define BLOCK_CORAL 32
|
||||
#define BLOCK_DRIPSTONE 33
|
||||
#define BLOCK_CONDUIT 34
|
||||
#define BLOCK_LIGHTNING_ROD 35
|
||||
#define BLOCK_POT 36
|
||||
#define BLOCK_SNOW_LAYERS 37
|
||||
#define BLOCK_COBWEB 80
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
// Cutout (alpha test)
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
// Material ID determination
|
||||
float matID = 0.0; // MATID_DEFAULT
|
||||
#ifdef IS_HAND
|
||||
matID = 5.0; // MATID_HAND
|
||||
#endif
|
||||
bool isTranslucent = false;
|
||||
|
||||
if (blockId == BLOCK_LEAVES){
|
||||
matID = 3.0; // MATID_LEAVES
|
||||
}else if (blockId == BLOCK_TRANSLUCENT){
|
||||
matID = 2.0; // MATID_STAINEDGLASS
|
||||
isTranslucent = true;
|
||||
}else if (blockId == BLOCK_WATER){
|
||||
matID = 1.0; // MATID_WATER (should be handled by gbuffers_water)
|
||||
isTranslucent = true;
|
||||
}else if (blockId == BLOCK_CROSS){
|
||||
matID = 4.0; // MATID_GRASS
|
||||
}else if (blockId == BLOCK_TORCH){
|
||||
matID = 11.0; // MATID_TORCH
|
||||
}else if (blockId == BLOCK_LANTERN){
|
||||
matID = 20.0; // MATID_COPPER_LANTERN
|
||||
}else if (blockId == BLOCK_FIRE || blockId == BLOCK_CAMPFIRE){
|
||||
matID = 12.0; // MATID_FIRE
|
||||
}else if (blockId == BLOCK_LAVA){
|
||||
matID = 12.0;
|
||||
}else if (blockId == BLOCK_GLASS_PANE){
|
||||
matID = 2.0; // MATID_STAINEDGLASS
|
||||
isTranslucent = true;
|
||||
}else if (blockId == BLOCK_ENDROD){
|
||||
matID = 13.0; // MATID_ENDROD
|
||||
}else if (blockId == BLOCK_AMETHYST){
|
||||
matID = 14.0; // MATID_AMETHYST
|
||||
}else if (blockId == BLOCK_PORTAL){
|
||||
matID = 18.0; // MATID_END_PORTAL
|
||||
}else if (blockId == BLOCK_COBWEB){
|
||||
matID = 17.0; // MATID_PARTICLE-like
|
||||
isTranslucent = true;
|
||||
}
|
||||
|
||||
// Emissive detection
|
||||
float emissive = 0.0;
|
||||
#ifdef HARDCODED_EMISSIVENESS_MODE
|
||||
if (blockId == BLOCK_LAVA || blockId == BLOCK_FIRE || blockId == BLOCK_CAMPFIRE ||
|
||||
blockId == BLOCK_GLOWSTONE || blockId == BLOCK_ENDROD || blockId == BLOCK_LANTERN ||
|
||||
blockId == BLOCK_AMETHYST || blockId == BLOCK_TORCH || blockId == BLOCK_CANDLE ||
|
||||
blockId == BLOCK_LIGHT || blockId == BLOCK_CONDUIT){
|
||||
emissive = 1.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VANILLA_EMISSIVE
|
||||
// Emissive blocks from vanilla light level (at_midBlock.w = 0-15)
|
||||
emissive = max(emissive, step(13.5, blockLightLevel) * blockLightLevel / 15.0);
|
||||
#endif
|
||||
|
||||
// LAB PBR specular
|
||||
vec4 specTex = vec4(0.0);
|
||||
#ifdef TEXTURE_PBR_FORMAT
|
||||
if (TEXTURE_PBR_FORMAT >= 1 && blockId != BLOCK_WATER){
|
||||
specTex = texture(atlasSpecular2D, texcoord);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Lightmap
|
||||
vec2 lm = lightmap;
|
||||
lm.y = SkyLightmapCurve(lightmap.y);
|
||||
|
||||
// Parallax shadow (POM)
|
||||
float parallaxShadow = 1.0;
|
||||
|
||||
// Encode normals (octahedral)
|
||||
vec2 worldNormalEnc = EncodeNormal(worldNormal);
|
||||
vec2 vertexNormalEnc = EncodeNormal(vertexNormal);
|
||||
|
||||
// Solid write
|
||||
colortex0Out = vec4(albedo.rgb, emissive);
|
||||
colortex1Out = vec4(worldNormalEnc, vertexNormalEnc);
|
||||
colortex2Out = vec4(specTex.r, specTex.g, specTex.b, matID / 255.0);
|
||||
colortex3Out = vec4(lm, parallaxShadow, 1.0);
|
||||
|
||||
// Translucent write (glass, panes, cobweb)
|
||||
if (isTranslucent){
|
||||
colortex4Out = vec4(albedo.rgb, albedo.a);
|
||||
colortex5Out = vec4(worldNormalEnc, matID / 255.0, specTex.r);
|
||||
}else{
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// MinecraftPT — Terrain Vertex Shader
|
||||
// Handles terrain, block entities, damaged blocks
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
out vec2 texcoord;
|
||||
out vec3 worldPos;
|
||||
out vec3 worldNormal;
|
||||
out vec3 vertexNormal;
|
||||
out vec4 color;
|
||||
out vec2 lightmap;
|
||||
flat out int blockId;
|
||||
flat out float blockLightLevel;
|
||||
|
||||
#ifdef WAVING_PLANTS
|
||||
#include "/Lib/IndividualFunctions/WavingPlants.glsl"
|
||||
#endif
|
||||
|
||||
void main(){
|
||||
// World position
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 wPos = gbufferModelViewInverse * viewPos;
|
||||
worldPos = wPos.xyz;
|
||||
|
||||
// Normals
|
||||
vertexNormal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
worldNormal = normalize(mat3(gbufferModelViewInverse) * vertexNormal);
|
||||
worldNormal = normalize(worldNormal);
|
||||
|
||||
// Lightmap (blocklight, skylight)
|
||||
lightmap = gl_MultiTexCoord1.xy / 240.0;
|
||||
lightmap = saturate(lightmap);
|
||||
|
||||
// Block ID from mc_Entity
|
||||
blockId = int(mc_Entity.x + 0.5);
|
||||
blockLightLevel = at_midBlock.w;
|
||||
|
||||
// Waving plants
|
||||
#ifdef WAVING_PLANTS
|
||||
if (blockId == 4){
|
||||
WavingPlants(wPos, lightmap.y);
|
||||
}
|
||||
#endif
|
||||
|
||||
texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
color = gl_Color;
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
gl_Position.xy += taaJitter * gl_Position.w;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// MinecraftPT — Textured Fragment Shader (textured non-terrain geometry)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
flat in int blockId;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
vec2 lm = lightmap;
|
||||
lm.y = SkyLightmapCurve(lightmap.y);
|
||||
|
||||
colortex0Out = vec4(albedo.rgb, 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 6.0 / 255.0); // MATID_ENTITIES
|
||||
colortex3Out = vec4(lm, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// MinecraftPT — Water Fragment Shader
|
||||
// Writes the water GBuffer with waves, caustics data
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out; // albedo + emissive
|
||||
layout(location = 1) out vec4 colortex1Out; // normals
|
||||
layout(location = 2) out vec4 colortex2Out; // spec + matID
|
||||
layout(location = 3) out vec4 colortex3Out; // lightmap
|
||||
layout(location = 4) out vec4 colortex4Out; // translucent albedo + alpha
|
||||
layout(location = 5) out vec4 colortex5Out; // translucent normal + matID
|
||||
|
||||
#include "/Lib/IndividualFunctions/WaterWaves.glsl"
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
// Water surface height / waves
|
||||
vec3 wPos = worldPos;
|
||||
#ifdef WAVE_PARALLAX
|
||||
vec3 waveNormal = GetWaveNormal(wPos, lightmap.y);
|
||||
#else
|
||||
vec3 waveNormal = GetWaveNormal(wPos, lightmap.y);
|
||||
#endif
|
||||
|
||||
// Water color — deep water tint
|
||||
vec3 waterColor = mix(vec3(0.05, 0.15, 0.2), vec3(0.1, 0.3, 0.4), wetness * 0.5);
|
||||
|
||||
// Water lightmap
|
||||
vec2 lm = lightmap;
|
||||
lm.y = SkyLightmapCurve(lightmap.y);
|
||||
|
||||
// Water is translucent
|
||||
colortex0Out = vec4(waterColor, 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(waveNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.018, 0.0, 1.0 / 255.0); // matID = MATID_WATER
|
||||
colortex3Out = vec4(lm, 1.0, 1.0);
|
||||
|
||||
// Translucent buffer: water albedo is mostly transparent, we store depth tint
|
||||
colortex4Out = vec4(waterColor, 0.6);
|
||||
colortex5Out = vec4(EncodeNormal(waveNormal), 1.0 / 255.0, 0.0);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// MinecraftPT — Water Vertex Shader
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
out vec2 texcoord;
|
||||
out vec3 worldPos;
|
||||
out vec3 worldNormal;
|
||||
out vec3 vertexNormal;
|
||||
out vec4 color;
|
||||
out vec2 lightmap;
|
||||
|
||||
void main(){
|
||||
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
|
||||
vec4 wPos = gbufferModelViewInverse * viewPos;
|
||||
worldPos = wPos.xyz;
|
||||
|
||||
vertexNormal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
worldNormal = normalize(mat3(gbufferModelViewInverse) * vertexNormal);
|
||||
|
||||
lightmap = gl_MultiTexCoord1.xy / 240.0;
|
||||
lightmap = saturate(lightmap);
|
||||
|
||||
texcoord = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||
color = gl_Color;
|
||||
|
||||
gl_Position = gl_ProjectionMatrix * viewPos;
|
||||
gl_Position.xy += taaJitter * gl_Position.w;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// MinecraftPT — Weather Fragment Shader (rain/snow)
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
in vec2 texcoord;
|
||||
in vec3 worldPos;
|
||||
in vec3 worldNormal;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 color;
|
||||
in vec2 lightmap;
|
||||
flat in int blockId;
|
||||
|
||||
layout(location = 0) out vec4 colortex0Out;
|
||||
layout(location = 1) out vec4 colortex1Out;
|
||||
layout(location = 2) out vec4 colortex2Out;
|
||||
layout(location = 3) out vec4 colortex3Out;
|
||||
layout(location = 4) out vec4 colortex4Out;
|
||||
layout(location = 5) out vec4 colortex5Out;
|
||||
|
||||
void main(){
|
||||
vec4 albedo = texture(tex, texcoord) * color;
|
||||
|
||||
if (albedo.a < 0.004) discard;
|
||||
|
||||
// Weather drops are thin — mark as particle-ish translucent
|
||||
colortex0Out = vec4(albedo.rgb, 0.0);
|
||||
colortex1Out = vec4(EncodeNormal(worldNormal), EncodeNormal(vertexNormal));
|
||||
colortex2Out = vec4(0.0, 0.0, 0.0, 17.0 / 255.0); // MATID_PARTICLE
|
||||
colortex3Out = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
colortex4Out = vec4(0.0);
|
||||
colortex5Out = vec4(0.0);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// MinecraftPT — Post_VS
|
||||
// Fullscreen triangle vertex shader for composite passes.
|
||||
|
||||
void main(){
|
||||
// Fullscreen triangle
|
||||
vec2 pos = vec2(
|
||||
gl_VertexID == 0 ? -1.0 : (gl_VertexID == 1 ? 3.0 : -1.0),
|
||||
gl_VertexID == 0 ? -1.0 : (gl_VertexID == 1 ? -1.0 : 3.0)
|
||||
);
|
||||
|
||||
gl_Position = vec4(pos, 1.0, 1.0);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// MinecraftPT — RTWSM Backward Analysis
|
||||
// Computes the importance map from the shadow map depth: which shadow map texels
|
||||
// need more resolution (near-field geometry, steep normals).
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
#include "/Lib/PathTracing/Voxelizer/VoxelProfile.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(32, 16, 1);
|
||||
layout (local_size_x = 32, local_size_y = 32) in;
|
||||
|
||||
layout (r32f) uniform writeonly image2D img_rtwImportance2D;
|
||||
|
||||
uniform sampler2D shadowcolor0;
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
vec2 uv = (vec2(texel) + 0.5) / vec2(RTW_RESOLUTION, RTW_RESOLUTION_Y);
|
||||
|
||||
// Sample shadow map depth (in the shadow region)
|
||||
vec2 shadowUv = vec2(uv.x * 0.5 + 0.5, uv.y * 0.5); // map to right region
|
||||
vec2 shadowTexel = shadowUv * shadowSize;
|
||||
|
||||
vec4 shadowData = texelFetch(shadowcolor0, ivec2(shadowTexel), 0);
|
||||
|
||||
float depth = shadowData.a;
|
||||
float importance = 0.0;
|
||||
|
||||
if (depth < 1.0){
|
||||
// Depth-based importance: closer = more important
|
||||
float dist = 1.0 - depth;
|
||||
importance = pow(dist, 2.0) * RTW_BACKWARD_DIST_FACTOR;
|
||||
|
||||
// Depth gradient importance (edges)
|
||||
float dLeft = texelFetch(shadowcolor0, ivec2(shadowTexel) + ivec2(-1, 0), 0).a;
|
||||
float dRight = texelFetch(shadowcolor0, ivec2(shadowTexel) + ivec2(1, 0), 0).a;
|
||||
float dUp = texelFetch(shadowcolor0, ivec2(shadowTexel) + ivec2(0, -1), 0).a;
|
||||
float dDown = texelFetch(shadowcolor0, ivec2(shadowTexel) + ivec2(0, 1), 0).a;
|
||||
|
||||
float gradient = abs(dLeft - dRight) + abs(dUp - dDown);
|
||||
importance += gradient * 0.5 * RTW_BACKWARD_NORMAL_FACTOR;
|
||||
}
|
||||
|
||||
imageStore(img_rtwImportance2D, texel, vec4(importance));
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// MinecraftPT — RTWSM Blur Importance
|
||||
// Gaussian-blurs the importance map to make the warp smooth.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(32, 16, 1);
|
||||
layout (local_size_x = 32, local_size_y = 32) in;
|
||||
|
||||
layout (r32f) uniform writeonly image2D img_rtwImportance2D;
|
||||
|
||||
uniform sampler2D rtwImportance2D;
|
||||
|
||||
void main(){
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
|
||||
float importance = 0.0;
|
||||
float weightSum = 0.0;
|
||||
|
||||
int radius = int(RTW_BLUR_FACTOR);
|
||||
|
||||
for (int i = -radius; i <= radius; i++){
|
||||
for (int j = -radius; j <= radius; j++){
|
||||
vec2 coord = vec2(texel + ivec2(i, j)) / vec2(RTW_RESOLUTION, RTW_RESOLUTION_Y);
|
||||
float w = exp(-(i * i + j * j) / (2.0 * RTW_BLUR_FACTOR * RTW_BLUR_FACTOR));
|
||||
importance += textureLod(rtwImportance2D, coord, 0.0).r * w;
|
||||
weightSum += w;
|
||||
}}
|
||||
|
||||
imageStore(img_rtwImportance2D, texel, vec4(importance / weightSum));
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// MinecraftPT — RTWSM Building Warp
|
||||
// Builds the final warp curve (cumulative importance) from the importance map.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(32, 1, 1);
|
||||
layout (local_size_x = 32) in;
|
||||
|
||||
layout (rg16) uniform writeonly image2D img_rtwWarp1D;
|
||||
|
||||
uniform sampler2D rtwImportance2D;
|
||||
|
||||
void main(){
|
||||
int y = int(gl_GlobalInvocationID.y);
|
||||
|
||||
// Compute the cumulative importance curve for this row
|
||||
float total = 0.0;
|
||||
for (int x = 0; x < RTW_RESOLUTION; x++){
|
||||
total += textureLod(rtwImportance2D, vec2(float(x) / float(RTW_RESOLUTION), float(y) / float(RTW_RESOLUTION_Y)), 0.0).r;
|
||||
}
|
||||
|
||||
// Write warp curve: row 0 = cumulative, row 1 = inverse
|
||||
if (total > 0.0){
|
||||
float cum = 0.0;
|
||||
for (int x = 0; x < RTW_RESOLUTION; x++){
|
||||
cum += textureLod(rtwImportance2D, vec2(float(x) / float(RTW_RESOLUTION), float(y) / float(RTW_RESOLUTION_Y)), 0.0).r;
|
||||
imageStore(img_rtwWarp1D, ivec2(x, 0), vec4(cum / total, 0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
// Inverse: for each output position find input position
|
||||
for (int x = 0; x < RTW_RESOLUTION; x++){
|
||||
float target = float(x) / float(RTW_RESOLUTION - 1);
|
||||
int lo = 0;
|
||||
int hi = RTW_RESOLUTION - 1;
|
||||
for (int i = 0; i < 10; i++){
|
||||
int mid = (lo + hi) / 2;
|
||||
float v = textureLod(rtwImportance2D, vec2(float(mid) / float(RTW_RESOLUTION), float(y) / float(RTW_RESOLUTION_Y)), 0.0).r;
|
||||
if (v < target) lo = mid; else hi = mid;
|
||||
}
|
||||
float inv = float(lo) / float(RTW_RESOLUTION);
|
||||
imageStore(img_rtwWarp1D, ivec2(x, 1), vec4(inv, 0.0, 0.0, 0.0));
|
||||
}
|
||||
}else{
|
||||
// Identity warp
|
||||
for (int x = 0; x < RTW_RESOLUTION; x++){
|
||||
float v = float(x) / float(RTW_RESOLUTION);
|
||||
imageStore(img_rtwWarp1D, ivec2(x, 0), vec4(v, 0.0, 0.0, 0.0));
|
||||
imageStore(img_rtwWarp1D, ivec2(x, 1), vec4(v, 0.0, 0.0, 0.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// MinecraftPT — RTWSM Collapse Importance
|
||||
// Collapses the 2D importance map into a 1D cumulative curve per row.
|
||||
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
|
||||
const ivec3 workGroups = ivec3(RTW_RESOLUTION, 1, 1);
|
||||
layout (local_size_x = 1) in;
|
||||
|
||||
layout (r32f) uniform writeonly image2D img_rtwImportance2D;
|
||||
layout (rg16) uniform writeonly image2D img_rtwWarp1D;
|
||||
|
||||
uniform sampler2D rtwImportance2D;
|
||||
|
||||
void main(){
|
||||
int y = int(gl_GlobalInvocationID.y);
|
||||
|
||||
// Sum importance across rows -> 1D profile
|
||||
float sum = 0.0;
|
||||
for (int x = 0; x < RTW_RESOLUTION; x++){
|
||||
sum += textureLod(rtwImportance2D, vec2(float(x) / float(RTW_RESOLUTION), float(y) / float(RTW_RESOLUTION_Y)), 0.0).r;
|
||||
}
|
||||
|
||||
// Build cumulative distribution
|
||||
float cumulative = 0.0;
|
||||
for (int x = 0; x < RTW_RESOLUTION; x++){
|
||||
float imp = textureLod(rtwImportance2D, vec2(float(x) / float(RTW_RESOLUTION), float(y) / float(RTW_RESOLUTION_Y)), 0.0).r;
|
||||
cumulative += imp;
|
||||
float normalized = sum > 0.0 ? cumulative / sum : float(x) / float(RTW_RESOLUTION);
|
||||
|
||||
imageStore(img_rtwWarp1D, ivec2(x, y), vec4(normalized, 1.0 - normalized, 0.0, 0.0));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
#include "/Lib/Utilities.glsl"
|
||||
// MinecraftPT — RTWSM SampleWarp
|
||||
// Samples the warp map to redistribute shadow map coordinates.
|
||||
|
||||
#ifndef SAMPLE_WARP_GLSL
|
||||
uniform sampler2D rtwWarp1D;
|
||||
#define SAMPLE_WARP_GLSL
|
||||
|
||||
// Warp curve sampling: rtwWarp1D is a RG16 texture, RTW_RESOLUTION x 2
|
||||
// Row 0: warp curve (cumulative importance), Row 1: inverse warp curve
|
||||
vec2 SampleWarp(float value){
|
||||
vec2 coord = vec2(value * (RTW_RESOLUTION - 1.0) + 0.5, 0.5) / vec2(RTW_RESOLUTION, 2.0);
|
||||
return textureLod(rtwWarp1D, coord, 0.0).rg;
|
||||
}
|
||||
|
||||
// Smooth warp sampling with lerp
|
||||
vec2 SampleRTWWarpSmooth(vec2 shadowScreenPos){
|
||||
// The warp is 1D along the shadow map's X axis (sun direction)
|
||||
float u = saturate(shadowScreenPos.x);
|
||||
|
||||
// Sample warp curve
|
||||
vec2 warp = SampleWarp(u);
|
||||
|
||||
// Apply warp: remap x based on cumulative importance
|
||||
float warpedX = warp.x;
|
||||
|
||||
// Also apply to y for 2D warping (using second channel)
|
||||
float warpedY = warp.y;
|
||||
|
||||
return vec2(warpedX - u, warpedY - shadowScreenPos.y);
|
||||
}
|
||||
|
||||
// Full warp application for shadow map sampling
|
||||
vec2 WarpShadowCoord(vec2 shadowScreenPos){
|
||||
float u = saturate(shadowScreenPos.x);
|
||||
vec2 warp = SampleWarp(u);
|
||||
|
||||
vec2 warped = vec2(warp.x, warp.y);
|
||||
|
||||
// The warp curve maps [0,1] -> [0,1] cumulative
|
||||
// Inverse: sample with the inverse curve
|
||||
return warped;
|
||||
}
|
||||
|
||||
// Unwarp (for reconstructing world positions)
|
||||
vec2 UnwarpShadowCoord(vec2 warpedCoord){
|
||||
// Binary search on the warp curve (forward map)
|
||||
float low = 0.0;
|
||||
float high = 1.0;
|
||||
|
||||
for (int i = 0; i < 8; i++){
|
||||
float mid = (low + high) * 0.5;
|
||||
vec2 sample = SampleWarp(mid);
|
||||
if (sample.x < warpedCoord.x){
|
||||
low = mid;
|
||||
}else{
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return vec2((low + high) * 0.5, warpedCoord.y);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,390 @@
|
||||
// MinecraftPT — Settings
|
||||
// All configurable options. Change values here or via the in-game GUI.
|
||||
|
||||
#ifndef SETTINGS_GLSL
|
||||
#define SETTINGS_GLSL
|
||||
|
||||
// =============================== Path Tracing: Voxel ===============================
|
||||
// Voxelization resolution (width x height x width)
|
||||
// 4004=128³, 6004=192x128x192, 8004=256x128x256, 8006=256x192x256, 8008=256³
|
||||
// 12004=384x128x384, 12006=384x192x384, 12008=384x256x384, 16004=512x128x512, 16008=512x256x512, 16016=512³
|
||||
#define PT_VOXEL_RESOLUTION 8006
|
||||
|
||||
// Full block verification (more accurate, slightly slower)
|
||||
#define PT_FULLBLOCK_VERIFICATION 0
|
||||
// Full block detection from geometry (helps modded blocks)
|
||||
#define PT_FULLBLOCK_DETECTION 0
|
||||
// Sparse tracing — hierarchical empty-voxel skipping (much faster, recommended)
|
||||
#define PT_SPARE_TRACING 1
|
||||
// Detect emissive blocks from vanilla light level
|
||||
#define VANILLA_EMISSIVE 1
|
||||
// Trace through alpha pixels of blocks
|
||||
#define PT_TRACING_ALPHA 0
|
||||
|
||||
// =============================== Path Tracing: Diffuse ===============================
|
||||
// Max tracing distance for diffuse rays (blocks)
|
||||
#define PT_DIFFUSE_TRACING_DISTANCE 32.0
|
||||
// Samples per pixel for diffuse tracing (1 = 1 ray)
|
||||
#define PT_DIFFUSE_SPP 1
|
||||
// Screen space tracing for diffuse (SST) — helps short-range detail
|
||||
#define PT_DIFFUSE_SST 1
|
||||
// Diffuse refraction through translucent blocks
|
||||
#define PT_DIFFUSE_REFRACTION 1
|
||||
#define PT_DIFFUSE_REFRACTION_IOR 1.3
|
||||
|
||||
// ---- Diffuse denoiser ----
|
||||
// Max temporal accumulation (frames)
|
||||
#define PT_DIFFUSE_TEMPORAL_MAX_ACCUM 8
|
||||
// Spatial filter detail (0=low,1=medium,2=high,3=ultra)
|
||||
#define PT_DIFFUSE_SPATIAL_FILTER_DETAIL 2
|
||||
#define PT_DIFFUSE_SPATIAL_FILTER_LUMINANCE_WEIGHT 0.4
|
||||
#define PT_DIFFUSE_SPATIAL_FILTER_DEPTH_WEIGHT 0.8
|
||||
#define PT_DIFFUSE_SPATIAL_FILTER_NORMAL_WEIGHT 0.4
|
||||
// Fix history bleeding (0=off,1=on)
|
||||
#define PT_DIFFUSE_TEMPORAL_HISTORY_FIX 1
|
||||
|
||||
// =============================== Path Tracing: Specular ===============================
|
||||
// Enable rough specular (GGX) reflections
|
||||
#define ENABLE_ROUGH_SPECULAR 1
|
||||
// Clamp minimum roughness
|
||||
#define ROUGHNESS_CLAMP 0
|
||||
// Max tracing distance for specular rays
|
||||
#define PT_SPECULAR_TRACING_DISTANCE 64.0
|
||||
// Screen space reflection mode (0=off,1=combined,2=only screen space)
|
||||
#define PT_SSR_MODE 1
|
||||
// SSR quality (steps)
|
||||
#define PT_SSR_QUALITY 32
|
||||
// Reuse screen-space data in specular tracing
|
||||
#define PT_SPECULAR_SCREEN_REUSE 1
|
||||
// Smooth IRC specular
|
||||
#define PT_SPECULAR_IRC_SMOOTH 0
|
||||
// Skybox resolution for reflections (32/48/64/96/128)
|
||||
#define SKYBOX_RESOLUTION 64
|
||||
|
||||
// =============================== Path Tracing: IRC ===============================
|
||||
// Irradiance cache resolution (16/32/48/64)
|
||||
#define PT_IRC_RESOLUTION 32
|
||||
// Samples per IRC update
|
||||
#define PT_IRC_SPP 8
|
||||
// IRC blend weight (0-1)
|
||||
#define PT_IRC_BLENDWEIGHT 0.5
|
||||
// Self-bounce attenuation
|
||||
#define PT_IRC_SELFBOUNCE_ATTENUATION 1.0
|
||||
|
||||
// =============================== Lighting ===============================
|
||||
#define BLOCKLIGHT_BRIGHTNESS 1.0
|
||||
#define SPHERELIGHT_BRIGHTNESS 1.0
|
||||
#define BLOCKLIGHT_TEMPERATURE 1.5
|
||||
#define PARTICLELIGHT_BRIGHTNESS 1.0
|
||||
#define NOLIGHT_BRIGHTNESS 0.05
|
||||
#define NIGHT_BRIGHTNESS 0.35
|
||||
#define NETHER_BRIGHTNESS 1.0
|
||||
#define COLD_MOONLIGHT 1
|
||||
#define SUNRISE_ROTATION 0.0
|
||||
#define SUN_ANGULAR_RADIUS 0.00465
|
||||
#define SUNLIGHT_INTENSITY 1.0
|
||||
|
||||
// Light colors
|
||||
#define BRIGHTNESS_TORCH 1.0
|
||||
#define COLOR_TORCH_R 1.0
|
||||
#define COLOR_TORCH_G 0.64
|
||||
#define COLOR_TORCH_B 0.32
|
||||
#define BRIGHTNESS_ENDROD 1.0
|
||||
#define COLOR_ENDROD_R 1.0
|
||||
#define COLOR_ENDROD_G 0.75
|
||||
#define COLOR_ENDROD_B 0.6
|
||||
#define BRIGHTNESS_FIRE 1.8
|
||||
#define COLOR_FIRE_R 1.0
|
||||
#define COLOR_FIRE_G 0.45
|
||||
#define COLOR_FIRE_B 0.13
|
||||
#define BRIGHTNESS_LIGHTBLOCK 1.0
|
||||
#define COLOR_LIGHTBLOCK_R 1.0
|
||||
#define COLOR_LIGHTBLOCK_G 1.0
|
||||
#define COLOR_LIGHTBLOCK_B 1.0
|
||||
#define BRIGHTNESS_SOULTORCH 0.4
|
||||
#define COLOR_SOULTORCH_R 0.4
|
||||
#define COLOR_SOULTORCH_G 0.98
|
||||
#define COLOR_SOULTORCH_B 1.0
|
||||
#define BRIGHTNESS_AMETHYST 0.3
|
||||
#define COLOR_AMETHYST_R 0.84
|
||||
#define COLOR_AMETHYST_G 0.52
|
||||
#define COLOR_AMETHYST_B 1.28
|
||||
#define BRIGHTNESS_REDSTONETORCH 0.1
|
||||
#define COLOR_REDSTONETORCH_R 1.0
|
||||
#define COLOR_REDSTONETORCH_G 0.48
|
||||
#define COLOR_REDSTONETORCH_B 0.39
|
||||
|
||||
// Held light (torch in hand)
|
||||
#define HELDLIGHT_BRIGHTNESS 1.0
|
||||
#define HELDLIGHT_MODE 1
|
||||
#define HELDLIGHT_FALLOFF 0.2
|
||||
#define HELDLIGHT_COLOR_TEMPERATURE 1.5
|
||||
#define SPECULAR_HELDLIGHT 0
|
||||
#define HELDLIGHT_SHADOW 1
|
||||
|
||||
// =============================== Shadows ===============================
|
||||
// Shadow map render distance (4/6/8/12/16/24/32/48/64/96/128)
|
||||
#define SHADOW_RENDER_DISTANCE 16
|
||||
// Variable penumbra shadows
|
||||
#define VARIABLE_PENUMBRA_SHADOWS 1
|
||||
#define VPS_SPREAD 1.0
|
||||
// Shadow map quality (1/2/3)
|
||||
#define SHADOW_QUALITY 2
|
||||
#define SHADOW_BASIC_BLUR 0.0
|
||||
// Use voxel shadow tracing instead of shadow map
|
||||
#define PT_SHADOW 1
|
||||
// Screen space shadows
|
||||
#define SCREEN_SPACE_SHADOWS 1
|
||||
// Colored shadows (from shadow map albedo)
|
||||
#define COLORED_SHADOWS 1
|
||||
#define HAND_SCREEN_SHADOW 1
|
||||
// Prevent light leaking at sun-grazing angles
|
||||
#define SUNLIGHT_LEAK_FIX 1
|
||||
|
||||
// RTWSM (warped shadow map)
|
||||
#define RTW_RESOLUTION 512
|
||||
#define RTW_BACKWARD_DIST_FACTOR 1.0
|
||||
#define RTW_BACKWARD_NORMAL_FACTOR 0.8
|
||||
#define RTW_BLUR_FACTOR 2.0
|
||||
|
||||
// =============================== Surface ===============================
|
||||
// Block atlas texture resolution (0=auto)
|
||||
#define TEXTURE_RESOLUTION 0
|
||||
// LAB PBR texture format (0=legacy,1=LAB-PBR 1.3,2=LAB-PBR 1.4)
|
||||
#define TEXTURE_PBR_FORMAT 1
|
||||
// Emissiveness from LAB PBR
|
||||
#define LABPBR_EMISSIVENESS 1
|
||||
// Hardcoded emissive blocks
|
||||
#define HARDCODED_EMISSIVENESS_MODE 1
|
||||
// Subsurface scattering
|
||||
#define LABPBR_SSS 1
|
||||
#define SSS_QUALITY 4
|
||||
#define SSS_STRENGTH 0.4
|
||||
#define SSS_STRENGTH_OFFSET 0.0
|
||||
#define SSS_BRIGHTNESS 1.0
|
||||
// Porosity (wetness)
|
||||
#define LABPBR_POROSITY 1
|
||||
#define TEXTURE_DEFAULT_POROSITY 0.2
|
||||
#define POROSITY_ABSORPTION 0.3
|
||||
#define SURFACE_WETNESS 0.5
|
||||
// Predefined metals
|
||||
#define LABPBR_PREDEFINED_METAL 1
|
||||
#define METAL_MINIMAL_F0 0.04
|
||||
#define METAL_ORIGIN_COLOR 1.0
|
||||
#define METALMASK_STRENGTH 1.0
|
||||
|
||||
// Parallax occlusion mapping
|
||||
#define PARALLAX_MODE 0
|
||||
#define ENTITIES_PARALLAX 0
|
||||
#define PARALLAX_DEPTH 0.08
|
||||
#define PARALLAX_QUALITY 6
|
||||
|
||||
// Waving plants
|
||||
#define WAVING_PLANTS 1
|
||||
#define SHADOW_WAVING_PLANTS 0
|
||||
#define WAVING_RANGE 24.0
|
||||
#define WAVING_SPEED 1.0
|
||||
#define GRASS_AMPLITUDE 0.05
|
||||
#define LEAVES_AMPLITUDE 0.08
|
||||
|
||||
// =============================== Water ===============================
|
||||
#define WAVE_SCALE 8.0
|
||||
#define WAVE_SPEED 1.0
|
||||
#define WAVE_NORMAL_STRENGTH 0.4
|
||||
#define WAVE_PARALLAX 1
|
||||
#define WAVE_PARALLAX_DEPTH 0.4
|
||||
#define WATER_FOG 1
|
||||
#define WATER_SCATTERING_DENSITY 0.3
|
||||
#define WATER_SCATTERING_R 0.3
|
||||
#define WATER_SCATTERING_G 0.6
|
||||
#define WATER_SCATTERING_B 0.8
|
||||
#define WATER_ATTENUATION_R 0.6
|
||||
#define WATER_ATTENUATION_G 0.4
|
||||
#define WATER_ATTENUATION_B 0.3
|
||||
#define UNDERWATER_VFOG 1
|
||||
#define UNDERWATER_VFOG_QUALITY 8
|
||||
#define UNDERWATER_VFOG_DENSITY 1.0
|
||||
|
||||
// Rain / wetness
|
||||
#define drynessHalflife 0.25
|
||||
#define wetnessHalflife 2.0
|
||||
#define RAIN_SHADOW 0.98
|
||||
#define RAIN_VISIBILITY 1.0
|
||||
#define RAIN_SPLASH_EFFECT 1
|
||||
#define RAIN_SPLASH_SPEED 1.0
|
||||
#define RAIN_SPLASH_STRENGTH 1.0
|
||||
#define RAIN_SPLASH_SCALE 1.0
|
||||
#define RAIN_WIND_X 1.0
|
||||
#define RAIN_WIND_Z 1.0
|
||||
#define RAIN_DISTURBANCE 1.0
|
||||
#define DISABLE_LOCAL_PRECIPITATION 0
|
||||
|
||||
// =============================== Sky / Atmosphere ===============================
|
||||
#define ATMO_HORIZON 1
|
||||
#define ATMO_REFLECTION_HORIZON 1
|
||||
#define SKY_TEXTURE_BRIGHTNESS 1.0
|
||||
#define HASHSTARS_BRIGHTNESS 1.0
|
||||
#define STAR_TYPE 0
|
||||
#define MOON_TEXTURE 1
|
||||
#define BILINEAR_MOON_TEXTURE 1
|
||||
#define END_PLANET_CYCLE 0
|
||||
#define ACCRETIONDISC_ANGLE 0.0
|
||||
#define BLACKHOLE_LQ 0
|
||||
|
||||
// =============================== Clouds ===============================
|
||||
#define PLANAR_CLOUDS 1
|
||||
#define VOLUMETRIC_CLOUDS 1
|
||||
#define PC_ALTITUDE 128.0
|
||||
#define PC_NOISE_SCALE 0.001
|
||||
#define PC_CLEAR_COVERAGE 0.4
|
||||
#define PC_CLEAR_DENSITY 0.5
|
||||
#define PC_CLEAR_SUNLIGHTING 1.0
|
||||
#define PC_CLEAR_SKYLIGHTING 0.6
|
||||
#define PC_RAIN_COVERAGE 0.9
|
||||
#define PC_RAIN_DENSITY 0.8
|
||||
#define PC_RAIN_SUNLIGHTING 1.0
|
||||
#define PC_RAIN_SKYLIGHTING 0.3
|
||||
|
||||
#define CLOUD_QUALITY 4
|
||||
#define CLOUD_DETAILED_NOISE_STRENGTH 0.5
|
||||
#define CLOUD_BASE_NOISE_SCALE 0.004
|
||||
#define CLOUD_DETAILED_NOISE_SCALE 0.016
|
||||
#define CLOUD_COVERAGE_NOISE_OFFSET 0.5
|
||||
#define CLOUD_FADE 0.2
|
||||
#define CLOUD_BOTTOM_BRIGHTNESS 0.6
|
||||
#define CLOUD_OUTSCATTER_FACTOR 0.4
|
||||
#define CLOUD_SHADOW 1
|
||||
#define CLOUD_SPEED 1.0
|
||||
#define CLOUD_CLEAR_ALTITUDE 192.0
|
||||
#define CLOUD_CLEAR_THICKNESS 64.0
|
||||
#define CLOUD_CLEAR_COVERY 0.5
|
||||
#define CLOUD_CLEAR_DENSITY 0.35
|
||||
#define CLOUD_CLEAR_SUNLIGHTING 1.0
|
||||
#define CLOUD_CLEAR_SKYLIGHTING 0.7
|
||||
#define CLOUD_CLEAR_SCALE 1.0
|
||||
|
||||
// =============================== Volumetric fog ===============================
|
||||
#define VFOG 1
|
||||
#define VFOG_REFLECTION 1
|
||||
#define VFOG_REFRACTION 1
|
||||
#define VFOG_HEIGHT 160.0
|
||||
#define VFOG_HEIGHT_2 40.0
|
||||
#define VFOG_FALLOFF 0.002
|
||||
#define VFOG_DENSITY 1.0
|
||||
#define VFOG_DENSITY_BASE 0.001
|
||||
#define VFOG_QUALITY 24
|
||||
#define VFOG_IGNORE_WORLDTIME 0
|
||||
#define VFOG_SUNLIGHT_ABSORPTION 1.0
|
||||
#define VFOG_RAIN_DENSITY_MUL 1.0
|
||||
#define VFOG_SUNLIGHT_DENSITY 1.0
|
||||
#define VFOG_STAINED 1
|
||||
#define VFOG_FOG_DENSITY 0.05
|
||||
#define VFOG_CLOUD_SHADOW 1
|
||||
#define VFOG_NOISE_TYPE 1
|
||||
#define VFOG_NOISE_OCTAVE 3
|
||||
#define VFOG_NOISE_COVERAGE 0.3
|
||||
#define VFOG_NOISE_HORIZONTAL_SCALE 0.004
|
||||
#define VFOG_NOISE_VERTICAL_SCALE 0.01
|
||||
#define LANDSCATTERING 1
|
||||
#define LANDSCATTERING_STRENGTH 1.0
|
||||
#define LANDSCATTERING_SHADOW 1
|
||||
#define LANDSCATTERING_SHADOW_QUALITY 8
|
||||
#define LANDSCATTERING_REFLECTION 1
|
||||
#define LANDSCATTERING_REFRACTION 1
|
||||
#define INDOOR_FOG 0
|
||||
#define CAVE_FOG 1
|
||||
#define CAVE_FOG_BRIGHTNESS 0.8
|
||||
#define NETHERFOG_DENSITY 1.0
|
||||
|
||||
// =============================== Post-processing ===============================
|
||||
// TAA
|
||||
#define TAA_BLENDWEIGHT 0.9
|
||||
#define TAA_AGGRESSION 0.05
|
||||
#define TAA_SUBPIXEL_SHARPNING 0.8
|
||||
|
||||
// DOF
|
||||
#define DOF 1
|
||||
#define DISABLE_HAND_DOF 1
|
||||
#define DOF_BLUR 0.5
|
||||
#define DOF_QUALITY 12
|
||||
#define DOF_COCSPREAD_QUALITY 12
|
||||
#define DOF_MAX_COC 12.0
|
||||
#define DOF_CATSEYE 0
|
||||
#define DOF_CATSEYE_STRENGTH 1.0
|
||||
#define DOF_CATSEYE_MIDPOINT 0.5
|
||||
#define CAMERA_FOCUS_MODE 0
|
||||
#define CAMERA_FOCAL_POINT 50.0
|
||||
#define DOF_DEPTH_SMMOOTH_HALFLIFE 0.1
|
||||
#define DOF_FOCUS_IGNORE_HAND_PARTICLE 0
|
||||
|
||||
// Exposure
|
||||
#define AE_MODE 0
|
||||
#define SMOOTH_EXPOSURE 0.3
|
||||
#define AE_CURVE 0.6
|
||||
#define AE_OFFSET 0.0
|
||||
#define EXPOSURE_TIME 0.1
|
||||
#define MANUAL_EXPOSURE 1.0
|
||||
#define LUMINANCE_WEIGHT_MODE 0
|
||||
#define LUMINANCE_WEIGHT_STRENGTH 1.0
|
||||
#define EV_VALUE 0.0
|
||||
|
||||
// Motion blur
|
||||
#define MOTION_BLUR 1
|
||||
#define MOTION_BLUR_DITHER 1
|
||||
#define MOTION_BLUR_QUALITY 8
|
||||
#define MOTION_BLUR_SUTTER_MODE 0
|
||||
#define MOTION_BLUR_SUTTER_ANGLE 0.0
|
||||
#define MOTION_BLUR_SUTTER_SPEED 1.0
|
||||
|
||||
// Vignette
|
||||
#define VIGNETTE 0
|
||||
#define VIGNETTE_FALLOFF 1.0
|
||||
#define VIGNETTE_ROUNDNESS 1.0
|
||||
#define SNEAKING_VIGNETTE 1
|
||||
|
||||
// Bloom
|
||||
#define BLOOM 1
|
||||
#define BLOOM_AMOUNT 0.3
|
||||
#define BLOOM_CLAMP_STRENGTH 1.0
|
||||
#define NETHER_END_BLOOM_BOOST 1.0
|
||||
|
||||
// Color
|
||||
#define TONEMAP_OPERATOR 0 // 0=ACES, 1=AGX, 2=filmic, 3=Vanilla
|
||||
#define AGX_EV 0.0
|
||||
#define AGX_HDR_EV 0.0
|
||||
#define ABNEY_EFFECT_CORRECTION 1
|
||||
#define AGX_HDR_MIDGREY 0.18
|
||||
#define ADVANCED_COLOR 1
|
||||
#define HIGHLIGHT_CURVE 1.0
|
||||
#define SHADOW_CURVE 1.0
|
||||
#define WHITE_POINT 1.0
|
||||
#define BLACK_POINT 0.0
|
||||
#define MIDTONE_HUE 0.0
|
||||
#define MIDTONE_STRENGTH 0.0
|
||||
#define HIGHLIGHT_HUE 0.0
|
||||
#define HIGHLIGHT_STRENGTH 0.0
|
||||
#define SHADOW_HUE 0.0
|
||||
#define SHADOW_STRENGTH 0.0
|
||||
#define KEEP_LUMINANCE 0
|
||||
#define SATURATION 1.0
|
||||
#define GAMMA 1.0
|
||||
|
||||
// =============================== Misc ===============================
|
||||
#define CAVE_MODE 0
|
||||
#define PT_HALF_RES 1
|
||||
#define DEBUG_COUNTER 0
|
||||
#define DEBUG_IRC 0
|
||||
#define DISABLE_NIGHTVISION 0
|
||||
#define DISABLE_BLINDNESS_DARKNESS 0
|
||||
#define WHITE_DEBUG_WORLD 0
|
||||
|
||||
// RTWSM resolution
|
||||
#if RTW_RESOLUTION == 256
|
||||
#define RTW_RESOLUTION_Y 258
|
||||
#elif RTW_RESOLUTION == 512
|
||||
#define RTW_RESOLUTION_Y 514
|
||||
#elif RTW_RESOLUTION == 1024
|
||||
#define RTW_RESOLUTION_Y 1026
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
// MinecraftPT — Custom resource declarations
|
||||
// The shader loader auto-declares standard uniforms, colortex/depthtex/shadowcolor
|
||||
// samplers, noisetex and tex. This file only declares CUSTOM samplers and images
|
||||
// (bound via shaders.properties customTexture / image declarations).
|
||||
|
||||
#ifndef UNIFORM_DECLARE_GLSL
|
||||
#define UNIFORM_DECLARE_GLSL
|
||||
|
||||
// Custom textures (from customTexture.* in shaders.properties)
|
||||
uniform sampler2D atlas2D;
|
||||
uniform sampler2D atlasSpecular2D;
|
||||
uniform sampler3D CloudNoise3D;
|
||||
uniform sampler3D CloudDetailedNoise3D;
|
||||
uniform sampler2D ripple2D;
|
||||
|
||||
// Custom image samplers (from image.img_* in shaders.properties)
|
||||
uniform sampler3D voxelData3D;
|
||||
uniform sampler2D skyBox2D;
|
||||
uniform sampler2D prevDepth2D;
|
||||
uniform sampler2D rtwImportance2D;
|
||||
uniform sampler2D rtwWarp1D;
|
||||
uniform sampler2D pixelData2D;
|
||||
|
||||
// Custom image bindings (write access)
|
||||
layout(rgba16) uniform writeonly image3D img_voxelData3D;
|
||||
layout(rgba16f) uniform writeonly image3D img_irradianceCache3D;
|
||||
layout(rgba16f) uniform writeonly image3D img_irradianceCache3D_Alt;
|
||||
layout(rgba16f) uniform writeonly image2D img_skyBox2D;
|
||||
layout(r32f) uniform writeonly image2D img_prevDepth2D;
|
||||
layout(r32f) uniform writeonly image2D img_rtwImportance2D;
|
||||
layout(rg16) uniform writeonly image2D img_rtwWarp1D;
|
||||
layout(rg16f) uniform writeonly image2D img_pixelData2D;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,213 @@
|
||||
#include "/Lib/Settings.glsl"
|
||||
// MinecraftPT — Utilities
|
||||
// Math helpers, noise functions, packing/unpacking, color space conversions
|
||||
|
||||
#ifndef UTILITIES_GLSL
|
||||
#define UTILITIES_GLSL
|
||||
|
||||
// --- Math helpers ---
|
||||
#define saturate(x) clamp(x, 0.0, 1.0)
|
||||
#define maxVec2(v) max(v.x, v.y)
|
||||
#define maxVec3(v) max(max(v.x, v.y), v.z)
|
||||
#define minVec3(v) min(min(v.x, v.y), v.z)
|
||||
#define fsign(x) ((x) >= 0.0 ? 1.0 : -1.0)
|
||||
#define sq(x) ((x) * (x))
|
||||
#define cube(x) ((x) * (x) * (x))
|
||||
|
||||
// Gamma correction
|
||||
vec3 LinearToGamma(vec3 linear){
|
||||
return pow(linear, vec3(1.0 / 2.2));
|
||||
}
|
||||
|
||||
vec3 GammaToLinear(vec3 gamma){
|
||||
return pow(gamma, vec3(2.2));
|
||||
}
|
||||
|
||||
float LinearToGamma(float linear){
|
||||
return pow(linear, 1.0 / 2.2);
|
||||
}
|
||||
|
||||
float GammaToLinear(float gamma){
|
||||
return pow(gamma, 2.2);
|
||||
}
|
||||
|
||||
// Normal packing (octahedral encoding)
|
||||
vec2 EncodeNormal(vec3 n){
|
||||
n /= abs(n.x) + abs(n.y) + abs(n.z);
|
||||
n.xy = n.z >= 0.0 ? n.xy : (1.0 - abs(n.yx)) * fsign(n.xy);
|
||||
return n.xy * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
vec3 DecodeNormal(vec2 e){
|
||||
e = e * 2.0 - 1.0;
|
||||
vec3 n = vec3(e.x, e.y, 1.0 - abs(e.x) - abs(e.y));
|
||||
float t = max(-n.z, 0.0);
|
||||
n.x += t * fsign(n.x);
|
||||
n.y += t * fsign(n.y);
|
||||
return normalize(n);
|
||||
}
|
||||
|
||||
// Pack two 8-bit values into a 16-bit uint
|
||||
float Pack2xU8_to_U16(vec2 v){
|
||||
v = floor(v * 255.0 + 0.5);
|
||||
return v.x * 256.0 + v.y;
|
||||
}
|
||||
|
||||
vec2 Unpack2xU8_from_U16(float v){
|
||||
return vec2(floor(v / 256.0), mod(v, 256.0)) / 255.0;
|
||||
}
|
||||
|
||||
// Pack two 8-bit values with ID (8-bit + 8-bit) into float
|
||||
vec2 Unpack2xU8_ID_from_U16(float v){
|
||||
return vec2(mod(v, 9362.0) / 9361.0, floor(v / 9362.0) / 10.0);
|
||||
}
|
||||
|
||||
float Unpack2xU8_ID_Y_from_U16(float v){
|
||||
return floor(v / 9362.0) / 10.0;
|
||||
}
|
||||
|
||||
// Luminance
|
||||
float luminance(vec3 color){
|
||||
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
||||
}
|
||||
|
||||
// Hash functions
|
||||
float hash1(vec2 p){
|
||||
p = fract(p * vec2(443.8975, 397.2973));
|
||||
p += dot(p, p + 19.19);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
float hash1(vec3 p){
|
||||
p = fract(p * vec3(443.8975, 397.2973, 491.1871));
|
||||
p += dot(p, p + 19.19);
|
||||
return fract(p.x * p.y);
|
||||
}
|
||||
|
||||
vec2 hash2(vec2 p){
|
||||
vec3 p3 = fract(vec3(p.xyx) * vec3(443.8975, 397.2973, 491.1871));
|
||||
p3 += dot(p3, p3.yxz + 19.19);
|
||||
return fract(p3.xy);
|
||||
}
|
||||
|
||||
vec2 hash2(vec3 p){
|
||||
vec3 p3 = fract(p * vec3(443.8975, 397.2973, 491.1871));
|
||||
p3 += dot(p3, p3.yxz + 19.19);
|
||||
return fract(p3.xy);
|
||||
}
|
||||
|
||||
vec3 hash3(vec2 p){
|
||||
vec3 p3 = fract(vec3(p.xyx) * vec3(443.8975, 397.2973, 491.1871));
|
||||
p3 += dot(p3, p3.yxz + 19.19);
|
||||
return fract(p3);
|
||||
}
|
||||
|
||||
// Interleaved gradient noise (temporal)
|
||||
float InterleavedGradientNoise(vec2 pos, float index){
|
||||
vec3 magic = vec3(0.06711056, 0.00583715, 52.9829189);
|
||||
return fract(magic.z * fract(dot(pos, magic.xy)) + index * 0.03125);
|
||||
}
|
||||
|
||||
// Blue noise temporal (from noise.png)
|
||||
// Used as dithering / ray offset
|
||||
float BlueNoiseTemporal(vec2 screenPos, float frame){
|
||||
vec2 coord = (screenPos + 0.5) / vec2(viewWidth, viewHeight);
|
||||
coord = fract(coord * vec2(128.0, 128.0) + 0.5);
|
||||
vec2 texel = coord * vec2(127.0 / 128.0) + vec2(0.5 / 128.0);
|
||||
float noise = textureLod(noisetex, texel, 0.0).r;
|
||||
// Temporal interleaving
|
||||
return fract(noise + frame * 0.03125);
|
||||
}
|
||||
|
||||
// Sky lightmap curve (vanilla sky light attenuation)
|
||||
float SkyLightmapCurve(float skylight){
|
||||
return skylight * skylight * (3.0 - 2.0 * skylight);
|
||||
}
|
||||
|
||||
// Packing a ray for DDA traversal
|
||||
struct Ray{
|
||||
vec3 ori;
|
||||
vec3 dir;
|
||||
vec3 rdir;
|
||||
vec3 sdir;
|
||||
};
|
||||
|
||||
Ray PackRay(vec3 origin, vec3 direction){
|
||||
Ray ray;
|
||||
ray.ori = origin;
|
||||
ray.dir = direction;
|
||||
ray.rdir = 1.0 / direction;
|
||||
ray.sdir = fsign(direction);
|
||||
return ray;
|
||||
}
|
||||
|
||||
// Smooth min/max
|
||||
float smoothMin(float a, float b, float k){
|
||||
float h = max(k - abs(a - b), 0.0) / k;
|
||||
return min(a, b) - h * h * h * k * (1.0 / 6.0);
|
||||
}
|
||||
|
||||
// Curve function for smooth transitions
|
||||
float curve(float x){
|
||||
return x * x * (3.0 - 2.0 * x);
|
||||
}
|
||||
|
||||
// Fresnel Schlick
|
||||
float FresnelSchlick(float cosTheta, float f0){
|
||||
return f0 + (1.0 - f0) * pow(1.0 - cosTheta, 5.0);
|
||||
}
|
||||
|
||||
vec3 FresnelSchlick(vec3 cosTheta, vec3 f0){
|
||||
return f0 + (1.0 - f0) * pow(1.0 - cosTheta, vec3(5.0));
|
||||
}
|
||||
|
||||
// GGX normal distribution
|
||||
float GGX_D(float NdotH, float roughness){
|
||||
float a = roughness * roughness;
|
||||
float a2 = a * a;
|
||||
float denom = NdotH * NdotH * (a2 - 1.0) + 1.0;
|
||||
return a2 / (3.14159 * denom * denom);
|
||||
}
|
||||
|
||||
// Smith geometry (GGX)
|
||||
float Smith_G(float NdotV, float NdotL, float roughness){
|
||||
float a = roughness * roughness;
|
||||
float k = a * 0.5;
|
||||
float g1 = NdotV / (NdotV * (1.0 - k) + k);
|
||||
float g2 = NdotL / (NdotL * (1.0 - k) + k);
|
||||
return g1 * g2;
|
||||
}
|
||||
|
||||
// Importance sample GGX
|
||||
vec3 ImportanceSampleGGX(vec2 uv, vec3 N, float roughness){
|
||||
float a = roughness * roughness;
|
||||
float phi = uv.x * 6.283185;
|
||||
float cosTheta = sqrt((1.0 - uv.y) / (1.0 + (a * a - 1.0) * uv.y));
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
|
||||
vec3 H = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
||||
|
||||
// Tangent space to world
|
||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 T = normalize(cross(up, N));
|
||||
vec3 B = cross(N, T);
|
||||
|
||||
return normalize(T * H.x + B * H.y + N * H.z);
|
||||
}
|
||||
|
||||
// Cosine-weighted hemisphere sampling (for diffuse)
|
||||
vec3 SampleHemisphere(vec2 uv, vec3 N){
|
||||
float phi = uv.x * 6.283185;
|
||||
float cosTheta = sqrt(uv.y);
|
||||
float sinTheta = sqrt(1.0 - uv.y);
|
||||
|
||||
vec3 dir = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
||||
|
||||
vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
|
||||
vec3 T = normalize(cross(up, N));
|
||||
vec3 B = cross(N, T);
|
||||
|
||||
return normalize(T * dir.x + B * dir.y + N * dir.z);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,5 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
|
||||
#include "/Lib/Programs/Begin/CausticsTex_CS.glsl"
|
||||
@@ -0,0 +1,566 @@
|
||||
# MinecraftPT block ID mapping v1
|
||||
# block.X = block_name block_name ...
|
||||
# Uses mc_Entity.x in gbuffer shaders to determine material type.
|
||||
|
||||
# In block.properties, any block that is not listed gets mc_Entity.x = 0 (default).
|
||||
|
||||
# Default full solid blocks (ID 0)
|
||||
block.0 = \
|
||||
# vanilla stone/rock
|
||||
stone granite diorite andesite cobblestone bedrock \
|
||||
stone_bricks mossy_stone_bricks cracked_stone_bricks chiseled_stone_bricks \
|
||||
deepslate cobbled_deepslate polished_deepslate deepslate_bricks cracked_deepslate_bricks deepslate_tiles cracked_deepslate_tiles chiseled_deepslate \
|
||||
tuff polished_tuff tuff_bricks chiseled_tuff chiseled_tuff_bricks \
|
||||
calcite dripstone_block \
|
||||
sandstone red_sandstone smooth_sandstone smooth_red_sandstone chiseled_sandstone chiseled_red_sandstone cut_sandstone cut_red_sandstone \
|
||||
prismarine prismarine_bricks dark_prismarine \
|
||||
netherrack nether_bricks red_nether_bricks chiseled_nether_bricks cracked_nether_bricks \
|
||||
blackstone polished_blackstone polished_blackstone_bricks chiseled_polished_blackstone cracked_polished_blackstone_bricks \
|
||||
basalt polished_basalt smooth_basalt \
|
||||
end_stone end_stone_bricks purpur_block purpur_pillar purpur_block \
|
||||
# dirt/grass
|
||||
grass_block dirt coarse_dirt rooted_dirt podzol mycelium path \
|
||||
# logs, planks
|
||||
oak_log spruce_log birch_log jungle_log acacia_log dark_oak_log mangrove_log cherry_log pale_oak_log \
|
||||
oak_planks spruce_planks birch_planks jungle_planks acacia_planks dark_oak_planks mangrove_planks cherry_planks pale_oak_planks \
|
||||
crimson_planks warped_planks bamboo_planks \
|
||||
stripped_oak_log stripped_spruce_log stripped_birch_log stripped_jungle_log stripped_acacia_log stripped_dark_oak_log stripped_mangrove_log stripped_cherry_log stripped_pale_oak_log \
|
||||
stripped_crimson_stem stripped_warped_stem stripped_bamboo_block \
|
||||
oak_wood spruce_wood birch_wood jungle_wood acacia_wood dark_oak_wood mangrove_wood cherry_wood pale_oak_wood \
|
||||
crimson_hyphae warped_hyphae \
|
||||
stripped_oak_wood stripped_spruce_wood stripped_birch_wood stripped_jungle_wood stripped_acacia_wood stripped_dark_oak_wood stripped_mangrove_wood stripped_cherry_wood stripped_pale_oak_wood \
|
||||
stripped_crimson_hyphae stripped_warped_hyphae \
|
||||
# ores
|
||||
coal_ore deepslate_coal_ore iron_ore deepslate_iron_ore copper_ore deepslate_copper_ore gold_ore deepslate_gold_ore redstone_ore deepslate_redstone_ore lapis_ore deepslate_lapis_ore diamond_ore deepslate_diamond_ore emerald_ore deepslate_emerald_ore nether_gold_ore nether_quartz_ore \
|
||||
# mineral blocks
|
||||
coal_block iron_block copper_block gold_block diamond_block emerald_block lapis_block netherite_block redstone_block quartz_block \
|
||||
raw_iron_block raw_copper_block raw_gold_block \
|
||||
# terracotta/concrete
|
||||
white_terracotta orange_terracotta magenta_terracotta light_blue_terracotta yellow_terracotta lime_terracotta pink_terracotta gray_terracotta light_gray_terracotta cyan_terracotta purple_terracotta blue_terracotta brown_terracotta green_terracotta red_terracotta black_terracotta \
|
||||
white_concrete orange_concrete magenta_concrete light_blue_concrete yellow_concrete lime_concrete pink_concrete gray_concrete light_gray_concrete cyan_concrete purple_concrete blue_concrete brown_concrete green_concrete red_concrete black_concrete \
|
||||
white_glazed_terracotta orange_glazed_terracotta magenta_glazed_terracotta light_blue_glazed_terracotta yellow_glazed_terracotta lime_glazed_terracotta pink_glazed_terracotta gray_glazed_terracotta light_gray_glazed_terracotta cyan_glazed_terracotta purple_glazed_terracotta blue_glazed_terracotta brown_glazed_terracotta green_glazed_terracotta red_glazed_terracotta black_glazed_terracotta \
|
||||
# wool
|
||||
white_wool orange_wool magenta_wool light_blue_wool yellow_wool lime_wool pink_wool gray_wool light_gray_wool cyan_wool purple_wool blue_wool brown_wool green_wool red_wool black_wool \
|
||||
# other
|
||||
bookshelf bones_block clay sponge wet_sponge hay_block dried_kelp_block target barrel smithing_table fletching_table cartography_table loom stonecutter grindstone crafting_table furnace blast_furnace smoker \
|
||||
brick_block nether_wart_block warped_wart_block shroomlight \
|
||||
pumpkin melon jack_o_lantern mushroom_stem red_mushroom_block brown_mushroom_block \
|
||||
smooth_stone smooth_quartz quartz_bricks quartz_pillar chiseled_quartz_block \
|
||||
obsidian crying_obsidian \
|
||||
gilded_blackstone ancient_debris lodestone respawn_anchor \
|
||||
white_wool orange_wool magenta_wool light_blue_wool yellow_wool lime_wool pink_wool gray_wool light_gray_wool cyan_wool purple_wool blue_wool brown_wool green_wool red_wool black_wool \
|
||||
# copper
|
||||
copper_block exposed_copper weathered_copper oxidized_copper cut_copper exposed_cut_copper weathered_cut_copper oxidized_cut_copper \
|
||||
chiseled_copper exposed_chiseled_copper weathered_chiseled_copper oxidized_chiseled_copper \
|
||||
copper_bulb:lit=false exposed_copper_bulb:lit=false weathered_copper_bulb:lit=false oxidized_copper_bulb:lit=false \
|
||||
copper_door:open=false exposed_copper_door:open=false weathered_copper_door:open=false oxidized_copper_door:open=false \
|
||||
copper_trapdoor:open=false exposed_copper_trapdoor:open=false weathered_copper_trapdoor:open=false oxidized_copper_trapdoor:open=false \
|
||||
copper_grate exposed_copper_grate weathered_copper_grate oxidized_copper_grate \
|
||||
# waxed copper
|
||||
waxed_copper_block waxed_exposed_copper waxed_weathered_copper waxed_oxidized_copper \
|
||||
waxed_cut_copper waxed_exposed_cut_copper waxed_weathered_cut_copper waxed_oxidized_cut_copper \
|
||||
waxed_chiseled_copper waxed_exposed_chiseled_copper waxed_weathered_chiseled_copper waxed_oxidized_chiseled_copper \
|
||||
waxed_copper_bulb:lit=false waxed_exposed_copper_bulb:lit=false waxed_weathered_copper_bulb:lit=false waxed_oxidized_copper_bulb:lit=false \
|
||||
waxed_copper_grate waxed_exposed_copper_grate waxed_weathered_copper_grate waxed_oxidized_copper_grate \
|
||||
# new blocks
|
||||
mud mud_bricks packed_mud mangrove_roots muddy_mangrove_roots \
|
||||
amethyst_block budding_amethyst \
|
||||
sculk sculk_catalyst sculk_shrieker sculk_sensor calibrated_sculk_sensor sculk_vein \
|
||||
reinforced_deepslate
|
||||
# many more blocks are ID 0 (default) — all solid blocks not listed below
|
||||
|
||||
# Leaves (cutout) — ID 1
|
||||
block.1 = \
|
||||
oak_leaves spruce_leaves birch_leaves jungle_leaves acacia_leaves dark_oak_leaves mangrove_leaves cherry_leaves pale_oak_leaves \
|
||||
azalea_leaves flowering_azalea_leaves \
|
||||
# vines
|
||||
vine cave_vines cave_vines_plant weeping_vines weeping_vines_plant twisting_vines twisting_vines_plant
|
||||
# other
|
||||
hanging_roots
|
||||
|
||||
# Full translucent blocks (glass, ice, etc.) — ID 2
|
||||
block.2 = \
|
||||
glass white_stained_glass orange_stained_glass magenta_stained_glass light_blue_stained_glass yellow_stained_glass lime_stained_glass pink_stained_glass gray_stained_glass light_gray_stained_glass cyan_stained_glass purple_stained_glass blue_stained_glass brown_stained_glass green_stained_glass red_stained_glass black_stained_glass \
|
||||
tinted_glass \
|
||||
ice packed_ice blue_ice frosted_ice \
|
||||
slime_block honey_block
|
||||
|
||||
# Water (handled by gbuffers_water) — ID 3
|
||||
block.3 = water
|
||||
|
||||
# Cross cutout plants (lower transparency — grass, flowers, etc.) — ID 4
|
||||
block.4 = \
|
||||
short_grass tall_grass fern large_fern \
|
||||
dandelion poppy blue_orchid allium azure_bluet red_tulip orange_tulip white_tulip pink_tulip oxeye_daisy cornflower lily_of_the_valley sunflower lilac rose_bush peony \
|
||||
wither_rose torchflower spore_blossom pink_petals \
|
||||
sweet_berry_bush \
|
||||
crimson_fungus warped_fungus crimson_roots warped_roots nether_sprouts \
|
||||
brown_mushroom red_mushroom \
|
||||
dead_bush bamboo_sapling cherry_leaves? no cherry_leaves are leaves
|
||||
|
||||
# Torch-like (emissive thin) — ID 5
|
||||
block.5 = torch soul_torch redstone_torch
|
||||
|
||||
# Lanterns (emissive with shape) — ID 6
|
||||
block.6 = lantern soul_lantern
|
||||
|
||||
# Fire (emissive anim) — ID 7
|
||||
block.7 = fire soul_fire
|
||||
|
||||
# Campfire — ID 8
|
||||
block.8 = campfire soul_campfire
|
||||
|
||||
# Lava (emissive liquid) — ID 9
|
||||
block.9 = lava
|
||||
|
||||
# Glass panes — ID 10
|
||||
block.10 = glass_pane white_stained_glass_pane orange_stained_glass_pane magenta_stained_glass_pane light_blue_stained_glass_pane yellow_stained_glass_pane lime_stained_glass_pane pink_stained_glass_pane gray_stained_glass_pane light_gray_stained_glass_pane cyan_stained_glass_pane purple_stained_glass_pane blue_stained_glass_pane brown_stained_glass_pane green_stained_glass_pane red_stained_glass_pane black_stained_glass_pane
|
||||
|
||||
# Iron bars — ID 11
|
||||
block.11 = iron_bars
|
||||
|
||||
# Stairs — ID 12
|
||||
block.12 = \
|
||||
# All stairs
|
||||
oak_stairs spruce_stairs birch_stairs jungle_stairs acacia_stairs dark_oak_stairs mangrove_stairs cherry_stairs pale_oak_stairs \
|
||||
cobblestone_stairs stone_stairs stone_brick_stairs mossy_stone_brick_stairs brick_stairs mud_brick_stairs sandstone_stairs red_sandstone_stairs \
|
||||
nether_brick_stairs red_nether_brick_stairs quartz_stairs purpur_stairs prismarine_stairs prismarine_brick_stairs dark_prismarine_stairs \
|
||||
granite_stairs diorite_stairs andesite_stairs polished_granite_stairs polished_diorite_stairs polished_andesite_stairs \
|
||||
deepslate_brick_stairs deepslate_tile_stairs cobbled_deepslate_stairs polished_deepslate_stairs \
|
||||
blackstone_stairs polished_blackstone_stairs polished_blackstone_brick_stairs \
|
||||
tuff_stairs tuff_brick_stairs polished_tuff_stairs \
|
||||
end_stone_brick_stairs resin_brick_stairs \
|
||||
mossy_cobblestone_stairs smooth_quartz_stairs smooth_sandstone_stairs smooth_red_sandstone_stairs \
|
||||
# Wood stairs
|
||||
crimson_stairs warped_stairs bamboo_stairs
|
||||
|
||||
# Slabs — ID 13
|
||||
block.13 = \
|
||||
# All slabs — single type only (double type handled by full block detection)
|
||||
oak_slab:type=bottom spruce_slab:type=bottom birch_slab:type=bottom jungle_slab:type=bottom acacia_slab:type=bottom dark_oak_slab:type=bottom mangrove_slab:type=bottom cherry_slab:type=bottom pale_oak_slab:type=bottom \
|
||||
cobblestone_slab:type=bottom stone_slab:type=bottom stone_brick_slab:type=bottom mossy_stone_brick_slab:type=bottom brick_slab:type=bottom mud_brick_slab:type=bottom sandstone_slab:type=bottom red_sandstone_slab:type=bottom cut_sandstone_slab:type=bottom cut_red_sandstone_slab:type=bottom \
|
||||
nether_brick_slab:type=bottom red_nether_brick_slab:type=bottom quartz_slab:type=bottom purpur_slab:type=bottom prismarine_slab:type=bottom prismarine_brick_slab:type=bottom dark_prismarine_slab:type=bottom \
|
||||
granite_slab:type=bottom diorite_slab:type=bottom andesite_slab:type=bottom polished_granite_slab:type=bottom polished_diorite_slab:type=bottom polished_andesite_slab:type=bottom \
|
||||
deepslate_brick_slab:type=bottom deepslate_tile_slab:type=bottom cobbled_deepslate_slab:type=bottom polished_deepslate_slab:type=bottom \
|
||||
blackstone_slab:type=bottom polished_blackstone_slab:type=bottom polished_blackstone_brick_slab:type=bottom \
|
||||
tuff_slab:type=bottom tuff_brick_slab:type=bottom polished_tuff_slab:type=bottom \
|
||||
end_stone_brick_slab:type=bottom resin_brick_slab:type=bottom \
|
||||
smooth_quartz_slab:type=bottom smooth_sandstone_slab:type=bottom smooth_red_sandstone_slab:type=bottom \
|
||||
mossy_cobblestone_slab:type=bottom \
|
||||
crimson_slab:type=bottom warped_slab:type=bottom bamboo_slab:type=bottom \
|
||||
# special slabs
|
||||
stone_slab:type=bottom? Actually stone_slab:type=bottom is the correct one.
|
||||
petrified_oak_slab:type=bottom \
|
||||
smooth_stone_slab:type=bottom
|
||||
|
||||
# Walls — ID 14
|
||||
block.14 = \
|
||||
cobblestone_wall mossy_cobblestone_wall stone_brick_wall mossy_stone_brick_wall \
|
||||
brick_wall mud_brick_wall sandstone_wall red_sandstone_wall \
|
||||
nether_brick_wall red_nether_brick_wall \
|
||||
granite_wall diorite_wall andesite_wall \
|
||||
deepslate_brick_wall deepslate_tile_wall cobbled_deepslate_wall polished_deepslate_wall \
|
||||
blackstone_wall polished_blackstone_wall polished_blackstone_brick_wall \
|
||||
tuff_wall tuff_brick_wall polished_tuff_wall \
|
||||
end_stone_brick_wall resin_brick_wall
|
||||
|
||||
# Fences — ID 15
|
||||
block.15 = \
|
||||
oak_fence spruce_fence birch_fence jungle_fence acacia_fence dark_oak_fence mangrove_fence cherry_fence pale_oak_fence \
|
||||
crimson_fence warped_fence bamboo_fence \
|
||||
nether_brick_fence
|
||||
|
||||
# Fence Gates — ID 16
|
||||
block.16 = \
|
||||
oak_fence_gate spruce_fence_gate birch_fence_gate jungle_fence_gate acacia_fence_gate dark_oak_fence_gate mangrove_fence_gate cherry_fence_gate pale_oak_fence_gate \
|
||||
crimson_fence_gate warped_fence_gate bamboo_fence_gate
|
||||
|
||||
# Doors — ID 17 (door facing south, hinge left, closed)
|
||||
# For simplicity, map all door orientations to ID 17 — the gbuffer will use the vertex normal and position to determine shape
|
||||
block.17 = \
|
||||
# All doors (all orientations)
|
||||
iron_door:open=false iron_door:open=true \
|
||||
oak_door:open=false oak_door:open=true \
|
||||
spruce_door:open=false spruce_door:open=true \
|
||||
birch_door:open=false birch_door:open=true \
|
||||
jungle_door:open=false jungle_door:open=true \
|
||||
acacia_door:open=false acacia_door:open=true \
|
||||
dark_oak_door:open=false dark_oak_door:open=true \
|
||||
mangrove_door:open=false mangrove_door:open=true \
|
||||
crimson_door:open=false crimson_door:open=true \
|
||||
warped_door:open=false warped_door:open=true \
|
||||
bamboo_door:open=false bamboo_door:open=true \
|
||||
cherry_door:open=false cherry_door:open=true \
|
||||
pale_oak_door:open=false pale_oak_door:open=true \
|
||||
copper_door:open=false copper_door:open=true \
|
||||
exposed_copper_door:open=false exposed_copper_door:open=true \
|
||||
weathered_copper_door:open=false weathered_copper_door:open=true \
|
||||
oxidized_copper_door:open=false oxidized_copper_door:open=true \
|
||||
waxed_copper_door:open=false waxed_copper_door:open=true \
|
||||
waxed_exposed_copper_door:open=false waxed_exposed_copper_door:open=true \
|
||||
waxed_weathered_copper_door:open=false waxed_weathered_copper_door:open=true \
|
||||
waxed_oxidized_copper_door:open=false waxed_oxidized_copper_door:open=true \
|
||||
# Trapdoors
|
||||
oak_trapdoor:open=false oak_trapdoor:open=true \
|
||||
spruce_trapdoor:open=false spruce_trapdoor:open=true \
|
||||
birch_trapdoor:open=false birch_trapdoor:open=true \
|
||||
jungle_trapdoor:open=false jungle_trapdoor:open=true \
|
||||
acacia_trapdoor:open=false acacia_trapdoor:open=true \
|
||||
dark_oak_trapdoor:open=false dark_oak_trapdoor:open=true \
|
||||
mangrove_trapdoor:open=false mangrove_trapdoor:open=true \
|
||||
crimson_trapdoor:open=false crimson_trapdoor:open=true \
|
||||
warped_trapdoor:open=false warped_trapdoor:open=true \
|
||||
bamboo_trapdoor:open=false bamboo_trapdoor:open=true \
|
||||
cherry_trapdoor:open=false cherry_trapdoor:open=true \
|
||||
pale_oak_trapdoor:open=false pale_oak_trapdoor:open=true \
|
||||
copper_trapdoor:open=false copper_trapdoor:open=true \
|
||||
exposed_copper_trapdoor:open=false exposed_copper_trapdoor:open=true \
|
||||
weathered_copper_trapdoor:open=false weathered_copper_trapdoor:open=true \
|
||||
oxidized_copper_trapdoor:open=false oxidized_copper_trapdoor:open=true \
|
||||
waxed_copper_trapdoor:open=false waxed_copper_trapdoor:open=true \
|
||||
waxed_exposed_copper_trapdoor:open=false waxed_exposed_copper_trapdoor:open=true \
|
||||
waxed_weathered_copper_trapdoor:open=false waxed_weathered_copper_trapdoor:open=true \
|
||||
waxed_oxidized_copper_trapdoor:open=false waxed_oxidized_copper_trapdoor:open=true
|
||||
|
||||
# Rails — ID 18
|
||||
block.18 = rail powered_rail detector_rail activator_rail
|
||||
|
||||
# Redstone components — ID 19
|
||||
block.19 = redstone_wire redstone_lamp:lit=false redstone_lamp:lit=true lever oak_button spruce_button birch_button jungle_button acacia_button dark_oak_button mangrove_button cherry_button crimson_button warped_button bamboo_button stone_button polished_blackstone_button \
|
||||
oak_pressure_plate spruce_pressure_plate birch_pressure_plate jungle_pressure_plate acacia_pressure_plate dark_oak_pressure_plate mangrove_pressure_plate cherry_pressure_plate pale_oak_pressure_plate \
|
||||
crimson_pressure_plate warped_pressure_plate bamboo_pressure_plate \
|
||||
stone_pressure_plate polished_blackstone_pressure_plate light_weighted_pressure_plate heavy_weighted_pressure_plate \
|
||||
tripwire tripwire_hook \
|
||||
repeater comparator daylight_detector
|
||||
|
||||
# End rod — ID 20
|
||||
block.20 = end_rod
|
||||
|
||||
# Chain — ID 21
|
||||
block.21 = chain
|
||||
|
||||
# Amethyst cluster and buds — ID 22
|
||||
block.22 = amethyst_cluster small_amethyst_bud medium_amethyst_bud large_amethyst_bud
|
||||
|
||||
# Candle — ID 23
|
||||
block.23 = candle:lit=true white_candle:lit=true orange_candle:lit=true magenta_candle:lit=true light_blue_candle:lit=true yellow_candle:lit=true lime_candle:lit=true pink_candle:lit=true gray_candle:lit=true light_gray_candle:lit=true cyan_candle:lit=true purple_candle:lit=true blue_candle:lit=true brown_candle:lit=true green_candle:lit=true red_candle:lit=true black_candle:lit=true
|
||||
|
||||
# Glowstone / Sea lantern — ID 24
|
||||
block.24 = glowstone sea_lantern
|
||||
|
||||
# Light block (vanilla light block) — ID 25
|
||||
block.25 = light
|
||||
|
||||
# End portal / Nether portal — ID 26
|
||||
block.26 = end_portal nether_portal
|
||||
|
||||
# Ladder — ID 27
|
||||
block.27 = ladder
|
||||
|
||||
# Sugar cane — ID 28
|
||||
block.28 = sugar_cane
|
||||
|
||||
# Bamboo — ID 29
|
||||
block.29 = bamboo
|
||||
|
||||
# Cactus — ID 30
|
||||
block.30 = cactus
|
||||
|
||||
# Chorus — ID 31
|
||||
block.31 = chorus_plant chorus_flower
|
||||
|
||||
# Coral — ID 32
|
||||
block.32 = tube_coral brain_coral bubble_coral fire_coral horn_coral tube_coral_fan brain_coral_fan bubble_coral_fan fire_coral_fan horn_coral_fan \
|
||||
tube_coral_wall_fan brain_coral_wall_fan bubble_coral_wall_fan fire_coral_wall_fan horn_coral_wall_fan \
|
||||
dead_tube_coral dead_brain_coral dead_bubble_coral dead_fire_coral dead_horn_coral dead_tube_coral_fan dead_brain_coral_fan dead_bubble_coral_fan dead_fire_coral_fan dead_horn_coral_fan \
|
||||
dead_tube_coral_wall_fan dead_brain_coral_wall_fan dead_bubble_coral_wall_fan dead_fire_coral_wall_fan dead_horn_coral_wall_fan coral_block
|
||||
|
||||
# Pointed dripstone — ID 33
|
||||
block.33 = pointed_dripstone
|
||||
|
||||
# Conduit — ID 34
|
||||
block.34 = conduit
|
||||
|
||||
# Lightning rod — ID 35
|
||||
block.35 = lightning_rod
|
||||
|
||||
# Decorated pot — ID 36
|
||||
block.36 = decorated_pot
|
||||
|
||||
# Snow layers — ID 37
|
||||
block.37 = snow:layers=1 snow:layers=2 snow:layers=3 snow:layers=4 snow:layers=5 snow:layers=6 snow:layers=7
|
||||
|
||||
# Moss/Spore things — ID 38
|
||||
block.38 = moss_carpet spore_blossom
|
||||
|
||||
# Big dripleaf — ID 39
|
||||
block.39 = big_dripleaf small_dripleaf
|
||||
|
||||
# Hanging roots — ID 40
|
||||
block.40 = hanging_roots
|
||||
|
||||
# Rooted dirt — ID 41
|
||||
block.41 = rooted_dirt
|
||||
|
||||
# Cave vines — ID 42
|
||||
block.42 = cave_vines cave_vines_plant
|
||||
|
||||
# Glow lichen — ID 43
|
||||
block.43 = glow_lichen
|
||||
|
||||
# Sculk — ID 44
|
||||
block.44 = sculk_vein
|
||||
|
||||
# Mangrove propagule — ID 45
|
||||
block.45 = mangrove_propagule:stage=0 mangrove_propagule:stage=1 mangrove_propagule:stage=2 mangrove_propagule:stage=3 mangrove_propagule:stage=4
|
||||
|
||||
# Azalea — ID 46
|
||||
block.46 = azalea flowering_azalea
|
||||
|
||||
# Big dripleaf stem — ID 47
|
||||
block.47 = big_dripleaf_stem
|
||||
|
||||
# Spawner — ID 48
|
||||
block.48 = spawner
|
||||
|
||||
# Barrier — ID 49
|
||||
block.49 = barrier
|
||||
|
||||
# Structure void — ID 50
|
||||
block.50 = structure_void
|
||||
|
||||
# Beacon — ID 51
|
||||
block.51 = beacon
|
||||
|
||||
# Piston — ID 52
|
||||
block.52 = piston_head:type=normal sticky_piston_head:type=sticky piston:extended=false piston:extended=true sticky_piston:extended=false sticky_piston:extended=true moving_piston
|
||||
|
||||
# Observer — ID 53
|
||||
block.53 = observer
|
||||
|
||||
# Dropper / Dispenser — ID 54
|
||||
block.54 = dropper dispenser
|
||||
|
||||
# Hopper — ID 55
|
||||
block.55 = hopper
|
||||
|
||||
# Cauldron — ID 56
|
||||
block.56 = cauldron water_cauldron lava_cauldron powder_snow_cauldron
|
||||
|
||||
# Brewing stand — ID 57
|
||||
block.57 = brewing_stand
|
||||
|
||||
# Enchanting table — ID 58
|
||||
block.58 = enchanting_table
|
||||
|
||||
# Anvil — ID 59
|
||||
block.59 = anvil chipped_anvil damaged_anvil
|
||||
|
||||
# Ender chest — ID 60
|
||||
block.60 = ender_chest
|
||||
|
||||
# Chest — ID 61
|
||||
block.61 = chest trapped_chest
|
||||
|
||||
# Crafting table — ID 62
|
||||
block.62 = crafting_table
|
||||
|
||||
# Furnace — ID 63
|
||||
block.63 = furnace blast_furnace smoker
|
||||
|
||||
# Lectern — ID 64
|
||||
block.64 = lectern
|
||||
|
||||
# Grindstone — ID 65
|
||||
block.65 = grindstone
|
||||
|
||||
# Stonecutter — ID 66
|
||||
block.66 = stonecutter
|
||||
|
||||
# Loom — ID 67
|
||||
block.67 = loom
|
||||
|
||||
# Smithing table — ID 68
|
||||
block.68 = smithing_table
|
||||
|
||||
# Composter — ID 69
|
||||
block.69 = composter
|
||||
|
||||
# Jukebox — ID 70
|
||||
block.70 = jukebox
|
||||
|
||||
# Bell — ID 71
|
||||
block.71 = bell
|
||||
|
||||
# Lantern (non-emissive) — ID 72
|
||||
block.72 = lantern soul_lantern
|
||||
|
||||
# Note block — ID 73
|
||||
block.73 = note_block
|
||||
|
||||
# Big dripleaf — ID 74
|
||||
block.74 = big_dripleaf
|
||||
|
||||
# Pink petals — ID 75
|
||||
block.75 = pink_petals
|
||||
|
||||
# Torchflower — ID 76
|
||||
block.76 = torchflower_crop
|
||||
|
||||
# Pitcher plant — ID 77
|
||||
block.77 = pitcher_crop pitcher_plant
|
||||
|
||||
# Frogspawn — ID 78
|
||||
block.78 = frogspawn
|
||||
|
||||
# Turtle egg — ID 79
|
||||
block.79 = turtle_egg sniffer_egg
|
||||
|
||||
# Cobweb — ID 80
|
||||
block.80 = cobweb
|
||||
|
||||
# Daylight sensor — ID 81
|
||||
block.81 = daylight_detector
|
||||
|
||||
# Respawn anchor — ID 82
|
||||
block.82 = respawn_anchor:charges=0 respawn_anchor:charges=1 respawn_anchor:charges=2 respawn_anchor:charges=3 respawn_anchor:charges=4
|
||||
|
||||
# Lodestone — ID 83
|
||||
block.83 = lodestone
|
||||
|
||||
# Target — ID 84
|
||||
block.84 = target
|
||||
|
||||
# End portal frame — ID 85
|
||||
block.85 = end_portal_frame
|
||||
|
||||
# Dragon egg — ID 86
|
||||
block.86 = dragon_egg
|
||||
|
||||
# Powder snow — ID 87
|
||||
block.87 = powder_snow
|
||||
|
||||
# Decorated pot — ID 88
|
||||
block.88 = decorated_pot
|
||||
|
||||
# Calibrated sculk sensor — ID 89
|
||||
block.89 = calibrated_sculk_sensor
|
||||
|
||||
# Chiseled bookshelf — ID 90
|
||||
block.90 = chiseled_bookshelf
|
||||
|
||||
# Suspicious sand/gravel — ID 91
|
||||
block.91 = suspicious_sand suspicious_gravel
|
||||
|
||||
# Crafter — ID 92
|
||||
block.92 = crafter
|
||||
|
||||
# Trial spawner — ID 93
|
||||
block.93 = trial_spawner vault
|
||||
|
||||
# Heavy core — ID 94
|
||||
block.94 = heavy_core
|
||||
|
||||
# Resin — ID 95
|
||||
block.95 = resin_block resin_bricks chiseled_resin_bricks resin_brick_slab:type=bottom resin_brick_stairs resin_brick_wall
|
||||
|
||||
# Pale moss — ID 96
|
||||
block.96 = pale_moss_block pale_moss_carpet
|
||||
|
||||
# Creeper head / skeleton skull / etc — ID 97
|
||||
block.97 = skeleton_skull wither_skeleton_skull creeper_head zombie_head player_head dragon_head piglin_head skeleton_wall_skull wither_skeleton_wall_skull creeper_wall_head zombie_wall_head player_wall_head dragon_wall_head piglin_wall_head
|
||||
|
||||
# Banner — ID 98
|
||||
block.98 = white_banner orange_banner magenta_banner light_blue_banner yellow_banner lime_banner pink_banner gray_banner light_gray_banner cyan_banner purple_banner blue_banner brown_banner green_banner red_banner black_banner \
|
||||
white_wall_banner orange_wall_banner magenta_wall_banner light_blue_wall_banner yellow_wall_banner lime_wall_banner pink_wall_banner gray_wall_banner light_gray_wall_banner cyan_wall_banner purple_wall_banner blue_wall_banner brown_wall_banner green_wall_banner red_wall_banner black_wall_banner
|
||||
|
||||
# Sign — ID 99
|
||||
block.99 = oak_sign spruce_sign birch_sign jungle_sign acacia_sign dark_oak_sign mangrove_sign cherry_sign pale_oak_sign crimson_sign warped_sign bamboo_sign \
|
||||
oak_wall_sign spruce_wall_sign birch_wall_sign jungle_wall_sign acacia_wall_sign dark_oak_wall_sign mangrove_wall_sign cherry_wall_sign pale_oak_wall_sign crimson_wall_sign warped_wall_sign bamboo_wall_sign \
|
||||
oak_hanging_sign spruce_hanging_sign birch_hanging_sign jungle_hanging_sign acacia_hanging_sign dark_oak_hanging_sign mangrove_hanging_sign cherry_hanging_sign pale_oak_hanging_sign crimson_hanging_sign warped_hanging_sign bamboo_hanging_sign \
|
||||
oak_wall_hanging_sign spruce_wall_hanging_sign birch_wall_hanging_sign jungle_wall_hanging_sign acacia_wall_hanging_sign dark_oak_wall_hanging_sign mangrove_wall_hanging_sign cherry_wall_hanging_sign pale_oak_wall_hanging_sign crimson_wall_hanging_sign warped_wall_hanging_sign bamboo_wall_hanging_sign
|
||||
|
||||
# Cake — ID 100
|
||||
block.100 = cake
|
||||
|
||||
# Sea pickle — ID 101
|
||||
block.101 = sea_pickle
|
||||
|
||||
# Kelp — ID 102
|
||||
block.102 = kelp kelp_plant
|
||||
|
||||
# Seagrass — ID 103
|
||||
block.103 = seagrass tall_seagrass
|
||||
|
||||
# Redstone ore (glows when touched) — ID 104
|
||||
block.104 = redstone_ore:lit=true deepslate_redstone_ore:lit=true
|
||||
|
||||
# End gateway — ID 105
|
||||
block.105 = end_gateway
|
||||
|
||||
# Light block — ID 106
|
||||
block.106 = light
|
||||
|
||||
# Structure block — ID 107
|
||||
block.107 = structure_block jigsaw
|
||||
|
||||
# Command block — ID 108
|
||||
block.108 = command_block chain_command_block repeating_command_block
|
||||
|
||||
# Debug stick — not a block
|
||||
|
||||
# Sculk sensor — ID 109
|
||||
block.109 = sculk_sensor
|
||||
|
||||
# Sculk shrieker — ID 110
|
||||
block.110 = sculk_shrieker
|
||||
|
||||
# Mangrove roots — ID 111
|
||||
block.111 = mangrove_roots muddy_mangrove_roots
|
||||
|
||||
# Bricks — ID 112
|
||||
block.112 = bricks
|
||||
|
||||
# Mud bricks — ID 113
|
||||
block.113 = mud_bricks
|
||||
|
||||
# Resin bricks — ID 114
|
||||
block.114 = resin_bricks chiseled_resin_bricks
|
||||
|
||||
# Tuff bricks — ID 115
|
||||
block.115 = tuff_bricks chiseled_tuff_bricks
|
||||
|
||||
# Polished tuff — ID 116
|
||||
block.116 = polished_tuff tuff_slab:type=bottom?
|
||||
|
||||
# Deeplslate — ID 117
|
||||
block.117 = deepslate_deepslate
|
||||
|
||||
# Calcite — ID 118
|
||||
block.118 = calcite
|
||||
|
||||
# Dripstone block — ID 119
|
||||
block.119 = dripstone_block
|
||||
|
||||
# Smooth basalt — ID 120
|
||||
block.120 = smooth_basalt
|
||||
|
||||
# Many more blocks... but these cover the essentials.
|
||||
|
||||
# Light block variants (8000-8015 for light level 0-15)
|
||||
block.8000 = light:level=0
|
||||
block.8001 = light:level=1
|
||||
block.8002 = light:level=2
|
||||
block.8003 = light:level=3
|
||||
block.8004 = light:level=4
|
||||
block.8005 = light:level=5
|
||||
block.8006 = light:level=6
|
||||
block.8007 = light:level=7
|
||||
block.8008 = light:level=8
|
||||
block.8009 = light:level=9
|
||||
block.8010 = light:level=10
|
||||
block.8011 = light:level=11
|
||||
block.8012 = light:level=12
|
||||
block.8013 = light:level=13
|
||||
block.8014 = light:level=14
|
||||
block.8015 = light:level=15
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
|
||||
/* RENDERTARGETS: 7 */
|
||||
|
||||
#include "/Lib/Programs/Composite/DiffuseTemporal_FS.glsl"
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
|
||||
/* RENDERTARGETS: 8 */
|
||||
|
||||
#include "/Lib/Programs/Composite/DiffuseVariance_FS.glsl"
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
#define SPATIAL_STEP_1
|
||||
|
||||
/* RENDERTARGETS: 7 */
|
||||
|
||||
#include "/Lib/Programs/Composite/DiffuseSpatial_FS.glsl"
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
#define SPATIAL_STEP_2
|
||||
|
||||
/* RENDERTARGETS: 7 */
|
||||
|
||||
#include "/Lib/Programs/Composite/DiffuseSpatial_FS.glsl"
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
#define SPATIAL_STEP_4
|
||||
|
||||
/* RENDERTARGETS: 7 */
|
||||
|
||||
#include "/Lib/Programs/Composite/DiffuseSpatial_FS.glsl"
|
||||
@@ -0,0 +1,8 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
#define SPATIAL_STEP_8
|
||||
|
||||
/* RENDERTARGETS: 7 */
|
||||
|
||||
#include "/Lib/Programs/Composite/DiffuseSpatial_FS.glsl"
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
|
||||
/* RENDERTARGETS: 12 */
|
||||
|
||||
#include "/Lib/Programs/Composite/Sky_Overworld_FS.glsl"
|
||||
@@ -0,0 +1,7 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
|
||||
/* RENDERTARGETS: 12 */
|
||||
|
||||
#include "/Lib/Programs/Composite/Soild_FS.glsl"
|
||||
@@ -0,0 +1,5 @@
|
||||
#version 430
|
||||
|
||||
#define DIMENSION_OVERWORLD
|
||||
|
||||
#include "/Lib/Programs/Composite/VoxelData_Copy_CS.glsl"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user