diff options
-rw-r--r-- | intern/cycles/kernel/kernel_emission.h | 6 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/light.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 22 | ||||
-rw-r--r-- | intern/cycles/render/shader.h | 4 |
5 files changed, 41 insertions, 6 deletions
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 149ac3ed4f9..9fbcd9b371b 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -49,6 +49,12 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg, } else #endif + if(ls->lamp != LAMP_NONE && (ls->shader & SHADER_FIXED_EMISSION)) + { + float4 L = kernel_tex_fetch(__light_data, ls->lamp*LIGHT_SIZE + 4); + eval = make_float3(L.y, L.z, L.w); + } + else { shader_setup_from_sample(kg, emission_sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 0646148f6a0..5e2b0d6cc38 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -454,8 +454,9 @@ typedef enum ShaderFlag { SHADER_EXCLUDE_CAMERA = (1 << 24), SHADER_EXCLUDE_SCATTER = (1 << 23), SHADER_EXCLUDE_ANY = (SHADER_EXCLUDE_DIFFUSE|SHADER_EXCLUDE_GLOSSY|SHADER_EXCLUDE_TRANSMIT|SHADER_EXCLUDE_CAMERA|SHADER_EXCLUDE_SCATTER), + SHADER_FIXED_EMISSION = (1 << 22), - SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY) + SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT|SHADER_USE_MIS|SHADER_EXCLUDE_ANY|SHADER_FIXED_EMISSION) } ShaderFlag; /* Light Type */ diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 787e5cf07b2..c833a8b1c46 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -664,6 +664,11 @@ void LightManager::device_update_points(Device *device, use_light_visibility = true; } + float3 fixed_emission = make_float3(0.0f, 0.0f, 0.0f); + if(shader->is_constant_emission(&fixed_emission)) { + shader_id |= SHADER_FIXED_EMISSION; + } + if(light->type == LIGHT_POINT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -677,7 +682,6 @@ void LightManager::device_update_points(Device *device, light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f); light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_DISTANT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -698,7 +702,6 @@ void LightManager::device_update_points(Device *device, light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea); light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_BACKGROUND) { uint visibility = scene->background->visibility; @@ -727,7 +730,6 @@ void LightManager::device_update_points(Device *device, light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f); light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[light_index*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); @@ -745,7 +747,6 @@ void LightManager::device_update_points(Device *device, light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z); light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z); light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z); - light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } else if(light->type == LIGHT_SPOT) { shader_id &= ~SHADER_AREA_LIGHT; @@ -765,9 +766,10 @@ void LightManager::device_update_points(Device *device, light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle); light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z); light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f); - light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f); } + light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, fixed_emission.x, fixed_emission.y, fixed_emission.z); + light_index++; } diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 70e1443be2c..1849161ead9 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -194,6 +194,28 @@ Shader::~Shader() delete graph_bump; } +bool Shader::is_constant_emission(float3 *emission) +{ + ShaderInput *surf = graph->output()->input("Surface"); + + if(!surf->link || surf->link->parent->type != EmissionNode::node_type) { + return false; + } + + EmissionNode *node = (EmissionNode*) surf->link->parent; + + assert(node->input("Color")); + assert(node->input("Strength")); + + if(node->input("Color")->link || node->input("Strength")->link) { + return false; + } + + *emission = node->color*node->strength; + + return true; +} + void Shader::set_graph(ShaderGraph *graph_) { /* do this here already so that we can detect if mesh or object attributes diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index 696e22bc3c9..7d896652196 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -139,6 +139,10 @@ public: Shader(); ~Shader(); + /* Checks whether the shader consists of just a emission node with fixed inputs that's connected directly to the output. + * If yes, it sets the content of emission to the constant value (color * strength), which is then used for speeding up light evaluation. */ + bool is_constant_emission(float3* emission); + void set_graph(ShaderGraph *graph); void tag_update(Scene *scene); void tag_used(Scene *scene); |