Cycles: Implement Mitchell-Netravali pixel filter
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 22 Oct 2014 16:08:17 +0000 (18:08 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 22 Oct 2014 16:11:40 +0000 (18:11 +0200)
It's the same filter which is used by default by Blender Internal renderer
and it gives crispier edges than gaussian filter.

Default filter for Cycles is unchanged because it's unclear if new filter
gives more noise or not. After some further real production tests we can
consider making Mitchell filter default for Cycles as well.

intern/cycles/blender/addon/properties.py
intern/cycles/render/film.cpp
intern/cycles/render/film.h

index 05a6f70d42338d33d8dc572f59d9c9c27f039363..7524fe366aa9da4f02a2f3770662f9b83120cb23 100644 (file)
@@ -54,6 +54,7 @@ enum_bvh_types = (
 enum_filter_types = (
     ('BOX', "Box", "Box filter"),
     ('GAUSSIAN', "Gaussian", "Gaussian filter"),
+    ('MITCHELL', "Mitchell-Netravali", "Mitchell-Netravali filter"),
     )
 
 enum_aperture_types = (
index 19f959d4ea12a93433e893262df2b2101ed0567c..76a92d3d7049c7e8e8d48af2f349c0a111e4e165 100644 (file)
@@ -198,6 +198,29 @@ static float filter_func_gaussian(float v, float width)
        return expf(-2.0f*v*v);
 }
 
+static float filter_func_mitchell(float v, float width)
+{
+       (void)width;  /* Ignored. */
+
+       /* B = 1,   C = 0   - cubic B-spline */
+       /* B = 1/3, C = 1/3 - recommended */
+       /* B = 0,   C = 1/2 - Catmull-Rom spline */
+       const float B = 1.0f / 3.0f;
+       const float C = 1.0f / 3.0f;
+
+       const float ax = fabsf(v);
+       if (ax < 1.0f) {
+               return ((12.0f - 9.0f * B - 6 * C) * ax * ax * ax +
+                       (-18.0f + 12.0f * B + 6.0f * C) * ax * ax +
+                       (6.0f - 2.0f * B)) / 6.0f;
+       } else if ((ax >= 1.0f) && (ax < 2.0f)) {
+               return ((-B - 6.0f * C) * ax * ax * ax +
+                       (6.0f * B + 30.0f * C) * ax * ax + (-12.0f * B - 48.0f * C) *
+                       ax + (8.0f * B + 24.0f * C)) / 6.0f;
+       }
+       return 0.0f;
+}
+
 static vector<float> filter_table(FilterType type, float width)
 {
        const int filter_table_size = FILTER_TABLE_SIZE-1;
@@ -213,6 +236,9 @@ static vector<float> filter_table(FilterType type, float width)
                case FILTER_GAUSSIAN:
                        filter_func = filter_func_gaussian;
                        break;
+               case FILTER_MITCHELL:
+                       filter_func = filter_func_mitchell;
+                       break;
                default:
                        assert(0);
        }
index cc7183bfd95567ec419e23f8e08d6a5f5538ab97..31cc7697679e7eec9d4f4b8a62a75345a8c6b7c2 100644 (file)
@@ -30,7 +30,8 @@ class Scene;
 
 typedef enum FilterType {
        FILTER_BOX,
-       FILTER_GAUSSIAN
+       FILTER_GAUSSIAN,
+       FILTER_MITCHELL,
 } FilterType;
 
 class Pass {