Cycles: mist pass added, with start/depth/falloff control. If the pass is
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 7 Jun 2013 12:45:26 +0000 (12:45 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 7 Jun 2013 12:45:26 +0000 (12:45 +0000)
enabled in a render layer a Mist Pass panel will be shown in the world
properties.

intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/kernel/kernel_accumulate.h
intern/cycles/kernel/kernel_passes.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/film.cpp
intern/cycles/render/film.h

index 9218e2ecf7ba4a209585bf54e520a89d8c0c2647..f9c516d1963eee3dd9007f3c60014f281851c9b7 100644 (file)
@@ -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"
index 076612f2d0d4fd88a5ffa2f7ab6049e91eba9b41..e69cf6b1bbff285b99a144157e0070f53392ec3d 100644 (file)
@@ -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;
        }
        
index 90d5e9244c48fe0aec4d3a1e8faa7d600d3b9f45..b4dbd46bd715d2c09367b44aca33205958037ad9 100644 (file)
@@ -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);
 }
index 1cf230634fc20b69ed256ec4d5c5148b373bf1b5..557990d7220db4a527c71ff4164e10738ffb0a85 100644 (file)
@@ -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);
index 57dbdc2ffc18dfdb9e1894fc77fc1d3772efd5bb..c7d216e46382c5cec1411318b1fd616775548bed 100644 (file)
@@ -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
 }
 
index f3bc7f45186c55b32005f31eda28e1d4304326cb..f165a1f3839a73573f97a3d66754459910888f3e 100644 (file)
@@ -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 {
index 50b7534f7a0111cd4073df6695d2e345f5180b52..1fe30376adcc095f2a384a70f6799dc3d8b759f4 100644 (file)
@@ -65,6 +65,9 @@ void Pass::add(PassType type, vector<Pass>& 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;
 }
 
index bc1619c3f2dcffae8d965abb5261a7a92f4fb5c8..1df0e95a48ab7d377d474c6a3582411ce37e9ea3 100644 (file)
@@ -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();