// Distortion warp pass — M2 gate 5. // // Full-screen pass over the direct-mode surface (left half = left eye): // for each panel pixel, evaluate the S3-verified per-channel POLY3 warp // (EvalDistortion formula) to get three source UVs, sample the eye texture // once per channel (distortion + lateral CA in one pass), and apply // display_color_mult. Outside the source [0,1] range samples black // (border sampler) — matches the grown render-target bounds. // // Sampling: linear for the live pipeline (free AA); point mode for the // gate-A pixel-diff against the S3 generator. #pragma once #include #include #include "calib/hmd_config.h" namespace sauna { class WarpPass { public: bool init(ID3D12Device* dev, DXGI_FORMAT rtFormat, const HmdConfig& cfg); // Records the warp for one eye into its half of the output RT (assumed // RENDER_TARGET state, full panel width). eyeSrv = shader-visible GPU // handle of the eye texture SRV (caller's heap must be set). panelW/H = // full output surface size (e.g. 5088x2544). pointSample: gate-A mode. // r2Clamp: clamp r^2 at undistort_r2_cutoff (the Monado/mesh behavior the // S3 ComputeDistortion dump does NOT show — A/B switch for the eyes-in // periphery question; the poly is extrapolation beyond the cutoff). void record(ID3D12GraphicsCommandList* list, int eye, D3D12_GPU_DESCRIPTOR_HANDLE eyeSrv, uint32_t panelW, uint32_t panelH, bool pointSample = false, bool colorMult = true, bool r2Clamp = false); private: Microsoft::WRL::ComPtr rootSig_; Microsoft::WRL::ComPtr pso_; float consts_[2][20]; // per eye: cx, cy, scale, pad, kr[4], kg[4], kb[4], colorMult[4] }; } // namespace sauna