diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-12 17:13:56 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-12 17:13:56 +0400 |
commit | ebc653463ddfd9f8b893b6acbcc6465972e6abc6 (patch) | |
tree | 6b3cc2ba3f04994cf9f8d8f5bca6d63cfe2c9d1f /intern/cycles/render | |
parent | c40492205b4369de3babe63b43d127ca622773ec (diff) |
Cycles:
* Fix missing update when editing objects with emission materials.
* Fix preview pass rendering set to 1 not showing full resolution.
* Fix CUDA runtime compiling failing due to missing cache directory.
* Use settings from first render layer for visibility and material override.
And a bunch of incomplete and still disabled code mostly related to closure
sampling.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/light.cpp | 60 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 5 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/render/session.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/render/session.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 99 | ||||
-rw-r--r-- | intern/cycles/render/svm.h | 6 | ||||
-rw-r--r-- | intern/cycles/render/tile.cpp | 2 |
9 files changed, 167 insertions, 34 deletions
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index feb9e35e785..b13cab55404 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -55,6 +55,9 @@ LightManager::~LightManager() void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { + /* option to always sample all point lights */ + bool multi_light = false; + /* count */ size_t num_lights = scene->lights.size(); size_t num_triangles = 0; @@ -82,7 +85,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen } } - size_t num_distribution = num_triangles + num_lights; + size_t num_distribution = num_triangles; + + if(!multi_light) + num_distribution += num_lights; /* emission area */ float4 *distribution = dscene->light_distribution.resize(num_distribution + 1); @@ -137,14 +143,16 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen float trianglearea = totarea; /* point lights */ - float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; - - for(size_t i = 0; i < scene->lights.size(); i++, offset++) { - distribution[offset].x = totarea; - distribution[offset].y = __int_as_float(-i-1); - distribution[offset].z = 1.0f; - distribution[offset].w = scene->lights[i]->radius; - totarea += lightarea; + if(!multi_light) { + float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; + + for(size_t i = 0; i < scene->lights.size(); i++, offset++) { + distribution[offset].x = totarea; + distribution[offset].y = __int_as_float(-i-1); + distribution[offset].z = 1.0f; + distribution[offset].w = scene->lights[i]->radius; + totarea += lightarea; + } } /* normalize cumulative distribution functions */ @@ -163,28 +171,40 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* update device */ KernelIntegrator *kintegrator = &dscene->data.integrator; - kintegrator->use_emission = (totarea > 0.0f); + kintegrator->use_emission = (totarea > 0.0f) || (multi_light && num_lights); if(kintegrator->use_emission) { /* number of emissives */ - kintegrator->num_triangles = num_triangles; - kintegrator->num_lights = num_lights; - kintegrator->num_distribution = num_distribution; + kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0; /* precompute pdfs */ kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_lights = 0.0f; - if(trianglearea > 0.0f) { - kintegrator->pdf_triangles = 1.0f/trianglearea; + if(multi_light) { + /* sample one of all triangles and all lights */ + kintegrator->num_all_lights = num_lights; + + if(trianglearea > 0.0f) + kintegrator->pdf_triangles = 1.0f/trianglearea; if(num_lights) - kintegrator->pdf_triangles *= 0.5f; + kintegrator->pdf_lights = 1.0f; } + else { + /* sample one, with 0.5 probability of light or triangle */ + kintegrator->num_all_lights = 0; + + if(trianglearea > 0.0f) { + kintegrator->pdf_triangles = 1.0f/trianglearea; + if(num_lights) + kintegrator->pdf_triangles *= 0.5f; + } - if(num_lights) { - kintegrator->pdf_lights = 1.0f/num_lights; - if(trianglearea > 0.0f) - kintegrator->pdf_lights *= 0.5f; + if(num_lights) { + kintegrator->pdf_lights = 1.0f/num_lights; + if(trianglearea > 0.0f) + kintegrator->pdf_lights *= 0.5f; + } } /* CDF */ diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index b73013fc378..7a6ce547486 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -21,6 +21,7 @@ #include "device.h" #include "shader.h" +#include "light.h" #include "mesh.h" #include "object.h" #include "scene.h" @@ -250,6 +251,10 @@ void Mesh::tag_update(Scene *scene, bool rebuild) scene->mesh_manager->need_update = true; scene->object_manager->need_update = true; + + foreach(uint sindex, used_shaders) + if(scene->shaders[sindex]->has_surface_emission) + scene->light_manager->need_update = true; } /* Mesh Manager */ diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 0ff774bce59..f2030256814 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1024,7 +1024,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, (param1)? param1->stack_offset: SVM_STACK_INVALID, - (param2)? param2->stack_offset: SVM_STACK_INVALID), + (param2)? param2->stack_offset: SVM_STACK_INVALID, + compiler.closure_mix_weight_offset()), __float_as_int((param1)? param1->value.x: 0.0f), __float_as_int((param2)? param2->value.x: 0.0f)); } @@ -1222,8 +1223,6 @@ EmissionNode::EmissionNode() void EmissionNode::compile(SVMCompiler& compiler) { - compiler.add_node(NODE_CLOSURE_EMISSION, CLOSURE_EMISSION_ID); - ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); @@ -1236,6 +1235,8 @@ void EmissionNode::compile(SVMCompiler& compiler) compiler.add_node(NODE_EMISSION_SET_WEIGHT_TOTAL, color_in->value * strength_in->value.x); else compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value * strength_in->value.x); + + compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset()); } void EmissionNode::compile(OSLCompiler& compiler) @@ -1256,8 +1257,6 @@ BackgroundNode::BackgroundNode() void BackgroundNode::compile(SVMCompiler& compiler) { - compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID); - ShaderInput *color_in = input("Color"); ShaderInput *strength_in = input("Strength"); @@ -1268,6 +1267,8 @@ void BackgroundNode::compile(SVMCompiler& compiler) } else compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value*strength_in->value.x); + + compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID); } void BackgroundNode::compile(OSLCompiler& compiler) @@ -1285,7 +1286,7 @@ HoldoutNode::HoldoutNode() void HoldoutNode::compile(SVMCompiler& compiler) { - compiler.add_node(NODE_CLOSURE_HOLDOUT, CLOSURE_HOLDOUT_ID); + compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset()); } void HoldoutNode::compile(OSLCompiler& compiler) diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index fab051bde72..1059254d5c4 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -17,6 +17,7 @@ */ #include "device.h" +#include "light.h" #include "mesh.h" #include "object.h" #include "scene.h" @@ -83,8 +84,15 @@ void Object::apply_transform() void Object::tag_update(Scene *scene) { - if(mesh && mesh->transform_applied) - mesh->need_update = true; + if(mesh) { + if(mesh->transform_applied) + mesh->need_update = true; + + foreach(uint sindex, mesh->used_shaders) + if(scene->shaders[sindex]->has_surface_emission) + scene->light_manager->need_update = true; + } + scene->mesh_manager->need_update = true; scene->object_manager->need_update = true; } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 5fb687971ef..5eb8d51a816 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -35,7 +35,7 @@ Session::Session(const SessionParams& params_) : params(params_), tile_manager(params.progressive, params.passes, params.tile_size, params.min_size) { - device_use_gl = ((params.device_type == DEVICE_CUDA || params.device_type == DEVICE_OPENCL) && !params.background); + device_use_gl = ((params.device_type != DEVICE_CPU) && !params.background); device = Device::create(params.device_type, params.background, params.threads); buffers = new RenderBuffers(device); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 4d5cf434098..ca775939c09 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -58,7 +58,7 @@ public: background = false; output_path = ""; - progressive = false; + progressive = true; passes = INT_MAX; tile_size = 64; min_size = 64; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index da52eaecc18..c4188fda421 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -105,6 +105,7 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man current_type = SHADER_TYPE_SURFACE; current_shader = NULL; background = false; + mix_weight_offset = SVM_STACK_INVALID; } int SVMCompiler::stack_size(ShaderSocketType type) @@ -419,6 +420,84 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*> done, Stac } } +void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset) +{ + /* todo: the weaks point here is that unlike the single closure sampling + we will evaluate all nodes even if they are used as input for closures + that are unused. it's not clear what would be the best way to skip such + nodes at runtime, especially if they are tangled up */ + + if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) { + ShaderInput *fin = node->input("Fac"); + ShaderInput *cl1in = node->input("Closure1"); + ShaderInput *cl2in = node->input("Closure2"); + + uint out1_offset = SVM_STACK_INVALID; + uint out2_offset = SVM_STACK_INVALID; + + if(fin) { + /* mix closure */ + set<ShaderNode*> dependencies; + find_dependencies(dependencies, done, fin); + generate_svm_nodes(dependencies, done); + + stack_assign(fin); + + if(cl1in->link) + out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT); + if(cl2in->link) + out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT); + + add_node(NODE_MIX_CLOSURE, + encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset)); + } + else { + /* add closure */ + out1_offset = in_offset; + out2_offset = in_offset; + } + + if(cl1in->link) { + generate_multi_closure(cl1in->link->parent, done, out1_offset); + + if(fin) + active_stack.users[out1_offset]--; + } + + if(cl2in->link) { + generate_multi_closure(cl2in->link->parent, done, out2_offset); + + if(fin) + active_stack.users[out2_offset]--; + } + } + else { + /* execute dependencies for closure */ + foreach(ShaderInput *in, node->inputs) { + if(!node_skip_input(node, in) && in->link) { + set<ShaderNode*> dependencies; + find_dependencies(dependencies, done, in); + generate_svm_nodes(dependencies, done); + } + } + + mix_weight_offset = in_offset; + + /* compile closure itself */ + node->compile(*this); + stack_clear_users(node, done); + stack_clear_temporary(node); + + mix_weight_offset = SVM_STACK_INVALID; + + if(node->name == ustring("emission")) + current_shader->has_surface_emission = true; + + /* end node is added outside of this */ + } +} + + void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type) { /* Converting a shader graph into svm_nodes that can be executed @@ -464,21 +543,35 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty } if(clin->link) { + bool generate = false; if(type == SHADER_TYPE_SURFACE) { /* generate surface shader */ - generate_closure(clin->link->parent, set<ShaderNode*>(), Stack()); + generate = true; shader->has_surface = true; } else if(type == SHADER_TYPE_VOLUME) { /* generate volume shader */ - generate_closure(clin->link->parent, set<ShaderNode*>(), Stack()); + generate = true; shader->has_volume = true; } else if(type == SHADER_TYPE_DISPLACEMENT) { /* generate displacement shader */ - generate_closure(clin->link->parent, set<ShaderNode*>(), Stack()); + generate = true; shader->has_displacement = true; } + + if(generate) { + set<ShaderNode*> done; + bool multi_closure = false; /* __MULTI_CLOSURE__ */ + + if(multi_closure) { + generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID); + } + else { + Stack stack; + generate_closure(clin->link->parent, done, stack); + } + } } /* compile output node */ diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index f76649e4a6f..05fb85b057f 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -24,6 +24,7 @@ #include "shader.h" #include "util_set.h" +#include "util_string.h" CCL_NAMESPACE_BEGIN @@ -65,6 +66,7 @@ public: uint attribute(ustring name); uint attribute(Attribute::Standard std); uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0); + uint closure_mix_weight_offset() { return mix_weight_offset; } ShaderType output_type() { return current_type; } @@ -75,6 +77,8 @@ public: protected: struct Stack { + Stack() { memset(users, 0, sizeof(users)); } + int users[SVM_STACK_SIZE]; }; @@ -88,6 +92,7 @@ protected: void find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input); void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done); void generate_closure(ShaderNode *node, set<ShaderNode*> done, Stack stack); + void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset); void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type); @@ -96,6 +101,7 @@ protected: Shader *current_shader; Stack active_stack; int max_stack_use; + uint mix_weight_offset; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp index 450090c42f8..61f3af7aa10 100644 --- a/intern/cycles/render/tile.cpp +++ b/intern/cycles/render/tile.cpp @@ -96,7 +96,7 @@ void TileManager::set_tiles() bool TileManager::done() { - return (state.pass+1 >= passes); + return (state.pass+1 >= passes && state.resolution == 1); } bool TileManager::next() |