Merged revision(s) 57768-57827 from trunk/blender into soc-2013-dingto
[blender.git] / intern / cycles / render / shader.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "bssrdf.h"
20 #include "blackbody.h"
21 #include "device.h"
22 #include "graph.h"
23 #include "light.h"
24 #include "mesh.h"
25 #include "nodes.h"
26 #include "osl.h"
27 #include "scene.h"
28 #include "shader.h"
29 #include "svm.h"
30 #include "tables.h"
31
32 #include "util_foreach.h"
33
34 CCL_NAMESPACE_BEGIN
35
36 /* Shader */
37
38 Shader::Shader()
39 {
40         name = "";
41         pass_id = 0;
42
43         graph = NULL;
44         graph_bump = NULL;
45
46         use_mis = true;
47         use_transparent_shadow = true;
48         homogeneous_volume = false;
49
50         has_surface = false;
51         has_surface_transparent = false;
52         has_surface_emission = false;
53         has_surface_bssrdf = false;
54         has_converter_blackbody = false;
55         has_volume = false;
56         has_displacement = false;
57
58         used = false;
59
60         need_update = true;
61         need_update_attributes = true;
62 }
63
64 Shader::~Shader()
65 {
66         delete graph;
67         delete graph_bump;
68 }
69
70 void Shader::set_graph(ShaderGraph *graph_)
71 {
72         /* do this here already so that we can detect if mesh or object attributes
73          * are needed, since the node attribute callbacks check if their sockets
74          * are connected but proxy nodes should not count */
75         if(graph_)
76                 graph_->remove_unneeded_nodes();
77
78         /* assign graph */
79         delete graph;
80         delete graph_bump;
81         graph = graph_;
82         graph_bump = NULL;
83 }
84
85 void Shader::tag_update(Scene *scene)
86 {
87         /* update tag */
88         need_update = true;
89         scene->shader_manager->need_update = true;
90
91         /* if the shader previously was emissive, update light distribution,
92          * if the new shader is emissive, a light manager update tag will be
93          * done in the shader manager device update. */
94         if(use_mis && has_surface_emission)
95                 scene->light_manager->need_update = true;
96
97         /* get requested attributes. this could be optimized by pruning unused
98          * nodes here already, but that's the job of the shader manager currently,
99          * and may not be so great for interactive rendering where you temporarily
100          * disconnect a node */
101         AttributeRequestSet prev_attributes = attributes;
102
103         attributes.clear();
104         foreach(ShaderNode *node, graph->nodes)
105                 node->attributes(&attributes);
106         
107         /* compare if the attributes changed, mesh manager will check
108          * need_update_attributes, update the relevant meshes and clear it. */
109         if(attributes.modified(prev_attributes)) {
110                 need_update_attributes = true;
111                 scene->mesh_manager->need_update = true;
112         }
113 }
114
115 void Shader::tag_used(Scene *scene)
116 {
117         /* if an unused shader suddenly gets used somewhere, it needs to be
118          * recompiled because it was skipped for compilation before */
119         if(!used) {
120                 need_update = true;
121                 scene->shader_manager->need_update = true;
122         }
123 }
124
125 /* Shader Manager */
126
127 ShaderManager::ShaderManager()
128 {
129         need_update = true;
130         bssrdf_table_offset = TABLE_OFFSET_INVALID;
131         blackbody_table_offset = TABLE_OFFSET_INVALID;
132 }
133
134 ShaderManager::~ShaderManager()
135 {
136 }
137
138 ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
139 {
140         ShaderManager *manager;
141
142 #ifdef WITH_OSL
143         if(shadingsystem == SceneParams::OSL)
144                 manager = new OSLShaderManager();
145         else
146 #endif
147                 manager = new SVMShaderManager();
148         
149         add_default(scene);
150
151         return manager;
152 }
153
154 uint ShaderManager::get_attribute_id(ustring name)
155 {
156         /* get a unique id for each name, for SVM attribute lookup */
157         AttributeIDMap::iterator it = unique_attribute_id.find(name);
158
159         if(it != unique_attribute_id.end())
160                 return it->second;
161         
162         uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
163         unique_attribute_id[name] = id;
164         return id;
165 }
166
167 uint ShaderManager::get_attribute_id(AttributeStandard std)
168 {
169         return (uint)std;
170 }
171
172 int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
173 {
174         /* get a shader id to pass to the kernel */
175         int id = shader*2;
176         
177         /* index depends bump since this setting is not in the shader */
178         if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
179                 id += 1;
180         /* smooth flag */
181         if(smooth)
182                 id |= SHADER_SMOOTH_NORMAL;
183         
184         /* default flags */
185         id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
186         
187         return id;
188 }
189
190 void ShaderManager::device_update_shaders_used(Scene *scene)
191 {
192         /* figure out which shaders are in use, so SVM/OSL can skip compiling them
193          * for speed and avoid loading image textures into memory */
194         foreach(Shader *shader, scene->shaders)
195                 shader->used = false;
196
197         scene->shaders[scene->default_surface]->used = true;
198         scene->shaders[scene->default_light]->used = true;
199         scene->shaders[scene->default_background]->used = true;
200         scene->shaders[scene->default_holdout]->used = true;
201         scene->shaders[scene->default_empty]->used = true;
202
203         foreach(Mesh *mesh, scene->meshes)
204                 foreach(uint shader, mesh->used_shaders)
205                         scene->shaders[shader]->used = true;
206
207         foreach(Light *light, scene->lights)
208                 scene->shaders[light->shader]->used = true;
209 }
210
211 void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
212 {
213         device->tex_free(dscene->shader_flag);
214         dscene->shader_flag.clear();
215
216         if(scene->shaders.size() == 0)
217                 return;
218
219         uint shader_flag_size = scene->shaders.size()*4;
220         uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
221         uint i = 0;
222         bool has_surface_bssrdf = false;
223         bool has_converter_blackbody = false;
224
225         foreach(Shader *shader, scene->shaders) {
226                 uint flag = 0;
227
228                 if(shader->use_mis)
229                         flag |= SD_USE_MIS;
230                 if(shader->has_surface_transparent && shader->use_transparent_shadow)
231                         flag |= SD_HAS_TRANSPARENT_SHADOW;
232                 if(shader->has_volume)
233                         flag |= SD_HAS_VOLUME;
234                 if(shader->homogeneous_volume)
235                         flag |= SD_HOMOGENEOUS_VOLUME;
236                 if(shader->has_surface_bssrdf)
237                         has_surface_bssrdf = true;
238                 if(shader->has_converter_blackbody)
239                         has_converter_blackbody = true;
240
241                 shader_flag[i++] = flag;
242                 shader_flag[i++] = shader->pass_id;
243                 shader_flag[i++] = flag;
244                 shader_flag[i++] = shader->pass_id;
245         }
246
247         device->tex_alloc("__shader_flag", dscene->shader_flag);
248
249         /* bssrdf lookup table */
250         KernelBSSRDF *kbssrdf = &dscene->data.bssrdf;
251
252         if(has_surface_bssrdf && bssrdf_table_offset == TABLE_OFFSET_INVALID) {
253                 vector<float> table;
254
255                 bssrdf_table_build(table);
256                 bssrdf_table_offset = scene->lookup_tables->add_table(dscene, table);
257
258                 kbssrdf->table_offset = (int)bssrdf_table_offset;
259                 kbssrdf->num_attempts = BSSRDF_MAX_ATTEMPTS;
260         }
261         else if(!has_surface_bssrdf && bssrdf_table_offset != TABLE_OFFSET_INVALID) {
262                 scene->lookup_tables->remove_table(bssrdf_table_offset);
263                 bssrdf_table_offset = TABLE_OFFSET_INVALID;
264         }
265
266         /* blackbody lookup table */
267         KernelBLACKBODY *kblackbody = &dscene->data.blackbody;
268         
269         if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) {
270                 vector<float> table = blackbody_table();
271                 blackbody_table_offset = scene->lookup_tables->add_table(dscene, table);
272                 
273                 kblackbody->table_offset = (int)blackbody_table_offset;
274         }
275         else if(!has_converter_blackbody && blackbody_table_offset != TABLE_OFFSET_INVALID) {
276                 scene->lookup_tables->remove_table(blackbody_table_offset);
277                 blackbody_table_offset = TABLE_OFFSET_INVALID;
278         }
279
280 }
281
282 void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
283 {
284         if(bssrdf_table_offset != TABLE_OFFSET_INVALID) {
285                 scene->lookup_tables->remove_table(bssrdf_table_offset);
286                 bssrdf_table_offset = TABLE_OFFSET_INVALID;
287         }
288
289         if(blackbody_table_offset != TABLE_OFFSET_INVALID) {
290                 scene->lookup_tables->remove_table(blackbody_table_offset);
291                 blackbody_table_offset = TABLE_OFFSET_INVALID;
292         }
293
294         device->tex_free(dscene->shader_flag);
295         dscene->shader_flag.clear();
296 }
297
298 void ShaderManager::add_default(Scene *scene)
299 {
300         Shader *shader;
301         ShaderGraph *graph;
302         ShaderNode *closure, *out;
303
304         /* default surface */
305         {
306                 graph = new ShaderGraph();
307
308                 closure = graph->add(new DiffuseBsdfNode());
309                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
310                 out = graph->output();
311
312                 graph->connect(closure->output("BSDF"), out->input("Surface"));
313
314                 shader = new Shader();
315                 shader->name = "default_surface";
316                 shader->graph = graph;
317                 scene->shaders.push_back(shader);
318                 scene->default_surface = scene->shaders.size() - 1;
319         }
320
321         /* default light */
322         {
323                 graph = new ShaderGraph();
324
325                 closure = graph->add(new EmissionNode());
326                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
327                 closure->input("Strength")->value.x = 0.0f;
328                 out = graph->output();
329
330                 graph->connect(closure->output("Emission"), out->input("Surface"));
331
332                 shader = new Shader();
333                 shader->name = "default_light";
334                 shader->graph = graph;
335                 scene->shaders.push_back(shader);
336                 scene->default_light = scene->shaders.size() - 1;
337         }
338
339         /* default background */
340         {
341                 graph = new ShaderGraph();
342
343                 closure = graph->add(new BackgroundNode());
344                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
345                 out = graph->output();
346
347                 graph->connect(closure->output("Background"), out->input("Surface"));
348
349                 shader = new Shader();
350                 shader->name = "default_background";
351                 shader->graph = graph;
352                 scene->shaders.push_back(shader);
353                 scene->default_background = scene->shaders.size() - 1;
354         }
355
356         /* default holdout */
357         {
358                 graph = new ShaderGraph();
359
360                 closure = graph->add(new HoldoutNode());
361                 out = graph->output();
362
363                 graph->connect(closure->output("Holdout"), out->input("Surface"));
364
365                 shader = new Shader();
366                 shader->name = "default_holdout";
367                 shader->graph = graph;
368                 scene->shaders.push_back(shader);
369                 scene->default_holdout = scene->shaders.size() - 1;
370         }
371
372         /* default empty */
373         {
374                 graph = new ShaderGraph();
375
376                 shader = new Shader();
377                 shader->name = "default_empty";
378                 shader->graph = graph;
379                 scene->shaders.push_back(shader);
380                 scene->default_empty = scene->shaders.size() - 1;
381         }
382 }
383
384 CCL_NAMESPACE_END
385