diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-02 20:15:18 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-02 20:15:18 +0400 |
commit | 67030aaf84229b4d0dc52fbe07e91c2c9d320b0d (patch) | |
tree | 9b8d2402b3dd92134d78d1661d678effd8a70ecd /intern/cycles/render | |
parent | 1135875ab1501ff38184b91dc541aa8a2fe89c92 (diff) |
Cycles: optimizations for instances in scene updates before render starts,
should load a non-trivial mesh instanced many times quite a bit faster now.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/light.cpp | 63 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 45 |
2 files changed, 79 insertions, 29 deletions
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 88a797f753d..feb9e35e785 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -61,12 +61,24 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; + bool have_emission = false; - for(size_t i = 0; i < mesh->triangles.size(); i++) { - Shader *shader = scene->shaders[mesh->shader[i]]; + /* skip if we have no emission shaders */ + foreach(uint sindex, mesh->used_shaders) { + if(scene->shaders[sindex]->has_surface_emission) { + have_emission = true; + break; + } + } - if(shader->has_surface_emission) - num_triangles++; + /* count triangles */ + if(have_emission) { + for(size_t i = 0; i < mesh->triangles.size(); i++) { + Shader *shader = scene->shaders[mesh->shader[i]]; + + if(shader->has_surface_emission) + num_triangles++; + } } } @@ -82,25 +94,38 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; - Transform tfm = object->tfm; - int object_id = (mesh->transform_applied)? -j-1: j; + bool have_emission = false; + + /* skip if we have no emission shaders */ + foreach(uint sindex, mesh->used_shaders) { + if(scene->shaders[sindex]->has_surface_emission) { + have_emission = true; + break; + } + } + + /* sum area */ + if(have_emission) { + Transform tfm = object->tfm; + int object_id = (mesh->transform_applied)? -j-1: j; - for(size_t i = 0; i < mesh->triangles.size(); i++) { - Shader *shader = scene->shaders[mesh->shader[i]]; + for(size_t i = 0; i < mesh->triangles.size(); i++) { + Shader *shader = scene->shaders[mesh->shader[i]]; - if(shader->has_surface_emission) { - distribution[offset].x = totarea; - distribution[offset].y = __int_as_float(i + mesh->tri_offset); - distribution[offset].z = 1.0f; - distribution[offset].w = __int_as_float(object_id); - offset++; + if(shader->has_surface_emission) { + distribution[offset].x = totarea; + distribution[offset].y = __int_as_float(i + mesh->tri_offset); + distribution[offset].z = 1.0f; + distribution[offset].w = __int_as_float(object_id); + offset++; - Mesh::Triangle t = mesh->triangles[i]; - float3 p1 = transform(&tfm, mesh->verts[t.v[0]]); - float3 p2 = transform(&tfm, mesh->verts[t.v[1]]); - float3 p3 = transform(&tfm, mesh->verts[t.v[2]]); + Mesh::Triangle t = mesh->triangles[i]; + float3 p1 = transform(&tfm, mesh->verts[t.v[0]]); + float3 p2 = transform(&tfm, mesh->verts[t.v[1]]); + float3 p3 = transform(&tfm, mesh->verts[t.v[2]]); - totarea += triangle_area(p1, p2, p3); + totarea += triangle_area(p1, p2, p3); + } } } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 4ba2de6e61b..fab051bde72 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -22,6 +22,7 @@ #include "scene.h" #include "util_foreach.h" +#include "util_map.h" #include "util_progress.h" CCL_NAMESPACE_BEGIN @@ -103,6 +104,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene { float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size()); int i = 0; + map<Mesh*, float> surface_area_map; foreach(Object *ob, scene->objects) { Mesh *mesh = ob->mesh; @@ -112,16 +114,39 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene Transform itfm = transform_inverse(tfm); Transform ntfm = transform_transpose(itfm); - /* compute surface area */ + /* compute surface area. for uniform scale we can do avoid the many + transform calls and share computation for instances */ /* todo: correct for displacement, and move to a better place */ - float surfacearea = 0.0f; - - foreach(Mesh::Triangle& t, mesh->triangles) { - float3 p1 = transform(&tfm, mesh->verts[t.v[0]]); - float3 p2 = transform(&tfm, mesh->verts[t.v[1]]); - float3 p3 = transform(&tfm, mesh->verts[t.v[2]]); - - surfacearea += triangle_area(p1, p2, p3); + float uniform_scale; + float surface_area = 0.0f; + + if(transform_uniform_scale(tfm, uniform_scale)) { + map<Mesh*, float>::iterator it = surface_area_map.find(mesh); + + if(it == surface_area_map.end()) { + foreach(Mesh::Triangle& t, mesh->triangles) { + float3 p1 = mesh->verts[t.v[0]]; + float3 p2 = mesh->verts[t.v[1]]; + float3 p3 = mesh->verts[t.v[2]]; + + surface_area += triangle_area(p1, p2, p3); + } + + surface_area_map[mesh] = surface_area; + } + else + surface_area = it->second; + + surface_area *= uniform_scale; + } + else { + foreach(Mesh::Triangle& t, mesh->triangles) { + float3 p1 = transform(&tfm, mesh->verts[t.v[0]]); + float3 p2 = transform(&tfm, mesh->verts[t.v[1]]); + float3 p3 = transform(&tfm, mesh->verts[t.v[2]]); + + surface_area += triangle_area(p1, p2, p3); + } } /* pack in texture */ @@ -130,7 +155,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene memcpy(&objects[offset], &tfm, sizeof(float4)*4); memcpy(&objects[offset+4], &itfm, sizeof(float4)*4); memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4); - objects[offset+12] = make_float4(surfacearea, 0.0f, 0.0f, 0.0f); + objects[offset+12] = make_float4(surface_area, 0.0f, 0.0f, 0.0f); i++; |