From a604fb730dd62a2730a3a753adc057abb93296cb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 7 Jun 2013 12:45:26 +0000 Subject: [PATCH] Cycles: mist pass added, with start/depth/falloff control. If the pass is enabled in a render layer a Mist Pass panel will be shown in the world properties. --- intern/cycles/blender/addon/ui.py | 29 +++++++++++++++++++++-- intern/cycles/blender/blender_session.cpp | 3 ++- intern/cycles/blender/blender_sync.cpp | 16 +++++++++++++ intern/cycles/kernel/kernel_accumulate.h | 1 + intern/cycles/kernel/kernel_passes.h | 27 +++++++++++++++++++++ intern/cycles/kernel/kernel_types.h | 12 +++++++--- intern/cycles/render/film.cpp | 16 +++++++++++++ intern/cycles/render/film.h | 4 ++++ 8 files changed, 102 insertions(+), 6 deletions(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9218e2ecf7b..f9c516d1963 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -326,16 +326,15 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel): col = split.column() col.prop(rl, "use_pass_combined") col.prop(rl, "use_pass_z") + col.prop(rl, "use_pass_mist") col.prop(rl, "use_pass_normal") col.prop(rl, "use_pass_vector") col.prop(rl, "use_pass_uv") col.prop(rl, "use_pass_object_index") col.prop(rl, "use_pass_material_index") - col.prop(rl, "use_pass_ambient_occlusion") col.prop(rl, "use_pass_shadow") col = split.column() - col.label() col.label(text="Diffuse:") row = col.row(align=True) row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True) @@ -354,6 +353,7 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel): col.prop(rl, "use_pass_emit", text="Emission") col.prop(rl, "use_pass_environment") + col.prop(rl, "use_pass_ambient_occlusion") class Cycles_PT_post_processing(CyclesButtonsPanel, Panel): @@ -748,6 +748,31 @@ class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel): row.prop(light, "ao_factor", text="Factor") row.prop(light, "distance", text="Distance") +class CyclesWorld_PT_mist(CyclesButtonsPanel, Panel): + bl_label = "Mist Pass" + bl_context = "world" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + if CyclesButtonsPanel.poll(context): + for rl in context.scene.render.layers: + if rl.use_pass_mist: + return True + + return False + + def draw(self, context): + layout = self.layout + + world = context.world + + split = layout.split(align=True) + split.prop(world.mist_settings, "start") + split.prop(world.mist_settings, "depth") + + layout.prop(world.mist_settings, "falloff") + class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): bl_label = "Settings" diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 076612f2d0d..e69cf6b1bbf 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -187,6 +187,8 @@ static PassType get_pass_type(BL::RenderPass b_pass) case BL::RenderPass::type_Z: return PASS_DEPTH; + case BL::RenderPass::type_MIST: + return PASS_MIST; case BL::RenderPass::type_NORMAL: return PASS_NORMAL; case BL::RenderPass::type_OBJECT_INDEX: @@ -233,7 +235,6 @@ static PassType get_pass_type(BL::RenderPass b_pass) case BL::RenderPass::type_REFRACTION: case BL::RenderPass::type_SPECULAR: case BL::RenderPass::type_REFLECTION: - case BL::RenderPass::type_MIST: return PASS_NONE; } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 90d5e9244c4..b4dbd46bd71 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -208,6 +208,7 @@ void BlenderSync::sync_integrator() void BlenderSync::sync_film() { PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); + BL::WorldMistSettings b_mist = b_scene.world().mist_settings(); Film *film = scene->film; Film prevfilm = *film; @@ -216,6 +217,21 @@ void BlenderSync::sync_film() film->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type"); film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width"); + film->mist_start = b_mist.start(); + film->mist_depth = b_mist.depth(); + + switch(b_mist.falloff()) { + case BL::WorldMistSettings::falloff_QUADRATIC: + film->mist_falloff = 2.0f; + break; + case BL::WorldMistSettings::falloff_LINEAR: + film->mist_falloff = 1.0f; + break; + case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC: + film->mist_falloff = 0.5f; + break; + } + if(film->modified(prevfilm)) film->tag_update(scene); } diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 1cf230634fc..557990d7220 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -141,6 +141,7 @@ __device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) L->background = make_float3(0.0f, 0.0f, 0.0f); L->ao = make_float3(0.0f, 0.0f, 0.0f); L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f); + L->mist = 0.0f; } else L->emission = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 57dbdc2ffc1..c7d216e4638 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -86,6 +86,31 @@ __device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float L->color_glossy += shader_bsdf_glossy(kg, sd)*throughput; if(flag & (PASS_TRANSMISSION_INDIRECT|PASS_TRANSMISSION_COLOR|PASS_TRANSMISSION_DIRECT)) L->color_transmission += shader_bsdf_transmission(kg, sd)*throughput; + + if(flag & PASS_MIST) { + /* bring depth into 0..1 range */ + float mist_start = kernel_data.film.mist_start; + float mist_inv_depth = kernel_data.film.mist_inv_depth; + + float depth = camera_distance(kg, sd->P); + float mist = clamp((depth - mist_start)*mist_inv_depth, 0.0f, 1.0f); + + /* falloff */ + float mist_falloff = kernel_data.film.mist_falloff; + + if(mist_falloff == 1.0f) + ; + else if(mist_falloff == 2.0f) + mist = mist*mist; + else if(mist_falloff == 0.5f) + mist = sqrtf(mist); + else + mist = powf(mist, mist_falloff); + + /* modulate by transparency */ + float3 alpha = throughput*(make_float3(1.0f, 1.0f, 1.0f) - shader_bsdf_transparency(kg, sd)); + L->mist += (1.0f - mist)*average(alpha); + } #endif } @@ -128,6 +153,8 @@ __device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float shadow.w = kernel_data.film.pass_shadow_scale; kernel_write_pass_float4(buffer + kernel_data.film.pass_shadow, sample, shadow); } + if(flag & PASS_MIST) + kernel_write_pass_float(buffer + kernel_data.film.pass_mist, sample, L->mist); #endif } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f3bc7f45186..f165a1f3839 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -253,7 +253,8 @@ typedef enum PassType { PASS_AO = 131072, PASS_SHADOW = 262144, PASS_MOTION = 524288, - PASS_MOTION_WEIGHT = 1048576 + PASS_MOTION_WEIGHT = 1048576, + PASS_MIST = 2097152 } PassType; #define PASS_ALL (~0) @@ -290,6 +291,7 @@ typedef struct PathRadiance { float3 path_transmission; float4 shadow; + float mist; } PathRadiance; typedef struct BsdfEval { @@ -658,9 +660,13 @@ typedef struct KernelFilm { int pass_shadow; float pass_shadow_scale; - int filter_table_offset; - int filter_pad; + int pass_pad1; + + int pass_mist; + float mist_start; + float mist_inv_depth; + float mist_falloff; } KernelFilm; typedef struct KernelBackground { diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 50b7534f7a0..1fe30376adc 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -65,6 +65,9 @@ void Pass::add(PassType type, vector& passes) pass.components = 1; pass.filter = false; break; + case PASS_MIST: + pass.components = 1; + break; case PASS_NORMAL: pass.components = 4; break; @@ -252,6 +255,10 @@ Film::Film() filter_width = 1.0f; filter_table_offset = TABLE_OFFSET_INVALID; + mist_start = 0.0f; + mist_depth = 100.0f; + mist_falloff = 1.0f; + need_update = true; } @@ -284,6 +291,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_DEPTH: kfilm->pass_depth = kfilm->pass_stride; break; + case PASS_MIST: + kfilm->pass_mist = kfilm->pass_stride; + kfilm->use_light_pass = 1; + break; case PASS_NORMAL: kfilm->pass_normal = kfilm->pass_stride; break; @@ -366,6 +377,11 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) filter_table_offset = scene->lookup_tables->add_table(dscene, table); kfilm->filter_table_offset = (int)filter_table_offset; + /* mist pass parameters */ + kfilm->mist_start = mist_start; + kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f; + kfilm->mist_falloff = mist_falloff; + need_update = false; } diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index bc1619c3f2d..1df0e95a48a 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -57,6 +57,10 @@ public: float filter_width; size_t filter_table_offset; + float mist_start; + float mist_depth; + float mist_falloff; + bool need_update; Film();