diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index 7b15daff379..f8fe2ef1242 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -1035,6 +1035,28 @@ class RENDER_PT_eevee_performance(RenderButtonsPanel, Panel): layout.prop(rd, "use_high_quality_normals") +class RENDER_PT_eevee_performance_viewport(RenderButtonsPanel, Panel): + bl_label = "Viewport" + bl_parent_id = "RENDER_PT_eevee_performance" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'} + + @classmethod + def poll(cls, context): + return (context.engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + scene = context.scene + rd = scene.render + + col = layout.column() + col.prop(rd, "preview_pixel_size", text="Pixel Size") + + class RENDER_PT_gpencil(RenderButtonsPanel, Panel): bl_label = "Grease Pencil" bl_options = {'DEFAULT_CLOSED'} @@ -1273,6 +1295,7 @@ classes = ( RENDER_PT_eevee_next_volumes_lighting, RENDER_PT_eevee_next_volumes_shadows, RENDER_PT_eevee_performance, + RENDER_PT_eevee_performance_viewport, RENDER_PT_eevee_hair, RENDER_PT_eevee_shadows, RENDER_PT_eevee_next_lights, diff --git a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl index c6408a630af..c7f94cc3178 100644 --- a/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/closure_type_lib.glsl @@ -51,6 +51,7 @@ vec3 coordinate_camera(vec3 P); vec3 coordinate_screen(vec3 P); vec3 coordinate_reflect(vec3 P, vec3 N); vec3 coordinate_incoming(vec3 P); +float film_scaling_factor_get(); /* Single BSDFs. */ Closure closure_eval(ClosureDiffuse diffuse); diff --git a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl index 68ce4d27617..676d4ef3505 100644 --- a/source/blender/draw/engines/eevee/shaders/surface_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/surface_lib.glsl @@ -250,3 +250,8 @@ vec3 coordinate_incoming(vec3 P) return cameraVec(P); #endif } + +float film_scaling_factor_get() +{ + return 1.0; +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index 17a6d98c28c..73821f83c84 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -62,6 +62,11 @@ vec3 coordinate_incoming(vec3 P) { return cameraVec(P); } + +float film_scaling_factor_get() +{ + return 1.0; +} #endif void main() diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl index b44e3e8e7f9..b51486113f5 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_vert.glsl @@ -107,6 +107,11 @@ vec3 coordinate_incoming(vec3 P) return vec3(0.0); } +float film_scaling_factor_get() +{ + return 1.0; +} + float attr_load_temperature_post(float attr) { return attr; diff --git a/source/blender/draw/engines/eevee_next/eevee_film.cc b/source/blender/draw/engines/eevee_next/eevee_film.cc index e06cd857fbb..7dd5d9b0e6f 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.cc +++ b/source/blender/draw/engines/eevee_next/eevee_film.cc @@ -241,6 +241,17 @@ void Film::init(const int2 &extent, const rcti *output_rect) enabled_passes_ &= ~EEVEE_RENDER_PASS_VECTOR; } } + { + data_.scaling_factor = 1; + if (inst_.is_viewport()) { + if (!bool(enabled_passes_ & + (EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET | EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL | + EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT | EEVEE_RENDER_PASS_NORMAL))) + { + data_.scaling_factor = BKE_render_preview_pixel_size(&inst_.scene->r); + } + } + } { rcti fallback_rect; if (BLI_rcti_is_empty(output_rect)) { @@ -253,9 +264,6 @@ void Film::init(const int2 &extent, const rcti *output_rect) data_.extent = int2(BLI_rcti_size_x(output_rect), BLI_rcti_size_y(output_rect)); data_.offset = int2(output_rect->xmin, output_rect->ymin); data_.extent_inv = 1.0f / float2(data_.extent); - /* TODO(fclem): parameter hidden in experimental. - * We need to figure out LOD bias first in order to preserve texture crispiness. */ - data_.scaling_factor = 1; data_.render_extent = math::divide_ceil(extent, int2(data_.scaling_factor)); data_.render_offset = data_.offset; @@ -380,7 +388,9 @@ void Film::init(const int2 &extent, const rcti *output_rect) } } { - int2 weight_extent = inst_.camera.is_panoramic() ? data_.extent : int2(data_.scaling_factor); + int2 weight_extent = (inst_.camera.is_panoramic() || (data_.scaling_factor > 1)) ? + data_.extent : + int2(1); eGPUTextureFormat color_format = GPU_RGBA16F; eGPUTextureFormat float_format = GPU_R16F; @@ -448,6 +458,7 @@ void Film::sync() accumulate_ps_.specialize_constant(sh, "enabled_categories", uint(enabled_categories_)); accumulate_ps_.specialize_constant(sh, "samples_len", &data_.samples_len); accumulate_ps_.specialize_constant(sh, "use_reprojection", &use_reprojection_); + accumulate_ps_.specialize_constant(sh, "scaling_factor", data_.scaling_factor); accumulate_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); accumulate_ps_.shader_set(sh); accumulate_ps_.bind_resources(inst_.uniform_data); diff --git a/source/blender/draw/engines/eevee_next/eevee_film.hh b/source/blender/draw/engines/eevee_next/eevee_film.hh index f8d563e846b..89039e763c8 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.hh +++ b/source/blender/draw/engines/eevee_next/eevee_film.hh @@ -120,6 +120,11 @@ class Film { return display_extent; } + int scaling_factor_get() const + { + return data_.scaling_factor; + } + float2 pixel_jitter_get() const; float background_opacity_get() const diff --git a/source/blender/draw/engines/eevee_next/eevee_sampling.cc b/source/blender/draw/engines/eevee_next/eevee_sampling.cc index c29039fbf06..3d739553945 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sampling.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sampling.cc @@ -143,8 +143,8 @@ void Sampling::step() } /* Using leaped Halton sequence so we can reused the same primes as lens. */ double3 r, offset = {0, 0, 0}; - uint64_t leap = 11; - uint3 primes = {5, 4, 7}; + uint64_t leap = 13; + uint3 primes = {5, 7, 11}; BLI_halton_3d(primes, offset, sample_raytrace * leap, r); data_.dimensions[SAMPLING_SHADOW_U] = r[0]; data_.dimensions[SAMPLING_SHADOW_V] = r[1]; diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index a5540d74a4f..20476cc83b3 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -210,10 +210,26 @@ void ShadingView::update_view() float4x4 viewmat = main_view_.viewmat(); float4x4 winmat = main_view_.winmat(); - /* TODO(fclem): Mixed-resolution rendering: We need to make sure we render with exactly the same - * distances between pixels to line up render samples and target pixels. - * So if the target resolution is not a multiple of the resolution divisor, we need to make the - * projection window bigger in the +X and +Y directions. */ + /* + * Mixed resolution rendering. The center of the display pixels must align with the center of + * the render pixels. If they don't align, the winmat needs to be re-projected. + */ + int2 scaling_factor = int2(inst_.film.scaling_factor_get()); + int2 rescaled_render_extent = extent_ * scaling_factor; + int2 display_extent = inst_.film.display_extent_get(); + if (rescaled_render_extent != display_extent) { + float left; + float right; + float bottom; + float top; + float near; + float far; + projmat_dimensions(winmat.ptr(), &left, &right, &bottom, &top, &near, &far); + float2 scale = (float2(rescaled_render_extent) / float2(display_extent)); + right = left + ((right - left) * scale.x); + top = bottom + ((top - bottom) * scale.y); + winmat = math::projection::perspective(left, right, bottom, top, near, far); + } /* Anti-Aliasing / Super-Sampling jitter. */ float2 jitter = inst_.film.pixel_jitter_get() / float2(extent_); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl index 0b3160ef447..ced00efdda2 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl @@ -54,24 +54,22 @@ FilmSample film_sample_get(int sample_n, ivec2 texel_film) * reprojecting the incoming pixel data into film pixel space. */ #else -# ifdef SCALED_RENDERING - texel_film /= uniform_buf.film.scaling_factor; -# endif - FilmSample film_sample = uniform_buf.film.samples[sample_n]; - film_sample.texel += texel_film + uniform_buf.film.render_offset; + film_sample.texel += (texel_film / scaling_factor) + uniform_buf.film.render_offset; /* Use extend on borders. */ film_sample.texel = clamp(film_sample.texel, ivec2(0, 0), uniform_buf.film.render_extent - 1); /* TODO(fclem): Panoramic projection will need to compute the sample weight in the shader * instead of precomputing it on CPU. */ -# ifdef SCALED_RENDERING - /* We need to compute the real distance and weight since a sample - * can be used by many final pixel. */ - vec2 offset = uniform_buf.film.subpixel_offset - - vec2(texel_film % uniform_buf.film.scaling_factor); - film_sample.weight = film_filter_weight(uniform_buf.film.filter_size, length_squared(offset)); -# endif + if (scaling_factor > 1) { + /* We need to compute the real distance and weight since a sample + * can be used by many final pixel. */ + vec2 offset = (vec2(film_sample.texel) + 0.5 - uniform_buf.film.subpixel_offset) * + scaling_factor - + (vec2(texel_film) + 0.5); + film_sample.weight = film_filter_weight(uniform_buf.film.filter_radius, + length_squared(offset)); + } #endif /* PANORAMIC */ @@ -84,13 +82,14 @@ FilmSample film_sample_get(int sample_n, ivec2 texel_film) /* Returns the combined weights of all samples affecting this film pixel. */ float film_weight_accumulation(ivec2 texel_film) { -#if 0 /* TODO(fclem): Reference implementation, also needed for panoramic cameras. */ - float weight = 0.0; - for (int i = 0; i < uniform_buf.film.samples_len; i++) { - weight += film_sample_get(i, texel_film).weight; + /* TODO(fclem): Reference implementation, also needed for panoramic cameras. */ + if (scaling_factor > 1) { + float weight = 0.0; + for (int i = 0; i < uniform_buf.film.samples_len; i++) { + weight += film_sample_get(i, texel_film).weight; + } + return weight; } - return weight; -#endif return uniform_buf.film.samples_weight_total; } diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index f9488363493..87ffbf7e8f5 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -8,6 +8,8 @@ #pragma BLENDER_REQUIRE(gpu_shader_codegen_lib.glsl) #pragma BLENDER_REQUIRE(eevee_renderpass_lib.glsl) +#define filmScalingFactor float(uniform_buf.film.scaling_factor) + vec3 g_emission; vec3 g_transmittance; float g_holdout; @@ -689,6 +691,20 @@ vec3 coordinate_incoming(vec3 P) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Mixed render resolution + * + * Callbacks image texture sampling. + * + * \{ */ + +float film_scaling_factor_get() +{ + return float(uniform_buf.film.scaling_factor); +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Volume Attribute post * diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh index b2cf95f108f..8005eaeec45 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_film_info.hh @@ -26,6 +26,7 @@ GPU_SHADER_CREATE_INFO(eevee_film) .specialization_constant(Type::UINT, "enabled_categories", 0) .specialization_constant(Type::INT, "samples_len", 0) .specialization_constant(Type::BOOL, "use_reprojection", false) + .specialization_constant(Type::INT, "scaling_factor", 1) .additional_info("eevee_shared") .additional_info("eevee_global_ubo") .additional_info("eevee_velocity_camera") diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl index 73524864409..b956029954e 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl @@ -56,7 +56,16 @@ void point_map_to_tube(vec3 vin, out vec3 vout) void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) { +#ifdef GPU_FRAGMENT_SHADER + vec2 scaling_factor = vec2(film_scaling_factor_get()); + vec2 dx = dFdx(co.xy) / scaling_factor; + vec2 dy = dFdy(co.xy) / scaling_factor; + + color = safe_color(textureGrad(ima, co.xy, dx, dy)); +#else color = safe_color(texture(ima, co.xy)); +#endif + alpha = color.a; }