Initial commit: Minecraft 光追着色器包(从零实现的 path tracing)

This commit is contained in:
WpyQwq
2026-09-19 12:06:22 +08:00
commit 59e30822f8
314 changed files with 9259 additions and 0 deletions
@@ -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
+37
View File
@@ -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