Blender V2.61 - r43446

shader.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "device.h"
00020 #include "graph.h"
00021 #include "light.h"
00022 #include "mesh.h"
00023 #include "nodes.h"
00024 #include "osl.h"
00025 #include "scene.h"
00026 #include "shader.h"
00027 #include "svm.h"
00028 
00029 #include "util_foreach.h"
00030 
00031 CCL_NAMESPACE_BEGIN
00032 
00033 /* Shader */
00034 
00035 Shader::Shader()
00036 {
00037     name = "";
00038 
00039     graph = NULL;
00040     graph_bump = NULL;
00041 
00042     sample_as_light = true;
00043     homogeneous_volume = false;
00044 
00045     has_surface = false;
00046     has_surface_transparent = false;
00047     has_surface_emission = false;
00048     has_volume = false;
00049     has_displacement = false;
00050 
00051     need_update = true;
00052     need_update_attributes = true;
00053 }
00054 
00055 Shader::~Shader()
00056 {
00057     delete graph;
00058     delete graph_bump;
00059 }
00060 
00061 void Shader::set_graph(ShaderGraph *graph_)
00062 {
00063     /* assign graph */
00064     delete graph;
00065     delete graph_bump;
00066     graph = graph_;
00067     graph_bump = NULL;
00068 }
00069 
00070 void Shader::tag_update(Scene *scene)
00071 {
00072     /* update tag */
00073     need_update = true;
00074     scene->shader_manager->need_update = true;
00075 
00076     /* if the shader previously was emissive, update light distribution,
00077      * if the new shader is emissive, a light manager update tag will be
00078      * done in the shader manager device update. */
00079     if(sample_as_light && has_surface_emission)
00080         scene->light_manager->need_update = true;
00081 
00082     /* get requested attributes. this could be optimized by pruning unused
00083        nodes here already, but that's the job of the shader manager currently,
00084        and may not be so great for interactive rendering where you temporarily
00085        disconnect a node */
00086     AttributeRequestSet prev_attributes = attributes;
00087 
00088     attributes.clear();
00089     foreach(ShaderNode *node, graph->nodes)
00090         node->attributes(&attributes);
00091     
00092     /* compare if the attributes changed, mesh manager will check
00093        need_update_attributes, update the relevant meshes and clear it. */
00094     if(attributes.modified(prev_attributes)) {
00095         need_update_attributes = true;
00096         scene->mesh_manager->need_update = true;
00097     }
00098 }
00099 
00100 /* Shader Manager */
00101 
00102 ShaderManager::ShaderManager()
00103 {
00104     need_update = true;
00105 }
00106 
00107 ShaderManager::~ShaderManager()
00108 {
00109 }
00110 
00111 ShaderManager *ShaderManager::create(Scene *scene)
00112 {
00113     ShaderManager *manager;
00114 
00115 #ifdef WITH_OSL
00116     if(scene->params.shadingsystem == SceneParams::OSL)
00117         manager = new OSLShaderManager();
00118     else
00119 #endif
00120         manager = new SVMShaderManager();
00121     
00122     add_default(scene);
00123 
00124     return manager;
00125 }
00126 
00127 uint ShaderManager::get_attribute_id(ustring name)
00128 {
00129     /* get a unique id for each name, for SVM attribute lookup */
00130     AttributeIDMap::iterator it = unique_attribute_id.find(name);
00131 
00132     if(it != unique_attribute_id.end())
00133         return it->second;
00134     
00135     uint id = (uint)Attribute::STD_NUM + unique_attribute_id.size();
00136     unique_attribute_id[name] = id;
00137     return id;
00138 }
00139 
00140 uint ShaderManager::get_attribute_id(Attribute::Standard std)
00141 {
00142     return (uint)std;
00143 }
00144 
00145 int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
00146 {
00147     /* get a shader id to pass to the kernel */
00148     int id = shader*2;
00149     
00150     /* index depends bump since this setting is not in the shader */
00151     if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
00152         id += 1;
00153     /* smooth flag */
00154     if(smooth)
00155         id |= SHADER_SMOOTH_NORMAL;
00156     
00157     /* default flags */
00158     id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
00159     
00160     return id;
00161 }
00162 
00163 void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
00164 {
00165     device_free_common(device, dscene);
00166 
00167     if(scene->shaders.size() == 0)
00168         return;
00169 
00170     uint shader_flag_size = scene->shaders.size()*2;
00171     uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
00172     uint i = 0;
00173 
00174     foreach(Shader *shader, scene->shaders) {
00175         uint flag = 0;
00176 
00177         if(shader->sample_as_light)
00178             flag |= SD_SAMPLE_AS_LIGHT;
00179         if(shader->has_surface_transparent)
00180             flag |= SD_HAS_SURFACE_TRANSPARENT;
00181         if(shader->has_volume)
00182             flag |= SD_HAS_VOLUME;
00183         if(shader->homogeneous_volume)
00184             flag |= SD_HOMOGENEOUS_VOLUME;
00185 
00186         shader_flag[i++] = flag;
00187         shader_flag[i++] = flag;
00188     }
00189 
00190     device->tex_alloc("__shader_flag", dscene->shader_flag);
00191 }
00192 
00193 void ShaderManager::device_free_common(Device *device, DeviceScene *dscene)
00194 {
00195     device->tex_free(dscene->shader_flag);
00196     dscene->shader_flag.clear();
00197 }
00198 
00199 void ShaderManager::add_default(Scene *scene)
00200 {
00201     Shader *shader;
00202     ShaderGraph *graph;
00203     ShaderNode *closure, *out;
00204 
00205     /* default surface */
00206     {
00207         graph = new ShaderGraph();
00208 
00209         closure = graph->add(new DiffuseBsdfNode());
00210         closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
00211         out = graph->output();
00212 
00213         graph->connect(closure->output("BSDF"), out->input("Surface"));
00214 
00215         shader = new Shader();
00216         shader->name = "default_surface";
00217         shader->graph = graph;
00218         scene->shaders.push_back(shader);
00219         scene->default_surface = scene->shaders.size() - 1;
00220     }
00221 
00222     /* default light */
00223     {
00224         graph = new ShaderGraph();
00225 
00226         closure = graph->add(new EmissionNode());
00227         closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
00228         closure->input("Strength")->value.x = 0.0f;
00229         out = graph->output();
00230 
00231         graph->connect(closure->output("Emission"), out->input("Surface"));
00232 
00233         shader = new Shader();
00234         shader->name = "default_light";
00235         shader->graph = graph;
00236         scene->shaders.push_back(shader);
00237         scene->default_light = scene->shaders.size() - 1;
00238     }
00239 
00240     /* default background */
00241     {
00242         graph = new ShaderGraph();
00243 
00244         closure = graph->add(new BackgroundNode());
00245         closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
00246         out = graph->output();
00247 
00248         graph->connect(closure->output("Background"), out->input("Surface"));
00249 
00250         shader = new Shader();
00251         shader->name = "default_background";
00252         shader->graph = graph;
00253         scene->shaders.push_back(shader);
00254         scene->default_background = scene->shaders.size() - 1;
00255     }
00256 }
00257 
00258 CCL_NAMESPACE_END
00259