Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion assets/materials/building.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ struct VsOut {
@builtin(position) clip_pos: vec4<f32>,
@location(0) world_pos: vec3<f32>,
@location(1) world_normal: vec3<f32>,
// EN-022 — clip positions for motion vectors.
@location(2) curr_clip: vec4<f32>,
@location(3) prev_clip: vec4<f32>,
};

@vertex
Expand All @@ -28,6 +31,9 @@ fn vs_main(in: VertexInput) -> VsOut {
out.world_pos = world.xyz;
out.world_normal = normalize((draw.model * vec4<f32>(in.normal, 0.0)).xyz);
out.clip_pos = view.view_proj * world;
// EN-022 — static geometry: camera-reprojection motion vector.
out.curr_clip = out.clip_pos;
out.prev_clip = view.prev_view_proj * world;
return out;
}

Expand Down Expand Up @@ -99,7 +105,8 @@ fn fs_main(in: VsOut) -> OpaqueOut {
var out: OpaqueOut;
out.hdr = vec4<f32>(lit, 1.0);
out.material = vec2<f32>(0.0, 0.78); // non-metal, mid-roughness stone
out.velocity = vec2<f32>(0.0, 0.0);
// EN-022 — real motion vectors (see terrain.wgsl).
out.velocity = abi_motion_vector(in.curr_clip, in.prev_clip);
out.albedo = vec4<f32>(albedo, 1.0);
return out;
}
20 changes: 19 additions & 1 deletion assets/materials/grass_instanced.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ struct VsOut {
@location(1) world_normal: vec3<f32>,
@location(2) blade_tint: vec3<f32>,
@location(3) tip_weight: f32,
// EN-022 — clip positions for motion vectors.
@location(4) curr_clip: vec4<f32>,
@location(5) prev_clip: vec4<f32>,
};

@vertex
Expand Down Expand Up @@ -94,6 +97,20 @@ fn vs_main(in: InstancedVertexInput) -> VsOut {
out.clip_pos = view.view_proj * vec4<f32>(world, 1.0);
out.tip_weight = tip;
out.blade_tint = grass.base.rgb * in.instance_tint.rgb;

// EN-022 — previous-frame position: same sway one frame back
// (PerFrame.delta_time), projected by the previous VP. Sub-pixel
// blades finally carry real motion vectors so TAA's motion clamp
// engages (the audit's thin-grass shimmer mechanism).
let t_prev = frame.time - frame.delta_time;
let phase_p = dot(in.instance_pos.xz, frame.wind.xy * 0.6)
+ t_prev * frame.wind.w;
let sway_p = sin(phase_p) * frame.wind.z * tip;
let world_p = rotated
+ vec3<f32>(frame.wind.x, 0.0, frame.wind.y) * sway_p
+ in.instance_pos;
out.curr_clip = out.clip_pos;
out.prev_clip = view.prev_view_proj * vec4<f32>(world_p, 1.0);
return out;
}

Expand Down Expand Up @@ -152,7 +169,8 @@ fn fs_main(in: VsOut) -> OpaqueOut {
var out: OpaqueOut;
out.hdr = vec4<f32>(lit, 1.0);
out.material = vec2<f32>(0.0, 0.92);
out.velocity = vec2<f32>(0.0, 0.0);
// EN-022 — real motion vectors, including per-blade sway.
out.velocity = abi_motion_vector(in.curr_clip, in.prev_clip);
out.albedo = vec4<f32>(albedo, 1.0);
return out;
}
11 changes: 10 additions & 1 deletion assets/materials/terrain.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ struct VsOut {
@builtin(position) clip_pos: vec4<f32>,
@location(0) world_pos: vec3<f32>,
@location(1) world_normal: vec3<f32>,
// EN-022 — clip positions for motion vectors.
@location(2) curr_clip: vec4<f32>,
@location(3) prev_clip: vec4<f32>,
};

@vertex
Expand All @@ -37,6 +40,10 @@ fn vs_main(in: VertexInput) -> VsOut {
out.world_pos = world.xyz;
out.world_normal = normalize((draw.model * vec4<f32>(in.normal, 0.0)).xyz);
out.clip_pos = view.view_proj * world;
// EN-022 — static geometry: previous world == current world, so the
// motion vector is pure camera reprojection.
out.curr_clip = out.clip_pos;
out.prev_clip = view.prev_view_proj * world;
return out;
}

