Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c168
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h12
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c27
6 files changed, 170 insertions, 60 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index a20c443171c..8c0a44b2c9b 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -47,6 +47,8 @@
#include "GPU_texture.h"
#include "eevee_private.h"
+#define CAMERA_JITTER_RING_DENSITY 6
+
static float coc_radius_from_camera_depth(bool is_ortho, EEVEE_EffectsInfo *fx, float camera_depth)
{
float multiplier = fx->dof_coc_params[0];
@@ -62,53 +64,97 @@ static float coc_radius_from_camera_depth(bool is_ortho, EEVEE_EffectsInfo *fx,
}
}
-static void regular_polygon_sample(
- float corners, float rotation, float u, float v, float r_sample[2])
+static float polygon_sides_length(float sides_count)
{
- /* Sample corner number and reuse u. */
- float corner = floorf(u * corners);
- u = u * corners - corner;
- /* Uniform sampled triangle weights. */
- u = sqrtf(u);
- v = v * u;
- u = 1.0f - u;
- /* Point in triangle. */
- float angle = M_PI / corners;
- float p[2] = {(u + v) * cosf(angle), (u - v) * sinf(angle)};
- /* Rotate. */
- rotation += corner * 2.0f * angle;
- float cr = cosf(rotation);
- float sr = sinf(rotation);
- r_sample[0] = cr * p[0] - sr * p[1];
- r_sample[1] = sr * p[0] + cr * p[1];
+ return 2.0 * sin(M_PI / sides_count);
+}
+
+/* Returns intersection ratio between the radius edge at theta and the polygon edge.
+ * Start first corners at theta == 0. */
+static float circle_to_polygon_radius(float sides_count, float theta)
+{
+ /* From Graphics Gems from CryENGINE 3 (Siggraph 2013) by Tiago Sousa (slide 36). */
+ float side_angle = (2.0f * M_PI) / sides_count;
+ return cosf(side_angle * 0.5f) /
+ cosf(theta - side_angle * floorf((sides_count * theta + M_PI) / (2.0f * M_PI)));
+}
+
+/* Remap input angle to have homogenous spacing of points along a polygon edge.
+ * Expect theta to be in [0..2pi] range. */
+static float circle_to_polygon_angle(float sides_count, float theta)
+{
+ float side_angle = (2.0f * M_PI) / sides_count;
+ float halfside_angle = side_angle * 0.5f;
+ float side = floorf(theta / side_angle);
+ /* Length of segment from center to the middle of polygon side. */
+ float adjacent = circle_to_polygon_radius(sides_count, 0.0f);
+
+ /* This is the relative position of the sample on the polygon half side. */
+ float local_theta = theta - side * side_angle;
+ float ratio = (local_theta - halfside_angle) / halfside_angle;
+
+ float halfside_len = polygon_sides_length(sides_count) * 0.5f;
+ float opposite = ratio * halfside_len;
+
+ /* NOTE: atan(y_over_x) has output range [-M_PI_2..M_PI_2]. */
+ float final_local_theta = atanf(opposite / adjacent);
+
+ return side * side_angle + final_local_theta;
+}
+
+static int dof_jitter_total_sample_count(int ring_density, int ring_count)
+{
+ return ((ring_count * ring_count + ring_count) / 2) * ring_density + 1;
}
bool EEVEE_depth_of_field_jitter_get(EEVEE_EffectsInfo *fx,
- const double ht_point[2],
float r_jitter[2],
float *r_focus_distance)
{
if (fx->dof_jitter_radius == 0.0f) {
return false;
}
- /* Maybe would be better to have another sequence ? */
- r_jitter[0] = ht_point[0];
- r_jitter[1] = ht_point[1];
+
+ int ring_density = CAMERA_JITTER_RING_DENSITY;
+ int ring_count = fx->dof_jitter_ring_count;
+ int sample_count = dof_jitter_total_sample_count(ring_density, ring_count);
+
+ int s = fx->taa_current_sample - 1;
+
+ int ring = 0;
+ int ring_sample_count = 1;
+ int ring_sample = 1;
+
+ s = s * (ring_density - 1);
+ s = s % sample_count;
+
+ int samples_passed = 1;
+ while (s >= samples_passed) {
+ ring++;
+ ring_sample_count = ring * ring_density;
+ ring_sample = s - samples_passed;
+ ring_sample = (ring_sample + 1) % ring_sample_count;
+ samples_passed += ring_sample_count;
+ }
+
+ r_jitter[0] = (float)ring / ring_count;
+ r_jitter[1] = (float)ring_sample / ring_sample_count;
{
/* Bokeh shape parametrisation */
- if (fx->dof_jitter_blades == 0.0f) {
- float r = sqrtf(r_jitter[0]);
- float T = r_jitter[1] * 2.0f * M_PI;
+ float r = r_jitter[0];
+ float T = r_jitter[1] * 2.0f * M_PI;
- r_jitter[0] = r * cosf(T);
- r_jitter[1] = r * sinf(T);
- }
- else {
- regular_polygon_sample(
- fx->dof_jitter_blades, fx->dof_bokeh_rotation, r_jitter[0], r_jitter[1], r_jitter);
+ if (fx->dof_jitter_blades >= 3.0f) {
+ T = circle_to_polygon_angle(fx->dof_jitter_blades, T);
+ r *= circle_to_polygon_radius(fx->dof_jitter_blades, T);
}
+ T += fx->dof_bokeh_rotation;
+
+ r_jitter[0] = r * cosf(T);
+ r_jitter[1] = r * sinf(T);
+
mul_v2_v2(r_jitter, fx->dof_bokeh_aniso);
}
@@ -118,6 +164,36 @@ bool EEVEE_depth_of_field_jitter_get(EEVEE_EffectsInfo *fx,
return true;
}
+int EEVEE_depth_of_field_sample_count_get(EEVEE_EffectsInfo *fx,
+ int sample_count,
+ int *r_ring_count)
+{
+ if (fx->dof_jitter_radius == 0.0f) {
+ if (r_ring_count != NULL) {
+ *r_ring_count = 0;
+ }
+ return 1;
+ }
+
+ if (sample_count == TAA_MAX_SAMPLE) {
+ /* Special case for viewport continuous rendering. We clamp to a max sample to avoid the
+ * jittered dof never converging. */
+ sample_count = 1024;
+ }
+ /* Inversion of dof_jitter_total_sample_count. */
+ float x = 2.0f * (sample_count - 1.0f) / CAMERA_JITTER_RING_DENSITY;
+ /* Solving polynomial. We only search positive solution. */
+ float discriminant = 1.0f + 4.0f * x;
+ int ring_count = ceilf(0.5f * (sqrt(discriminant) - 1.0f));
+
+ sample_count = dof_jitter_total_sample_count(CAMERA_JITTER_RING_DENSITY, ring_count);
+
+ if (r_ring_count != NULL) {
+ *r_ring_count = ring_count;
+ }
+ return sample_count;
+}
+
int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
EEVEE_Data *vedata,
Object *camera)
@@ -185,18 +261,24 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
effects->dof_jitter_focus = focus_dist;
effects->dof_jitter_blades = blades;
- int sample_count = DRW_state_is_image_render() ? stl->g_data->render_tot_samples :
- scene_eval->eevee.taa_samples;
- /* Set to very high value in case of continuous rendering. */
- sample_count = (sample_count == 0) ? 1024 : sample_count;
-
- /* Compute a minimal overblur radius to fill the gaps between the samples.
- * This is just the simplified form of dividing the area of the bokeh
- * by the number of samples. */
- float minimal_overblur = 1.0f / sqrtf(sample_count);
- float user_overblur = scene_eval->eevee.bokeh_overblur / 100.0f;
-
- effects->dof_coc_params[1] *= minimal_overblur + user_overblur;
+ int sample_count = EEVEE_temporal_sampling_sample_count_get(scene_eval, stl);
+ sample_count = EEVEE_depth_of_field_sample_count_get(
+ effects, sample_count, &effects->dof_jitter_ring_count);
+
+ if (effects->dof_jitter_ring_count == 0) {
+ effects->dof_jitter_radius = 0.0f;
+ }
+ else {
+ /* Compute a minimal overblur radius to fill the gaps between the samples.
+ * This is just the simplified form of dividing the area of the bokeh
+ * by the number of samples. */
+ float minimal_overblur = 1.0f / sqrtf(sample_count);
+ float user_overblur = scene_eval->eevee.bokeh_overblur / 100.0f;
+
+ effects->dof_coc_params[1] *= minimal_overblur + user_overblur;
+ /* Avoid dilating the shape. Overblur only soften. */
+ effects->dof_jitter_radius -= effects->dof_coc_params[1];
+ }
}
else {
effects->dof_jitter_radius = 0.0f;
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index ca583143572..9d3aaea4adc 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -102,11 +102,9 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata,
effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata);
effects->enabled_effects |= EEVEE_screen_raytrace_init(sldata, vedata);
- if ((effects->enabled_effects & EFFECT_TAA) && effects->taa_current_sample > 1) {
- /* Update matrices here because EEVEE_screen_raytrace_init can have reset the
- * taa_current_sample. (See T66811) */
- EEVEE_temporal_sampling_update_matrices(vedata);
- }
+ /* Update matrices here because EEVEE_screen_raytrace_init can have reset the
+ * taa_current_sample. (See T66811) */
+ EEVEE_temporal_sampling_update_matrices(vedata);
EEVEE_volumes_init(sldata, vedata);
EEVEE_subsurface_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index c6760de5cfa..0a3c7ddff49 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -456,13 +456,17 @@ static void eevee_render_to_image(void *vedata,
}
EEVEE_PrivateData *g_data = ved->stl->g_data;
- EEVEE_render_modules_init(vedata, engine, depsgraph);
-
int initial_frame = CFRA;
float initial_subframe = SUBFRA;
float shuttertime = (do_motion_blur) ? scene->eevee.motion_blur_shutter : 0.0f;
int time_steps_tot = (do_motion_blur) ? max_ii(1, scene->eevee.motion_blur_steps) : 1;
- g_data->render_tot_samples = divide_ceil_u(scene->eevee.taa_render_samples, time_steps_tot);
+ g_data->render_timesteps = time_steps_tot;
+
+ EEVEE_render_modules_init(vedata, engine, depsgraph);
+
+ g_data->render_sample_count_per_timestep = EEVEE_temporal_sampling_sample_count_get(scene,
+ ved->stl);
+
/* Compute start time. The motion blur will cover `[time ...time + shuttertime]`. */
float time = initial_frame + initial_subframe;
switch (scene->eevee.motion_blur_position) {
@@ -553,7 +557,8 @@ static void eevee_render_to_image(void *vedata,
/* Actual drawing. */
{
- EEVEE_renderpasses_output_init(sldata, vedata, g_data->render_tot_samples * time_steps_tot);
+ EEVEE_renderpasses_output_init(
+ sldata, vedata, g_data->render_sample_count_per_timestep * time_steps_tot);
EEVEE_temporal_sampling_create_view(vedata);
EEVEE_render_draw(vedata, engine, render_layer, rect);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 11b4d5e4679..1ad11ab03c7 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -55,6 +55,9 @@ extern struct DrawEngineType draw_engine_eevee_type;
#define MAX_BLOOM_STEP 16
#define MAX_AOVS 64
+/* Special value chosen to not be altered by depth of field sample count. */
+#define TAA_MAX_SAMPLE 10000926
+
// #define DEBUG_SHADOW_DISTRIBUTION
/* Only define one of these. */
@@ -779,6 +782,7 @@ typedef struct EEVEE_EffectsInfo {
float dof_jitter_radius;
float dof_jitter_blades;
float dof_jitter_focus;
+ int dof_jitter_ring_count;
float dof_coc_params[2], dof_coc_near_dist, dof_coc_far_dist;
float dof_bokeh_blades, dof_bokeh_rotation, dof_bokeh_aniso[2], dof_bokeh_max_size;
float dof_bokeh_aniso_inv[2];
@@ -1079,7 +1083,8 @@ typedef struct EEVEE_PrivateData {
/** For rendering planar reflections. */
struct DRWView *planar_views[MAX_PLANAR];
- int render_tot_samples;
+ int render_timesteps;
+ int render_sample_count_per_timestep;
} EEVEE_PrivateData; /* Transient data */
/* eevee_data.c */
@@ -1317,9 +1322,11 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, O
void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_depth_of_field_draw(EEVEE_Data *vedata);
bool EEVEE_depth_of_field_jitter_get(EEVEE_EffectsInfo *effects,
- const double ht_point[2],
float r_jitter[2],
float *r_focus_distance);
+int EEVEE_depth_of_field_sample_count_get(EEVEE_EffectsInfo *effects,
+ int sample_count,
+ int *r_ring_count);
/* eevee_bloom.c */
int EEVEE_bloom_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -1433,6 +1440,7 @@ int EEVEE_renderpasses_aov_hash(const ViewLayerAOV *aov);
/* eevee_temporal_sampling.c */
void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata);
void EEVEE_temporal_sampling_create_view(EEVEE_Data *vedata);
+int EEVEE_temporal_sampling_sample_count_get(const Scene *scene, const EEVEE_StorageList *stl);
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_temporal_sampling_offset_calc(const double ht_point[2],
const float filter_size,
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index bb974688404..e689ed972f1 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -563,7 +563,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Sort transparents before the loop. */
DRW_pass_sort_shgroup_z(psl->transparent_pass);
- uint tot_sample = stl->g_data->render_tot_samples;
+ uint tot_sample = stl->g_data->render_sample_count_per_timestep;
uint render_samples = 0;
/* SSR needs one iteration to start properly. */
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index f9f2886f3de..8fa7d899b6b 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -155,7 +155,7 @@ void EEVEE_temporal_sampling_matrices_calc(EEVEE_EffectsInfo *effects, const dou
/* Jitter is in pixel space. Focus distance in world space units. */
float dof_jitter[2], focus_distance;
- if (EEVEE_depth_of_field_jitter_get(effects, ht_point, dof_jitter, &focus_distance)) {
+ if (EEVEE_depth_of_field_jitter_get(effects, dof_jitter, &focus_distance)) {
/* Convert to NDC space [-1..1]. */
dof_jitter[0] /= viewport_size[0] * 0.5f;
dof_jitter[1] /= viewport_size[1] * 0.5f;
@@ -230,6 +230,21 @@ void EEVEE_temporal_sampling_create_view(EEVEE_Data *vedata)
DRW_view_clip_planes_set(effects->taa_view, NULL, 0);
}
+int EEVEE_temporal_sampling_sample_count_get(const Scene *scene, const EEVEE_StorageList *stl)
+{
+ const bool is_render = DRW_state_is_image_render();
+ int sample_count = is_render ? scene->eevee.taa_render_samples : scene->eevee.taa_samples;
+ int timesteps = is_render ? stl->g_data->render_timesteps : 1;
+
+ sample_count = max_ii(0, sample_count);
+ sample_count = (sample_count == 0) ? TAA_MAX_SAMPLE : sample_count;
+ sample_count = divide_ceil_u(sample_count, timesteps);
+
+ int dof_sample_count = EEVEE_depth_of_field_sample_count_get(stl->effects, sample_count, NULL);
+ sample_count = dof_sample_count * divide_ceil_u(sample_count, dof_sample_count);
+ return sample_count;
+}
+
int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
@@ -274,10 +289,12 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL);
}
- const bool first_sample_only = EEVEE_renderpasses_only_first_sample_pass_active(vedata);
- view_is_valid = view_is_valid && !first_sample_only;
- effects->taa_total_sample = first_sample_only ? 1 : scene_eval->eevee.taa_samples;
- MAX2(effects->taa_total_sample, 0);
+ effects->taa_total_sample = EEVEE_temporal_sampling_sample_count_get(scene_eval, stl);
+
+ if (EEVEE_renderpasses_only_first_sample_pass_active(vedata)) {
+ view_is_valid = false;
+ effects->taa_total_sample = 1;
+ }
/* Motion blur steps could reset the sampling when camera is animated (see T79970). */
if (!DRW_state_is_scene_render()) {