Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render/light.cpp')
-rw-r--r--intern/cycles/render/light.cpp112
1 files changed, 77 insertions, 35 deletions
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 1f006637e67..56bec4053d5 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
#include "background.h"
@@ -26,6 +26,7 @@
#include "util_foreach.h"
#include "util_progress.h"
+#include "util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -82,6 +83,8 @@ static void shade_background_pixels(Device *device, DeviceScene *dscene, int res
device->mem_free(d_input);
device->mem_free(d_output);
+ d_input.clear();
+
float4 *d_output_data = reinterpret_cast<float4*>(d_output.data_pointer);
pixels.resize(width*height);
@@ -125,6 +128,7 @@ Light::Light()
shader = 0;
samples = 1;
+ max_bounces = 1024;
}
void Light::tag_update(Scene *scene)
@@ -374,6 +378,45 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
}
}
+static void background_cdf(int start,
+ int end,
+ int res,
+ int cdf_count,
+ const vector<float3> *pixels,
+ float2 *cond_cdf)
+{
+ /* Conditional CDFs (rows, U direction). */
+ for(int i = start; i < end; i++) {
+ float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
+ float3 env_color = (*pixels)[i * res];
+ float ave_luminamce = average(env_color);
+
+ cond_cdf[i * cdf_count].x = ave_luminamce * sin_theta;
+ cond_cdf[i * cdf_count].y = 0.0f;
+
+ for(int j = 1; j < res; j++) {
+ env_color = (*pixels)[i * res + j];
+ ave_luminamce = average(env_color);
+
+ cond_cdf[i * cdf_count + j].x = ave_luminamce * sin_theta;
+ cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
+ }
+
+ float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
+ float cdf_total_inv = 1.0f / cdf_total;
+
+ /* stuff the total into the brightness value for the last entry, because
+ * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
+ cond_cdf[i * cdf_count + res].x = cdf_total;
+
+ if(cdf_total > 0.0f)
+ for(int j = 1; j < res; j++)
+ cond_cdf[i * cdf_count + j].y *= cdf_total_inv;
+
+ cond_cdf[i * cdf_count + res].y = 1.0f;
+ }
+}
+
void LightManager::device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
KernelIntegrator *kintegrator = &dscene->data.integrator;
@@ -414,34 +457,28 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene,
float2 *marg_cdf = dscene->light_background_marginal_cdf.resize(cdf_count);
float2 *cond_cdf = dscene->light_background_conditional_cdf.resize(cdf_count * cdf_count);
- /* conditional CDFs (rows, U direction) */
- for(int i = 0; i < res; i++) {
- float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
- float3 env_color = pixels[i * res];
- float ave_luminamce = average(env_color);
-
- cond_cdf[i * cdf_count].x = ave_luminamce * sin_theta;
- cond_cdf[i * cdf_count].y = 0.0f;
-
- for(int j = 1; j < res; j++) {
- env_color = pixels[i * res + j];
- ave_luminamce = average(env_color);
-
- cond_cdf[i * cdf_count + j].x = ave_luminamce * sin_theta;
- cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
+ double time_start = time_dt();
+ if(res < 512) {
+ /* Small enough resolution, faster to do single-threaded. */
+ background_cdf(0, res, res, cdf_count, &pixels, cond_cdf);
+ }
+ else {
+ /* Threaded evaluation for large resolution. */
+ const int num_blocks = TaskScheduler::num_threads();
+ const int chunk_size = res / num_blocks;
+ TaskPool pool;
+ for(int i = 0; i < num_blocks; ++i) {
+ const int current_chunk_size =
+ (i != num_blocks - 1) ? chunk_size
+ : (res - i * chunk_size);
+ pool.push(function_bind(&background_cdf,
+ i, i + current_chunk_size,
+ res,
+ cdf_count,
+ &pixels,
+ cond_cdf));
}
-
- float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
-
- /* stuff the total into the brightness value for the last entry, because
- * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
- cond_cdf[i * cdf_count + res].x = cdf_total;
-
- if(cdf_total > 0.0f)
- for(int j = 1; j < res; j++)
- cond_cdf[i * cdf_count + j].y /= cdf_total;
-
- cond_cdf[i * cdf_count + res].y = 1.0f;
+ pool.wait_work();
}
/* marginal CDFs (column, V direction, sum of rows) */
@@ -462,6 +499,8 @@ void LightManager::device_update_background(Device *device, DeviceScene *dscene,
marg_cdf[res].y = 1.0f;
+ VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
+
/* update device */
device->tex_alloc("__light_background_marginal_cdf", dscene->light_background_marginal_cdf);
device->tex_alloc("__light_background_conditional_cdf", dscene->light_background_conditional_cdf);
@@ -489,6 +528,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float3 co = light->co;
int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
float samples = __int_as_float(light->samples);
+ float max_bounces = __int_as_float(light->max_bounces);
if(!light->cast_shadow)
shader_id &= ~SHADER_CAST_SHADOW;
@@ -523,6 +563,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
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);
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -533,9 +574,8 @@ 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;
float3 dir = light->dir;
-
- if(len(dir) > 0.0f)
- dir = normalize(dir);
+
+ dir = safe_normalize(dir);
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
@@ -544,6 +584,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
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);
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_BACKGROUND) {
uint visibility = scene->background->visibility;
@@ -572,6 +613,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_AREA) {
float3 axisu = light->axisu*(light->sizeu*light->size);
@@ -580,8 +622,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
float3 dir = light->dir;
- if(len(dir) > 0.0f)
- dir = normalize(dir);
+ dir = safe_normalize(dir);
if(light->use_mis && area > 0.0f)
shader_id |= SHADER_USE_MIS;
@@ -590,6 +631,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
+ light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_SPOT) {
shader_id &= ~SHADER_AREA_LIGHT;
@@ -600,8 +642,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
float3 dir = light->dir;
- if(len(dir) > 0.0f)
- dir = normalize(dir);
+ dir = safe_normalize(dir);
if(light->use_mis && radius > 0.0f)
shader_id |= SHADER_USE_MIS;
@@ -610,6 +651,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
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);
light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
+ light_data[i*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
}
}