Expand Down Expand Up @@ -117,7 +124,9 @@ fn fs_main(in: VsOut) -> OpaqueOut {
var out: OpaqueOut;
out.hdr = vec4<f32>(lit, 1.0);
out.material = vec2<f32>(0.0, 0.95);
out.velocity = vec2<f32>(0.0, 0.0);
// EN-022 — real motion vectors: lets TAA's motion-adaptive clamp
// engage on the terrain (audit F8's shimmer mechanism).
out.velocity = abi_motion_vector(in.curr_clip, in.prev_clip);
out.albedo = vec4<f32>(final_albedo, 1.0);
return out;
}
19 changes: 18 additions & 1 deletion assets/materials/tree.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ struct VsOut {
@location(1) world_normal: vec3<f32>,
// local-y of the vertex — used in fs to blend trunk vs leaf colour
@location(2) local_y: f32,
// EN-022 — clip positions for motion vectors.
@location(3) curr_clip: vec4<f32>,
@location(4) prev_clip: vec4<f32>,
};

@vertex
Expand Down Expand Up @@ -61,6 +64,19 @@ fn vs_main(in: VertexInput) -> VsOut {
out.world_normal = world_normal;
out.clip_pos = view.view_proj * vec4<f32>(world_pos, 1.0);
out.local_y = in.position.y;

// EN-022 — previous-frame position: the same sway evaluated one
// frame back (PerFrame carries delta_time), projected by the
// previous VP. Wind sway finally produces real motion vectors
// instead of ghosting through TAA with velocity 0.
let t_prev = frame.time - frame.delta_time;
let big_p = sin(t_prev * tp.wind.w + phase);
let small_p = sin(t_prev * tp.wind.w * 2.7 + phase * 1.6) * 0.35;
let sway_prev = (big_p + small_p) * tp.wind.z * w;
let prev_world = (draw.model * vec4<f32>(in.position, 1.0)).xyz
+ vec3<f32>(tp.wind.x, 0.0, tp.wind.y) * sway_prev;
out.curr_clip = out.clip_pos;
out.prev_clip = view.prev_view_proj * vec4<f32>(prev_world, 1.0);
return out;
}

Expand Down Expand Up @@ -137,7 +153,8 @@ fn fs_main(in: VsOut) -> OpaqueOut {
var out: OpaqueOut;
out.hdr = vec4<f32>(lit, 1.0);
out.material = vec2<f32>(0.0, 0.85);
out.velocity = vec2<f32>(0.0, 0.0);
// EN-022 — real motion vectors, including the wind sway.
out.velocity = abi_motion_vector(in.curr_clip, in.prev_clip);
out.albedo = vec4<f32>(albedo, 1.0);
return out;
}
12 changes: 11 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,8 @@ const GRASS_INSTANCED_WGSL =
' @location(1) world_normal: vec3<f32>,\n' +
' @location(2) blade_tint: vec3<f32>,\n' +
' @location(3) tip_weight: f32,\n' +
' @location(4) curr_clip: vec4<f32>,\n' +
' @location(5) prev_clip: vec4<f32>,\n' +
'};\n' +
'\n' +
'@vertex fn vs_main(in: InstancedVertexInput) -> VsOut {\n' +
Expand All @@ -694,6 +696,14 @@ const GRASS_INSTANCED_WGSL =
' out.clip_pos = view.view_proj * vec4<f32>(world, 1.0);\n' +
' out.tip_weight = tip;\n' +
' out.blade_tint = grass.base.rgb * in.instance_tint.rgb;\n' +
// EN-022 — previous-frame sway → real motion vectors (mirrors
// assets/materials/grass_instanced.wgsl; keep in sync).
' let t_prev = frame.time - frame.delta_time;\n' +
' let phase_p = dot(in.instance_pos.xz, frame.wind.xy * 0.6) + t_prev * frame.wind.w;\n' +
' let sway_p = sin(phase_p) * frame.wind.z * tip;\n' +
' let world_p = rotated + vec3<f32>(frame.wind.x, 0.0, frame.wind.y) * sway_p + in.instance_pos;\n' +
' out.curr_clip = out.clip_pos;\n' +
' out.prev_clip = view.prev_view_proj * vec4<f32>(world_p, 1.0);\n' +
' return out;\n' +
'}\n' +
'\n' +
Expand Down Expand Up @@ -736,7 +746,7 @@ const GRASS_INSTANCED_WGSL =
' var out: OpaqueOut;\n' +
' out.hdr = vec4<f32>(lit, 1.0);\n' +
' out.material = vec2<f32>(0.0, 0.92);\n' +
' out.velocity = vec2<f32>(0.0, 0.0);\n' +
' out.velocity = abi_motion_vector(in.curr_clip, in.prev_clip);\n' +
' out.albedo = vec4<f32>(albedo, 1.0);\n' +
' return out;\n' +
'}\n';
Expand Down