From dc0f4b56183cd81b6ba4653d281f6b8ec236a574 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 30 Jan 2013 15:57:15 +0000 Subject: 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 --- intern/cycles/render/light.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'intern/cycles/render/light.cpp') 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); -- cgit v1.2.3