dof
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
//!
|
||||
//! ## Uniform Contract
|
||||
//! Four bind groups, shared by every material (one single pipeline layout — voir Étape 3) :
|
||||
//! - `@group(0) @binding(0)` : `FrameUniforms` (per-frame, camera + lights + shadow) [784 bytes]
|
||||
//! - `@group(0) @binding(0)` : `FrameUniforms` (per-frame, camera + lights + shadow + fog) [816 bytes]
|
||||
//! - `@group(1) @binding(0)` : `ObjectUniform` (per-entity model matrix) [64 bytes]
|
||||
//! - `@group(2) @binding(0)` : `texture_sampler` (sampler) — diffuse (Étape 10)
|
||||
//! - `@group(2) @binding(1)` : `diffuse_texture` (texture_2d<f32>) (Étape 10)
|
||||
@@ -93,6 +93,8 @@ struct FrameUniforms {
|
||||
light_view_proj: mat4x4<f32>, // world → shadow light clip space (Étape 14, D3)
|
||||
shadow_params: vec4<f32>, // .x = map size, .y = constant bias, .z = slope bias
|
||||
options: vec4<u32>, // .x = unlit flag ; .y = shadows on
|
||||
fog_a: vec4<f32>, // .x=enabled .y=mode .z=near .w=far (Étape 25)
|
||||
fog_b: vec4<f32>, // .x=density .y/.z/.w=fog color RGB (Étape 25)
|
||||
};
|
||||
|
||||
struct ObjectUniform {
|
||||
@@ -151,7 +153,8 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
// Flat (unlit) mode : pas d'éclairage, texel * couleur du vertex + emissive.
|
||||
if (frame.options.x != 0u) {
|
||||
let emissive_contrib = base * object.emissive.rgb * object.emissive.a;
|
||||
return vec4<f32>(base + emissive_contrib, in.color.a);
|
||||
let final_rgb = base + emissive_contrib;
|
||||
return vec4<f32>(apply_fog(final_rgb, in.world_pos), in.color.a);
|
||||
}
|
||||
|
||||
let n = normalize(in.normal);
|
||||
@@ -208,7 +211,32 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
// Étape 22 (6.2): emissive — added to the lit result (independent of lights/shadows).
|
||||
// Zero emissive (default) → no change (non-regression). In HDR, intensity > 1.0 glows.
|
||||
let emissive_contrib = base * object.emissive.rgb * object.emissive.a;
|
||||
return vec4<f32>(lit + emissive_contrib, in.color.a);
|
||||
let final_rgb = lit + emissive_contrib;
|
||||
return vec4<f32>(apply_fog(final_rgb, in.world_pos), in.color.a);
|
||||
}
|
||||
|
||||
// Étape 25 : distance fog. Blends the final color toward the fog color based on the
|
||||
// fragment's distance from the camera. Three modes: linear, exponential, exponential².
|
||||
// When `fog_a.x == 0` (disabled), returns the input color unchanged — zero cost.
|
||||
fn apply_fog(color: vec3<f32>, world_pos: vec3<f32>) -> vec3<f32> {
|
||||
if (frame.fog_a.x < 0.5) {
|
||||
return color;
|
||||
}
|
||||
let dist = length(world_pos - frame.cam_pos.xyz);
|
||||
var fog_factor: f32;
|
||||
if (frame.fog_a.y < 0.5) {
|
||||
// Linear: 1.0 at near, 0.0 at far.
|
||||
fog_factor = saturate((frame.fog_a.w - dist) / max(frame.fog_a.w - frame.fog_a.z, 1e-4));
|
||||
} else if (frame.fog_a.y < 1.5) {
|
||||
// Exponential: exp(-density * distance).
|
||||
fog_factor = exp(-frame.fog_b.x * dist);
|
||||
} else {
|
||||
// Exponential²: exp(-density² * distance²) — sharper cutoff.
|
||||
let d2 = frame.fog_b.x * frame.fog_b.x;
|
||||
fog_factor = exp(-d2 * dist * dist);
|
||||
}
|
||||
let fog_color = frame.fog_b.yzw;
|
||||
return mix(color, fog_color, 1.0 - fog_factor);
|
||||
}
|
||||
|
||||
// Étape 14 (DRAFT 3.2, D5) : PCF shadow factor for this fragment. Reprojects the world position
|
||||
|
||||
Reference in New Issue
Block a user