diff --git a/src/render/extract.rs b/src/render/extract.rs
index affd6750ee6c97491bef70e13593e5904e2fc35b..0833e9d2882f437407cbf2035a528fd95970d172 100644
--- a/src/render/extract.rs
+++ b/src/render/extract.rs
@@ -144,6 +144,7 @@ pub struct UIViewUniforms {
 #[derive(Clone, ShaderType)]
 pub struct UIViewUniform {
     pub view_proj: Mat4,
+    pub unjittered_view_proj: Mat4,
     pub inverse_view_proj: Mat4,
     pub view: Mat4,
     pub inverse_view: Mat4,
@@ -153,6 +154,7 @@ pub struct UIViewUniform {
     // viewport(x_origin, y_origin, width, height)
     pub viewport: Vec4,
     pub color_grading: ColorGrading,
+    pub mip_bias: f32,
 }
 
 #[derive(Component, Debug)]
@@ -160,16 +162,31 @@ pub struct UIViewUniformOffset {
     pub offset: u32,
 }
 
-fn prepare_view_uniforms(
+use bevy::math::Vec4Swizzles;
+use bevy::render::camera::{MipBias, TemporalJitter};
+
+pub fn prepare_view_uniforms(
     mut commands: Commands,
     render_device: Res<RenderDevice>,
     render_queue: Res<RenderQueue>,
     mut view_uniforms: ResMut<UIViewUniforms>,
-    views: Query<(Entity, &UIExtractedView)>,
+    views: Query<(
+        Entity,
+        &UIExtractedView,
+        Option<&TemporalJitter>,
+        Option<&MipBias>,
+    )>,
 ) {
     view_uniforms.uniforms.clear();
-    for (entity, camera) in &views {
-        let projection = camera.projection;
+    for (entity, camera, temporal_jitter, mip_bias) in &views {
+        let viewport = camera.viewport.as_vec4();
+        let unjittered_projection = camera.projection;
+        let mut projection = unjittered_projection;
+
+        if let Some(temporal_jitter) = temporal_jitter {
+            temporal_jitter.jitter_projection(&mut projection, viewport.zw());
+        }
+
         let inverse_projection = projection.inverse();
         let view = camera.transform.compute_matrix();
         let inverse_view = view.inverse();
@@ -178,14 +195,16 @@ fn prepare_view_uniforms(
                 view_proj: camera
                     .view_projection
                     .unwrap_or_else(|| projection * inverse_view),
+                unjittered_view_proj: unjittered_projection * inverse_view,
                 inverse_view_proj: view * inverse_projection,
                 view,
                 inverse_view,
                 projection,
                 inverse_projection,
                 world_position: camera.transform.translation(),
-                viewport: camera.viewport.as_vec4(),
+                viewport,
                 color_grading: camera.color_grading,
+                mip_bias: mip_bias.unwrap_or(&MipBias(0.0)).0,
             }),
         };
         commands.entity(entity).insert(view_uniforms);
diff --git a/src/render/mod.rs b/src/render/mod.rs
index 49a7bca4ab4b35612212f72006bd97f97d25f999..3bb49d8a620c1d5a997cffa058d2fb0f9de9afed 100644
--- a/src/render/mod.rs
+++ b/src/render/mod.rs
@@ -37,9 +37,6 @@ pub use opacity_layer::MAX_OPACITY_LAYERS;
 
 pub mod draw_ui_graph {
     pub const NAME: &str = "kayak_draw_ui";
-    pub mod input {
-        pub const VIEW_ENTITY: &str = "kayak_view_entity";
-    }
     pub mod node {
         pub const MAIN_PASS: &str = "kayak_ui_pass";
     }
diff --git a/src/render/ui_pass.rs b/src/render/ui_pass.rs
index e18f4e84bd3e1b907556e3ba2d8433a6bfdd765b..d12de7e035223f978dfff541a521d27e900390b0 100644
--- a/src/render/ui_pass.rs
+++ b/src/render/ui_pass.rs
@@ -8,7 +8,7 @@ use bevy::render::render_phase::{
 };
 use bevy::render::render_resource::{CachedRenderPipelineId, RenderPassColorAttachment};
 use bevy::render::{
-    render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
+    render_graph::{Node, NodeRunError, RenderGraphContext},
     render_phase::RenderPhase,
     render_resource::{LoadOp, Operations, RenderPassDescriptor},
     renderer::RenderContext,
@@ -170,8 +170,6 @@ pub struct MainPassUINode {
 }
 
 impl MainPassUINode {
-    pub const IN_VIEW: &'static str = "view";
-
     pub fn new(world: &mut World) -> Self {
         Self {
             query: world.query_filtered(),
@@ -180,10 +178,6 @@ impl MainPassUINode {
 }
 
 impl Node for MainPassUINode {
-    fn input(&self) -> Vec<SlotInfo> {
-        vec![SlotInfo::new(MainPassUINode::IN_VIEW, SlotType::Entity)]
-    }
-
     fn update(&mut self, world: &mut World) {
         self.query.update_archetypes(world);
     }
@@ -194,7 +188,7 @@ impl Node for MainPassUINode {
         render_context: &mut RenderContext,
         world: &World,
     ) -> Result<(), NodeRunError> {
-        let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
+        let view_entity = graph.view_entity();
         // adapted from bevy itself;
         // see: <https://github.com/bevyengine/bevy/commit/09a3d8abe062984479bf0e99fcc1508bb722baf6>
         let (transparent_phase, transparent_opacity_phase, target, _camera_ui) =
diff --git a/src/render/unified/shaders/bindings.wgsl b/src/render/unified/shaders/bindings.wgsl
index ff02245ed819811dc0aee948e01c24ed728b3ef8..8de802c35c05b4f3e4eba7b86fdf5334031b1dde 100644
--- a/src/render/unified/shaders/bindings.wgsl
+++ b/src/render/unified/shaders/bindings.wgsl
@@ -18,6 +18,9 @@ var<uniform> globals: Globals;
 
 struct QuadType {
     t: i32,
+    _padding_a: i32,
+    _padding_b: i32,
+    _padding_c: i32,
 };
 
 @group(2) @binding(0)
diff --git a/src/render/unified/shaders/sample_quad.wgsl b/src/render/unified/shaders/sample_quad.wgsl
index 7a8adee5d46b7e8e1a956695cd1a617272cbdf7c..fb7c8af679f895c8791709ba34595c945df75358 100644
--- a/src/render/unified/shaders/sample_quad.wgsl
+++ b/src/render/unified/shaders/sample_quad.wgsl
@@ -1,10 +1,6 @@
 #define_import_path kayak_ui::sample_quad
 
-#import kayak_ui::bindings font_texture
-#import kayak_ui::bindings font_sampler
-#import kayak_ui::bindings image_texture
-#import kayak_ui::bindings image_sampler
-#import kayak_ui::bindings quad_type
+#import kayak_ui::bindings font_texture, font_sampler, image_texture, image_sampler, quad_type
 
 #import kayak_ui::vertex_output VertexOutput
 
@@ -14,13 +10,13 @@ fn sdRoundBox(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32 {
     return min(max(q.x, q.y), 0.0) + length(max(q, vec2<f32>(0.0))) - r;
 }
 
-fn median3(v: vec3<f32>) -> f32 {
+fn median_three(v: vec3<f32>) -> f32 {
     return max(min(v.x, v.y), min(max(v.x, v.y), v.z));
 }
 
 fn sample_sdf(coords: vec2<f32>, arr: i32, scale: f32) -> f32 {
     let sample = textureSample(font_texture, font_sampler, vec2(coords.xy), arr);
-    return median3(sample.rgb);
+    return median_three(sample.rgb);
 }
 
 fn range_curve(font_size: f32) -> f32 {
diff --git a/src/render/unified/shaders/shader.wgsl b/src/render/unified/shaders/shader.wgsl
index de7b77442a5e7c31a60a006f5765257f78aee54b..8f0645bbe7b4e513f814c092224186458926dad6 100644
--- a/src/render/unified/shaders/shader.wgsl
+++ b/src/render/unified/shaders/shader.wgsl
@@ -1,4 +1,4 @@
-#import kayak_ui::bindings
+#import kayak_ui::bindings view
 
 #import kayak_ui::vertex_output VertexOutput
 
@@ -20,7 +20,7 @@ fn vertex(
     return out;
 }
 
-#import kayak_ui::sample_quad
+#import kayak_ui::sample_quad sample_quad
 
 @fragment
 fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {