Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.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 "device.h"
20 #include "graph.h"
21 #include "light.h"
22 #include "mesh.h"
23 #include "nodes.h"
24 #include "osl.h"
25 #include "scene.h"
26 #include "shader.h"
27 #include "svm.h"
28
29 #include "util_foreach.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 /* Shader */
34
35 Shader::Shader()
36 {
37         name = "";
38         pass_id = 0;
39
40         graph = NULL;
41         graph_bump = NULL;
42
43         sample_as_light = true;
44         homogeneous_volume = false;
45
46         has_surface = false;
47         has_surface_transparent = false;
48         has_surface_emission = false;
49         has_volume = false;
50         has_displacement = false;
51
52         need_update = true;
53         need_update_attributes = true;
54 }
55
56 Shader::~Shader()
57 {
58         delete graph;
59         delete graph_bump;
60 }
61
62 void Shader::set_graph(ShaderGraph *graph_)
63 {
64         /* assign graph */
65         delete graph;
66         delete graph_bump;
67         graph = graph_;
68         graph_bump = NULL;
69 }
70
71 void Shader::tag_update(Scene *scene)
72 {
73         /* update tag */
74         need_update = true;
75         scene->shader_manager->need_update = true;
76
77         /* if the shader previously was emissive, update light distribution,
78          * if the new shader is emissive, a light manager update tag will be
79          * done in the shader manager device update. */
80         if(sample_as_light && has_surface_emission)
81                 scene->light_manager->need_update = true;
82
83         /* get requested attributes. this could be optimized by pruning unused
84            nodes here already, but that's the job of the shader manager currently,
85            and may not be so great for interactive rendering where you temporarily
86            disconnect a node */
87         AttributeRequestSet prev_attributes = attributes;
88
89         attributes.clear();
90         foreach(ShaderNode *node, graph->nodes)
91                 node->attributes(&attributes);
92         
93         /* compare if the attributes changed, mesh manager will check
94            need_update_attributes, update the relevant meshes and clear it. */
95         if(attributes.modified(prev_attributes)) {
96                 need_update_attributes = true;
97                 scene->mesh_manager->need_update = true;
98         }
99 }
100
101 /* Shader Manager */
102
103 ShaderManager::ShaderManager()
104 {
105         need_update = true;
106 }
107
108 ShaderManager::~ShaderManager()
109 {
110 }
111
112 ShaderManager *ShaderManager::create(Scene *scene)
113 {
114         ShaderManager *manager;
115
116 #ifdef WITH_OSL
117         if(scene->params.shadingsystem == SceneParams::OSL)
118                 manager = new OSLShaderManager();
119         else
120 #endif
121                 manager = new SVMShaderManager();
122         
123         add_default(scene);
124
125         return manager;
126 }
127
128 uint ShaderManager::get_attribute_id(ustring name)
129 {
130         /* get a unique id for each name, for SVM attribute lookup */
131         AttributeIDMap::iterator it = unique_attribute_id.find(name);
132
133         if(it != unique_attribute_id.end())
134                 return it->second;
135         
136         uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
137         unique_attribute_id[name] = id;
138         return id;
139 }
140
141 uint ShaderManager::get_attribute_id(AttributeStandard std)
142 {
143         return (uint)std;
144 }
145
146 int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
147 {
148         /* get a shader id to pass to the kernel */
149         int id = shader*2;
150         
151         /* index depends bump since this setting is not in the shader */
152         if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
153                 id += 1;
154         /* smooth flag */
155         if(smooth)
156                 id |= SHADER_SMOOTH_NORMAL;
157         
158         /* default flags */
159         id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
160         
161         return id;
162 }
163
164 void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
165 {
166         device_free_common(device, dscene);
167
168         if(scene->shaders.size() == 0)
169                 return;
170
171         uint shader_flag_size = scene->shaders.size()*4;
172         uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
173         uint i = 0;
174
175         foreach(Shader *shader, scene->shaders) {
176                 uint flag = 0;
177
178                 if(shader->sample_as_light)
179                         flag |= SD_SAMPLE_AS_LIGHT;
180                 if(shader->has_surface_transparent)
181                         flag |= SD_HAS_SURFACE_TRANSPARENT;
182                 if(shader->has_volume)
183                         flag |= SD_HAS_VOLUME;
184                 if(shader->homogeneous_volume)
185                         flag |= SD_HOMOGENEOUS_VOLUME;
186
187                 shader_flag[i++] = flag;
188                 shader_flag[i++] = shader->pass_id;
189                 shader_flag[i++] = flag;
190                 shader_flag[i++] = shader->pass_id;
191         }
192
193         device->tex_alloc("__shader_flag", dscene->shader_flag);
194 }
195
196 void ShaderManager::device_free_common(Device *device, DeviceScene *dscene)
197 {
198         device->tex_free(dscene->shader_flag);
199         dscene->shader_flag.clear();
200 }
201
202 void ShaderManager::add_default(Scene *scene)
203 {
204         Shader *shader;
205         ShaderGraph *graph;
206         ShaderNode *closure, *out;
207
208         /* default surface */
209         {
210                 graph = new ShaderGraph();
211
212                 closure = graph->add(new DiffuseBsdfNode());
213                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
214                 out = graph->output();
215
216                 graph->connect(closure->output("BSDF"), out->input("Surface"));
217
218                 shader = new Shader();
219                 shader->name = "default_surface";
220                 shader->graph = graph;
221                 scene->shaders.push_back(shader);
222                 scene->default_surface = scene->shaders.size() - 1;
223         }
224
225         /* default light */
226         {
227                 graph = new ShaderGraph();
228
229                 closure = graph->add(new EmissionNode());
230                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
231                 closure->input("Strength")->value.x = 0.0f;
232                 out = graph->output();
233
234                 graph->connect(closure->output("Emission"), out->input("Surface"));
235
236                 shader = new Shader();
237                 shader->name = "default_light";
238                 shader->graph = graph;
239                 scene->shaders.push_back(shader);
240                 scene->default_light = scene->shaders.size() - 1;
241         }
242
243         /* default background */
244         {
245                 graph = new ShaderGraph();
246
247                 closure = graph->add(new BackgroundNode());
248                 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
249                 out = graph->output();
250
251                 graph->connect(closure->output("Background"), out->input("Surface"));
252
253                 shader = new Shader();
254                 shader->name = "default_background";
255                 shader->graph = graph;
256                 scene->shaders.push_back(shader);
257                 scene->default_background = scene->shaders.size() - 1;
258         }
259
260         /* default holdout */
261         {
262                 graph = new ShaderGraph();
263
264                 closure = graph->add(new HoldoutNode());
265                 out = graph->output();
266
267                 graph->connect(closure->output("Holdout"), out->input("Surface"));
268
269                 shader = new Shader();
270                 shader->name = "default_holdout";
271                 shader->graph = graph;
272                 scene->shaders.push_back(shader);
273                 scene->default_holdout = scene->shaders.size() - 1;
274         }
275
276         /* default empty */
277         {
278                 graph = new ShaderGraph();
279
280                 shader = new Shader();
281                 shader->name = "default_empty";
282                 shader->graph = graph;
283                 scene->shaders.push_back(shader);
284                 scene->default_empty = scene->shaders.size() - 1;
285         }
286 }
287
288 CCL_NAMESPACE_END
289