forked from 1b-agent/opencadstudio-upstream
feat(render): add relative-to-eye uniform fields (inert)
Append a rotation-only view-projection plus the eye split into high/low f32 (double-single) to the shared Uniforms buffer, and the matching Camera helpers (view_proj_rte, eye_high_low). Fields are added at the end so existing field offsets — and every shader still reading only the legacy view_proj — are unaffected. No shader consumes them yet; the wire pipeline migrates first in the next step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
091b8e1805
commit
8f16ba1ac2
2 files changed
+61
No files matched your search
@@ -26,6 +26,19 @@ pub struct Uniforms {
|
||||
/// Pads the struct to 112 B (next multiple of 16) so wgpu's uniform
|
||||
/// alignment rules are satisfied.
|
||||
pub _pad: [f32; 2],
|
||||
|
||||
// ── Relative-to-eye (double-single) additions ───────────────────────────
|
||||
// Appended at the end so existing field offsets are unchanged; shaders that
|
||||
// still read only the legacy fields keep working. Pipelines migrate to RTE
|
||||
// one at a time. `view_rot` is the rotation-only view-projection; vertices
|
||||
// pre-subtract the eye (via `eye_high`/`eye_low`, two f32 emulating f64) so
|
||||
// the large eye translation never enters the f32 matrix → no large-coord
|
||||
// jitter.
|
||||
pub view_rot: glam::Mat4,
|
||||
pub eye_high: [f32; 3],
|
||||
pub _pad_eh: f32,
|
||||
pub eye_low: [f32; 3],
|
||||
pub _pad_el: f32,
|
||||
}
|
||||
|
||||
impl Uniforms {
|
||||
@@ -36,6 +49,7 @@ impl Uniforms {
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let (eye_high, eye_low) = camera.eye_high_low();
|
||||
Self {
|
||||
view_proj: camera.view_proj(bounds),
|
||||
camera_pos: camera.position_vec4(),
|
||||
@@ -45,6 +59,11 @@ impl Uniforms {
|
||||
flat_shade: 0.0,
|
||||
transparency_enable: 1.0,
|
||||
_pad: [0.0; 2],
|
||||
view_rot: camera.view_proj_rte(bounds),
|
||||
eye_high,
|
||||
_pad_eh: 0.0,
|
||||
eye_low,
|
||||
_pad_el: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,6 +113,48 @@ impl Camera {
|
||||
OPENGL_TO_WGPU * proj * view
|
||||
}
|
||||
|
||||
/// Relative-to-eye view-projection: identical projection, but the view
|
||||
/// matrix carries rotation only (translation zeroed). Positions fed to it
|
||||
/// must already be expressed relative to the eye (done per-vertex with
|
||||
/// double-single precision in the shader), so the large eye translation
|
||||
/// never enters the f32 matrix and large-coordinate jitter disappears.
|
||||
#[allow(dead_code)] // consumed by the RTE uniform / shaders (next phase)
|
||||
pub fn view_proj_rte(&self, bounds: Rectangle) -> Mat4 {
|
||||
let near = self.distance * 0.001;
|
||||
let far = self.distance * 1000.0;
|
||||
let aspect = bounds.width / bounds.height;
|
||||
let up_dir = self.rotation * Vec3::Y;
|
||||
|
||||
let mut view = Mat4::look_at_rh(self.eye(), self.target.as_vec3(), up_dir);
|
||||
// Zero the translation column → pure rotation (world→view basis).
|
||||
view.w_axis = glam::vec4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
let proj = match self.projection {
|
||||
Projection::Perspective => Mat4::perspective_rh(self.fov_y, aspect, near, far),
|
||||
Projection::Orthographic => {
|
||||
let h = self.ortho_size();
|
||||
let w = h * aspect;
|
||||
Mat4::orthographic_rh(-w, w, -h, h, near, far)
|
||||
}
|
||||
};
|
||||
OPENGL_TO_WGPU * proj * view
|
||||
}
|
||||
|
||||
/// Eye position split into two f32 (high + low) emulating f64, for the
|
||||
/// double-single relative-to-eye shaders. `high + low ≈ eye` to ~f64
|
||||
/// precision; the shader subtracts these from each vertex's own high/low.
|
||||
#[allow(dead_code)] // consumed by the RTE uniform (next phase)
|
||||
pub fn eye_high_low(&self) -> ([f32; 3], [f32; 3]) {
|
||||
let e = self.eye_f64();
|
||||
let high = [e.x as f32, e.y as f32, e.z as f32];
|
||||
let low = [
|
||||
(e.x - high[0] as f64) as f32,
|
||||
(e.y - high[1] as f64) as f32,
|
||||
(e.z - high[2] as f64) as f32,
|
||||
];
|
||||
(high, low)
|
||||
}
|
||||
|
||||
/// Project a screen point onto an arbitrary world-space plane.
|
||||
///
|
||||
/// The plane is defined by `plane_normal` (unit vector) and a `plane_point`
|
||||
|
||||
Reference in new issue
Block a user