diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-01-30 19:57:15 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-01-30 19:57:15 +0400 |
commit | dc0f4b56183cd81b6ba4653d281f6b8ec236a574 (patch) | |
tree | 96bb9e62d6e78e224d3de22a5ef18a7f72c67853 /intern | |
parent | 4c971d572785c63a4c715210308664941c5c8f26 (diff) |
Cycles: make multiple importance sampling for lamps an option per lamp now,
disabled by default for backwards compatibility.
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Integrator
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 14 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 5 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_emission.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_light.h | 39 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_path.h | 4 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 5 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 28 | ||||
-rw-r--r-- | intern/cycles/render/light.h | 1 |
9 files changed, 55 insertions, 46 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 3661274ae43..5f585fcb99c 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -462,8 +462,8 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup): type=cls, ) cls.sample_as_light = BoolProperty( - name="Sample as Lamp", - description="Use direct light sampling for this material, " + name="Multiple Importance Sample", + description="Use multiple importance sampling for this material, " "disabling may reduce overall noise for large " "objects that emit little light compared to other light sources", default=True, @@ -499,6 +499,12 @@ class CyclesLampSettings(bpy.types.PropertyGroup): min=1, max=10000, default=1, ) + cls.use_multiple_importance_sampling = BoolProperty( + name="Multiple Importance Sample", + description="Use multiple importance sampling for the lamp, " + "reduces noise for area lamps and sharp glossy materials", + default=False, + ) @classmethod def unregister(cls): @@ -514,8 +520,8 @@ class CyclesWorldSettings(bpy.types.PropertyGroup): type=cls, ) cls.sample_as_light = BoolProperty( - name="Sample as Lamp", - description="Use direct light sampling for the environment, " + name="Multiple Importance Sample", + description="Use multiple importance sampling for the environment, " "enabling for non-solid colors is recommended", default=False, ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index a42b69dc5c6..ad9253fd68b 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -574,6 +574,8 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): col = split.column() col.prop(clamp, "cast_shadow") + layout.prop(clamp, "use_multiple_importance_sampling") + if lamp.type == 'HEMI': layout.label(text="Not supported, interpreted as sun lamp.") @@ -807,9 +809,10 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel): col.prop(mat, "diffuse_color", text="Viewport Color") col = split.column() - col.prop(cmat, "sample_as_light") col.prop(mat, "pass_index") + layout.prop(cmat, "sample_as_light") + class CyclesTexture_PT_context(CyclesButtonsPanel, Panel): bl_label = "" diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index e9bcea70ab6..a9d37dbed99 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -156,6 +156,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI /* shadow */ PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles"); light->cast_shadow = get_boolean(clamp, "cast_shadow"); + light->use_mis = get_boolean(clamp, "use_multiple_importance_sampling"); light->samples = get_int(clamp, "samples"); /* tag */ diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 54bc0717b60..e234d54e228 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -93,7 +93,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, } /* return lamp index for MIS */ - if(ls.use_mis) + if(ls.shader & SHADER_USE_MIS) *lamp = ls.lamp; else *lamp= ~0; @@ -114,7 +114,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, shader_bsdf_eval(kg, sd, ls.D, eval, &bsdf_pdf); - if(ls.use_mis) { + if(ls.shader & SHADER_USE_MIS) { /* multiple importance sampling */ float mis_weight = power_heuristic(ls.pdf, bsdf_pdf); light_eval *= mis_weight; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 6ba3e439329..8b32b7bd2e8 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -31,7 +31,6 @@ typedef struct LightSample { int prim; /* primitive id for triangle/curve ligths */ int shader; /* shader id */ int lamp; /* lamp id */ - int use_mis; /* for lamps with size zero */ LightType type; /* type of light */ } LightSample; @@ -218,11 +217,10 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, LightType type = (LightType)__float_as_int(data0.x); ls->type = type; -#ifdef __LAMP_MIS__ - ls->use_mis = true; -#else - ls->use_mis = false; -#endif + ls->shader = __float_as_int(data1.x); + ls->object = ~0; + ls->prim = ~0; + ls->lamp = lamp; if(type == LIGHT_DISTANT) { /* distant light */ @@ -233,10 +231,6 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, if(radius > 0.0f) D = distant_light_sample(D, radius, randu, randv); -#ifdef __LAMP_MIS__ - else - ls->use_mis = false; -#endif ls->P = D; ls->Ng = D; @@ -257,9 +251,6 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, ls->D = -D; ls->t = FLT_MAX; ls->eval_fac = 1.0f; -#ifndef __LAMP_MIS__ - ls->use_mis = true; -#endif } #endif else { @@ -271,10 +262,6 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, if(radius > 0.0f) /* sphere light */ ls->P += sphere_light_sample(P, ls->P, radius, randu, randv); -#ifdef __LAMP_MIS__ - else - ls->use_mis = false; -#endif ls->D = normalize_len(ls->P - P, &ls->t); ls->Ng = -ls->D; @@ -304,13 +291,6 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, float invarea = data2.x; - if(invarea == 0.0f) { -#ifdef __LAMP_MIS__ - ls->use_mis = false; -#endif - invarea = 1.0f; - } - ls->eval_fac = 0.25f*invarea; ls->pdf = invarea; } @@ -318,11 +298,6 @@ __device void lamp_light_sample(KernelGlobals *kg, int lamp, ls->eval_fac *= kernel_data.integrator.inv_pdf_lights; ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t); } - - ls->shader = __float_as_int(data1.x); - ls->object = ~0; - ls->prim = ~0; - ls->lamp = lamp; } __device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, float t, LightSample *ls) @@ -336,7 +311,6 @@ __device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D, f ls->object = ~0; ls->prim = ~0; ls->lamp = lamp; - ls->use_mis = false; /* flag not used for eval */ if(type == LIGHT_DISTANT) { /* distant light */ @@ -475,7 +449,7 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object, ls->object = object; ls->prim = prim; ls->lamp = ~0; - ls->use_mis = true; + ls->shader |= SHADER_USE_MIS; ls->t = 0.0f; ls->type = LIGHT_AREA; ls->eval_fac = 1.0f; @@ -529,11 +503,10 @@ __device void curve_segment_light_sample(KernelGlobals *kg, int prim, int object ls->object = object; ls->prim = prim; ls->lamp = ~0; - ls->use_mis = true; ls->t = 0.0f; ls->type = LIGHT_STRAND; ls->eval_fac = 1.0f; - ls->shader = __float_as_int(v00.z); + ls->shader = __float_as_int(v00.z) | SHADER_USE_MIS; object_transform_light_sample(kg, ls, object, time); } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 1a5df66e6c2..06276c8167a 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -254,7 +254,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, bool hit = scene_intersect(kg, &ray, visibility, &isect); #ifdef __LAMP_MIS__ - if(kernel_data.integrator.pdf_lights > 0.0f && !(state.flag & PATH_RAY_CAMERA)) { + if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) { /* ray starting from previous non-transparent bounce */ Ray light_ray; @@ -501,7 +501,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray bool hit = scene_intersect(kg, &ray, visibility, &isect); #ifdef __LAMP_MIS__ - if(kernel_data.integrator.pdf_lights > 0.0f && !(state.flag & PATH_RAY_CAMERA)) { + if(kernel_data.integrator.use_lamp_mis && !(state.flag & PATH_RAY_CAMERA)) { /* ray starting from previous non-transparent bounce */ Ray light_ray; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 1236f43e018..2ef3d71dd1d 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -288,8 +288,9 @@ typedef enum ShaderFlag { SHADER_SMOOTH_NORMAL = (1 << 31), SHADER_CAST_SHADOW = (1 << 30), SHADER_AREA_LIGHT = (1 << 29), + SHADER_USE_MIS = (1 << 28), - SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT) + SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS) } ShaderFlag; /* Light Type */ @@ -680,7 +681,7 @@ typedef struct KernelIntegrator { int transmission_samples; int ao_samples; int mesh_light_samples; - int pad1; + int use_lamp_mis; } KernelIntegrator; typedef struct KernelBVH { diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 04fea1953e7..e7fb9514371 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -115,6 +115,8 @@ Light::Light() spot_smooth = 0.0f; cast_shadow = true; + use_mis = false; + shader = 0; samples = 1; } @@ -291,13 +293,19 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* point lights */ float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; + bool use_lamp_mis = false; for(int i = 0; i < scene->lights.size(); i++, offset++) { + Light *light = scene->lights[i]; + distribution[offset].x = totarea; distribution[offset].y = __int_as_float(~(int)i); distribution[offset].z = 1.0f; - distribution[offset].w = scene->lights[i]->size; + distribution[offset].w = light->size; totarea += lightarea; + + if(light->size > 0.0f && light->use_mis) + use_lamp_mis = true; } /* normalize cumulative distribution functions */ @@ -344,6 +352,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen kintegrator->inv_pdf_lights = 1.0f/kintegrator->pdf_lights; } + kintegrator->use_lamp_mis = use_lamp_mis; + /* CDF */ device->tex_alloc("__light_distribution", dscene->light_distribution); } @@ -355,6 +365,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; kintegrator->inv_pdf_lights = 0.0f; + kintegrator->use_lamp_mis = false; } } @@ -484,6 +495,9 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce float radius = light->size; float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f; + if(light->use_mis && radius > 0.0f) + shader_id |= SHADER_USE_MIS; + light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f); light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); @@ -498,6 +512,9 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce float area = M_PI_F*radius*radius; float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + if(light->use_mis && area > 0.0f) + shader_id |= SHADER_USE_MIS; + light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea); light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); @@ -505,6 +522,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce } else if(light->type == LIGHT_BACKGROUND) { shader_id &= ~SHADER_AREA_LIGHT; + shader_id |= SHADER_USE_MIS; light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f); @@ -515,7 +533,10 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce float3 axisu = light->axisu*(light->sizeu*light->size); float3 axisv = light->axisv*(light->sizev*light->size); float area = len(axisu)*len(axisv); - float invarea = (area > 0.0f)? 1.0f/area: 0.0f; + float invarea = (area > 0.0f)? 1.0f/area: 1.0f; + + if(light->use_mis && area > 0.0f) + shader_id |= SHADER_USE_MIS; light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); @@ -530,6 +551,9 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce float spot_angle = cosf(light->spot_angle*0.5f); float spot_smooth = (1.0f - spot_angle)*light->spot_smooth; + if(light->use_mis && radius > 0.0f) + shader_id |= SHADER_USE_MIS; + light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle); light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z); diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 3cedde2596e..acd1692a41f 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -52,6 +52,7 @@ public: float spot_smooth; bool cast_shadow; + bool use_mis; int shader; int samples; |