2 * Copyright 2011-2013 Blender Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 #include "background.h"
18 #include "blackbody.h"
30 #include "util_foreach.h"
45 use_transparent_shadow = true;
46 heterogeneous_volume = true;
49 has_surface_transparent = false;
50 has_surface_emission = false;
51 has_surface_bssrdf = false;
52 has_converter_blackbody = false;
54 has_displacement = false;
55 has_bssrdf_bump = false;
56 has_heterogeneous_volume = false;
61 need_update_attributes = true;
70 void Shader::set_graph(ShaderGraph *graph_)
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 */
76 graph_->remove_unneeded_nodes();
85 void Shader::tag_update(Scene *scene)
89 scene->shader_manager->need_update = true;
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;
97 /* quick detection of which kind of shaders we have to avoid loading
98 * e.g. surface attributes when there is only a volume shader. this could
99 * be more fine grained but it's better than nothing */
100 OutputNode *output = graph->output();
101 has_surface = has_surface || output->input("Surface")->link;
102 has_volume = has_volume || output->input("Volume")->link;
103 has_displacement = has_displacement || output->input("Displacement")->link;
105 /* get requested attributes. this could be optimized by pruning unused
106 * nodes here already, but that's the job of the shader manager currently,
107 * and may not be so great for interactive rendering where you temporarily
108 * disconnect a node */
110 AttributeRequestSet prev_attributes = attributes;
113 foreach(ShaderNode *node, graph->nodes)
114 node->attributes(this, &attributes);
116 /* compare if the attributes changed, mesh manager will check
117 * need_update_attributes, update the relevant meshes and clear it. */
118 if(attributes.modified(prev_attributes)) {
119 need_update_attributes = true;
120 scene->mesh_manager->need_update = true;
124 void Shader::tag_used(Scene *scene)
126 /* if an unused shader suddenly gets used somewhere, it needs to be
127 * recompiled because it was skipped for compilation before */
130 scene->shader_manager->need_update = true;
136 ShaderManager::ShaderManager()
139 blackbody_table_offset = TABLE_OFFSET_INVALID;
142 ShaderManager::~ShaderManager()
146 ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
148 ShaderManager *manager;
151 if(shadingsystem == SceneParams::OSL)
152 manager = new OSLShaderManager();
155 manager = new SVMShaderManager();
162 uint ShaderManager::get_attribute_id(ustring name)
164 /* get a unique id for each name, for SVM attribute lookup */
165 AttributeIDMap::iterator it = unique_attribute_id.find(name);
167 if(it != unique_attribute_id.end())
170 uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
171 unique_attribute_id[name] = id;
175 uint ShaderManager::get_attribute_id(AttributeStandard std)
180 int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
182 /* get a shader id to pass to the kernel */
185 /* index depends bump since this setting is not in the shader */
186 if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
190 id |= SHADER_SMOOTH_NORMAL;
193 id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
198 void ShaderManager::device_update_shaders_used(Scene *scene)
200 /* figure out which shaders are in use, so SVM/OSL can skip compiling them
201 * for speed and avoid loading image textures into memory */
202 foreach(Shader *shader, scene->shaders)
203 shader->used = false;
205 scene->shaders[scene->background->shader]->used = true;
206 scene->shaders[scene->default_surface]->used = true;
207 scene->shaders[scene->default_light]->used = true;
208 scene->shaders[scene->default_background]->used = true;
209 scene->shaders[scene->default_empty]->used = true;
211 foreach(Mesh *mesh, scene->meshes)
212 foreach(uint shader, mesh->used_shaders)
213 scene->shaders[shader]->used = true;
215 foreach(Light *light, scene->lights)
216 scene->shaders[light->shader]->used = true;
219 void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
221 device->tex_free(dscene->shader_flag);
222 dscene->shader_flag.clear();
224 if(scene->shaders.size() == 0)
227 uint shader_flag_size = scene->shaders.size()*4;
228 uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
230 bool has_converter_blackbody = false;
231 bool has_volumes = false;
233 foreach(Shader *shader, scene->shaders) {
238 if(shader->has_surface_transparent && shader->use_transparent_shadow)
239 flag |= SD_HAS_TRANSPARENT_SHADOW;
240 if(shader->has_volume) {
241 flag |= SD_HAS_VOLUME;
244 /* in this case we can assume transparent surface */
245 if(!shader->has_surface)
246 flag |= SD_HAS_ONLY_VOLUME;
248 /* todo: this could check more fine grained, to skip useless volumes
249 * enclosed inside an opaque bsdf, although we still need to handle
250 * the case with camera inside volumes too */
251 flag |= SD_HAS_TRANSPARENT_SHADOW;
253 if(shader->heterogeneous_volume && shader->has_heterogeneous_volume)
254 flag |= SD_HETEROGENEOUS_VOLUME;
255 if(shader->has_bssrdf_bump)
256 flag |= SD_HAS_BSSRDF_BUMP;
257 if(shader->has_converter_blackbody)
258 has_converter_blackbody = true;
261 shader_flag[i++] = flag;
262 shader_flag[i++] = shader->pass_id;
264 /* shader with bump mapping */
265 if(shader->graph_bump)
266 flag |= SD_HAS_BSSRDF_BUMP;
268 shader_flag[i++] = flag;
269 shader_flag[i++] = shader->pass_id;
272 device->tex_alloc("__shader_flag", dscene->shader_flag);
274 /* blackbody lookup table */
275 KernelBlackbody *kblackbody = &dscene->data.blackbody;
277 if(has_converter_blackbody && blackbody_table_offset == TABLE_OFFSET_INVALID) {
278 vector<float> table = blackbody_table();
279 blackbody_table_offset = scene->lookup_tables->add_table(dscene, table);
281 kblackbody->table_offset = (int)blackbody_table_offset;
283 else if(!has_converter_blackbody && blackbody_table_offset != TABLE_OFFSET_INVALID) {
284 scene->lookup_tables->remove_table(blackbody_table_offset);
285 blackbody_table_offset = TABLE_OFFSET_INVALID;
289 KernelIntegrator *kintegrator = &dscene->data.integrator;
290 kintegrator->use_volumes = has_volumes;
293 void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
295 if(blackbody_table_offset != TABLE_OFFSET_INVALID) {
296 scene->lookup_tables->remove_table(blackbody_table_offset);
297 blackbody_table_offset = TABLE_OFFSET_INVALID;
300 device->tex_free(dscene->shader_flag);
301 dscene->shader_flag.clear();
304 void ShaderManager::add_default(Scene *scene)
308 ShaderNode *closure, *out;
310 /* default surface */
312 graph = new ShaderGraph();
314 closure = graph->add(new DiffuseBsdfNode());
315 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
316 out = graph->output();
318 graph->connect(closure->output("BSDF"), out->input("Surface"));
320 shader = new Shader();
321 shader->name = "default_surface";
322 shader->graph = graph;
323 scene->shaders.push_back(shader);
324 scene->default_surface = scene->shaders.size() - 1;
329 graph = new ShaderGraph();
331 closure = graph->add(new EmissionNode());
332 closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
333 closure->input("Strength")->value.x = 0.0f;
334 out = graph->output();
336 graph->connect(closure->output("Emission"), out->input("Surface"));
338 shader = new Shader();
339 shader->name = "default_light";
340 shader->graph = graph;
341 scene->shaders.push_back(shader);
342 scene->default_light = scene->shaders.size() - 1;
345 /* default background */
347 graph = new ShaderGraph();
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;
358 graph = new ShaderGraph();
360 shader = new Shader();
361 shader->name = "default_empty";
362 shader->graph = graph;
363 scene->shaders.push_back(shader);
364 scene->default_empty = scene->shaders.size() - 1;