2011-04-27 11:58:34 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011, Blender Foundation.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
2013-06-28 13:05:21 +00:00
|
|
|
#include "background.h"
|
2013-04-01 20:26:52 +00:00
|
|
|
#include "bssrdf.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
#include "device.h"
|
|
|
|
#include "graph.h"
|
|
|
|
#include "light.h"
|
|
|
|
#include "mesh.h"
|
|
|
|
#include "nodes.h"
|
|
|
|
#include "osl.h"
|
|
|
|
#include "scene.h"
|
|
|
|
#include "shader.h"
|
|
|
|
#include "svm.h"
|
2013-04-01 20:26:52 +00:00
|
|
|
#include "tables.h"
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
#include "util_foreach.h"
|
|
|
|
|
|
|
|
CCL_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
/* Shader */
|
|
|
|
|
|
|
|
Shader::Shader()
|
|
|
|
{
|
|
|
|
name = "";
|
Cycles: Render Passes
Currently supported passes:
* Combined, Z, Normal, Object Index, Material Index, Emission, Environment,
Diffuse/Glossy/Transmission x Direct/Indirect/Color
Not supported yet:
* UV, Vector, Mist
Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow,
also for environment importance sampling.
Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
2012-01-25 17:23:52 +00:00
|
|
|
pass_id = 0;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
graph = NULL;
|
|
|
|
graph_bump = NULL;
|
|
|
|
|
2013-06-18 09:36:00 +00:00
|
|
|
use_mis = true;
|
|
|
|
use_transparent_shadow = true;
|
2011-09-27 20:37:24 +00:00
|
|
|
homogeneous_volume = false;
|
|
|
|
|
2011-10-12 23:03:12 +00:00
|
|
|
has_surface = false;
|
2011-09-27 20:37:24 +00:00
|
|
|
has_surface_transparent = false;
|
2011-04-27 11:58:34 +00:00
|
|
|
has_surface_emission = false;
|
2013-04-01 20:26:52 +00:00
|
|
|
has_surface_bssrdf = false;
|
2011-04-27 11:58:34 +00:00
|
|
|
has_volume = false;
|
|
|
|
has_displacement = false;
|
|
|
|
|
2012-10-30 11:51:17 +00:00
|
|
|
used = false;
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
need_update = true;
|
2011-05-31 11:31:00 +00:00
|
|
|
need_update_attributes = true;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Shader::~Shader()
|
|
|
|
{
|
|
|
|
delete graph;
|
|
|
|
delete graph_bump;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shader::set_graph(ShaderGraph *graph_)
|
|
|
|
{
|
2013-05-10 11:31:57 +00:00
|
|
|
/* do this here already so that we can detect if mesh or object attributes
|
|
|
|
* are needed, since the node attribute callbacks check if their sockets
|
|
|
|
* are connected but proxy nodes should not count */
|
|
|
|
if(graph_)
|
|
|
|
graph_->remove_unneeded_nodes();
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* assign graph */
|
|
|
|
delete graph;
|
|
|
|
delete graph_bump;
|
|
|
|
graph = graph_;
|
|
|
|
graph_bump = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shader::tag_update(Scene *scene)
|
|
|
|
{
|
|
|
|
/* update tag */
|
|
|
|
need_update = true;
|
|
|
|
scene->shader_manager->need_update = true;
|
|
|
|
|
|
|
|
/* if the shader previously was emissive, update light distribution,
|
|
|
|
* if the new shader is emissive, a light manager update tag will be
|
|
|
|
* done in the shader manager device update. */
|
2013-06-18 09:36:00 +00:00
|
|
|
if(use_mis && has_surface_emission)
|
2011-04-27 11:58:34 +00:00
|
|
|
scene->light_manager->need_update = true;
|
|
|
|
|
|
|
|
/* get requested attributes. this could be optimized by pruning unused
|
2012-06-09 17:22:52 +00:00
|
|
|
* nodes here already, but that's the job of the shader manager currently,
|
|
|
|
* and may not be so great for interactive rendering where you temporarily
|
|
|
|
* disconnect a node */
|
2011-04-27 11:58:34 +00:00
|
|
|
AttributeRequestSet prev_attributes = attributes;
|
|
|
|
|
|
|
|
attributes.clear();
|
|
|
|
foreach(ShaderNode *node, graph->nodes)
|
|
|
|
node->attributes(&attributes);
|
|
|
|
|
|
|
|
/* compare if the attributes changed, mesh manager will check
|
2012-06-09 17:22:52 +00:00
|
|
|
* need_update_attributes, update the relevant meshes and clear it. */
|
2011-04-27 11:58:34 +00:00
|
|
|
if(attributes.modified(prev_attributes)) {
|
|
|
|
need_update_attributes = true;
|
|
|
|
scene->mesh_manager->need_update = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-30 11:51:17 +00:00
|
|
|
void Shader::tag_used(Scene *scene)
|
|
|
|
{
|
|
|
|
/* if an unused shader suddenly gets used somewhere, it needs to be
|
|
|
|
* recompiled because it was skipped for compilation before */
|
|
|
|
if(!used) {
|
|
|
|
need_update = true;
|
|
|
|
scene->shader_manager->need_update = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
/* Shader Manager */
|
|
|
|
|
|
|
|
ShaderManager::ShaderManager()
|
|
|
|
{
|
|
|
|
need_update = true;
|
2013-04-01 20:26:52 +00:00
|
|
|
bssrdf_table_offset = TABLE_OFFSET_INVALID;
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ShaderManager::~ShaderManager()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-12-04 07:48:09 +00:00
|
|
|
ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
ShaderManager *manager;
|
|
|
|
|
|
|
|
#ifdef WITH_OSL
|
2012-12-04 07:48:09 +00:00
|
|
|
if(shadingsystem == SceneParams::OSL)
|
2011-04-27 11:58:34 +00:00
|
|
|
manager = new OSLShaderManager();
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
manager = new SVMShaderManager();
|
|
|
|
|
|
|
|
add_default(scene);
|
|
|
|
|
|
|
|
return manager;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint ShaderManager::get_attribute_id(ustring name)
|
|
|
|
{
|
|
|
|
/* get a unique id for each name, for SVM attribute lookup */
|
|
|
|
AttributeIDMap::iterator it = unique_attribute_id.find(name);
|
|
|
|
|
|
|
|
if(it != unique_attribute_id.end())
|
|
|
|
return it->second;
|
|
|
|
|
2012-04-30 12:49:26 +00:00
|
|
|
uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
|
2011-04-27 11:58:34 +00:00
|
|
|
unique_attribute_id[name] = id;
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2012-04-30 12:49:26 +00:00
|
|
|
uint ShaderManager::get_attribute_id(AttributeStandard std)
|
2011-04-27 11:58:34 +00:00
|
|
|
{
|
|
|
|
return (uint)std;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
|
|
|
|
{
|
|
|
|
/* get a shader id to pass to the kernel */
|
|
|
|
int id = shader*2;
|
|
|
|
|
|
|
|
/* index depends bump since this setting is not in the shader */
|
|
|
|
if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
|
|
|
|
id += 1;
|
2011-09-27 20:37:24 +00:00
|
|
|
/* smooth flag */
|
2011-04-27 11:58:34 +00:00
|
|
|
if(smooth)
|
2011-09-27 20:37:24 +00:00
|
|
|
id |= SHADER_SMOOTH_NORMAL;
|
|
|
|
|
|
|
|
/* default flags */
|
|
|
|
id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2012-10-30 11:51:17 +00:00
|
|
|
void ShaderManager::device_update_shaders_used(Scene *scene)
|
|
|
|
{
|
|
|
|
/* figure out which shaders are in use, so SVM/OSL can skip compiling them
|
|
|
|
* for speed and avoid loading image textures into memory */
|
|
|
|
foreach(Shader *shader, scene->shaders)
|
|
|
|
shader->used = false;
|
|
|
|
|
2013-06-28 13:05:21 +00:00
|
|
|
scene->shaders[scene->background->shader]->used = true;
|
2012-10-30 11:51:17 +00:00
|
|
|
scene->shaders[scene->default_surface]->used = true;
|
|
|
|
scene->shaders[scene->default_light]->used = true;
|
|
|
|
scene->shaders[scene->default_background]->used = true;
|
|
|
|
scene->shaders[scene->default_empty]->used = true;
|
|
|
|
|
|
|
|
foreach(Mesh *mesh, scene->meshes)
|
|
|
|
foreach(uint shader, mesh->used_shaders)
|
|
|
|
scene->shaders[shader]->used = true;
|
|
|
|
|
|
|
|
foreach(Light *light, scene->lights)
|
|
|
|
scene->shaders[light->shader]->used = true;
|
|
|
|
}
|
|
|
|
|
2011-09-27 20:37:24 +00:00
|
|
|
void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
|
|
|
{
|
2013-04-01 20:26:52 +00:00
|
|
|
device->tex_free(dscene->shader_flag);
|
|
|
|
dscene->shader_flag.clear();
|
2011-09-27 20:37:24 +00:00
|
|
|
|
|
|
|
if(scene->shaders.size() == 0)
|
|
|
|
return;
|
|
|
|
|
Cycles: Render Passes
Currently supported passes:
* Combined, Z, Normal, Object Index, Material Index, Emission, Environment,
Diffuse/Glossy/Transmission x Direct/Indirect/Color
Not supported yet:
* UV, Vector, Mist
Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow,
also for environment importance sampling.
Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
2012-01-25 17:23:52 +00:00
|
|
|
uint shader_flag_size = scene->shaders.size()*4;
|
2011-09-27 20:37:24 +00:00
|
|
|
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
|
|
|
|
uint i = 0;
|
2013-04-01 20:26:52 +00:00
|
|
|
bool has_surface_bssrdf = false;
|
2011-09-27 20:37:24 +00:00
|
|
|
|
|
|
|
foreach(Shader *shader, scene->shaders) {
|
|
|
|
uint flag = 0;
|
|
|
|
|
2013-06-18 09:36:00 +00:00
|
|
|
if(shader->use_mis)
|
|
|
|
flag |= SD_USE_MIS;
|
|
|
|
if(shader->has_surface_transparent && shader->use_transparent_shadow)
|
|
|
|
flag |= SD_HAS_TRANSPARENT_SHADOW;
|
2011-09-27 20:37:24 +00:00
|
|
|
if(shader->has_volume)
|
|
|
|
flag |= SD_HAS_VOLUME;
|
|
|
|
if(shader->homogeneous_volume)
|
|
|
|
flag |= SD_HOMOGENEOUS_VOLUME;
|
2013-04-01 20:26:52 +00:00
|
|
|
if(shader->has_surface_bssrdf)
|
|
|
|
has_surface_bssrdf = true;
|
2011-09-27 20:37:24 +00:00
|
|
|
|
|
|
|
shader_flag[i++] = flag;
|
Cycles: Render Passes
Currently supported passes:
* Combined, Z, Normal, Object Index, Material Index, Emission, Environment,
Diffuse/Glossy/Transmission x Direct/Indirect/Color
Not supported yet:
* UV, Vector, Mist
Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow,
also for environment importance sampling.
Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
2012-01-25 17:23:52 +00:00
|
|
|
shader_flag[i++] = shader->pass_id;
|
2011-09-27 20:37:24 +00:00
|
|
|
shader_flag[i++] = flag;
|
Cycles: Render Passes
Currently supported passes:
* Combined, Z, Normal, Object Index, Material Index, Emission, Environment,
Diffuse/Glossy/Transmission x Direct/Indirect/Color
Not supported yet:
* UV, Vector, Mist
Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow,
also for environment importance sampling.
Documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
2012-01-25 17:23:52 +00:00
|
|
|
shader_flag[i++] = shader->pass_id;
|
2011-09-27 20:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
device->tex_alloc("__shader_flag", dscene->shader_flag);
|
2013-04-01 20:26:52 +00:00
|
|
|
|
|
|
|
/* bssrdf lookup table */
|
|
|
|
KernelBSSRDF *kbssrdf = &dscene->data.bssrdf;
|
|
|
|
|
|
|
|
if(has_surface_bssrdf && bssrdf_table_offset == TABLE_OFFSET_INVALID) {
|
|
|
|
vector<float> table;
|
|
|
|
|
|
|
|
bssrdf_table_build(table);
|
|
|
|
bssrdf_table_offset = scene->lookup_tables->add_table(dscene, table);
|
|
|
|
|
|
|
|
kbssrdf->table_offset = (int)bssrdf_table_offset;
|
|
|
|
kbssrdf->num_attempts = BSSRDF_MAX_ATTEMPTS;
|
|
|
|
}
|
|
|
|
else if(!has_surface_bssrdf && bssrdf_table_offset != TABLE_OFFSET_INVALID) {
|
|
|
|
scene->lookup_tables->remove_table(bssrdf_table_offset);
|
|
|
|
bssrdf_table_offset = TABLE_OFFSET_INVALID;
|
|
|
|
}
|
2011-09-27 20:37:24 +00:00
|
|
|
}
|
|
|
|
|
2013-04-01 20:26:52 +00:00
|
|
|
void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene)
|
2011-09-27 20:37:24 +00:00
|
|
|
{
|
2013-04-01 20:26:52 +00:00
|
|
|
if(bssrdf_table_offset != TABLE_OFFSET_INVALID) {
|
|
|
|
scene->lookup_tables->remove_table(bssrdf_table_offset);
|
|
|
|
bssrdf_table_offset = TABLE_OFFSET_INVALID;
|
|
|
|
}
|
|
|
|
|
2011-09-27 20:37:24 +00:00
|
|
|
device->tex_free(dscene->shader_flag);
|
|
|
|
dscene->shader_flag.clear();
|
|
|
|
}
|
|
|
|
|
2011-04-27 11:58:34 +00:00
|
|
|
void ShaderManager::add_default(Scene *scene)
|
|
|
|
{
|
|
|
|
Shader *shader;
|
|
|
|
ShaderGraph *graph;
|
|
|
|
ShaderNode *closure, *out;
|
|
|
|
|
|
|
|
/* default surface */
|
|
|
|
{
|
|
|
|
graph = new ShaderGraph();
|
|
|
|
|
|
|
|
closure = graph->add(new DiffuseBsdfNode());
|
|
|
|
closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
|
|
|
|
out = graph->output();
|
|
|
|
|
2011-10-12 23:03:12 +00:00
|
|
|
graph->connect(closure->output("BSDF"), out->input("Surface"));
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
shader = new Shader();
|
|
|
|
shader->name = "default_surface";
|
|
|
|
shader->graph = graph;
|
|
|
|
scene->shaders.push_back(shader);
|
|
|
|
scene->default_surface = scene->shaders.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* default light */
|
|
|
|
{
|
|
|
|
graph = new ShaderGraph();
|
|
|
|
|
|
|
|
closure = graph->add(new EmissionNode());
|
|
|
|
closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
|
|
|
|
closure->input("Strength")->value.x = 0.0f;
|
|
|
|
out = graph->output();
|
|
|
|
|
2011-10-12 23:03:12 +00:00
|
|
|
graph->connect(closure->output("Emission"), out->input("Surface"));
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
shader = new Shader();
|
|
|
|
shader->name = "default_light";
|
|
|
|
shader->graph = graph;
|
|
|
|
scene->shaders.push_back(shader);
|
|
|
|
scene->default_light = scene->shaders.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* default background */
|
|
|
|
{
|
|
|
|
graph = new ShaderGraph();
|
|
|
|
|
|
|
|
closure = graph->add(new BackgroundNode());
|
|
|
|
closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
|
|
|
|
out = graph->output();
|
|
|
|
|
2011-10-12 23:03:12 +00:00
|
|
|
graph->connect(closure->output("Background"), out->input("Surface"));
|
2011-04-27 11:58:34 +00:00
|
|
|
|
|
|
|
shader = new Shader();
|
|
|
|
shader->name = "default_background";
|
|
|
|
shader->graph = graph;
|
|
|
|
scene->shaders.push_back(shader);
|
|
|
|
scene->default_background = scene->shaders.size() - 1;
|
|
|
|
}
|
2012-02-28 16:44:45 +00:00
|
|
|
|
2012-04-13 12:58:12 +00:00
|
|
|
/* default empty */
|
|
|
|
{
|
|
|
|
graph = new ShaderGraph();
|
|
|
|
|
|
|
|
shader = new Shader();
|
|
|
|
shader->name = "default_empty";
|
|
|
|
shader->graph = graph;
|
|
|
|
scene->shaders.push_back(shader);
|
|
|
|
scene->default_empty = scene->shaders.size() - 1;
|
|
|
|
}
|
2011-04-27 11:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCL_NAMESPACE_END
|
|
|
|
|