diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-04-02 00:26:52 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-04-02 00:26:52 +0400 |
commit | de9dffc61e15a6af41947cbcf09ada89779e86ac (patch) | |
tree | c3f6e42482085a3a18c8278adf55dbb1e0f76c8d /intern/cycles/render | |
parent | 40b05d364e988bca01dd338026dc24765f56187a (diff) |
Cycles: initial subsurface multiple scattering support. It's not working as
well as I would like, but it works, just add a subsurface scattering node and
you can use it like any other BSDF.
It is using fully raytraced sampling compatible with progressive rendering
and other more advanced rendering algorithms we might used in the future, and
it uses no extra memory so it's suitable for complex scenes.
Disadvantage is that it can be quite noisy and slow. Two limitations that will
be solved are that it does not work with bump mapping yet, and that the falloff
function used is a simple cubic function, it's not using the real BSSRDF
falloff function yet.
The node has a color input, along with a scattering radius for each RGB color
channel along with an overall scale factor for the radii.
There is also no GPU support yet, will test if I can get that working later.
Node Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#BSSRDF
Implementation notes:
http://wiki.blender.org/index.php/Dev:2.6/Source/Render/Cycles/Subsurface_Scattering
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/CMakeLists.txt | 2 | ||||
-rw-r--r-- | intern/cycles/render/bssrdf.cpp | 139 | ||||
-rw-r--r-- | intern/cycles/render/bssrdf.h | 31 | ||||
-rw-r--r-- | intern/cycles/render/film.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/render/graph.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/integrator.cpp | 3 | ||||
-rw-r--r-- | intern/cycles/render/integrator.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 37 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 10 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/render/osl.h | 6 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 3 | ||||
-rw-r--r-- | intern/cycles/render/shader.cpp | 34 | ||||
-rw-r--r-- | intern/cycles/render/shader.h | 7 | ||||
-rw-r--r-- | intern/cycles/render/svm.cpp | 11 | ||||
-rw-r--r-- | intern/cycles/render/svm.h | 2 | ||||
-rw-r--r-- | intern/cycles/render/tables.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/render/tables.h | 1 |
18 files changed, 288 insertions, 24 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 0f45f63d78a..e06364c6715 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -17,6 +17,7 @@ set(SRC attribute.cpp background.cpp buffers.cpp + bssrdf.cpp camera.cpp film.cpp # film_response.cpp (code unused) @@ -44,6 +45,7 @@ set(SRC_HEADERS attribute.h background.h buffers.h + bssrdf.h camera.h film.h # film_response.h (code unused) diff --git a/intern/cycles/render/bssrdf.cpp b/intern/cycles/render/bssrdf.cpp new file mode 100644 index 00000000000..91064fe45ba --- /dev/null +++ b/intern/cycles/render/bssrdf.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "bssrdf.h" + +#include "util_algorithm.h" +#include "util_math.h" +#include "util_types.h" + +#include "kernel_types.h" +#include "kernel_montecarlo.h" + +#include "closure/bsdf_diffuse.h" +#include "closure/bssrdf.h" + +CCL_NAMESPACE_BEGIN + +/* Cumulative density function utilities */ + +static float cdf_lookup_inverse(const vector<float>& table, float2 range, float x) +{ + int index = upper_bound(table.begin(), table.end(), x) - table.begin(); + + if(index == 0) + return range[0]; + else + index--; + + float t = (x - table[index])/(table[index+1] - table[index]); + float y = ((index + t)/(table.size() - 1)); + + return y*(range[1] - range[0]) + range[0]; +} + +static void cdf_invert(vector<float>& to, float2 to_range, const vector<float>& from, float2 from_range) +{ + float step = 1.0f/(float)(to.size() - 1); + + for(int i = 0; i < to.size(); i++) { + float x = (i*step)*(from_range[1] - from_range[0]) + from_range[0]; + to[i] = cdf_lookup_inverse(from, to_range, x); + } +} + +/* BSSRDF */ + +static float bssrdf_lookup_table_max_radius(const BSSRDFParams *ss) +{ + /* todo: adjust when we use the real BSSRDF */ + return ss->ld; +} + +static void bssrdf_lookup_table_create(const BSSRDFParams *ss, vector<float>& sample_table, vector<float>& pdf_table) +{ + const int size = BSSRDF_RADIUS_TABLE_SIZE; + vector<float> cdf(size); + vector<float> pdf(size); + float step = 1.0f/(float)(size - 1); + float max_radius = bssrdf_lookup_table_max_radius(ss); + float pdf_sum = 0.0f; + + /* compute the probability density function */ + for(int i = 0; i < pdf.size(); i++) { + float x = (i*step)*max_radius; + pdf[i] = bssrdf_cubic(ss->ld, x); + pdf_sum += pdf[i]; + } + + /* adjust for area covered by each distance */ + for(int i = 0; i < pdf.size(); i++) { + float x = (i*step)*max_radius; + pdf[i] *= 2*M_PI_F*x; + } + + /* normalize pdf, we multiply in reflectance later */ + if(pdf_sum > 0.0f) + for(int i = 0; i < pdf.size(); i++) + pdf[i] /= pdf_sum; + + /* sum to account for sampling which uses overlapping sphere */ + for(int i = pdf.size() - 2; i >= 0; i--) + pdf[i] = pdf[i] + pdf[i+1]; + + /* compute the cumulative density function */ + cdf[0] = 0.0f; + + for(int i = 1; i < size; i++) + cdf[i] = cdf[i-1] + 0.5f*(pdf[i-1] + pdf[i])*step*max_radius; + + /* invert cumulative density function for importance sampling */ + float2 cdf_range = make_float2(0.0f, cdf[size - 1]); + float2 table_range = make_float2(0.0f, max_radius); + + cdf_invert(sample_table, table_range, cdf, cdf_range); + + /* copy pdf table */ + for(int i = 0; i < pdf.size(); i++) + pdf_table[i] = pdf[i]; +} + +void bssrdf_table_build(vector<float>& table) +{ + vector<float> sample_table(BSSRDF_RADIUS_TABLE_SIZE); + vector<float> pdf_table(BSSRDF_RADIUS_TABLE_SIZE); + + table.resize(BSSRDF_LOOKUP_TABLE_SIZE); + + /* create a 2D lookup table, for reflection x sample radius */ + for(int i = 0; i < BSSRDF_REFL_TABLE_SIZE; i++) { + float refl = (float)i/(float)(BSSRDF_REFL_TABLE_SIZE-1); + float ior = 1.3f; + float radius = 1.0f; + + BSSRDFParams ss; + bssrdf_setup_params(&ss, refl, radius, ior); + bssrdf_lookup_table_create(&ss, sample_table, pdf_table); + + memcpy(&table[i*BSSRDF_RADIUS_TABLE_SIZE], &sample_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float)); + memcpy(&table[BSSRDF_PDF_TABLE_OFFSET + i*BSSRDF_RADIUS_TABLE_SIZE], &pdf_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float)); + } +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/render/bssrdf.h b/intern/cycles/render/bssrdf.h new file mode 100644 index 00000000000..975ac0b46ec --- /dev/null +++ b/intern/cycles/render/bssrdf.h @@ -0,0 +1,31 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __BSSRDF_H__ +#define __BSSRDF_H__ + +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +void bssrdf_table_build(vector<float>& table); + +CCL_NAMESPACE_END + +#endif /* __BSSRDF_H__ */ + diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 7dcbfa2278c..9fc6e867166 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -250,7 +250,7 @@ Film::Film() filter_type = FILTER_BOX; filter_width = 1.0f; - filter_table_offset = -1; + filter_table_offset = TABLE_OFFSET_INVALID; need_update = true; } @@ -371,8 +371,10 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene) { - if(filter_table_offset != -1) + if(filter_table_offset != TABLE_OFFSET_INVALID) { scene->lookup_tables->remove_table(filter_table_offset); + filter_table_offset = TABLE_OFFSET_INVALID; + } } bool Film::modified(const Film& film) diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index c6b9ae08508..46043cf85d2 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -187,6 +187,7 @@ public: virtual bool has_surface_emission() { return false; } virtual bool has_surface_transparent() { return false; } + virtual bool has_surface_bssrdf() { return false; } vector<ShaderInput*> inputs; vector<ShaderOutput*> outputs; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index 699e6979990..00039170733 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -54,6 +54,7 @@ Integrator::Integrator() transmission_samples = 1; ao_samples = 1; mesh_light_samples = 1; + subsurface_samples = 1; progressive = true; need_update = true; @@ -108,6 +109,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->transmission_samples = transmission_samples; kintegrator->ao_samples = ao_samples; kintegrator->mesh_light_samples = mesh_light_samples; + kintegrator->subsurface_samples = subsurface_samples; /* sobol directions table */ int max_samples = 1; @@ -163,6 +165,7 @@ bool Integrator::modified(const Integrator& integrator) transmission_samples == integrator.transmission_samples && ao_samples == integrator.ao_samples && mesh_light_samples == integrator.mesh_light_samples && + subsurface_samples == integrator.subsurface_samples && motion_blur == integrator.motion_blur); } diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 8fb341182b7..9867e310d4d 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -54,6 +54,7 @@ public: int transmission_samples; int ao_samples; int mesh_light_samples; + int subsurface_samples; bool progressive; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index a4ffc2518fb..b4ff6e3152b 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1262,16 +1262,19 @@ void ProxyNode::compile(OSLCompiler& compiler) /* BSDF Closure */ -BsdfNode::BsdfNode() -: ShaderNode("bsdf") +BsdfNode::BsdfNode(bool scattering_) +: ShaderNode("subsurface_scattering"), scattering(scattering_) { - closure = ccl::CLOSURE_BSDF_DIFFUSE_ID; + closure = ccl::CLOSURE_BSSRDF_ID; add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); - add_output("BSDF", SHADER_SOCKET_CLOSURE); + if(scattering) + add_output("BSSRDF", SHADER_SOCKET_CLOSURE); + else + add_output("BSDF", SHADER_SOCKET_CLOSURE); } void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3) @@ -1313,7 +1316,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * (param3)? param3->stack_offset: SVM_STACK_INVALID); } else { - compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset); + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, SVM_STACK_INVALID, + (param3)? param3->stack_offset: SVM_STACK_INVALID); } } @@ -1548,6 +1552,29 @@ void TransparentBsdfNode::compile(OSLCompiler& compiler) compiler.add(this, "node_transparent_bsdf"); } +/* Subsurface Scattering Closure */ + +SubsurfaceScatteringNode::SubsurfaceScatteringNode() +: BsdfNode(true) +{ + name = "subsurface_scattering"; + closure = CLOSURE_BSSRDF_ID; + + add_input("Scale", SHADER_SOCKET_FLOAT, 0.01f); + add_input("Radius", SHADER_SOCKET_VECTOR, make_float3(0.1f, 0.1f, 0.1f)); + add_input("IOR", SHADER_SOCKET_FLOAT, 1.3f); +} + +void SubsurfaceScatteringNode::compile(SVMCompiler& compiler) +{ + BsdfNode::compile(compiler, input("Scale"), input("IOR"), input("Radius")); +} + +void SubsurfaceScatteringNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_subsurface_scattering"); +} + /* Emissive Closure */ EmissionNode::EmissionNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 1efe4ae076d..0d9f84327d0 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -198,11 +198,13 @@ public: class BsdfNode : public ShaderNode { public: - SHADER_NODE_CLASS(BsdfNode) + BsdfNode(bool scattering = false); + SHADER_NODE_BASE_CLASS(BsdfNode); void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL); ClosureType closure; + bool scattering; }; class WardBsdfNode : public BsdfNode { @@ -257,6 +259,12 @@ public: static ShaderEnum distribution_enum; }; +class SubsurfaceScatteringNode : public BsdfNode { +public: + SHADER_NODE_CLASS(SubsurfaceScatteringNode) + bool has_surface_bssrdf() { return true; } +}; + class EmissionNode : public ShaderNode { public: SHADER_NODE_CLASS(EmissionNode) diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index f5585babf5c..cefb6315725 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -73,7 +73,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(!need_update) return; - device_free(device, dscene); + device_free(device, dscene, scene); /* determine which shaders are in use */ device_update_shaders_used(scene); @@ -114,11 +114,11 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene device_update_common(device, dscene, scene, progress); } -void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) +void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene) { OSLGlobals *og = (OSLGlobals*)device->osl_memory(); - device_free_common(device, dscene); + device_free_common(device, dscene, scene); /* clear shader engine */ og->use = false; @@ -328,6 +328,7 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str OSLShaderInfo info; info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos); info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos); + info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos); loaded_shaders[hash] = info; return loaded_shaders.find(hash)->first.c_str(); @@ -511,6 +512,8 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) current_shader->has_surface_emission = true; if(info->has_surface_transparent) current_shader->has_surface_transparent = true; + if(info->has_surface_bssrdf) + current_shader->has_surface_bssrdf = true; } } @@ -671,6 +674,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) + current_shader->has_surface_bssrdf = true; } else nodes_done = false; @@ -736,6 +741,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_surface = false; shader->has_surface_emission = false; shader->has_surface_transparent = false; + shader->has_surface_bssrdf = false; shader->has_volume = false; shader->has_displacement = false; diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 4b4ed6cba00..2d3996df0eb 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -50,11 +50,13 @@ class ShaderOutput; struct OSLShaderInfo { OSLShaderInfo() - : has_surface_emission(false), has_surface_transparent(false) + : has_surface_emission(false), has_surface_transparent(false), + has_surface_bssrdf(false) {} bool has_surface_emission; bool has_surface_transparent; + bool has_surface_bssrdf; }; /* Shader Manage */ @@ -69,7 +71,7 @@ public: bool use_osl() { return true; } void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, Scene *scene); /* osl compile and query */ static bool osl_compile(const string& inputfile, const string& outputfile); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 2b0609fdf1f..a6dca62ffd0 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -99,7 +99,7 @@ void Scene::free_memory(bool final) object_manager->device_free(device, &dscene); mesh_manager->device_free(device, &dscene); - shader_manager->device_free(device, &dscene); + shader_manager->device_free(device, &dscene, this); light_manager->device_free(device, &dscene); particle_system_manager->device_free(device, &dscene); @@ -187,7 +187,6 @@ void Scene::device_update(Device *device_, Progress& progress) progress.set_status("Updating Particle Systems"); particle_system_manager->device_update(device, &dscene, this, progress); - if(progress.get_cancel()) return; progress.set_status("Updating Film"); diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index b9b49bf2989..c7f39b4151a 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -16,6 +16,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "bssrdf.h" #include "device.h" #include "graph.h" #include "light.h" @@ -25,6 +26,7 @@ #include "scene.h" #include "shader.h" #include "svm.h" +#include "tables.h" #include "util_foreach.h" @@ -46,6 +48,7 @@ Shader::Shader() has_surface = false; has_surface_transparent = false; has_surface_emission = false; + has_surface_bssrdf = false; has_volume = false; has_displacement = false; @@ -115,6 +118,7 @@ void Shader::tag_used(Scene *scene) ShaderManager::ShaderManager() { need_update = true; + bssrdf_table_offset = TABLE_OFFSET_INVALID; } ShaderManager::~ShaderManager() @@ -196,7 +200,8 @@ void ShaderManager::device_update_shaders_used(Scene *scene) void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { - device_free_common(device, dscene); + device->tex_free(dscene->shader_flag); + dscene->shader_flag.clear(); if(scene->shaders.size() == 0) return; @@ -204,6 +209,7 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc uint shader_flag_size = scene->shaders.size()*4; uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); uint i = 0; + bool has_surface_bssrdf = false; foreach(Shader *shader, scene->shaders) { uint flag = 0; @@ -216,6 +222,8 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc flag |= SD_HAS_VOLUME; if(shader->homogeneous_volume) flag |= SD_HOMOGENEOUS_VOLUME; + if(shader->has_surface_bssrdf) + has_surface_bssrdf = true; shader_flag[i++] = flag; shader_flag[i++] = shader->pass_id; @@ -224,10 +232,32 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc } device->tex_alloc("__shader_flag", dscene->shader_flag); + + /* bssrdf lookup table */ + KernelBSSRDF *kbssrdf = &dscene->data.bssrdf; + + if(has_surface_bssrdf && bssrdf_table_offset == TABLE_OFFSET_INVALID) { + vector<float> table; + + bssrdf_table_build(table); + bssrdf_table_offset = scene->lookup_tables->add_table(dscene, table); + + kbssrdf->table_offset = (int)bssrdf_table_offset; + kbssrdf->num_attempts = BSSRDF_MAX_ATTEMPTS; + } + else if(!has_surface_bssrdf && bssrdf_table_offset != TABLE_OFFSET_INVALID) { + scene->lookup_tables->remove_table(bssrdf_table_offset); + bssrdf_table_offset = TABLE_OFFSET_INVALID; + } } -void ShaderManager::device_free_common(Device *device, DeviceScene *dscene) +void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene) { + if(bssrdf_table_offset != TABLE_OFFSET_INVALID) { + scene->lookup_tables->remove_table(bssrdf_table_offset); + bssrdf_table_offset = TABLE_OFFSET_INVALID; + } + device->tex_free(dscene->shader_flag); dscene->shader_flag.clear(); } diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index b38e098e3cb..2a9f1198467 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -75,6 +75,7 @@ public: bool has_surface_transparent; bool has_volume; bool has_displacement; + bool has_surface_bssrdf; /* requested mesh attributes */ AttributeRequestSet attributes; @@ -116,11 +117,11 @@ public: /* device update */ virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; - virtual void device_free(Device *device, DeviceScene *dscene) = 0; + virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0; void device_update_shaders_used(Scene *scene); void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_free_common(Device *device, DeviceScene *dscene); + void device_free_common(Device *device, DeviceScene *dscene, Scene *scene); /* get globally unique id for a type of attribute */ uint get_attribute_id(ustring name); @@ -138,6 +139,8 @@ protected: typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap; AttributeIDMap unique_attribute_id; + + size_t bssrdf_table_offset; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 5cb11a4ec1a..ea2fe4991db 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -50,7 +50,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene return; /* test if we need to update */ - device_free(device, dscene); + device_free(device, dscene, scene); /* determine which shaders are in use */ device_update_shaders_used(scene); @@ -99,9 +99,9 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene need_update = false; } -void SVMShaderManager::device_free(Device *device, DeviceScene *dscene) +void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene) { - device_free_common(device, dscene); + device_free_common(device, dscene, scene); device->tex_free(dscene->svm_nodes); dscene->svm_nodes.clear(); @@ -486,6 +486,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done) current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) + current_shader->has_surface_bssrdf = true; /* end node is added outside of this */ } @@ -546,6 +548,8 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) + current_shader->has_surface_bssrdf = true; } done.insert(node); @@ -654,6 +658,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_surface_bssrdf = false; shader->has_volume = false; shader->has_displacement = false; diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index c1ce619e12a..e09144a4e76 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -48,7 +48,7 @@ public: void reset(Scene *scene); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, Scene *scene); }; /* Graph Compiler */ diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp index fecdd52c60c..c7c86f68960 100644 --- a/intern/cycles/render/tables.cpp +++ b/intern/cycles/render/tables.cpp @@ -24,6 +24,8 @@ CCL_NAMESPACE_BEGIN +/* Lookup Tables */ + LookupTables::LookupTables() { need_update = true; @@ -39,7 +41,7 @@ void LookupTables::device_update(Device *device, DeviceScene *dscene) if(!need_update) return; - device->tex_alloc("__lookup_table", dscene->lookup_table, true); // XXX interpolation + device->tex_alloc("__lookup_table", dscene->lookup_table); need_update = false; } @@ -73,6 +75,8 @@ size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data) lookup_tables.insert(table, new_table); break; } + else + new_table.offset = table->offset + table->size; } if(table == lookup_tables.end()) { diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h index 5fa5136ae79..605efd3747f 100644 --- a/intern/cycles/render/tables.h +++ b/intern/cycles/render/tables.h @@ -28,6 +28,7 @@ class DeviceScene; class Scene; enum { TABLE_CHUNK_SIZE = 256 }; +enum { TABLE_OFFSET_INVALID = -1 }; class LookupTables { public: |