c2cbd7fadb
Implement shadow mapping for directional lights: - Scene::set_shadow_caster(Option<usize>) selects the shadow-casting light by packed frame-array index (None disables; point lights rejected at render). - Lights::get(index) resolves a packed index across the directional/point/spot lists. - Renderer allocates a shadow depth map, comparison sampler, group-3 bind groups, shadow uniform buffer and shadow pipeline; render_scene does a depth-only shadow pass before the main pass; compute_shadow_light_view_proj builds an orthographic light-space frustum from the scene radius. - standard_shader: shadow_light_index/light_view_proj/shadow_params uniforms, @group(3) depth map + comparison sampler, 3x3 PCF compute_shadow(). - shadow_shader: path/vertex shader with attribute layout matching the shared vertex buffer (only position consumed). - shadow_test example: directional shadow caster casts a PCF-softened shadow onto a ground slab; documented in examples README.
57 lines
2.5 KiB
Rust
57 lines
2.5 KiB
Rust
//! # Validation WGSL (naga)
|
||
//!
|
||
//! Le shader `standard_shader.wgsl` n'est pas encore chargé par un `RenderPipeline` (voir Étapes 3–5) :
|
||
//! cette validation hors-ligne via `wgpu::naga` est donc la **seule** garantie de sa validité tant qu'il
|
||
//! n'est pas branché. Elle protège contre les régressions futures (ré-édition du shader, changement de
|
||
//! layout) sans nécessiter de contexte GPU.
|
||
//!
|
||
//! Aucune nouvelle dépendance n'est introduite : `wgpu` ré-exporte `naga`, déjà dépendance de `wsg-lib`.
|
||
|
||
use wgpu::naga;
|
||
|
||
/// Parse et valide complètement le shader embarqué `standard_shader.wgsl` via naga.
|
||
/// Un échec ici signifie que le shader serait rejeté par `Device::create_shader_module` à l'Étape 3.
|
||
#[test]
|
||
fn standard_shader_is_valid_wgsl() {
|
||
let src = include_str!("../src/shaders/standard_shader.wgsl");
|
||
let module = naga::front::wgsl::parse_str(src)
|
||
.unwrap_or_else(|e| panic!("standard_shader.wgsl : erreur de parsing : {e:?}"));
|
||
|
||
let mut validator = naga::valid::Validator::new(
|
||
naga::valid::ValidationFlags::all(),
|
||
naga::valid::Capabilities::all(),
|
||
);
|
||
validator
|
||
.validate(&module)
|
||
.unwrap_or_else(|e| panic!("standard_shader.wgsl : échec de validation : {e:?}"));
|
||
|
||
// Contrat : exactement les deux entrées vs_main / fs_main attendues.
|
||
assert!(module.entry_points.len() >= 2, "vs_main + fs_main attendus");
|
||
}
|
||
|
||
/// Parse et valide complètement le shader embarqué `shadow_shader.wgsl` (Étape 14, D4) via naga.
|
||
/// Le pipeline « shadow » est câblé directement par `build_shadow_pipeline` (sans passer par le
|
||
/// PipelineCache), donc cette validation hors-ligne est la garantie de sa validité. Le contrat
|
||
/// n'attend qu'une seule entrée (`vs_main` — pipeline sans fragment stage).
|
||
#[test]
|
||
fn shadow_shader_is_valid_wgsl() {
|
||
let src = include_str!("../src/shaders/shadow_shader.wgsl");
|
||
let module = naga::front::wgsl::parse_str(src)
|
||
.unwrap_or_else(|e| panic!("shadow_shader.wgsl : erreur de parsing : {e:?}"));
|
||
|
||
let mut validator = naga::valid::Validator::new(
|
||
naga::valid::ValidationFlags::all(),
|
||
naga::valid::Capabilities::all(),
|
||
);
|
||
validator
|
||
.validate(&module)
|
||
.unwrap_or_else(|e| panic!("shadow_shader.wgsl : échec de validation : {e:?}"));
|
||
|
||
let entry_names: Vec<&str> = module
|
||
.entry_points
|
||
.iter()
|
||
.map(|ep| ep.name.as_str())
|
||
.collect();
|
||
assert_eq!(entry_names, vec!["vs_main"], "seule vs_main attendue");
|
||
}
|