EEVEE-Next: Viewport pixel size with up-scaling #118903

Merged
Jeroen Bakker merged 27 commits from Jeroen-Bakker/blender:eevee-next/preview-pixel-size into main 2024-03-13 12:00:38 +01:00
13 changed files with 124 additions and 28 deletions

View File

@ -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,

View File

@ -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);

View File

@ -250,3 +250,8 @@ vec3 coordinate_incoming(vec3 P)
return cameraVec(P);
#endif
}
float film_scaling_factor_get()
{
return 1.0;
}

View File

@ -62,6 +62,11 @@ vec3 coordinate_incoming(vec3 P)
{
return cameraVec(P);
}
float film_scaling_factor_get()
{
return 1.0;
}
#endif
void main()

View File

@ -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;

View File

@ -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)))
Jeroen-Bakker marked this conversation as resolved Outdated

This is making all viewport reduce size even if preview pixel size is 1. This is very unconfortable and messes with a bunch of TAA algorithm that are reset because render size changes on navigation.

So remove that all-together.

This is making all viewport reduce size even if preview pixel size is 1. This is very unconfortable and messes with a bunch of TAA algorithm that are reset because render size changes on navigation. So remove that all-together.
{
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);

View File

@ -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

View File

@ -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];

View File

@ -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_);

View File

@ -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;
}

View File

@ -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)
Jeroen-Bakker marked this conversation as resolved

Nitpick1: Don't use camecase, so film_scaling_factor. This is old codestyle and will eventually fade away.

Nitpicl2: Use functions instead of macros.

Nitpick1: Don't use camecase, so `film_scaling_factor`. This is old codestyle and will eventually fade away. Nitpicl2: Use functions instead of macros.
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
*

View File

@ -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")

View File

@ -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;
}