Resolution override (#19817)
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com> Co-authored-by: atlv <email@atlasdostal.com>
This commit is contained in:
parent
410ca48023
commit
a0b90cd618
@ -4,7 +4,7 @@ use crate::{
|
||||
};
|
||||
use bevy_ecs::{prelude::World, query::QueryItem};
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
diagnostic::RecordDiagnostics,
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
render_phase::{TrackedRenderPass, ViewBinnedRenderPhases},
|
||||
@ -31,6 +31,7 @@ impl ViewNode for MainOpaquePass3dNode {
|
||||
Option<&'static SkyboxPipelineId>,
|
||||
Option<&'static SkyboxBindGroup>,
|
||||
&'static ViewUniformOffset,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
);
|
||||
|
||||
fn run<'w>(
|
||||
@ -45,6 +46,7 @@ impl ViewNode for MainOpaquePass3dNode {
|
||||
skybox_pipeline,
|
||||
skybox_bind_group,
|
||||
view_uniform_offset,
|
||||
resolution_override,
|
||||
): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
@ -90,7 +92,7 @@ impl ViewNode for MainOpaquePass3dNode {
|
||||
let pass_span = diagnostics.pass_span(&mut render_pass, "main_opaque_pass_3d");
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
// Opaque draws
|
||||
|
@ -3,7 +3,7 @@ use crate::core_3d::Transmissive3d;
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_image::ToExtents;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
render_phase::ViewSortedRenderPhases,
|
||||
render_resource::{RenderPassDescriptor, StoreOp},
|
||||
@ -28,13 +28,16 @@ impl ViewNode for MainTransmissivePass3dNode {
|
||||
&'static ViewTarget,
|
||||
Option<&'static ViewTransmissionTexture>,
|
||||
&'static ViewDepthTexture,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
(camera, view, camera_3d, target, transmission, depth): QueryItem<Self::ViewQuery>,
|
||||
(camera, view, camera_3d, target, transmission, depth, resolution_override): QueryItem<
|
||||
Self::ViewQuery,
|
||||
>,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let view_entity = graph.view_entity();
|
||||
@ -108,7 +111,7 @@ impl ViewNode for MainTransmissivePass3dNode {
|
||||
render_context.begin_tracked_render_pass(render_pass_descriptor);
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
if let Err(err) = transmissive_phase.render(&mut render_pass, world, view_entity) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::core_3d::Transparent3d;
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
diagnostic::RecordDiagnostics,
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
render_phase::ViewSortedRenderPhases,
|
||||
@ -24,12 +24,13 @@ impl ViewNode for MainTransparentPass3dNode {
|
||||
&'static ExtractedView,
|
||||
&'static ViewTarget,
|
||||
&'static ViewDepthTexture,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
);
|
||||
fn run(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
(camera, view, target, depth): QueryItem<Self::ViewQuery>,
|
||||
(camera, view, target, depth, resolution_override): QueryItem<Self::ViewQuery>,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let view_entity = graph.view_entity();
|
||||
@ -69,7 +70,7 @@ impl ViewNode for MainTransparentPass3dNode {
|
||||
let pass_span = diagnostics.pass_span(&mut render_pass, "main_transparent_pass_3d");
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
if let Err(err) = transparent_phase.render(&mut render_pass, world, view_entity) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_render::camera::MainPassResolutionOverride;
|
||||
use bevy_render::experimental::occlusion_culling::OcclusionCulling;
|
||||
use bevy_render::render_graph::ViewNode;
|
||||
|
||||
@ -66,6 +67,7 @@ impl ViewNode for LateDeferredGBufferPrepassNode {
|
||||
&'static ExtractedView,
|
||||
&'static ViewDepthTexture,
|
||||
&'static ViewPrepassTextures,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
Has<OcclusionCulling>,
|
||||
Has<NoIndirectDrawing>,
|
||||
);
|
||||
@ -77,7 +79,7 @@ impl ViewNode for LateDeferredGBufferPrepassNode {
|
||||
view_query: QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let (_, _, _, _, occlusion_culling, no_indirect_drawing) = view_query;
|
||||
let (.., occlusion_culling, no_indirect_drawing) = view_query;
|
||||
if !occlusion_culling || no_indirect_drawing {
|
||||
return Ok(());
|
||||
}
|
||||
@ -105,7 +107,7 @@ impl ViewNode for LateDeferredGBufferPrepassNode {
|
||||
fn run_deferred_prepass<'w>(
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, extracted_view, view_depth_texture, view_prepass_textures, _, _): QueryItem<
|
||||
(camera, extracted_view, view_depth_texture, view_prepass_textures, resolution_override, _, _): QueryItem<
|
||||
'w,
|
||||
'_,
|
||||
<LateDeferredGBufferPrepassNode as ViewNode>::ViewQuery,
|
||||
@ -220,7 +222,7 @@ fn run_deferred_prepass<'w>(
|
||||
});
|
||||
let mut render_pass = TrackedRenderPass::new(&render_device, render_pass);
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
// Opaque draws
|
||||
|
@ -1,6 +1,6 @@
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
render_graph::{NodeRunError, RenderGraphContext, RenderLabel, ViewNode},
|
||||
render_resource::{BindGroupEntries, PipelineCache, RenderPassDescriptor},
|
||||
renderer::RenderContext,
|
||||
@ -23,13 +23,14 @@ impl ViewNode for OitResolveNode {
|
||||
&'static ViewUniformOffset,
|
||||
&'static OitResolvePipelineId,
|
||||
&'static ViewDepthTexture,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
(camera, view_target, view_uniform, oit_resolve_pipeline_id, depth): QueryItem<
|
||||
(camera, view_target, view_uniform, oit_resolve_pipeline_id, depth, resolution_override): QueryItem<
|
||||
Self::ViewQuery,
|
||||
>,
|
||||
world: &World,
|
||||
@ -63,7 +64,7 @@ impl ViewNode for OitResolveNode {
|
||||
});
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
render_pass.set_render_pipeline(pipeline);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use bevy_ecs::{prelude::*, query::QueryItem};
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
diagnostic::RecordDiagnostics,
|
||||
experimental::occlusion_culling::OcclusionCulling,
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
@ -64,6 +64,7 @@ impl ViewNode for LatePrepassNode {
|
||||
Option<&'static RenderSkyboxPrepassPipeline>,
|
||||
Option<&'static SkyboxPrepassBindGroup>,
|
||||
Option<&'static PreviousViewUniformOffset>,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
Has<OcclusionCulling>,
|
||||
Has<NoIndirectDrawing>,
|
||||
Has<DeferredPrepass>,
|
||||
@ -78,7 +79,7 @@ impl ViewNode for LatePrepassNode {
|
||||
) -> Result<(), NodeRunError> {
|
||||
// We only need a late prepass if we have occlusion culling and indirect
|
||||
// drawing.
|
||||
let (_, _, _, _, _, _, _, _, _, occlusion_culling, no_indirect_drawing, _) = query;
|
||||
let (.., occlusion_culling, no_indirect_drawing, _) = query;
|
||||
if !occlusion_culling || no_indirect_drawing {
|
||||
return Ok(());
|
||||
}
|
||||
@ -109,6 +110,7 @@ fn run_prepass<'w>(
|
||||
skybox_prepass_pipeline,
|
||||
skybox_prepass_bind_group,
|
||||
view_prev_uniform_offset,
|
||||
resolution_override,
|
||||
_,
|
||||
_,
|
||||
has_deferred,
|
||||
@ -183,7 +185,7 @@ fn run_prepass<'w>(
|
||||
let pass_span = diagnostics.pass_span(&mut render_pass, label);
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
// Opaque draws
|
||||
|
@ -18,7 +18,7 @@ use bevy_ecs::{
|
||||
world::World,
|
||||
};
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
render_resource::{
|
||||
LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor,
|
||||
@ -42,6 +42,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||
&'static ViewLightProbesUniformOffset,
|
||||
&'static ViewScreenSpaceReflectionsUniformOffset,
|
||||
&'static ViewEnvironmentMapUniformOffset,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
&'static MeshletViewMaterialsMainOpaquePass,
|
||||
&'static MeshletViewBindGroups,
|
||||
&'static MeshletViewResources,
|
||||
@ -61,6 +62,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||
view_light_probes_offset,
|
||||
view_ssr_offset,
|
||||
view_environment_map_offset,
|
||||
resolution_override,
|
||||
meshlet_view_materials,
|
||||
meshlet_view_bind_groups,
|
||||
meshlet_view_resources,
|
||||
@ -101,7 +103,7 @@ impl ViewNode for MeshletMainOpaquePass3dNode {
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
render_pass.set_bind_group(
|
||||
@ -147,6 +149,7 @@ impl ViewNode for MeshletPrepassNode {
|
||||
&'static ViewPrepassTextures,
|
||||
&'static ViewUniformOffset,
|
||||
&'static PreviousViewUniformOffset,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
Has<MotionVectorPrepass>,
|
||||
&'static MeshletViewMaterialsPrepass,
|
||||
&'static MeshletViewBindGroups,
|
||||
@ -162,6 +165,7 @@ impl ViewNode for MeshletPrepassNode {
|
||||
view_prepass_textures,
|
||||
view_uniform_offset,
|
||||
previous_view_uniform_offset,
|
||||
resolution_override,
|
||||
view_has_motion_vector_prepass,
|
||||
meshlet_view_materials,
|
||||
meshlet_view_bind_groups,
|
||||
@ -219,7 +223,7 @@ impl ViewNode for MeshletPrepassNode {
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
if view_has_motion_vector_prepass {
|
||||
@ -270,6 +274,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode {
|
||||
&'static ViewPrepassTextures,
|
||||
&'static ViewUniformOffset,
|
||||
&'static PreviousViewUniformOffset,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
Has<MotionVectorPrepass>,
|
||||
&'static MeshletViewMaterialsDeferredGBufferPrepass,
|
||||
&'static MeshletViewBindGroups,
|
||||
@ -285,6 +290,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode {
|
||||
view_prepass_textures,
|
||||
view_uniform_offset,
|
||||
previous_view_uniform_offset,
|
||||
resolution_override,
|
||||
view_has_motion_vector_prepass,
|
||||
meshlet_view_materials,
|
||||
meshlet_view_bind_groups,
|
||||
@ -347,7 +353,7 @@ impl ViewNode for MeshletDeferredGBufferPrepassNode {
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
if view_has_motion_vector_prepass {
|
||||
|
@ -111,6 +111,17 @@ impl Viewport {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_override(
|
||||
&self,
|
||||
main_pass_resolution_override: Option<&MainPassResolutionOverride>,
|
||||
) -> Self {
|
||||
let mut viewport = self.clone();
|
||||
if let Some(override_size) = main_pass_resolution_override {
|
||||
viewport.physical_size = **override_size;
|
||||
}
|
||||
viewport
|
||||
}
|
||||
}
|
||||
|
||||
/// Settings to define a camera sub view.
|
||||
@ -1366,6 +1377,19 @@ impl TemporalJitter {
|
||||
#[reflect(Default, Component)]
|
||||
pub struct MipBias(pub f32);
|
||||
|
||||
/// Override the resolution a 3d camera's main pass is rendered at.
|
||||
///
|
||||
/// Does not affect post processing.
|
||||
///
|
||||
/// ## Usage
|
||||
///
|
||||
/// * Insert this component on a 3d camera entity in the render world.
|
||||
/// * The resolution override must be smaller than the camera's viewport size.
|
||||
/// * The resolution override is specified in physical pixels.
|
||||
#[derive(Component, Reflect, Deref)]
|
||||
#[reflect(Component)]
|
||||
pub struct MainPassResolutionOverride(pub UVec2);
|
||||
|
||||
impl Default for MipBias {
|
||||
fn default() -> Self {
|
||||
Self(-1.0)
|
||||
|
@ -29,6 +29,7 @@ impl Plugin for CameraPlugin {
|
||||
.register_type::<Exposure>()
|
||||
.register_type::<TemporalJitter>()
|
||||
.register_type::<MipBias>()
|
||||
.register_type::<MainPassResolutionOverride>()
|
||||
.init_resource::<ManualTextureViews>()
|
||||
.init_resource::<ClearColor>()
|
||||
.add_plugins((
|
||||
|
@ -34,7 +34,7 @@ use bevy::{
|
||||
},
|
||||
GetBatchData, GetFullBatchData,
|
||||
},
|
||||
camera::ExtractedCamera,
|
||||
camera::{ExtractedCamera, MainPassResolutionOverride},
|
||||
extract_component::{ExtractComponent, ExtractComponentPlugin},
|
||||
mesh::{allocator::MeshAllocator, MeshVertexBufferLayoutRef, RenderMesh},
|
||||
render_asset::RenderAssets,
|
||||
@ -589,13 +589,14 @@ impl ViewNode for CustomDrawNode {
|
||||
&'static ExtractedCamera,
|
||||
&'static ExtractedView,
|
||||
&'static ViewTarget,
|
||||
Option<&'static MainPassResolutionOverride>,
|
||||
);
|
||||
|
||||
fn run<'w>(
|
||||
&self,
|
||||
graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext<'w>,
|
||||
(camera, view, target): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
(camera, view, target, resolution_override): QueryItem<'w, '_, Self::ViewQuery>,
|
||||
world: &'w World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
// First, we need to get our phases resource
|
||||
@ -625,7 +626,7 @@ impl ViewNode for CustomDrawNode {
|
||||
});
|
||||
|
||||
if let Some(viewport) = camera.viewport.as_ref() {
|
||||
render_pass.set_camera_viewport(viewport);
|
||||
render_pass.set_camera_viewport(&viewport.with_override(resolution_override));
|
||||
}
|
||||
|
||||
// Render the phase
|
||||
|
Loading…
Reference in New Issue
Block a user