diff options
author | Lukas Stockner <lukas.stockner@freenet.de> | 2019-02-06 14:42:10 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-02-06 17:18:29 +0300 |
commit | 405cacd4cd955552e1f7b50a176ddcdd9baf8d3b (patch) | |
tree | e54e2bf0c79bcc04d669088393b1d16df554bffd /intern/cycles/render/buffers.cpp | |
parent | 81159e99b819910b72cb3caba6b3cd4f35184ea9 (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/buffers.cpp')
-rw-r--r-- | intern/cycles/render/buffers.cpp | 123 |
1 files changed, 60 insertions, 63 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; |