diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-28 00:37:24 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2011-09-28 00:37:24 +0400 |
commit | cdee3435c67abebb633cb09410c4a87d42ff61e3 (patch) | |
tree | 9647e36a3661caab918e7726a5971b58b444d403 /intern/cycles/render | |
parent | 136d27b350355232ebe4d0a13427777445334b05 (diff) |
Cycles: internal changes that should have no effect on user level yet, added
shader flags for various purposes, and some code for light types other than
points.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/light.cpp | 72 | ||||
-rw-r--r-- | intern/cycles/render/light.h | 15 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 9 | ||||
-rw-r--r-- | intern/cycles/render/scene.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 49 | ||||
-rw-r--r-- | intern/cycles/render/shader.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 11 |
9 files changed, 152 insertions, 23 deletions
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index b13cab55404..74943fd0ff7 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -32,8 +32,19 @@ CCL_NAMESPACE_BEGIN Light::Light() { + type = LIGHT_POINT; + co = make_float3(0.0f, 0.0f, 0.0f); - radius = 0.0f; + + dir = make_float3(0.0f, 0.0f, 0.0f); + size = 0.0f; + + axisu = make_float3(0.0f, 0.0f, 0.0f); + sizeu = 1.0f; + axisv = make_float3(0.0f, 0.0f, 0.0f); + sizev = 1.0f; + + cast_shadow = true; shader = 0; } @@ -68,7 +79,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { - if(scene->shaders[sindex]->has_surface_emission) { + Shader *shader = scene->shaders[sindex]; + + if(shader->sample_as_light && shader->has_surface_emission) { have_emission = true; break; } @@ -79,7 +92,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen for(size_t i = 0; i < mesh->triangles.size(); i++) { Shader *shader = scene->shaders[mesh->shader[i]]; - if(shader->has_surface_emission) + if(shader->sample_as_light && shader->has_surface_emission) num_triangles++; } } @@ -104,7 +117,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { - if(scene->shaders[sindex]->has_surface_emission) { + Shader *shader = scene->shaders[sindex]; + + if(shader->sample_as_light && shader->has_surface_emission) { have_emission = true; break; } @@ -118,7 +133,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen for(size_t i = 0; i < mesh->triangles.size(); i++) { Shader *shader = scene->shaders[mesh->shader[i]]; - if(shader->has_surface_emission) { + if(shader->sample_as_light && shader->has_surface_emission) { distribution[offset].x = totarea; distribution[offset].y = __int_as_float(i + mesh->tri_offset); distribution[offset].z = 1.0f; @@ -150,7 +165,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen distribution[offset].x = totarea; distribution[offset].y = __int_as_float(-i-1); distribution[offset].z = 1.0f; - distribution[offset].w = scene->lights[i]->radius; + distribution[offset].w = scene->lights[i]->size; totarea += lightarea; } } @@ -171,9 +186,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen /* update device */ KernelIntegrator *kintegrator = &dscene->data.integrator; - kintegrator->use_emission = (totarea > 0.0f) || (multi_light && num_lights); + kintegrator->use_direct_light = (totarea > 0.0f) || (multi_light && num_lights); - if(kintegrator->use_emission) { + if(kintegrator->use_direct_light) { /* number of emissives */ kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0; @@ -219,16 +234,45 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce if(scene->lights.size() == 0) return; - float4 *light_point = dscene->light_point.resize(scene->lights.size()); + float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE); for(size_t i = 0; i < scene->lights.size(); i++) { - float3 co = scene->lights[i]->co; + Light *light = scene->lights[i]; + float3 co = light->co; + float3 dir = normalize(light->dir); int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader); - light_point[i] = make_float4(co.x, co.y, co.z, __int_as_float(shader_id)); + if(!light->cast_shadow) + shader_id &= ~SHADER_CAST_SHADOW; + + if(light->type == LIGHT_POINT) { + shader_id &= ~SHADER_AREA_LIGHT; + + 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), light->size, 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(0.0f, 0.0f, 0.0f, 0.0f); + } + else if(light->type == LIGHT_DISTANT) { + shader_id &= ~SHADER_AREA_LIGHT; + + 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), light->size, 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(0.0f, 0.0f, 0.0f, 0.0f); + } + else if(light->type == LIGHT_AREA) { + float3 axisu = light->axisu*(light->sizeu*light->size); + float3 axisv = light->axisv*(light->sizev*light->size); + + 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); + light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z); + light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z); + } } - device->tex_alloc("__light_point", dscene->light_point); + device->tex_alloc("__light_data", dscene->light_data); } void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) @@ -250,10 +294,10 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce void LightManager::device_free(Device *device, DeviceScene *dscene) { device->tex_free(dscene->light_distribution); - device->tex_free(dscene->light_point); + device->tex_free(dscene->light_data); dscene->light_distribution.clear(); - dscene->light_point.clear(); + dscene->light_data.clear(); } void LightManager::tag_update(Scene *scene) diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index dbc333260ee..19cbcb55386 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -19,6 +19,8 @@ #ifndef __LIGHT_H__ #define __LIGHT_H__ +#include "kernel_types.h" + #include "util_types.h" #include "util_vector.h" @@ -33,8 +35,19 @@ class Light { public: Light(); + LightType type; float3 co; - float radius; /* not implemented yet */ + + float3 dir; + float size; + + float3 axisu; + float sizeu; + float3 axisv; + float sizev; + + bool cast_shadow; + int shader; void tag_update(Scene *scene); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 4fd562b540c..9e7e2a8a81d 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1214,6 +1214,7 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler) TransparentBsdfNode::TransparentBsdfNode() { + name = "transparent"; closure = CLOSURE_BSDF_TRANSPARENT_ID; } diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index fec1ab7f4c8..b91531ac462 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -88,9 +88,12 @@ void Object::tag_update(Scene *scene) if(mesh->transform_applied) mesh->need_update = true; - foreach(uint sindex, mesh->used_shaders) - if(scene->shaders[sindex]->has_surface_emission) + foreach(uint sindex, mesh->used_shaders) { + Shader *shader = scene->shaders[sindex]; + + if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; + } } scene->mesh_manager->need_update = true; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 446cf72f5d6..b0173334c76 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -91,7 +91,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(progress.get_cancel()) return; - if(shader->has_surface_emission) + if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; OSLCompiler compiler((void*)ss); @@ -112,12 +112,16 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene /* set texture system */ scene->image_manager->set_osl_texture_system((void*)ts); + + device_update_common(device, dscene, scene, progress); } void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) { OSLGlobals *og = (OSLGlobals*)device->osl_memory(); + device_free_common(device, dscene); + /* clear shader engine */ og->use = false; og->ss = NULL; @@ -340,6 +344,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) if(node->name == ustring("emission")) current_shader->has_surface_emission = true; + if(node->name == ustring("transparent")) + current_shader->has_surface_transparent = true; } else nodes_done = false; @@ -403,6 +409,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_surface = false; shader->has_surface_emission = false; + shader->has_surface_transparent = false; shader->has_volume = false; shader->has_displacement = false; diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 93d8ebf1301..a969dd66c4c 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -77,10 +77,11 @@ public: /* lights */ device_vector<float4> light_distribution; - device_vector<float4> light_point; + device_vector<float4> light_data; /* shaders */ device_vector<uint4> svm_nodes; + device_vector<uint> shader_flag; /* filter */ device_vector<float> filter_table; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 548beaaecdd..6e827ec94bb 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -39,7 +39,11 @@ Shader::Shader() graph = NULL; graph_bump = NULL; + sample_as_light = true; + homogeneous_volume = false; + has_surface = false; + has_surface_transparent = false; has_surface_emission = false; has_volume = false; has_displacement = false; @@ -72,7 +76,7 @@ void Shader::tag_update(Scene *scene) /* if the shader previously was emissive, update light distribution, * if the new shader is emissive, a light manager update tag will be * done in the shader manager device update. */ - if(has_surface_emission) + if(sample_as_light && has_surface_emission) scene->light_manager->need_update = true; /* get requested attributes. this could be optimized by pruning unused @@ -146,13 +150,52 @@ int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth) /* index depends bump since this setting is not in the shader */ if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE) id += 1; - /* stuff in smooth flag too */ + /* smooth flag */ if(smooth) - id= -id; + id |= SHADER_SMOOTH_NORMAL; + + /* default flags */ + id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT; return id; } +void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) +{ + device_free_common(device, dscene); + + if(scene->shaders.size() == 0) + return; + + uint shader_flag_size = scene->shaders.size()*2; + uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); + uint i = 0; + + foreach(Shader *shader, scene->shaders) { + uint flag = 0; + + if(shader->sample_as_light) + flag |= SD_SAMPLE_AS_LIGHT; + if(shader->has_surface_transparent) + flag |= SD_HAS_SURFACE_TRANSPARENT; + if(shader->has_volume) + flag |= SD_HAS_VOLUME; + if(shader->homogeneous_volume) + flag |= SD_HOMOGENEOUS_VOLUME; + + shader_flag[i++] = flag; + shader_flag[i++] = flag; + } + + device->tex_alloc("__shader_flag", dscene->shader_flag); +} + +void ShaderManager::device_free_common(Device *device, DeviceScene *dscene) +{ + device->tex_free(dscene->shader_flag); + dscene->shader_flag.clear(); +} + void ShaderManager::add_default(Scene *scene) { Shader *shader; diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index cc8bc473a3f..45efa123ef6 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -56,6 +56,10 @@ public: level setting, so we need to handle both */ ShaderGraph *graph_bump; + /* sampling */ + bool sample_as_light; + bool homogeneous_volume; + /* synchronization */ bool need_update; bool need_update_attributes; @@ -63,6 +67,7 @@ public: /* information about shader after compiling */ bool has_surface; bool has_surface_emission; + bool has_surface_transparent; bool has_volume; bool has_displacement; @@ -92,6 +97,9 @@ public: virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; virtual void device_free(Device *device, DeviceScene *dscene) = 0; + void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); + void device_free_common(Device *device, DeviceScene *dscene); + /* get globally unique id for a type of attribute */ uint get_attribute_id(ustring name); uint get_attribute_id(Attribute::Standard std); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 8b527691bd9..a1687ae5e29 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -66,7 +66,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene assert(shader->graph); - if(shader->has_surface_emission) + if(shader->sample_as_light && shader->has_surface_emission) scene->light_manager->need_update = true; SVMCompiler compiler(scene->shader_manager, scene->image_manager, @@ -86,11 +86,15 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene shader->need_update = false; } + device_update_common(device, dscene, scene, progress); + need_update = false; } void SVMShaderManager::device_free(Device *device, DeviceScene *dscene) { + device_free_common(device, dscene); + device->tex_free(dscene->svm_nodes); dscene->svm_nodes.clear(); } @@ -461,6 +465,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done) if(node->name == ustring("emission")) current_shader->has_surface_emission = true; + if(node->name == ustring("transparent")) + current_shader->has_surface_transparent = true; /* end node is added outside of this */ } @@ -538,6 +544,8 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don if(node->name == ustring("emission")) current_shader->has_surface_emission = true; + if(node->name == ustring("transparent")) + current_shader->has_surface_transparent = true; /* end node is added outside of this */ } @@ -641,6 +649,7 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in shader->has_surface = false; shader->has_surface_emission = false; + shader->has_surface_transparent = false; shader->has_volume = false; shader->has_displacement = false; |