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