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