use windows::Win32::Foundation::RECT;
use windows::Win32::Graphics::Direct3D12::*;
use crate::directx::context::DxContext;
use super::shadow::ShadowPassBinding;
impl DxContext {
pub(in crate::directx) fn encode_spot_shadow_pass(
&self,
cmd: &ID3D12GraphicsCommandList,
frame_idx: usize,
cam_pos: [f32; 3],
) {
let (Some(shadow_pso), Some(shadow_root_sig)) =
(self.shadow_pso.as_ref(), self.shadow_root_sig.as_ref())
else {
return;
};
let count = self.spot_shadow.count();
if count == 0 {
return;
}
let all = if count >= 32 {
u32::MAX
} else {
(1u32 << count) - 1
};
let mask = if self.spot_shadow.render_mask == 0 {
all
} else {
self.spot_shadow.render_mask
};
let sz = self.spot_shadow.slice_size;
unsafe {
let vp = D3D12_VIEWPORT {
TopLeftX: 0.0,
TopLeftY: 0.0,
Width: sz as f32,
Height: sz as f32,
MinDepth: 0.0,
MaxDepth: 1.0,
};
cmd.RSSetViewports(&[vp]);
let scissor = RECT {
left: 0,
top: 0,
right: sz as i32,
bottom: sz as i32,
};
cmd.RSSetScissorRects(&[scissor]);
cmd.IASetPrimitiveTopology(
windows::Win32::Graphics::Direct3D::D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
);
}
for slice in 0..count {
if mask & (1u32 << slice) == 0 {
continue;
}
let ubo_gva = self.spot_shadow.slice_ubo_gva(slice);
let dsv = self.spot_shadow.dsvs[slice as usize];
unsafe {
cmd.OMSetRenderTargets(0, None, false, Some(&dsv));
cmd.ClearDepthStencilView(dsv, D3D12_CLEAR_FLAG_DEPTH, 1.0, 0, None);
}
self.encode_shadow_casters_into(
cmd,
ShadowPassBinding {
pso: shadow_pso,
root_sig: shadow_root_sig,
ubo_gva,
},
cam_pos,
);
self.encode_shadow_skinned_into(cmd, ubo_gva, frame_idx, cam_pos);
}
}
}