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:
authorLukas Stockner <lukas.stockner@freenet.de>2019-02-06 14:42:10 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-02-06 17:18:29 +0300
commit405cacd4cd955552e1f7b50a176ddcdd9baf8d3b (patch)
treee54e2bf0c79bcc04d669088393b1d16df554bffd /intern/cycles/render
parent81159e99b819910b72cb3caba6b3cd4f35184ea9 (diff)
Cycles: prefilter feature passes separate from denoising.
Prefiltering of feature passes will happen during rendering, which can then be used for denoising immediately or written as a render pass for later (animation) denoising. The number of denoising data passes written is reduced because of this, leaving out the feature variance passes. The passes are now Normal, Albedo, Depth, Shadowing, Variance and Intensity. Ref D3889.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/buffers.cpp123
-rw-r--r--intern/cycles/render/buffers.h5
-rw-r--r--intern/cycles/render/film.cpp4
-rw-r--r--intern/cycles/render/film.h1
-rw-r--r--intern/cycles/render/session.cpp11
-rw-r--r--intern/cycles/render/session.h10
6 files changed, 84 insertions, 70 deletions
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index f901885e679..66b8ef73acc 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -42,6 +42,7 @@ BufferParams::BufferParams()
denoising_data_pass = false;
denoising_clean_pass = false;
+ denoising_prefiltered_pass = false;
Pass::add(PASS_COMBINED, passes);
}
@@ -73,6 +74,7 @@ int BufferParams::get_passes_size()
if(denoising_data_pass) {
size += DENOISING_PASS_SIZE_BASE;
if(denoising_clean_pass) size += DENOISING_PASS_SIZE_CLEAN;
+ if(denoising_prefiltered_pass) size += DENOISING_PASS_SIZE_PREFILTERED;
}
return align_up(size, 4);
@@ -88,6 +90,20 @@ int BufferParams::get_denoising_offset()
return offset;
}
+int BufferParams::get_denoising_prefiltered_offset()
+{
+ assert(denoising_prefiltered_pass);
+
+ int offset = get_denoising_offset();
+
+ offset += DENOISING_PASS_SIZE_BASE;
+ if(denoising_clean_pass) {
+ offset += DENOISING_PASS_SIZE_CLEAN;
+ }
+
+ return offset;
+}
+
/* Render Buffer Task */
RenderTile::RenderTile()
@@ -153,81 +169,62 @@ bool RenderBuffers::get_denoising_pass_rect(int type, float exposure, int sample
return false;
}
- float invsample = 1.0f/sample;
- float scale = invsample;
- bool variance = (type == DENOISING_PASS_NORMAL_VAR) ||
- (type == DENOISING_PASS_ALBEDO_VAR) ||
- (type == DENOISING_PASS_DEPTH_VAR) ||
- (type == DENOISING_PASS_COLOR_VAR);
+ float scale = 1.0f;
+ float alpha_scale = 1.0f/sample;
+ if(type == DENOISING_PASS_PREFILTERED_COLOR ||
+ type == DENOISING_PASS_CLEAN ||
+ type == DENOISING_PASS_PREFILTERED_INTENSITY) {
+ scale *= exposure;
+ }
+ else if(type == DENOISING_PASS_PREFILTERED_VARIANCE) {
+ scale *= exposure*exposure * (sample - 1);
+ }
- float scale_exposure = scale;
- if(type == DENOISING_PASS_COLOR || type == DENOISING_PASS_CLEAN) {
- scale_exposure *= exposure;
+ int offset;
+ if(type == DENOISING_PASS_CLEAN) {
+ /* The clean pass isn't changed by prefiltering, so we use the original one there. */
+ offset = type + params.get_denoising_offset();
}
- else if(type == DENOISING_PASS_COLOR_VAR) {
- scale_exposure *= exposure*exposure;
+ else if (type == DENOISING_PASS_PREFILTERED_COLOR && !params.denoising_prefiltered_pass) {
+ /* If we're not saving the prefiltering result, return the original noisy pass. */
+ offset = params.get_denoising_offset() + DENOISING_PASS_COLOR;
+ scale /= sample;
+ }
+ else {
+ offset = type + params.get_denoising_prefiltered_offset();
}
- int offset = type + params.get_denoising_offset();
int pass_stride = params.get_passes_size();
int size = params.width*params.height;
- if(variance) {
- /* Approximate variance as E[x^2] - 1/N * (E[x])^2, since online variance
- * update does not work efficiently with atomics in the kernel. */
- int mean_offset = offset - components;
- float *mean = buffer.data() + mean_offset;
- float *var = buffer.data() + offset;
- assert(mean_offset >= 0);
-
- if(components == 1) {
- for(int i = 0; i < size; i++, mean += pass_stride, var += pass_stride, pixels++) {
- pixels[0] = max(0.0f, var[0] - mean[0]*mean[0]*invsample)*scale_exposure;
- }
+ float *in = buffer.data() + offset;
+
+ if(components == 1) {
+ for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ pixels[0] = in[0]*scale;
}
- else if(components == 3) {
- for(int i = 0; i < size; i++, mean += pass_stride, var += pass_stride, pixels += 3) {
- pixels[0] = max(0.0f, var[0] - mean[0]*mean[0]*invsample)*scale_exposure;
- pixels[1] = max(0.0f, var[1] - mean[1]*mean[1]*invsample)*scale_exposure;
- pixels[2] = max(0.0f, var[2] - mean[2]*mean[2]*invsample)*scale_exposure;
- }
+ }
+ else if(components == 3) {
+ for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ pixels[0] = in[0]*scale;
+ pixels[1] = in[1]*scale;
+ pixels[2] = in[2]*scale;
}
- else {
- return false;
+ }
+ else if(components == 4) {
+ /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
+ assert(params.passes[0].type == PASS_COMBINED);
+ float *in_combined = buffer.data();
+
+ for(int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
+ pixels[0] = in[0]*scale;
+ pixels[1] = in[1]*scale;
+ pixels[2] = in[2]*scale;
+ pixels[3] = saturate(in_combined[3]*alpha_scale);
}
}
else {
- float *in = buffer.data() + offset;
-
- if(components == 1) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- pixels[0] = in[0]*scale_exposure;
- }
- }
- else if(components == 3) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- pixels[0] = in[0]*scale_exposure;
- pixels[1] = in[1]*scale_exposure;
- pixels[2] = in[2]*scale_exposure;
- }
- }
- else if(components == 4) {
- assert(type == DENOISING_PASS_COLOR);
-
- /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
- assert(params.passes[0].type == PASS_COMBINED);
- float *in_combined = buffer.data();
-
- for(int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
- pixels[0] = in[0]*scale_exposure;
- pixels[1] = in[1]*scale_exposure;
- pixels[2] = in[2]*scale_exposure;
- pixels[3] = saturate(in_combined[3]*scale);
- }
- }
- else {
- return false;
- }
+ return false;
}
return true;
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 46c3b89bd84..0a010718d6d 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -54,6 +54,10 @@ public:
bool denoising_data_pass;
/* If only some light path types should be denoised, an additional pass is needed. */
bool denoising_clean_pass;
+ /* When we're prefiltering the passes during rendering, we need to keep both the
+ * original and the prefiltered data around because neighboring tiles might still
+ * need the original data. */
+ bool denoising_prefiltered_pass;
/* functions */
BufferParams();
@@ -63,6 +67,7 @@ public:
void add_pass(PassType type);
int get_passes_size();
int get_denoising_offset();
+ int get_denoising_prefiltered_offset();
};
/* Render Buffers */
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index d0f15496e50..b305fa59123 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -286,6 +286,7 @@ NODE_DEFINE(Film)
SOCKET_BOOLEAN(denoising_data_pass, "Generate Denoising Data Pass", false);
SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
+ SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
SOCKET_INT(denoising_flags, "Denoising Flags", 0);
return type;
@@ -469,6 +470,9 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
kfilm->pass_stride += DENOISING_PASS_SIZE_CLEAN;
kfilm->use_light_pass = 1;
}
+ if(denoising_prefiltered_pass) {
+ kfilm->pass_stride += DENOISING_PASS_SIZE_PREFILTERED;
+ }
}
kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index c597db4e4c5..8330a4cf413 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -60,6 +60,7 @@ public:
vector<Pass> passes;
bool denoising_data_pass;
bool denoising_clean_pass;
+ bool denoising_prefiltered_pass;
int denoising_flags;
float pass_alpha_threshold;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index c818f2b496c..3cee3b8bece 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -689,7 +689,7 @@ DeviceRequestedFeatures Session::get_requested_device_features()
BakeManager *bake_manager = scene->bake_manager;
requested_features.use_baking = bake_manager->get_baking();
requested_features.use_integrator_branched = (scene->integrator->method == Integrator::BRANCHED_PATH);
- if(params.denoising_passes) {
+ if(params.run_denoising) {
requested_features.use_denoising = true;
requested_features.use_shadow_tricks = true;
}
@@ -927,7 +927,7 @@ void Session::update_status_time(bool show_pause, bool show_done)
*/
substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
}
- if(params.use_denoising) {
+ if(params.run_denoising) {
substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
}
}
@@ -975,7 +975,7 @@ void Session::render()
task.requested_tile_size = params.tile_size;
task.passes_size = tile_manager.params.get_passes_size();
- if(params.use_denoising) {
+ if(params.run_denoising) {
task.denoising_radius = params.denoising_radius;
task.denoising_strength = params.denoising_strength;
task.denoising_feature_strength = params.denoising_feature_strength;
@@ -983,8 +983,13 @@ void Session::render()
assert(!scene->film->need_update);
task.pass_stride = scene->film->pass_stride;
+ task.target_pass_stride = task.pass_stride;
task.pass_denoising_data = scene->film->denoising_data_offset;
task.pass_denoising_clean = scene->film->denoising_clean_offset;
+
+ task.denoising_from_render = true;
+ task.denoising_do_filter = params.full_denoising;
+ task.denoising_write_passes = params.write_denoising_passes;
}
device->task_add(task);
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index c7f590915e7..cb1d8fed68f 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -60,8 +60,9 @@ public:
bool display_buffer_linear;
- bool use_denoising;
- bool denoising_passes;
+ bool run_denoising;
+ bool write_denoising_passes;
+ bool full_denoising;
int denoising_radius;
float denoising_strength;
float denoising_feature_strength;
@@ -94,8 +95,9 @@ public:
use_profiling = false;
- use_denoising = false;
- denoising_passes = false;
+ run_denoising = false;
+ write_denoising_passes = false;
+ full_denoising = false;
denoising_radius = 8;
denoising_strength = 0.0f;
denoising_feature_strength = 0.0f;