Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /intern/cycles/render
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/CMakeLists.txt132
-rw-r--r--intern/cycles/render/attribute.cpp969
-rw-r--r--intern/cycles/render/attribute.h300
-rw-r--r--intern/cycles/render/background.cpp150
-rw-r--r--intern/cycles/render/background.h38
-rw-r--r--intern/cycles/render/bake.cpp374
-rw-r--r--intern/cycles/render/bake.h91
-rw-r--r--intern/cycles/render/buffers.cpp709
-rw-r--r--intern/cycles/render/buffers.h180
-rw-r--r--intern/cycles/render/camera.cpp1297
-rw-r--r--intern/cycles/render/camera.h344
-rw-r--r--intern/cycles/render/constant_fold.cpp575
-rw-r--r--intern/cycles/render/constant_fold.h58
-rw-r--r--intern/cycles/render/coverage.cpp187
-rw-r--r--intern/cycles/render/coverage.h36
-rw-r--r--intern/cycles/render/curves.cpp222
-rw-r--r--intern/cycles/render/curves.h122
-rw-r--r--intern/cycles/render/denoising.cpp1370
-rw-r--r--intern/cycles/render/denoising.h238
-rw-r--r--intern/cycles/render/film.cpp856
-rw-r--r--intern/cycles/render/film.h92
-rw-r--r--intern/cycles/render/graph.cpp1906
-rw-r--r--intern/cycles/render/graph.h450
-rw-r--r--intern/cycles/render/image.cpp1741
-rw-r--r--intern/cycles/render/image.h259
-rw-r--r--intern/cycles/render/integrator.cpp363
-rw-r--r--intern/cycles/render/integrator.h96
-rw-r--r--intern/cycles/render/light.cpp1792
-rw-r--r--intern/cycles/render/light.h167
-rw-r--r--intern/cycles/render/merge.cpp824
-rw-r--r--intern/cycles/render/merge.h18
-rw-r--r--intern/cycles/render/mesh.cpp3754
-rw-r--r--intern/cycles/render/mesh.h642
-rw-r--r--intern/cycles/render/mesh_displace.cpp571
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp1044
-rw-r--r--intern/cycles/render/mesh_volume.cpp728
-rw-r--r--intern/cycles/render/nodes.cpp8204
-rw-r--r--intern/cycles/render/nodes.h1834
-rw-r--r--intern/cycles/render/object.cpp1423
-rw-r--r--intern/cycles/render/object.h182
-rw-r--r--intern/cycles/render/osl.cpp1911
-rw-r--r--intern/cycles/render/osl.h223
-rw-r--r--intern/cycles/render/particles.cpp109
-rw-r--r--intern/cycles/render/particles.h47
-rw-r--r--intern/cycles/render/scene.cpp513
-rw-r--r--intern/cycles/render/scene.h396
-rw-r--r--intern/cycles/render/session.cpp1901
-rw-r--r--intern/cycles/render/session.h314
-rw-r--r--intern/cycles/render/shader.cpp1067
-rw-r--r--intern/cycles/render/shader.h248
-rw-r--r--intern/cycles/render/sobol.h2
-rw-r--r--intern/cycles/render/stats.cpp397
-rw-r--r--intern/cycles/render/stats.h134
-rw-r--r--intern/cycles/render/svm.cpp1398
-rw-r--r--intern/cycles/render/svm.h350
-rw-r--r--intern/cycles/render/tables.cpp98
-rw-r--r--intern/cycles/render/tables.h28
-rw-r--r--intern/cycles/render/tile.cpp854
-rw-r--r--intern/cycles/render/tile.h239
59 files changed, 22447 insertions, 22120 deletions
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 140fcb206dc..378957d21f4 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -1,86 +1,86 @@
set(INC
- ..
- ../../glew-mx
+ ..
+ ../../glew-mx
)
set(INC_SYS
- ${GLEW_INCLUDE_DIR}
+ ${GLEW_INCLUDE_DIR}
)
set(SRC
- attribute.cpp
- background.cpp
- bake.cpp
- buffers.cpp
- camera.cpp
- constant_fold.cpp
- coverage.cpp
- denoising.cpp
- film.cpp
- graph.cpp
- image.cpp
- integrator.cpp
- light.cpp
- merge.cpp
- mesh.cpp
- mesh_displace.cpp
- mesh_subdivision.cpp
- mesh_volume.cpp
- nodes.cpp
- object.cpp
- osl.cpp
- particles.cpp
- curves.cpp
- scene.cpp
- session.cpp
- shader.cpp
- sobol.cpp
- stats.cpp
- svm.cpp
- tables.cpp
- tile.cpp
+ attribute.cpp
+ background.cpp
+ bake.cpp
+ buffers.cpp
+ camera.cpp
+ constant_fold.cpp
+ coverage.cpp
+ denoising.cpp
+ film.cpp
+ graph.cpp
+ image.cpp
+ integrator.cpp
+ light.cpp
+ merge.cpp
+ mesh.cpp
+ mesh_displace.cpp
+ mesh_subdivision.cpp
+ mesh_volume.cpp
+ nodes.cpp
+ object.cpp
+ osl.cpp
+ particles.cpp
+ curves.cpp
+ scene.cpp
+ session.cpp
+ shader.cpp
+ sobol.cpp
+ stats.cpp
+ svm.cpp
+ tables.cpp
+ tile.cpp
)
set(SRC_HEADERS
- attribute.h
- bake.h
- background.h
- buffers.h
- camera.h
- constant_fold.h
- coverage.h
- denoising.h
- film.h
- graph.h
- image.h
- integrator.h
- light.h
- merge.h
- mesh.h
- nodes.h
- object.h
- osl.h
- particles.h
- curves.h
- scene.h
- session.h
- shader.h
- sobol.h
- stats.h
- svm.h
- tables.h
- tile.h
+ attribute.h
+ bake.h
+ background.h
+ buffers.h
+ camera.h
+ constant_fold.h
+ coverage.h
+ denoising.h
+ film.h
+ graph.h
+ image.h
+ integrator.h
+ light.h
+ merge.h
+ mesh.h
+ nodes.h
+ object.h
+ osl.h
+ particles.h
+ curves.h
+ scene.h
+ session.h
+ shader.h
+ sobol.h
+ stats.h
+ svm.h
+ tables.h
+ tile.h
)
set(LIB
- cycles_bvh
+ cycles_bvh
)
if(WITH_CYCLES_OSL)
- list(APPEND LIB
- cycles_kernel_osl
- )
+ list(APPEND LIB
+ cycles_kernel_osl
+ )
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RTTI_DISABLE_FLAGS}")
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index f7788b6a490..dad6cb4fe6d 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -27,319 +27,316 @@ CCL_NAMESPACE_BEGIN
Attribute::~Attribute()
{
- /* for voxel data, we need to remove the image from the image manager */
- if(element == ATTR_ELEMENT_VOXEL) {
- VoxelAttribute *voxel_data = data_voxel();
+ /* for voxel data, we need to remove the image from the image manager */
+ if (element == ATTR_ELEMENT_VOXEL) {
+ VoxelAttribute *voxel_data = data_voxel();
- if(voxel_data && voxel_data->slot != -1) {
- voxel_data->manager->remove_image(voxel_data->slot);
- }
- }
+ if (voxel_data && voxel_data->slot != -1) {
+ voxel_data->manager->remove_image(voxel_data->slot);
+ }
+ }
}
void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
{
- name = name_;
- type = type_;
- element = element_;
- std = ATTR_STD_NONE;
- flags = 0;
+ name = name_;
+ type = type_;
+ element = element_;
+ std = ATTR_STD_NONE;
+ flags = 0;
- /* string and matrix not supported! */
- assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
- type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
- type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix ||
- type == TypeFloat2);
+ /* string and matrix not supported! */
+ assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
+ type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
+ type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2);
}
void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
{
- if(reserve_only) {
- buffer.reserve(buffer_size(mesh, prim));
- }
- else {
- buffer.resize(buffer_size(mesh, prim), 0);
- }
+ if (reserve_only) {
+ buffer.reserve(buffer_size(mesh, prim));
+ }
+ else {
+ buffer.resize(buffer_size(mesh, prim), 0);
+ }
}
void Attribute::resize(size_t num_elements)
{
- buffer.resize(num_elements * data_sizeof(), 0);
+ buffer.resize(num_elements * data_sizeof(), 0);
}
-void Attribute::add(const float& f)
+void Attribute::add(const float &f)
{
- assert(data_sizeof() == sizeof(float));
+ assert(data_sizeof() == sizeof(float));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const uchar4& f)
+void Attribute::add(const uchar4 &f)
{
- assert(data_sizeof() == sizeof(uchar4));
+ assert(data_sizeof() == sizeof(uchar4));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const float2& f)
+void Attribute::add(const float2 &f)
{
- assert(data_sizeof() == sizeof(float2));
+ assert(data_sizeof() == sizeof(float2));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const float3& f)
+void Attribute::add(const float3 &f)
{
- assert(data_sizeof() == sizeof(float3));
+ assert(data_sizeof() == sizeof(float3));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const Transform& f)
+void Attribute::add(const Transform &f)
{
- assert(data_sizeof() == sizeof(Transform));
+ assert(data_sizeof() == sizeof(Transform));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
-void Attribute::add(const VoxelAttribute& f)
+void Attribute::add(const VoxelAttribute &f)
{
- assert(data_sizeof() == sizeof(VoxelAttribute));
+ assert(data_sizeof() == sizeof(VoxelAttribute));
- char *data = (char*)&f;
- size_t size = sizeof(f);
+ char *data = (char *)&f;
+ size_t size = sizeof(f);
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
void Attribute::add(const char *data)
{
- size_t size = data_sizeof();
+ size_t size = data_sizeof();
- for(size_t i = 0; i < size; i++)
- buffer.push_back(data[i]);
+ for (size_t i = 0; i < size; i++)
+ buffer.push_back(data[i]);
}
size_t Attribute::data_sizeof() const
{
- if(element == ATTR_ELEMENT_VOXEL)
- return sizeof(VoxelAttribute);
- else if(element == ATTR_ELEMENT_CORNER_BYTE)
- return sizeof(uchar4);
- else if(type == TypeDesc::TypeFloat)
- return sizeof(float);
- else if(type == TypeFloat2)
- return sizeof(float2);
- else if(type == TypeDesc::TypeMatrix)
- return sizeof(Transform);
- else
- return sizeof(float3);
+ if (element == ATTR_ELEMENT_VOXEL)
+ return sizeof(VoxelAttribute);
+ else if (element == ATTR_ELEMENT_CORNER_BYTE)
+ return sizeof(uchar4);
+ else if (type == TypeDesc::TypeFloat)
+ return sizeof(float);
+ else if (type == TypeFloat2)
+ return sizeof(float2);
+ else if (type == TypeDesc::TypeMatrix)
+ return sizeof(Transform);
+ else
+ return sizeof(float3);
}
size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
{
- if(flags & ATTR_FINAL_SIZE) {
- return buffer.size() / data_sizeof();
- }
-
- size_t size;
-
- switch(element) {
- case ATTR_ELEMENT_OBJECT:
- case ATTR_ELEMENT_MESH:
- case ATTR_ELEMENT_VOXEL:
- size = 1;
- break;
- case ATTR_ELEMENT_VERTEX:
- size = mesh->verts.size() + mesh->num_ngons;
- if(prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts;
- }
- break;
- case ATTR_ELEMENT_VERTEX_MOTION:
- size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
- if(prim == ATTR_PRIM_SUBD) {
- size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
- }
- break;
- case ATTR_ELEMENT_FACE:
- if(prim == ATTR_PRIM_TRIANGLE) {
- size = mesh->num_triangles();
- }
- else {
- size = mesh->subd_faces.size() + mesh->num_ngons;
- }
- break;
- case ATTR_ELEMENT_CORNER:
- case ATTR_ELEMENT_CORNER_BYTE:
- if(prim == ATTR_PRIM_TRIANGLE) {
- size = mesh->num_triangles()*3;
- }
- else {
- size = mesh->subd_face_corners.size() + mesh->num_ngons;
- }
- break;
- case ATTR_ELEMENT_CURVE:
- size = mesh->num_curves();
- break;
- case ATTR_ELEMENT_CURVE_KEY:
- size = mesh->curve_keys.size();
- break;
- case ATTR_ELEMENT_CURVE_KEY_MOTION:
- size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
- break;
- default:
- size = 0;
- break;
- }
-
- return size;
+ if (flags & ATTR_FINAL_SIZE) {
+ return buffer.size() / data_sizeof();
+ }
+
+ size_t size;
+
+ switch (element) {
+ case ATTR_ELEMENT_OBJECT:
+ case ATTR_ELEMENT_MESH:
+ case ATTR_ELEMENT_VOXEL:
+ size = 1;
+ break;
+ case ATTR_ELEMENT_VERTEX:
+ size = mesh->verts.size() + mesh->num_ngons;
+ if (prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts;
+ }
+ break;
+ case ATTR_ELEMENT_VERTEX_MOTION:
+ size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
+ if (prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
+ }
+ break;
+ case ATTR_ELEMENT_FACE:
+ if (prim == ATTR_PRIM_TRIANGLE) {
+ size = mesh->num_triangles();
+ }
+ else {
+ size = mesh->subd_faces.size() + mesh->num_ngons;
+ }
+ break;
+ case ATTR_ELEMENT_CORNER:
+ case ATTR_ELEMENT_CORNER_BYTE:
+ if (prim == ATTR_PRIM_TRIANGLE) {
+ size = mesh->num_triangles() * 3;
+ }
+ else {
+ size = mesh->subd_face_corners.size() + mesh->num_ngons;
+ }
+ break;
+ case ATTR_ELEMENT_CURVE:
+ size = mesh->num_curves();
+ break;
+ case ATTR_ELEMENT_CURVE_KEY:
+ size = mesh->curve_keys.size();
+ break;
+ case ATTR_ELEMENT_CURVE_KEY_MOTION:
+ size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
+ break;
+ default:
+ size = 0;
+ break;
+ }
+
+ return size;
}
size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
{
- return element_size(mesh, prim)*data_sizeof();
+ return element_size(mesh, prim) * data_sizeof();
}
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
{
- if(a == b)
- return true;
+ if (a == b)
+ return true;
- if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
- a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
- {
- if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
- b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
- {
- return true;
- }
- }
- return false;
+ if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector ||
+ a == TypeDesc::TypeNormal) {
+ if (b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || b == TypeDesc::TypeVector ||
+ b == TypeDesc::TypeNormal) {
+ return true;
+ }
+ }
+ return false;
}
-void Attribute::zero_data(void* dst)
+void Attribute::zero_data(void *dst)
{
- memset(dst, 0, data_sizeof());
+ memset(dst, 0, data_sizeof());
}
-void Attribute::add_with_weight(void* dst, void* src, float weight)
+void Attribute::add_with_weight(void *dst, void *src, float weight)
{
- if(element == ATTR_ELEMENT_CORNER_BYTE) {
- for(int i = 0; i < 4; i++) {
- ((uchar*)dst)[i] += uchar(((uchar*)src)[i] * weight);
- }
- }
- else if(same_storage(type, TypeDesc::TypeFloat)) {
- *((float*)dst) += *((float*)src) * weight;
- }
- else if(same_storage(type, TypeDesc::TypeVector)) {
- *((float4*)dst) += *((float4*)src) * weight;
- }
- else {
- assert(!"not implemented for this type");
- }
+ if (element == ATTR_ELEMENT_CORNER_BYTE) {
+ for (int i = 0; i < 4; i++) {
+ ((uchar *)dst)[i] += uchar(((uchar *)src)[i] * weight);
+ }
+ }
+ else if (same_storage(type, TypeDesc::TypeFloat)) {
+ *((float *)dst) += *((float *)src) * weight;
+ }
+ else if (same_storage(type, TypeDesc::TypeVector)) {
+ *((float4 *)dst) += *((float4 *)src) * weight;
+ }
+ else {
+ assert(!"not implemented for this type");
+ }
}
const char *Attribute::standard_name(AttributeStandard std)
{
- switch(std) {
- case ATTR_STD_VERTEX_NORMAL:
- return "N";
- case ATTR_STD_FACE_NORMAL:
- return "Ng";
- case ATTR_STD_UV:
- return "uv";
- case ATTR_STD_GENERATED:
- return "generated";
- case ATTR_STD_GENERATED_TRANSFORM:
- return "generated_transform";
- case ATTR_STD_UV_TANGENT:
- return "tangent";
- case ATTR_STD_UV_TANGENT_SIGN:
- return "tangent_sign";
- case ATTR_STD_POSITION_UNDEFORMED:
- return "undeformed";
- case ATTR_STD_POSITION_UNDISPLACED:
- return "undisplaced";
- case ATTR_STD_MOTION_VERTEX_POSITION:
- return "motion_P";
- case ATTR_STD_MOTION_VERTEX_NORMAL:
- return "motion_N";
- case ATTR_STD_PARTICLE:
- return "particle";
- case ATTR_STD_CURVE_INTERCEPT:
- return "curve_intercept";
- case ATTR_STD_CURVE_RANDOM:
- return "curve_random";
- case ATTR_STD_PTEX_FACE_ID:
- return "ptex_face_id";
- case ATTR_STD_PTEX_UV:
- return "ptex_uv";
- case ATTR_STD_VOLUME_DENSITY:
- return "density";
- case ATTR_STD_VOLUME_COLOR:
- return "color";
- case ATTR_STD_VOLUME_FLAME:
- return "flame";
- case ATTR_STD_VOLUME_HEAT:
- return "heat";
- case ATTR_STD_VOLUME_TEMPERATURE:
- return "temperature";
- case ATTR_STD_VOLUME_VELOCITY:
- return "velocity";
- case ATTR_STD_POINTINESS:
- return "pointiness";
- case ATTR_STD_NOT_FOUND:
- case ATTR_STD_NONE:
- case ATTR_STD_NUM:
- return "";
- }
-
- return "";
+ switch (std) {
+ case ATTR_STD_VERTEX_NORMAL:
+ return "N";
+ case ATTR_STD_FACE_NORMAL:
+ return "Ng";
+ case ATTR_STD_UV:
+ return "uv";
+ case ATTR_STD_GENERATED:
+ return "generated";
+ case ATTR_STD_GENERATED_TRANSFORM:
+ return "generated_transform";
+ case ATTR_STD_UV_TANGENT:
+ return "tangent";
+ case ATTR_STD_UV_TANGENT_SIGN:
+ return "tangent_sign";
+ case ATTR_STD_POSITION_UNDEFORMED:
+ return "undeformed";
+ case ATTR_STD_POSITION_UNDISPLACED:
+ return "undisplaced";
+ case ATTR_STD_MOTION_VERTEX_POSITION:
+ return "motion_P";
+ case ATTR_STD_MOTION_VERTEX_NORMAL:
+ return "motion_N";
+ case ATTR_STD_PARTICLE:
+ return "particle";
+ case ATTR_STD_CURVE_INTERCEPT:
+ return "curve_intercept";
+ case ATTR_STD_CURVE_RANDOM:
+ return "curve_random";
+ case ATTR_STD_PTEX_FACE_ID:
+ return "ptex_face_id";
+ case ATTR_STD_PTEX_UV:
+ return "ptex_uv";
+ case ATTR_STD_VOLUME_DENSITY:
+ return "density";
+ case ATTR_STD_VOLUME_COLOR:
+ return "color";
+ case ATTR_STD_VOLUME_FLAME:
+ return "flame";
+ case ATTR_STD_VOLUME_HEAT:
+ return "heat";
+ case ATTR_STD_VOLUME_TEMPERATURE:
+ return "temperature";
+ case ATTR_STD_VOLUME_VELOCITY:
+ return "velocity";
+ case ATTR_STD_POINTINESS:
+ return "pointiness";
+ case ATTR_STD_NOT_FOUND:
+ case ATTR_STD_NONE:
+ case ATTR_STD_NUM:
+ return "";
+ }
+
+ return "";
}
AttributeStandard Attribute::name_standard(const char *name)
{
- if(name) {
- for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
- if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
- return (AttributeStandard)std;
- }
- }
- }
+ if (name) {
+ for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
+ if (strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
+ return (AttributeStandard)std;
+ }
+ }
+ }
- return ATTR_STD_NONE;
+ return ATTR_STD_NONE;
}
/* Attribute Set */
AttributeSet::AttributeSet()
{
- triangle_mesh = NULL;
- curve_mesh = NULL;
- subd_mesh = NULL;
+ triangle_mesh = NULL;
+ curve_mesh = NULL;
+ subd_mesh = NULL;
}
AttributeSet::~AttributeSet()
@@ -348,280 +345,280 @@ AttributeSet::~AttributeSet()
Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
{
- Attribute *attr = find(name);
+ Attribute *attr = find(name);
- if(attr) {
- /* return if same already exists */
- if(attr->type == type && attr->element == element)
- return attr;
+ if (attr) {
+ /* return if same already exists */
+ if (attr->type == type && attr->element == element)
+ return attr;
- /* overwrite attribute with same name but different type/element */
- remove(name);
- }
+ /* overwrite attribute with same name but different type/element */
+ remove(name);
+ }
#if __cplusplus >= 201103L
- attributes.emplace_back();
- attr = &attributes.back();
- attr->set(name, type, element);
+ attributes.emplace_back();
+ attr = &attributes.back();
+ attr->set(name, type, element);
#else
- {
- Attribute attr_temp;
- attr_temp.set(name, type, element);
- attributes.push_back(attr_temp);
- attr = &attributes.back();
- }
+ {
+ Attribute attr_temp;
+ attr_temp.set(name, type, element);
+ attributes.push_back(attr_temp);
+ attr = &attributes.back();
+ }
#endif
- /* this is weak .. */
- if(triangle_mesh)
- attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
- if(curve_mesh)
- attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
- if(subd_mesh)
- attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
+ /* this is weak .. */
+ if (triangle_mesh)
+ attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
+ if (curve_mesh)
+ attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
+ if (subd_mesh)
+ attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
- return attr;
+ return attr;
}
Attribute *AttributeSet::find(ustring name) const
{
- foreach(const Attribute& attr, attributes)
- if(attr.name == name)
- return (Attribute*)&attr;
+ foreach (const Attribute &attr, attributes)
+ if (attr.name == name)
+ return (Attribute *)&attr;
- return NULL;
+ return NULL;
}
void AttributeSet::remove(ustring name)
{
- Attribute *attr = find(name);
+ Attribute *attr = find(name);
- if(attr) {
- list<Attribute>::iterator it;
+ if (attr) {
+ list<Attribute>::iterator it;
- for(it = attributes.begin(); it != attributes.end(); it++) {
- if(&*it == attr) {
- attributes.erase(it);
- return;
- }
- }
- }
+ for (it = attributes.begin(); it != attributes.end(); it++) {
+ if (&*it == attr) {
+ attributes.erase(it);
+ return;
+ }
+ }
+ }
}
Attribute *AttributeSet::add(AttributeStandard std, ustring name)
{
- Attribute *attr = NULL;
-
- if(name == ustring())
- name = Attribute::standard_name(std);
-
- if(triangle_mesh || subd_mesh) {
- switch(std) {
- case ATTR_STD_VERTEX_NORMAL:
- attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
- break;
- case ATTR_STD_FACE_NORMAL:
- attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
- break;
- case ATTR_STD_UV:
- attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
- break;
- case ATTR_STD_UV_TANGENT:
- attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
- break;
- case ATTR_STD_UV_TANGENT_SIGN:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
- break;
- case ATTR_STD_GENERATED:
- case ATTR_STD_POSITION_UNDEFORMED:
- case ATTR_STD_POSITION_UNDISPLACED:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
- break;
- case ATTR_STD_MOTION_VERTEX_POSITION:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
- break;
- case ATTR_STD_MOTION_VERTEX_NORMAL:
- attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
- break;
- case ATTR_STD_PTEX_FACE_ID:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
- break;
- case ATTR_STD_PTEX_UV:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
- break;
- case ATTR_STD_GENERATED_TRANSFORM:
- attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
- break;
- case ATTR_STD_VOLUME_DENSITY:
- case ATTR_STD_VOLUME_FLAME:
- case ATTR_STD_VOLUME_HEAT:
- case ATTR_STD_VOLUME_TEMPERATURE:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
- break;
- case ATTR_STD_VOLUME_COLOR:
- attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
- break;
- case ATTR_STD_VOLUME_VELOCITY:
- attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
- break;
- case ATTR_STD_POINTINESS:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
- break;
- default:
- assert(0);
- break;
- }
- }
- else if(curve_mesh) {
- switch(std) {
- case ATTR_STD_UV:
- attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
- break;
- case ATTR_STD_GENERATED:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
- break;
- case ATTR_STD_MOTION_VERTEX_POSITION:
- attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
- break;
- case ATTR_STD_CURVE_INTERCEPT:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
- break;
- case ATTR_STD_CURVE_RANDOM:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
- break;
- case ATTR_STD_GENERATED_TRANSFORM:
- attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
- break;
- case ATTR_STD_POINTINESS:
- attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
- break;
- default:
- assert(0);
- break;
- }
- }
-
- attr->std = std;
-
- return attr;
+ Attribute *attr = NULL;
+
+ if (name == ustring())
+ name = Attribute::standard_name(std);
+
+ if (triangle_mesh || subd_mesh) {
+ switch (std) {
+ case ATTR_STD_VERTEX_NORMAL:
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
+ break;
+ case ATTR_STD_FACE_NORMAL:
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
+ break;
+ case ATTR_STD_UV:
+ attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
+ break;
+ case ATTR_STD_UV_TANGENT:
+ attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
+ break;
+ case ATTR_STD_UV_TANGENT_SIGN:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
+ break;
+ case ATTR_STD_GENERATED:
+ case ATTR_STD_POSITION_UNDEFORMED:
+ case ATTR_STD_POSITION_UNDISPLACED:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ break;
+ case ATTR_STD_MOTION_VERTEX_POSITION:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
+ break;
+ case ATTR_STD_MOTION_VERTEX_NORMAL:
+ attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
+ break;
+ case ATTR_STD_PTEX_FACE_ID:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
+ break;
+ case ATTR_STD_PTEX_UV:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
+ break;
+ case ATTR_STD_GENERATED_TRANSFORM:
+ attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
+ break;
+ case ATTR_STD_VOLUME_DENSITY:
+ case ATTR_STD_VOLUME_FLAME:
+ case ATTR_STD_VOLUME_HEAT:
+ case ATTR_STD_VOLUME_TEMPERATURE:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
+ break;
+ case ATTR_STD_VOLUME_COLOR:
+ attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
+ break;
+ case ATTR_STD_VOLUME_VELOCITY:
+ attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
+ break;
+ case ATTR_STD_POINTINESS:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else if (curve_mesh) {
+ switch (std) {
+ case ATTR_STD_UV:
+ attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
+ break;
+ case ATTR_STD_GENERATED:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+ break;
+ case ATTR_STD_MOTION_VERTEX_POSITION:
+ attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
+ break;
+ case ATTR_STD_CURVE_INTERCEPT:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
+ break;
+ case ATTR_STD_CURVE_RANDOM:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
+ break;
+ case ATTR_STD_GENERATED_TRANSFORM:
+ attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
+ break;
+ case ATTR_STD_POINTINESS:
+ attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ attr->std = std;
+
+ return attr;
}
Attribute *AttributeSet::find(AttributeStandard std) const
{
- foreach(const Attribute& attr, attributes)
- if(attr.std == std)
- return (Attribute*)&attr;
+ foreach (const Attribute &attr, attributes)
+ if (attr.std == std)
+ return (Attribute *)&attr;
- return NULL;
+ return NULL;
}
void AttributeSet::remove(AttributeStandard std)
{
- Attribute *attr = find(std);
+ Attribute *attr = find(std);
- if(attr) {
- list<Attribute>::iterator it;
+ if (attr) {
+ list<Attribute>::iterator it;
- for(it = attributes.begin(); it != attributes.end(); it++) {
- if(&*it == attr) {
- attributes.erase(it);
- return;
- }
- }
- }
+ for (it = attributes.begin(); it != attributes.end(); it++) {
+ if (&*it == attr) {
+ attributes.erase(it);
+ return;
+ }
+ }
+ }
}
-Attribute *AttributeSet::find(AttributeRequest& req)
+Attribute *AttributeSet::find(AttributeRequest &req)
{
- if(req.std == ATTR_STD_NONE)
- return find(req.name);
- else
- return find(req.std);
+ if (req.std == ATTR_STD_NONE)
+ return find(req.name);
+ else
+ return find(req.std);
}
void AttributeSet::remove(Attribute *attribute)
{
- if(attribute->std == ATTR_STD_NONE) {
- remove(attribute->name);
- }
- else {
- remove(attribute->std);
- }
+ if (attribute->std == ATTR_STD_NONE) {
+ remove(attribute->name);
+ }
+ else {
+ remove(attribute->std);
+ }
}
void AttributeSet::resize(bool reserve_only)
{
- foreach(Attribute& attr, attributes) {
- if(triangle_mesh)
- attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
- if(curve_mesh)
- attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
- if(subd_mesh)
- attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
- }
+ foreach (Attribute &attr, attributes) {
+ if (triangle_mesh)
+ attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
+ if (curve_mesh)
+ attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
+ if (subd_mesh)
+ attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
+ }
}
void AttributeSet::clear(bool preserve_voxel_data)
{
- if(preserve_voxel_data) {
- list<Attribute>::iterator it;
+ if (preserve_voxel_data) {
+ list<Attribute>::iterator it;
- for(it = attributes.begin(); it != attributes.end();) {
- if(it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
- it++;
- }
- else {
- attributes.erase(it++);
- }
- }
- }
- else {
- attributes.clear();
- }
+ for (it = attributes.begin(); it != attributes.end();) {
+ if (it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
+ it++;
+ }
+ else {
+ attributes.erase(it++);
+ }
+ }
+ }
+ else {
+ attributes.clear();
+ }
}
/* AttributeRequest */
AttributeRequest::AttributeRequest(ustring name_)
{
- name = name_;
- std = ATTR_STD_NONE;
+ name = name_;
+ std = ATTR_STD_NONE;
- triangle_type = TypeDesc::TypeFloat;
- triangle_desc.element = ATTR_ELEMENT_NONE;
- triangle_desc.offset = 0;
- triangle_desc.type = NODE_ATTR_FLOAT;
+ triangle_type = TypeDesc::TypeFloat;
+ triangle_desc.element = ATTR_ELEMENT_NONE;
+ triangle_desc.offset = 0;
+ triangle_desc.type = NODE_ATTR_FLOAT;
- curve_type = TypeDesc::TypeFloat;
- curve_desc.element = ATTR_ELEMENT_NONE;
- curve_desc.offset = 0;
- curve_desc.type = NODE_ATTR_FLOAT;
+ curve_type = TypeDesc::TypeFloat;
+ curve_desc.element = ATTR_ELEMENT_NONE;
+ curve_desc.offset = 0;
+ curve_desc.type = NODE_ATTR_FLOAT;
- subd_type = TypeDesc::TypeFloat;
- subd_desc.element = ATTR_ELEMENT_NONE;
- subd_desc.offset = 0;
- subd_desc.type = NODE_ATTR_FLOAT;
+ subd_type = TypeDesc::TypeFloat;
+ subd_desc.element = ATTR_ELEMENT_NONE;
+ subd_desc.offset = 0;
+ subd_desc.type = NODE_ATTR_FLOAT;
}
AttributeRequest::AttributeRequest(AttributeStandard std_)
{
- name = ustring();
- std = std_;
+ name = ustring();
+ std = std_;
- triangle_type = TypeDesc::TypeFloat;
- triangle_desc.element = ATTR_ELEMENT_NONE;
- triangle_desc.offset = 0;
- triangle_desc.type = NODE_ATTR_FLOAT;
+ triangle_type = TypeDesc::TypeFloat;
+ triangle_desc.element = ATTR_ELEMENT_NONE;
+ triangle_desc.offset = 0;
+ triangle_desc.type = NODE_ATTR_FLOAT;
- curve_type = TypeDesc::TypeFloat;
- curve_desc.element = ATTR_ELEMENT_NONE;
- curve_desc.offset = 0;
- curve_desc.type = NODE_ATTR_FLOAT;
+ curve_type = TypeDesc::TypeFloat;
+ curve_desc.element = ATTR_ELEMENT_NONE;
+ curve_desc.offset = 0;
+ curve_desc.type = NODE_ATTR_FLOAT;
- subd_type = TypeDesc::TypeFloat;
- subd_desc.element = ATTR_ELEMENT_NONE;
- subd_desc.offset = 0;
- subd_desc.type = NODE_ATTR_FLOAT;
+ subd_type = TypeDesc::TypeFloat;
+ subd_desc.element = ATTR_ELEMENT_NONE;
+ subd_desc.offset = 0;
+ subd_desc.type = NODE_ATTR_FLOAT;
}
/* AttributeRequestSet */
@@ -634,101 +631,99 @@ AttributeRequestSet::~AttributeRequestSet()
{
}
-bool AttributeRequestSet::modified(const AttributeRequestSet& other)
+bool AttributeRequestSet::modified(const AttributeRequestSet &other)
{
- if(requests.size() != other.requests.size())
- return true;
+ if (requests.size() != other.requests.size())
+ return true;
- for(size_t i = 0; i < requests.size(); i++) {
- bool found = false;
+ for (size_t i = 0; i < requests.size(); i++) {
+ bool found = false;
- for(size_t j = 0; j < requests.size() && !found; j++)
- if(requests[i].name == other.requests[j].name &&
- requests[i].std == other.requests[j].std)
- {
- found = true;
- }
+ for (size_t j = 0; j < requests.size() && !found; j++)
+ if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
+ found = true;
+ }
- if(!found) {
- return true;
- }
- }
+ if (!found) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
void AttributeRequestSet::add(ustring name)
{
- foreach(AttributeRequest& req, requests) {
- if(req.name == name) {
- return;
- }
- }
+ foreach (AttributeRequest &req, requests) {
+ if (req.name == name) {
+ return;
+ }
+ }
- requests.push_back(AttributeRequest(name));
+ requests.push_back(AttributeRequest(name));
}
void AttributeRequestSet::add(AttributeStandard std)
{
- foreach(AttributeRequest& req, requests)
- if(req.std == std)
- return;
+ foreach (AttributeRequest &req, requests)
+ if (req.std == std)
+ return;
- requests.push_back(AttributeRequest(std));
+ requests.push_back(AttributeRequest(std));
}
-void AttributeRequestSet::add(AttributeRequestSet& reqs)
+void AttributeRequestSet::add(AttributeRequestSet &reqs)
{
- foreach(AttributeRequest& req, reqs.requests) {
- if(req.std == ATTR_STD_NONE)
- add(req.name);
- else
- add(req.std);
- }
+ foreach (AttributeRequest &req, reqs.requests) {
+ if (req.std == ATTR_STD_NONE)
+ add(req.name);
+ else
+ add(req.std);
+ }
}
void AttributeRequestSet::add_standard(ustring name)
{
- if(name.empty()) {
- return;
- }
+ if (name.empty()) {
+ return;
+ }
- AttributeStandard std = Attribute::name_standard(name.c_str());
+ AttributeStandard std = Attribute::name_standard(name.c_str());
- if(std) {
- add(std);
- }
- else {
- add(name);
- }
+ if (std) {
+ add(std);
+ }
+ else {
+ add(name);
+ }
}
bool AttributeRequestSet::find(ustring name)
{
- foreach(AttributeRequest& req, requests)
- if(req.name == name)
- return true;
+ foreach (AttributeRequest &req, requests)
+ if (req.name == name)
+ return true;
- return false;
+ return false;
}
bool AttributeRequestSet::find(AttributeStandard std)
{
- foreach(AttributeRequest& req, requests)
- if(req.std == std)
- return true;
+ foreach (AttributeRequest &req, requests)
+ if (req.std == std)
+ return true;
- return false;
+ return false;
}
size_t AttributeRequestSet::size()
{
- return requests.size();
+ return requests.size();
}
void AttributeRequestSet::clear()
{
- requests.clear();
+ requests.clear();
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index ed9e9fe76d6..ebab0fe7f88 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -37,8 +37,8 @@ struct Transform;
/* Attributes for voxels are images */
struct VoxelAttribute {
- ImageManager *manager;
- int slot;
+ ImageManager *manager;
+ int slot;
};
/* Attribute
@@ -47,114 +47,116 @@ struct VoxelAttribute {
* Supported types: Float, Color, Vector, Normal, Point */
class Attribute {
-public:
- ustring name;
- AttributeStandard std;
-
- TypeDesc type;
- vector<char> buffer;
- AttributeElement element;
- uint flags; /* enum AttributeFlag */
-
- Attribute() {}
- ~Attribute();
- void set(ustring name, TypeDesc type, AttributeElement element);
- void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only);
- void resize(size_t num_elements);
-
- size_t data_sizeof() const;
- size_t element_size(Mesh *mesh, AttributePrimitive prim) const;
- size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const;
-
- char *data()
- {
- return (buffer.size())? &buffer[0]: NULL;
- }
- float2 *data_float2()
- {
- assert(data_sizeof() == sizeof(float2));
- return (float2*)data();
- }
- float3 *data_float3()
- {
- assert(data_sizeof() == sizeof(float3));
- return (float3*)data();
- }
- float4 *data_float4()
- {
- assert(data_sizeof() == sizeof(float4));
- return (float4*)data();
- }
- float *data_float()
- {
- assert(data_sizeof() == sizeof(float));
- return (float*)data();
- }
- uchar4 *data_uchar4()
- {
- assert(data_sizeof() == sizeof(uchar4));
- return (uchar4*)data();
- }
- Transform *data_transform()
- {
- assert(data_sizeof() == sizeof(Transform));
- return (Transform*)data();
- }
- VoxelAttribute *data_voxel()
- {
- assert(data_sizeof() == sizeof(VoxelAttribute));
- return ( VoxelAttribute*)data();
- }
-
- const char *data() const
- {
- return (buffer.size())? &buffer[0]: NULL;
- }
- const float2 *data_float2() const
- {
- assert(data_sizeof() == sizeof(float2));
- return (const float2*)data();
- }
- const float3 *data_float3() const
- {
- assert(data_sizeof() == sizeof(float3));
- return (const float3*)data();
- }
- const float4 *data_float4() const
- {
- assert(data_sizeof() == sizeof(float4));
- return (const float4*)data();
- }
- const float *data_float() const
- {
- assert(data_sizeof() == sizeof(float));
- return (const float*)data();
- }
- const Transform *data_transform() const
- {
- assert(data_sizeof() == sizeof(Transform));
- return (const Transform*)data();
- }
- const VoxelAttribute *data_voxel() const
- {
- assert(data_sizeof() == sizeof(VoxelAttribute));
- return (const VoxelAttribute*)data();
- }
-
- void zero_data(void* dst);
- void add_with_weight(void* dst, void* src, float weight);
-
- void add(const float& f);
- void add(const float2& f);
- void add(const float3& f);
- void add(const uchar4& f);
- void add(const Transform& f);
- void add(const VoxelAttribute& f);
- void add(const char *data);
-
- static bool same_storage(TypeDesc a, TypeDesc b);
- static const char *standard_name(AttributeStandard std);
- static AttributeStandard name_standard(const char *name);
+ public:
+ ustring name;
+ AttributeStandard std;
+
+ TypeDesc type;
+ vector<char> buffer;
+ AttributeElement element;
+ uint flags; /* enum AttributeFlag */
+
+ Attribute()
+ {
+ }
+ ~Attribute();
+ void set(ustring name, TypeDesc type, AttributeElement element);
+ void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only);
+ void resize(size_t num_elements);
+
+ size_t data_sizeof() const;
+ size_t element_size(Mesh *mesh, AttributePrimitive prim) const;
+ size_t buffer_size(Mesh *mesh, AttributePrimitive prim) const;
+
+ char *data()
+ {
+ return (buffer.size()) ? &buffer[0] : NULL;
+ }
+ float2 *data_float2()
+ {
+ assert(data_sizeof() == sizeof(float2));
+ return (float2 *)data();
+ }
+ float3 *data_float3()
+ {
+ assert(data_sizeof() == sizeof(float3));
+ return (float3 *)data();
+ }
+ float4 *data_float4()
+ {
+ assert(data_sizeof() == sizeof(float4));
+ return (float4 *)data();
+ }
+ float *data_float()
+ {
+ assert(data_sizeof() == sizeof(float));
+ return (float *)data();
+ }
+ uchar4 *data_uchar4()
+ {
+ assert(data_sizeof() == sizeof(uchar4));
+ return (uchar4 *)data();
+ }
+ Transform *data_transform()
+ {
+ assert(data_sizeof() == sizeof(Transform));
+ return (Transform *)data();
+ }
+ VoxelAttribute *data_voxel()
+ {
+ assert(data_sizeof() == sizeof(VoxelAttribute));
+ return (VoxelAttribute *)data();
+ }
+
+ const char *data() const
+ {
+ return (buffer.size()) ? &buffer[0] : NULL;
+ }
+ const float2 *data_float2() const
+ {
+ assert(data_sizeof() == sizeof(float2));
+ return (const float2 *)data();
+ }
+ const float3 *data_float3() const
+ {
+ assert(data_sizeof() == sizeof(float3));
+ return (const float3 *)data();
+ }
+ const float4 *data_float4() const
+ {
+ assert(data_sizeof() == sizeof(float4));
+ return (const float4 *)data();
+ }
+ const float *data_float() const
+ {
+ assert(data_sizeof() == sizeof(float));
+ return (const float *)data();
+ }
+ const Transform *data_transform() const
+ {
+ assert(data_sizeof() == sizeof(Transform));
+ return (const Transform *)data();
+ }
+ const VoxelAttribute *data_voxel() const
+ {
+ assert(data_sizeof() == sizeof(VoxelAttribute));
+ return (const VoxelAttribute *)data();
+ }
+
+ void zero_data(void *dst);
+ void add_with_weight(void *dst, void *src, float weight);
+
+ void add(const float &f);
+ void add(const float2 &f);
+ void add(const float3 &f);
+ void add(const uchar4 &f);
+ void add(const Transform &f);
+ void add(const VoxelAttribute &f);
+ void add(const char *data);
+
+ static bool same_storage(TypeDesc a, TypeDesc b);
+ static const char *standard_name(AttributeStandard std);
+ static AttributeStandard name_standard(const char *name);
};
/* Attribute Set
@@ -162,29 +164,29 @@ public:
* Set of attributes on a mesh. */
class AttributeSet {
-public:
- Mesh *triangle_mesh;
- Mesh *curve_mesh;
- Mesh *subd_mesh;
- list<Attribute> attributes;
+ public:
+ Mesh *triangle_mesh;
+ Mesh *curve_mesh;
+ Mesh *subd_mesh;
+ list<Attribute> attributes;
- AttributeSet();
- ~AttributeSet();
+ AttributeSet();
+ ~AttributeSet();
- Attribute *add(ustring name, TypeDesc type, AttributeElement element);
- Attribute *find(ustring name) const;
- void remove(ustring name);
+ Attribute *add(ustring name, TypeDesc type, AttributeElement element);
+ Attribute *find(ustring name) const;
+ void remove(ustring name);
- Attribute *add(AttributeStandard std, ustring name = ustring());
- Attribute *find(AttributeStandard std) const;
- void remove(AttributeStandard std);
+ Attribute *add(AttributeStandard std, ustring name = ustring());
+ Attribute *find(AttributeStandard std) const;
+ void remove(AttributeStandard std);
- Attribute *find(AttributeRequest& req);
+ Attribute *find(AttributeRequest &req);
- void remove(Attribute *attribute);
+ void remove(Attribute *attribute);
- void resize(bool reserve_only = false);
- void clear(bool preserve_voxel_data = false);
+ void resize(bool reserve_only = false);
+ void clear(bool preserve_voxel_data = false);
};
/* AttributeRequest
@@ -194,16 +196,16 @@ public:
* The attribute is found either by name or by standard attribute type. */
class AttributeRequest {
-public:
- ustring name;
- AttributeStandard std;
+ public:
+ ustring name;
+ AttributeStandard std;
- /* temporary variables used by MeshManager */
- TypeDesc triangle_type, curve_type, subd_type;
- AttributeDescriptor triangle_desc, curve_desc, subd_desc;
+ /* temporary variables used by MeshManager */
+ TypeDesc triangle_type, curve_type, subd_type;
+ AttributeDescriptor triangle_desc, curve_desc, subd_desc;
- explicit AttributeRequest(ustring name_);
- explicit AttributeRequest(AttributeStandard std);
+ explicit AttributeRequest(ustring name_);
+ explicit AttributeRequest(AttributeStandard std);
};
/* AttributeRequestSet
@@ -211,26 +213,26 @@ public:
* Set of attributes requested by a shader. */
class AttributeRequestSet {
-public:
- vector<AttributeRequest> requests;
+ public:
+ vector<AttributeRequest> requests;
- AttributeRequestSet();
- ~AttributeRequestSet();
+ AttributeRequestSet();
+ ~AttributeRequestSet();
- void add(ustring name);
- void add(AttributeStandard std);
- void add(AttributeRequestSet& reqs);
- void add_standard(ustring name);
+ void add(ustring name);
+ void add(AttributeStandard std);
+ void add(AttributeRequestSet &reqs);
+ void add_standard(ustring name);
- bool find(ustring name);
- bool find(AttributeStandard std);
+ bool find(ustring name);
+ bool find(AttributeStandard std);
- size_t size();
- void clear();
+ size_t size();
+ void clear();
- bool modified(const AttributeRequestSet& other);
+ bool modified(const AttributeRequestSet &other);
};
CCL_NAMESPACE_END
-#endif /* __ATTRIBUTE_H__ */
+#endif /* __ATTRIBUTE_H__ */
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index d8a49bf6a5e..b32cc55903d 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -30,28 +30,27 @@ CCL_NAMESPACE_BEGIN
NODE_DEFINE(Background)
{
- NodeType* type = NodeType::add("background", create);
+ NodeType *type = NodeType::add("background", create);
- SOCKET_FLOAT(ao_factor, "AO Factor", 0.0f);
- SOCKET_FLOAT(ao_distance, "AO Distance", FLT_MAX);
+ SOCKET_FLOAT(ao_factor, "AO Factor", 0.0f);
+ SOCKET_FLOAT(ao_distance, "AO Distance", FLT_MAX);
- SOCKET_BOOLEAN(use_shader, "Use Shader", true);
- SOCKET_BOOLEAN(use_ao, "Use AO", false);
- SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
+ SOCKET_BOOLEAN(use_shader, "Use Shader", true);
+ SOCKET_BOOLEAN(use_ao, "Use AO", false);
+ SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
- SOCKET_BOOLEAN(transparent, "Transparent", false);
- SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false);
- SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f);
+ SOCKET_BOOLEAN(transparent, "Transparent", false);
+ SOCKET_BOOLEAN(transparent_glass, "Transparent Glass", false);
+ SOCKET_FLOAT(transparent_roughness_threshold, "Transparent Roughness Threshold", 0.0f);
- SOCKET_NODE(shader, "Shader", &Shader::node_type);
+ SOCKET_NODE(shader, "Shader", &Shader::node_type);
- return type;
+ return type;
}
-Background::Background()
-: Node(node_type)
+Background::Background() : Node(node_type)
{
- need_update = true;
+ need_update = true;
}
Background::~Background()
@@ -60,78 +59,79 @@ Background::~Background()
void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(!need_update)
- return;
-
- device_free(device, dscene);
-
- Shader *bg_shader = shader;
-
- if(use_shader) {
- if(!bg_shader)
- bg_shader = scene->default_background;
- }
- else
- bg_shader = scene->default_empty;
-
- /* set shader index and transparent option */
- KernelBackground *kbackground = &dscene->data.background;
-
- kbackground->ao_factor = (use_ao)? ao_factor: 0.0f;
- kbackground->ao_bounces_factor = ao_factor;
- kbackground->ao_distance = ao_distance;
-
- kbackground->transparent = transparent;
- kbackground->surface_shader = scene->shader_manager->get_shader_id(bg_shader);
-
- if(transparent && transparent_glass) {
- /* Square twice, once for principled BSDF convention, and once for
- * faster comparison in kernel with anisotropic roughness. */
- kbackground->transparent_roughness_squared_threshold = sqr(sqr(transparent_roughness_threshold));
- }
- else {
- kbackground->transparent_roughness_squared_threshold = -1.0f;
- }
-
- if(bg_shader->has_volume)
- kbackground->volume_shader = kbackground->surface_shader;
- else
- kbackground->volume_shader = SHADER_NONE;
-
- /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
- if(bg_shader->graph->nodes.size() <= 1) {
- kbackground->surface_shader |= SHADER_EXCLUDE_ANY;
- }
- /* Background present, check visibilities */
- else {
- if(!(visibility & PATH_RAY_DIFFUSE))
- kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
- if(!(visibility & PATH_RAY_GLOSSY))
- kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
- if(!(visibility & PATH_RAY_TRANSMIT))
- kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
- if(!(visibility & PATH_RAY_VOLUME_SCATTER))
- kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
- if(!(visibility & PATH_RAY_CAMERA))
- kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
- }
-
- need_update = false;
+ if (!need_update)
+ return;
+
+ device_free(device, dscene);
+
+ Shader *bg_shader = shader;
+
+ if (use_shader) {
+ if (!bg_shader)
+ bg_shader = scene->default_background;
+ }
+ else
+ bg_shader = scene->default_empty;
+
+ /* set shader index and transparent option */
+ KernelBackground *kbackground = &dscene->data.background;
+
+ kbackground->ao_factor = (use_ao) ? ao_factor : 0.0f;
+ kbackground->ao_bounces_factor = ao_factor;
+ kbackground->ao_distance = ao_distance;
+
+ kbackground->transparent = transparent;
+ kbackground->surface_shader = scene->shader_manager->get_shader_id(bg_shader);
+
+ if (transparent && transparent_glass) {
+ /* Square twice, once for principled BSDF convention, and once for
+ * faster comparison in kernel with anisotropic roughness. */
+ kbackground->transparent_roughness_squared_threshold = sqr(
+ sqr(transparent_roughness_threshold));
+ }
+ else {
+ kbackground->transparent_roughness_squared_threshold = -1.0f;
+ }
+
+ if (bg_shader->has_volume)
+ kbackground->volume_shader = kbackground->surface_shader;
+ else
+ kbackground->volume_shader = SHADER_NONE;
+
+ /* No background node, make world shader invisible to all rays, to skip evaluation in kernel. */
+ if (bg_shader->graph->nodes.size() <= 1) {
+ kbackground->surface_shader |= SHADER_EXCLUDE_ANY;
+ }
+ /* Background present, check visibilities */
+ else {
+ if (!(visibility & PATH_RAY_DIFFUSE))
+ kbackground->surface_shader |= SHADER_EXCLUDE_DIFFUSE;
+ if (!(visibility & PATH_RAY_GLOSSY))
+ kbackground->surface_shader |= SHADER_EXCLUDE_GLOSSY;
+ if (!(visibility & PATH_RAY_TRANSMIT))
+ kbackground->surface_shader |= SHADER_EXCLUDE_TRANSMIT;
+ if (!(visibility & PATH_RAY_VOLUME_SCATTER))
+ kbackground->surface_shader |= SHADER_EXCLUDE_SCATTER;
+ if (!(visibility & PATH_RAY_CAMERA))
+ kbackground->surface_shader |= SHADER_EXCLUDE_CAMERA;
+ }
+
+ need_update = false;
}
void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
-bool Background::modified(const Background& background)
+bool Background::modified(const Background &background)
{
- return !Node::equals(background);
+ return !Node::equals(background);
}
void Background::tag_update(Scene *scene)
{
- scene->integrator->tag_update(scene);
- need_update = true;
+ scene->integrator->tag_update(scene);
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index 17c3eaaaaf5..020db7bf6aa 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -29,34 +29,34 @@ class Scene;
class Shader;
class Background : public Node {
-public:
- NODE_DECLARE
+ public:
+ NODE_DECLARE
- float ao_factor;
- float ao_distance;
+ float ao_factor;
+ float ao_distance;
- bool use_shader;
- bool use_ao;
+ bool use_shader;
+ bool use_ao;
- uint visibility;
- Shader *shader;
+ uint visibility;
+ Shader *shader;
- bool transparent;
- bool transparent_glass;
- float transparent_roughness_threshold;
+ bool transparent;
+ bool transparent_glass;
+ float transparent_roughness_threshold;
- bool need_update;
+ bool need_update;
- Background();
- ~Background();
+ Background();
+ ~Background();
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Background& background);
- void tag_update(Scene *scene);
+ bool modified(const Background &background);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __BACKGROUND_H__ */
+#endif /* __BACKGROUND_H__ */
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 927e04abc7f..73893921500 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -24,221 +24,220 @@
CCL_NAMESPACE_BEGIN
-BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels):
-m_object(object),
-m_tri_offset(tri_offset),
-m_num_pixels(num_pixels)
+BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels)
+ : m_object(object), m_tri_offset(tri_offset), m_num_pixels(num_pixels)
{
- m_primitive.resize(num_pixels);
- m_u.resize(num_pixels);
- m_v.resize(num_pixels);
- m_dudx.resize(num_pixels);
- m_dudy.resize(num_pixels);
- m_dvdx.resize(num_pixels);
- m_dvdy.resize(num_pixels);
+ m_primitive.resize(num_pixels);
+ m_u.resize(num_pixels);
+ m_v.resize(num_pixels);
+ m_dudx.resize(num_pixels);
+ m_dudy.resize(num_pixels);
+ m_dvdx.resize(num_pixels);
+ m_dvdy.resize(num_pixels);
}
BakeData::~BakeData()
{
- m_primitive.clear();
- m_u.clear();
- m_v.clear();
- m_dudx.clear();
- m_dudy.clear();
- m_dvdx.clear();
- m_dvdy.clear();
+ m_primitive.clear();
+ m_u.clear();
+ m_v.clear();
+ m_dudx.clear();
+ m_dudy.clear();
+ m_dvdx.clear();
+ m_dvdy.clear();
}
void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
{
- m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
- m_u[i] = uv[0];
- m_v[i] = uv[1];
- m_dudx[i] = dudx;
- m_dudy[i] = dudy;
- m_dvdx[i] = dvdx;
- m_dvdy[i] = dvdy;
+ m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
+ m_u[i] = uv[0];
+ m_v[i] = uv[1];
+ m_dudx[i] = dudx;
+ m_dudy[i] = dudy;
+ m_dvdx[i] = dvdx;
+ m_dvdy[i] = dvdy;
}
void BakeData::set_null(int i)
{
- m_primitive[i] = -1;
+ m_primitive[i] = -1;
}
int BakeData::object()
{
- return m_object;
+ return m_object;
}
size_t BakeData::size()
{
- return m_num_pixels;
+ return m_num_pixels;
}
bool BakeData::is_valid(int i)
{
- return m_primitive[i] != -1;
+ return m_primitive[i] != -1;
}
uint4 BakeData::data(int i)
{
- return make_uint4(
- m_object,
- m_primitive[i],
- __float_as_int(m_u[i]),
- __float_as_int(m_v[i])
- );
+ return make_uint4(m_object, m_primitive[i], __float_as_int(m_u[i]), __float_as_int(m_v[i]));
}
uint4 BakeData::differentials(int i)
{
- return make_uint4(
- __float_as_int(m_dudx[i]),
- __float_as_int(m_dudy[i]),
- __float_as_int(m_dvdx[i]),
- __float_as_int(m_dvdy[i])
- );
+ return make_uint4(__float_as_int(m_dudx[i]),
+ __float_as_int(m_dudy[i]),
+ __float_as_int(m_dvdx[i]),
+ __float_as_int(m_dvdy[i]));
}
BakeManager::BakeManager()
{
- m_bake_data = NULL;
- m_is_baking = false;
- need_update = true;
- m_shader_limit = 512 * 512;
+ m_bake_data = NULL;
+ m_is_baking = false;
+ need_update = true;
+ m_shader_limit = 512 * 512;
}
BakeManager::~BakeManager()
{
- if(m_bake_data)
- delete m_bake_data;
+ if (m_bake_data)
+ delete m_bake_data;
}
bool BakeManager::get_baking()
{
- return m_is_baking;
+ return m_is_baking;
}
void BakeManager::set_baking(const bool value)
{
- m_is_baking = value;
+ m_is_baking = value;
}
BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
{
- m_bake_data = new BakeData(object, tri_offset, num_pixels);
- return m_bake_data;
+ m_bake_data = new BakeData(object, tri_offset, num_pixels);
+ return m_bake_data;
}
void BakeManager::set_shader_limit(const size_t x, const size_t y)
{
- m_shader_limit = x * y;
- m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit)/log(2)));
+ m_shader_limit = x * y;
+ m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit) / log(2)));
}
-bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[])
+bool BakeManager::bake(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress,
+ ShaderEvalType shader_type,
+ const int pass_filter,
+ BakeData *bake_data,
+ float result[])
{
- size_t num_pixels = bake_data->size();
-
- int num_samples = aa_samples(scene, bake_data, shader_type);
-
- /* calculate the total pixel samples for the progress bar */
- total_pixel_samples = 0;
- for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
- total_pixel_samples += shader_size * num_samples;
- }
- progress.reset_sample();
- progress.set_total_pixel_samples(total_pixel_samples);
-
- /* needs to be up to date for baking specific AA samples */
- dscene->data.integrator.aa_samples = num_samples;
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- for(size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
- size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
-
- /* setup input for device task */
- device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(shader_size * 2);
- size_t d_input_size = 0;
-
- for(size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
- d_input_data[d_input_size++] = bake_data->data(i);
- d_input_data[d_input_size++] = bake_data->differentials(i);
- }
-
- if(d_input_size == 0) {
- m_is_baking = false;
- return false;
- }
-
- /* run device task */
- device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
- d_output.alloc(shader_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = shader_type;
- task.shader_filter = pass_filter;
- task.shader_x = 0;
- task.offset = shader_offset;
- task.shader_w = d_output.size();
- task.num_samples = num_samples;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
- task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
-
- device->task_add(task);
- device->task_wait();
-
- if(progress.get_cancel()) {
- d_input.free();
- d_output.free();
- m_is_baking = false;
- return false;
- }
-
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
-
- /* read result */
- int k = 0;
-
- float4 *offset = d_output.data();
-
- size_t depth = 4;
- for(size_t i=shader_offset; i < (shader_offset + shader_size); i++) {
- size_t index = i * depth;
- float4 out = offset[k++];
-
- if(bake_data->is_valid(i)) {
- for(size_t j=0; j < 4; j++) {
- result[index + j] = out[j];
- }
- }
- }
-
- d_output.free();
- }
-
- m_is_baking = false;
- return true;
+ size_t num_pixels = bake_data->size();
+
+ int num_samples = aa_samples(scene, bake_data, shader_type);
+
+ /* calculate the total pixel samples for the progress bar */
+ total_pixel_samples = 0;
+ for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
+ size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
+ total_pixel_samples += shader_size * num_samples;
+ }
+ progress.reset_sample();
+ progress.set_total_pixel_samples(total_pixel_samples);
+
+ /* needs to be up to date for baking specific AA samples */
+ dscene->data.integrator.aa_samples = num_samples;
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
+ size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
+
+ /* setup input for device task */
+ device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
+ uint4 *d_input_data = d_input.alloc(shader_size * 2);
+ size_t d_input_size = 0;
+
+ for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
+ d_input_data[d_input_size++] = bake_data->data(i);
+ d_input_data[d_input_size++] = bake_data->differentials(i);
+ }
+
+ if (d_input_size == 0) {
+ m_is_baking = false;
+ return false;
+ }
+
+ /* run device task */
+ device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
+ d_output.alloc(shader_size);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = shader_type;
+ task.shader_filter = pass_filter;
+ task.shader_x = 0;
+ task.offset = shader_offset;
+ task.shader_w = d_output.size();
+ task.num_samples = num_samples;
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+ task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if (progress.get_cancel()) {
+ d_input.free();
+ d_output.free();
+ m_is_baking = false;
+ return false;
+ }
+
+ d_output.copy_from_device(0, 1, d_output.size());
+ d_input.free();
+
+ /* read result */
+ int k = 0;
+
+ float4 *offset = d_output.data();
+
+ size_t depth = 4;
+ for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
+ size_t index = i * depth;
+ float4 out = offset[k++];
+
+ if (bake_data->is_valid(i)) {
+ for (size_t j = 0; j < 4; j++) {
+ result[index + j] = out[j];
+ }
+ }
+ }
+
+ d_output.free();
+ }
+
+ m_is_baking = false;
+ return true;
}
void BakeManager::device_update(Device * /*device*/,
DeviceScene * /*dscene*/,
Scene * /*scene*/,
- Progress& progress)
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- need_update = false;
+ need_update = false;
}
void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
@@ -247,51 +246,52 @@ void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type)
{
- if(type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
- return 1;
- }
- else if(type == SHADER_EVAL_NORMAL) {
- /* Only antialias normal if mesh has bump mapping. */
- Object *object = scene->objects[bake_data->object()];
-
- if(object->mesh) {
- foreach(Shader *shader, object->mesh->used_shaders) {
- if(shader->has_bump) {
- return scene->integrator->aa_samples;
- }
- }
- }
-
- return 1;
- }
- else {
- return scene->integrator->aa_samples;
- }
+ if (type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
+ return 1;
+ }
+ else if (type == SHADER_EVAL_NORMAL) {
+ /* Only antialias normal if mesh has bump mapping. */
+ Object *object = scene->objects[bake_data->object()];
+
+ if (object->mesh) {
+ foreach (Shader *shader, object->mesh->used_shaders) {
+ if (shader->has_bump) {
+ return scene->integrator->aa_samples;
+ }
+ }
+ }
+
+ return 1;
+ }
+ else {
+ return scene->integrator->aa_samples;
+ }
}
/* Keep it synced with kernel_bake.h logic */
int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
{
- const int component_flags = pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
-
- switch(type) {
- case SHADER_EVAL_AO:
- return BAKE_FILTER_AO;
- case SHADER_EVAL_SHADOW:
- return BAKE_FILTER_DIRECT;
- case SHADER_EVAL_DIFFUSE:
- return BAKE_FILTER_DIFFUSE | component_flags;
- case SHADER_EVAL_GLOSSY:
- return BAKE_FILTER_GLOSSY | component_flags;
- case SHADER_EVAL_TRANSMISSION:
- return BAKE_FILTER_TRANSMISSION | component_flags;
- case SHADER_EVAL_SUBSURFACE:
- return BAKE_FILTER_SUBSURFACE | component_flags;
- case SHADER_EVAL_COMBINED:
- return pass_filter;
- default:
- return 0;
- }
+ const int component_flags = pass_filter &
+ (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
+
+ switch (type) {
+ case SHADER_EVAL_AO:
+ return BAKE_FILTER_AO;
+ case SHADER_EVAL_SHADOW:
+ return BAKE_FILTER_DIRECT;
+ case SHADER_EVAL_DIFFUSE:
+ return BAKE_FILTER_DIFFUSE | component_flags;
+ case SHADER_EVAL_GLOSSY:
+ return BAKE_FILTER_GLOSSY | component_flags;
+ case SHADER_EVAL_TRANSMISSION:
+ return BAKE_FILTER_TRANSMISSION | component_flags;
+ case SHADER_EVAL_SUBSURFACE:
+ return BAKE_FILTER_SUBSURFACE | component_flags;
+ case SHADER_EVAL_COMBINED:
+ return pass_filter;
+ default:
+ return 0;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index fce8f2fa606..88537623efb 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -26,61 +26,68 @@
CCL_NAMESPACE_BEGIN
class BakeData {
-public:
- BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
- ~BakeData();
-
- void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
- void set_null(int i);
- int object();
- size_t size();
- uint4 data(int i);
- uint4 differentials(int i);
- bool is_valid(int i);
-
-private:
- int m_object;
- size_t m_tri_offset;
- size_t m_num_pixels;
- vector<int>m_primitive;
- vector<float>m_u;
- vector<float>m_v;
- vector<float>m_dudx;
- vector<float>m_dudy;
- vector<float>m_dvdx;
- vector<float>m_dvdy;
+ public:
+ BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
+ ~BakeData();
+
+ void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
+ void set_null(int i);
+ int object();
+ size_t size();
+ uint4 data(int i);
+ uint4 differentials(int i);
+ bool is_valid(int i);
+
+ private:
+ int m_object;
+ size_t m_tri_offset;
+ size_t m_num_pixels;
+ vector<int> m_primitive;
+ vector<float> m_u;
+ vector<float> m_v;
+ vector<float> m_dudx;
+ vector<float> m_dudy;
+ vector<float> m_dvdx;
+ vector<float> m_dvdy;
};
class BakeManager {
-public:
- BakeManager();
- ~BakeManager();
+ public:
+ BakeManager();
+ ~BakeManager();
- bool get_baking();
- void set_baking(const bool value);
+ bool get_baking();
+ void set_baking(const bool value);
- BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
+ BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
- void set_shader_limit(const size_t x, const size_t y);
+ void set_shader_limit(const size_t x, const size_t y);
- bool bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[]);
+ bool bake(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress,
+ ShaderEvalType shader_type,
+ const int pass_filter,
+ BakeData *bake_data,
+ float result[]);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
- static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
- static int aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type);
+ static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
+ static int aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type);
- bool need_update;
+ bool need_update;
- size_t total_pixel_samples;
+ size_t total_pixel_samples;
-private:
- BakeData *m_bake_data;
- bool m_is_baking;
- size_t m_shader_limit;
+ private:
+ BakeData *m_bake_data;
+ bool m_is_baking;
+ size_t m_shader_limit;
};
CCL_NAMESPACE_END
-#endif /* __BAKE_H__ */
+#endif /* __BAKE_H__ */
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index 678105aeeb1..5405aaefc1d 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -32,455 +32,458 @@ CCL_NAMESPACE_BEGIN
BufferParams::BufferParams()
{
- width = 0;
- height = 0;
+ width = 0;
+ height = 0;
- full_x = 0;
- full_y = 0;
- full_width = 0;
- full_height = 0;
+ full_x = 0;
+ full_y = 0;
+ full_width = 0;
+ full_height = 0;
- denoising_data_pass = false;
- denoising_clean_pass = false;
- denoising_prefiltered_pass = false;
+ denoising_data_pass = false;
+ denoising_clean_pass = false;
+ denoising_prefiltered_pass = false;
- Pass::add(PASS_COMBINED, passes);
+ Pass::add(PASS_COMBINED, passes);
}
-void BufferParams::get_offset_stride(int& offset, int& stride)
+void BufferParams::get_offset_stride(int &offset, int &stride)
{
- offset = -(full_x + full_y*width);
- stride = width;
+ offset = -(full_x + full_y * width);
+ stride = width;
}
-bool BufferParams::modified(const BufferParams& params)
+bool BufferParams::modified(const BufferParams &params)
{
- return !(full_x == params.full_x
- && full_y == params.full_y
- && width == params.width
- && height == params.height
- && full_width == params.full_width
- && full_height == params.full_height
- && Pass::equals(passes, params.passes));
+ return !(full_x == params.full_x && full_y == params.full_y && width == params.width &&
+ height == params.height && full_width == params.full_width &&
+ full_height == params.full_height && Pass::equals(passes, params.passes));
}
int BufferParams::get_passes_size()
{
- int size = 0;
+ int size = 0;
- for(size_t i = 0; i < passes.size(); i++)
- size += passes[i].components;
+ for (size_t i = 0; i < passes.size(); i++)
+ size += passes[i].components;
- if(denoising_data_pass) {
- size += DENOISING_PASS_SIZE_BASE;
- if(denoising_clean_pass) size += DENOISING_PASS_SIZE_CLEAN;
- if(denoising_prefiltered_pass) size += DENOISING_PASS_SIZE_PREFILTERED;
- }
+ if (denoising_data_pass) {
+ size += DENOISING_PASS_SIZE_BASE;
+ if (denoising_clean_pass)
+ size += DENOISING_PASS_SIZE_CLEAN;
+ if (denoising_prefiltered_pass)
+ size += DENOISING_PASS_SIZE_PREFILTERED;
+ }
- return align_up(size, 4);
+ return align_up(size, 4);
}
int BufferParams::get_denoising_offset()
{
- int offset = 0;
+ int offset = 0;
- for(size_t i = 0; i < passes.size(); i++)
- offset += passes[i].components;
+ for (size_t i = 0; i < passes.size(); i++)
+ offset += passes[i].components;
- return offset;
+ return offset;
}
int BufferParams::get_denoising_prefiltered_offset()
{
- assert(denoising_prefiltered_pass);
+ assert(denoising_prefiltered_pass);
- int offset = get_denoising_offset();
+ int offset = get_denoising_offset();
- offset += DENOISING_PASS_SIZE_BASE;
- if(denoising_clean_pass) {
- offset += DENOISING_PASS_SIZE_CLEAN;
- }
+ offset += DENOISING_PASS_SIZE_BASE;
+ if (denoising_clean_pass) {
+ offset += DENOISING_PASS_SIZE_CLEAN;
+ }
- return offset;
+ return offset;
}
/* Render Buffer Task */
RenderTile::RenderTile()
{
- x = 0;
- y = 0;
- w = 0;
- h = 0;
+ x = 0;
+ y = 0;
+ w = 0;
+ h = 0;
- sample = 0;
- start_sample = 0;
- num_samples = 0;
- resolution = 0;
+ sample = 0;
+ start_sample = 0;
+ num_samples = 0;
+ resolution = 0;
- offset = 0;
- stride = 0;
+ offset = 0;
+ stride = 0;
- buffer = 0;
+ buffer = 0;
- buffers = NULL;
+ buffers = NULL;
}
/* Render Buffers */
RenderBuffers::RenderBuffers(Device *device)
-: buffer(device, "RenderBuffers", MEM_READ_WRITE),
- map_neighbor_copied(false), render_time(0.0f)
+ : buffer(device, "RenderBuffers", MEM_READ_WRITE),
+ map_neighbor_copied(false),
+ render_time(0.0f)
{
}
RenderBuffers::~RenderBuffers()
{
- buffer.free();
+ buffer.free();
}
-void RenderBuffers::reset(BufferParams& params_)
+void RenderBuffers::reset(BufferParams &params_)
{
- params = params_;
+ params = params_;
- /* re-allocate buffer */
- buffer.alloc(params.width*params.height*params.get_passes_size());
- buffer.zero_to_device();
+ /* re-allocate buffer */
+ buffer.alloc(params.width * params.height * params.get_passes_size());
+ buffer.zero_to_device();
}
void RenderBuffers::zero()
{
- buffer.zero_to_device();
+ buffer.zero_to_device();
}
bool RenderBuffers::copy_from_device()
{
- if(!buffer.device_pointer)
- return false;
+ if (!buffer.device_pointer)
+ return false;
- buffer.copy_from_device(0, params.width * params.get_passes_size(), params.height);
+ buffer.copy_from_device(0, params.width * params.get_passes_size(), params.height);
- return true;
+ return true;
}
-bool RenderBuffers::get_denoising_pass_rect(int type, float exposure, int sample, int components, float *pixels)
+bool RenderBuffers::get_denoising_pass_rect(
+ int type, float exposure, int sample, int components, float *pixels)
{
- if(buffer.data() == NULL) {
- return false;
- }
-
- float scale = 1.0f;
- float alpha_scale = 1.0f/sample;
- if(type == DENOISING_PASS_PREFILTERED_COLOR ||
- type == DENOISING_PASS_CLEAN ||
- type == DENOISING_PASS_PREFILTERED_INTENSITY) {
- scale *= exposure;
- }
- else if(type == DENOISING_PASS_PREFILTERED_VARIANCE) {
- scale *= exposure*exposure * (sample - 1);
- }
-
- int offset;
- if(type == DENOISING_PASS_CLEAN) {
- /* The clean pass isn't changed by prefiltering, so we use the original one there. */
- offset = type + params.get_denoising_offset();
- scale /= sample;
- }
- else if (type == DENOISING_PASS_PREFILTERED_COLOR && !params.denoising_prefiltered_pass) {
- /* If we're not saving the prefiltering result, return the original noisy pass. */
- offset = params.get_denoising_offset() + DENOISING_PASS_COLOR;
- scale /= sample;
- }
- else {
- offset = type + params.get_denoising_prefiltered_offset();
- }
-
- int pass_stride = params.get_passes_size();
- int size = params.width*params.height;
-
- float *in = buffer.data() + offset;
-
- if(components == 1) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- pixels[0] = in[0]*scale;
- }
- }
- else if(components == 3) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- pixels[0] = in[0]*scale;
- pixels[1] = in[1]*scale;
- pixels[2] = in[2]*scale;
- }
- }
- else if(components == 4) {
- /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
- assert(params.passes[0].type == PASS_COMBINED);
- float *in_combined = buffer.data();
-
- for(int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
- pixels[0] = in[0]*scale;
- pixels[1] = in[1]*scale;
- pixels[2] = in[2]*scale;
- pixels[3] = saturate(in_combined[3]*alpha_scale);
- }
- }
- else {
- return false;
- }
-
- return true;
+ if (buffer.data() == NULL) {
+ return false;
+ }
+
+ float scale = 1.0f;
+ float alpha_scale = 1.0f / sample;
+ if (type == DENOISING_PASS_PREFILTERED_COLOR || type == DENOISING_PASS_CLEAN ||
+ type == DENOISING_PASS_PREFILTERED_INTENSITY) {
+ scale *= exposure;
+ }
+ else if (type == DENOISING_PASS_PREFILTERED_VARIANCE) {
+ scale *= exposure * exposure * (sample - 1);
+ }
+
+ int offset;
+ if (type == DENOISING_PASS_CLEAN) {
+ /* The clean pass isn't changed by prefiltering, so we use the original one there. */
+ offset = type + params.get_denoising_offset();
+ scale /= sample;
+ }
+ else if (type == DENOISING_PASS_PREFILTERED_COLOR && !params.denoising_prefiltered_pass) {
+ /* If we're not saving the prefiltering result, return the original noisy pass. */
+ offset = params.get_denoising_offset() + DENOISING_PASS_COLOR;
+ scale /= sample;
+ }
+ else {
+ offset = type + params.get_denoising_prefiltered_offset();
+ }
+
+ int pass_stride = params.get_passes_size();
+ int size = params.width * params.height;
+
+ float *in = buffer.data() + offset;
+
+ if (components == 1) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ pixels[0] = in[0] * scale;
+ }
+ }
+ else if (components == 3) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ pixels[0] = in[0] * scale;
+ pixels[1] = in[1] * scale;
+ pixels[2] = in[2] * scale;
+ }
+ }
+ else if (components == 4) {
+ /* Since the alpha channel is not involved in denoising, output the Combined alpha channel. */
+ assert(params.passes[0].type == PASS_COMBINED);
+ float *in_combined = buffer.data();
+
+ for (int i = 0; i < size; i++, in += pass_stride, in_combined += pass_stride, pixels += 4) {
+ pixels[0] = in[0] * scale;
+ pixels[1] = in[1] * scale;
+ pixels[2] = in[2] * scale;
+ pixels[3] = saturate(in_combined[3] * alpha_scale);
+ }
+ }
+ else {
+ return false;
+ }
+
+ return true;
}
-bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels, const string &name)
+bool RenderBuffers::get_pass_rect(
+ PassType type, float exposure, int sample, int components, float *pixels, const string &name)
{
- if(buffer.data() == NULL) {
- return false;
- }
-
- int pass_offset = 0;
-
- for(size_t j = 0; j < params.passes.size(); j++) {
- Pass& pass = params.passes[j];
-
- if(pass.type != type) {
- pass_offset += pass.components;
- continue;
- }
-
- /* Tell Cryptomatte passes apart by their name. */
- if(pass.type == PASS_CRYPTOMATTE) {
- if(pass.name != name) {
- pass_offset += pass.components;
- continue;
- }
- }
-
- float *in = buffer.data() + pass_offset;
- int pass_stride = params.get_passes_size();
-
- float scale = (pass.filter)? 1.0f/(float)sample: 1.0f;
- float scale_exposure = (pass.exposure)? scale*exposure: scale;
-
- int size = params.width*params.height;
-
- if(components == 1 && type == PASS_RENDER_TIME) {
- /* Render time is not stored by kernel, but measured per tile. */
- float val = (float) (1000.0 * render_time/(params.width * params.height * sample));
- for(int i = 0; i < size; i++, pixels++) {
- pixels[0] = val;
- }
- }
- else if(components == 1) {
- assert(pass.components == components);
-
- /* Scalar */
- if(type == PASS_DEPTH) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = (f == 0.0f)? 1e10f: f*scale_exposure;
- }
- }
- else if(type == PASS_MIST) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = saturate(f*scale_exposure);
- }
- }
+ if (buffer.data() == NULL) {
+ return false;
+ }
+
+ int pass_offset = 0;
+
+ for (size_t j = 0; j < params.passes.size(); j++) {
+ Pass &pass = params.passes[j];
+
+ if (pass.type != type) {
+ pass_offset += pass.components;
+ continue;
+ }
+
+ /* Tell Cryptomatte passes apart by their name. */
+ if (pass.type == PASS_CRYPTOMATTE) {
+ if (pass.name != name) {
+ pass_offset += pass.components;
+ continue;
+ }
+ }
+
+ float *in = buffer.data() + pass_offset;
+ int pass_stride = params.get_passes_size();
+
+ float scale = (pass.filter) ? 1.0f / (float)sample : 1.0f;
+ float scale_exposure = (pass.exposure) ? scale * exposure : scale;
+
+ int size = params.width * params.height;
+
+ if (components == 1 && type == PASS_RENDER_TIME) {
+ /* Render time is not stored by kernel, but measured per tile. */
+ float val = (float)(1000.0 * render_time / (params.width * params.height * sample));
+ for (int i = 0; i < size; i++, pixels++) {
+ pixels[0] = val;
+ }
+ }
+ else if (components == 1) {
+ assert(pass.components == components);
+
+ /* Scalar */
+ if (type == PASS_DEPTH) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = (f == 0.0f) ? 1e10f : f * scale_exposure;
+ }
+ }
+ else if (type == PASS_MIST) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = saturate(f * scale_exposure);
+ }
+ }
#ifdef WITH_CYCLES_DEBUG
- else if(type == PASS_BVH_TRAVERSED_NODES ||
- type == PASS_BVH_TRAVERSED_INSTANCES ||
- type == PASS_BVH_INTERSECTIONS ||
- type == PASS_RAY_BOUNCES)
- {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = f*scale;
- }
- }
+ else if (type == PASS_BVH_TRAVERSED_NODES || type == PASS_BVH_TRAVERSED_INSTANCES ||
+ type == PASS_BVH_INTERSECTIONS || type == PASS_RAY_BOUNCES) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f * scale;
+ }
+ }
#endif
- else {
- for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
- float f = *in;
- pixels[0] = f*scale_exposure;
- }
- }
- }
- else if(components == 3) {
- assert(pass.components == 4);
-
- /* RGBA */
- if(type == PASS_SHADOW) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
-
- pixels[0] = f.x*invw;
- pixels[1] = f.y*invw;
- pixels[2] = f.z*invw;
- }
- }
- else if(pass.divide_type != PASS_NONE) {
- /* RGB lighting passes that need to divide out color */
- pass_offset = 0;
- for(size_t k = 0; k < params.passes.size(); k++) {
- Pass& color_pass = params.passes[k];
- if(color_pass.type == pass.divide_type)
- break;
- pass_offset += color_pass.components;
- }
-
- float *in_divide = buffer.data() + pass_offset;
-
- for(int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
- float3 f = make_float3(in[0], in[1], in[2]);
- float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
-
- f = safe_divide_even_color(f*exposure, f_divide);
-
- pixels[0] = f.x;
- pixels[1] = f.y;
- pixels[2] = f.z;
- }
- }
- else {
- /* RGB/vector */
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
- float3 f = make_float3(in[0], in[1], in[2]);
-
- pixels[0] = f.x*scale_exposure;
- pixels[1] = f.y*scale_exposure;
- pixels[2] = f.z*scale_exposure;
- }
- }
- }
- else if(components == 4) {
- assert(pass.components == components);
-
- /* RGBA */
- if(type == PASS_SHADOW) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
-
- pixels[0] = f.x*invw;
- pixels[1] = f.y*invw;
- pixels[2] = f.z*invw;
- pixels[3] = 1.0f;
- }
- }
- else if(type == PASS_MOTION) {
- /* need to normalize by number of samples accumulated for motion */
- pass_offset = 0;
- for(size_t k = 0; k < params.passes.size(); k++) {
- Pass& color_pass = params.passes[k];
- if(color_pass.type == PASS_MOTION_WEIGHT)
- break;
- pass_offset += color_pass.components;
- }
-
- float *in_weight = buffer.data() + pass_offset;
-
- for(int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- float w = in_weight[0];
- float invw = (w > 0.0f)? 1.0f/w: 0.0f;
-
- pixels[0] = f.x*invw;
- pixels[1] = f.y*invw;
- pixels[2] = f.z*invw;
- pixels[3] = f.w*invw;
- }
- }
- else if(type == PASS_CRYPTOMATTE) {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
- /* x and z contain integer IDs, don't rescale them.
- y and w contain matte weights, they get scaled. */
- pixels[0] = f.x;
- pixels[1] = f.y * scale;
- pixels[2] = f.z;
- pixels[3] = f.w * scale;
- }
- }
- else {
- for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
- float4 f = make_float4(in[0], in[1], in[2], in[3]);
-
- pixels[0] = f.x*scale_exposure;
- pixels[1] = f.y*scale_exposure;
- pixels[2] = f.z*scale_exposure;
-
- /* clamp since alpha might be > 1.0 due to russian roulette */
- pixels[3] = saturate(f.w*scale);
- }
- }
- }
-
- return true;
- }
-
- return false;
+ else {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels++) {
+ float f = *in;
+ pixels[0] = f * scale_exposure;
+ }
+ }
+ }
+ else if (components == 3) {
+ assert(pass.components == 4);
+
+ /* RGBA */
+ if (type == PASS_SHADOW) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ float invw = (f.w > 0.0f) ? 1.0f / f.w : 1.0f;
+
+ pixels[0] = f.x * invw;
+ pixels[1] = f.y * invw;
+ pixels[2] = f.z * invw;
+ }
+ }
+ else if (pass.divide_type != PASS_NONE) {
+ /* RGB lighting passes that need to divide out color */
+ pass_offset = 0;
+ for (size_t k = 0; k < params.passes.size(); k++) {
+ Pass &color_pass = params.passes[k];
+ if (color_pass.type == pass.divide_type)
+ break;
+ pass_offset += color_pass.components;
+ }
+
+ float *in_divide = buffer.data() + pass_offset;
+
+ for (int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
+ float3 f = make_float3(in[0], in[1], in[2]);
+ float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
+
+ f = safe_divide_even_color(f * exposure, f_divide);
+
+ pixels[0] = f.x;
+ pixels[1] = f.y;
+ pixels[2] = f.z;
+ }
+ }
+ else {
+ /* RGB/vector */
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
+ float3 f = make_float3(in[0], in[1], in[2]);
+
+ pixels[0] = f.x * scale_exposure;
+ pixels[1] = f.y * scale_exposure;
+ pixels[2] = f.z * scale_exposure;
+ }
+ }
+ }
+ else if (components == 4) {
+ assert(pass.components == components);
+
+ /* RGBA */
+ if (type == PASS_SHADOW) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ float invw = (f.w > 0.0f) ? 1.0f / f.w : 1.0f;
+
+ pixels[0] = f.x * invw;
+ pixels[1] = f.y * invw;
+ pixels[2] = f.z * invw;
+ pixels[3] = 1.0f;
+ }
+ }
+ else if (type == PASS_MOTION) {
+ /* need to normalize by number of samples accumulated for motion */
+ pass_offset = 0;
+ for (size_t k = 0; k < params.passes.size(); k++) {
+ Pass &color_pass = params.passes[k];
+ if (color_pass.type == PASS_MOTION_WEIGHT)
+ break;
+ pass_offset += color_pass.components;
+ }
+
+ float *in_weight = buffer.data() + pass_offset;
+
+ for (int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ float w = in_weight[0];
+ float invw = (w > 0.0f) ? 1.0f / w : 0.0f;
+
+ pixels[0] = f.x * invw;
+ pixels[1] = f.y * invw;
+ pixels[2] = f.z * invw;
+ pixels[3] = f.w * invw;
+ }
+ }
+ else if (type == PASS_CRYPTOMATTE) {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+ /* x and z contain integer IDs, don't rescale them.
+ y and w contain matte weights, they get scaled. */
+ pixels[0] = f.x;
+ pixels[1] = f.y * scale;
+ pixels[2] = f.z;
+ pixels[3] = f.w * scale;
+ }
+ }
+ else {
+ for (int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
+ float4 f = make_float4(in[0], in[1], in[2], in[3]);
+
+ pixels[0] = f.x * scale_exposure;
+ pixels[1] = f.y * scale_exposure;
+ pixels[2] = f.z * scale_exposure;
+
+ /* clamp since alpha might be > 1.0 due to russian roulette */
+ pixels[3] = saturate(f.w * scale);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ return false;
}
/* Display Buffer */
DisplayBuffer::DisplayBuffer(Device *device, bool linear)
-: draw_width(0),
- draw_height(0),
- transparent(true), /* todo: determine from background */
- half_float(linear),
- rgba_byte(device, "display buffer byte"),
- rgba_half(device, "display buffer half")
+ : draw_width(0),
+ draw_height(0),
+ transparent(true), /* todo: determine from background */
+ half_float(linear),
+ rgba_byte(device, "display buffer byte"),
+ rgba_half(device, "display buffer half")
{
}
DisplayBuffer::~DisplayBuffer()
{
- rgba_byte.free();
- rgba_half.free();
+ rgba_byte.free();
+ rgba_half.free();
}
-void DisplayBuffer::reset(BufferParams& params_)
+void DisplayBuffer::reset(BufferParams &params_)
{
- draw_width = 0;
- draw_height = 0;
-
- params = params_;
-
- /* allocate display pixels */
- if(half_float) {
- rgba_half.alloc_to_device(params.width, params.height);
- }
- else {
- rgba_byte.alloc_to_device(params.width, params.height);
- }
+ draw_width = 0;
+ draw_height = 0;
+
+ params = params_;
+
+ /* allocate display pixels */
+ if (half_float) {
+ rgba_half.alloc_to_device(params.width, params.height);
+ }
+ else {
+ rgba_byte.alloc_to_device(params.width, params.height);
+ }
}
void DisplayBuffer::draw_set(int width, int height)
{
- assert(width <= params.width && height <= params.height);
+ assert(width <= params.width && height <= params.height);
- draw_width = width;
- draw_height = height;
+ draw_width = width;
+ draw_height = height;
}
-void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
+void DisplayBuffer::draw(Device *device, const DeviceDrawParams &draw_params)
{
- if(draw_width != 0 && draw_height != 0) {
- device_memory& rgba = (half_float)? (device_memory&)rgba_half:
- (device_memory&)rgba_byte;
-
- device->draw_pixels(
- rgba, 0,
- draw_width, draw_height, params.width, params.height,
- params.full_x, params.full_y, params.full_width, params.full_height,
- transparent, draw_params);
- }
+ if (draw_width != 0 && draw_height != 0) {
+ device_memory &rgba = (half_float) ? (device_memory &)rgba_half : (device_memory &)rgba_byte;
+
+ device->draw_pixels(rgba,
+ 0,
+ draw_width,
+ draw_height,
+ params.width,
+ params.height,
+ params.full_x,
+ params.full_y,
+ params.full_width,
+ params.full_height,
+ transparent,
+ draw_params);
+ }
}
bool DisplayBuffer::draw_ready()
{
- return (draw_width != 0 && draw_height != 0);
+ return (draw_width != 0 && draw_height != 0);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index 0a010718d6d..1c49038cd4b 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -38,59 +38,65 @@ struct float4;
* Size of render buffer and how it fits in the full image (border render). */
class BufferParams {
-public:
- /* width/height of the physical buffer */
- int width;
- int height;
-
- /* offset into and width/height of the full buffer */
- int full_x;
- int full_y;
- int full_width;
- int full_height;
-
- /* passes */
- vector<Pass> passes;
- bool denoising_data_pass;
- /* If only some light path types should be denoised, an additional pass is needed. */
- bool denoising_clean_pass;
- /* When we're prefiltering the passes during rendering, we need to keep both the
- * original and the prefiltered data around because neighboring tiles might still
- * need the original data. */
- bool denoising_prefiltered_pass;
-
- /* functions */
- BufferParams();
-
- void get_offset_stride(int& offset, int& stride);
- bool modified(const BufferParams& params);
- void add_pass(PassType type);
- int get_passes_size();
- int get_denoising_offset();
- int get_denoising_prefiltered_offset();
+ public:
+ /* width/height of the physical buffer */
+ int width;
+ int height;
+
+ /* offset into and width/height of the full buffer */
+ int full_x;
+ int full_y;
+ int full_width;
+ int full_height;
+
+ /* passes */
+ vector<Pass> passes;
+ bool denoising_data_pass;
+ /* If only some light path types should be denoised, an additional pass is needed. */
+ bool denoising_clean_pass;
+ /* When we're prefiltering the passes during rendering, we need to keep both the
+ * original and the prefiltered data around because neighboring tiles might still
+ * need the original data. */
+ bool denoising_prefiltered_pass;
+
+ /* functions */
+ BufferParams();
+
+ void get_offset_stride(int &offset, int &stride);
+ bool modified(const BufferParams &params);
+ void add_pass(PassType type);
+ int get_passes_size();
+ int get_denoising_offset();
+ int get_denoising_prefiltered_offset();
};
/* Render Buffers */
class RenderBuffers {
-public:
- /* buffer parameters */
- BufferParams params;
-
- /* float buffer */
- device_vector<float> buffer;
- bool map_neighbor_copied;
- double render_time;
-
- explicit RenderBuffers(Device *device);
- ~RenderBuffers();
-
- void reset(BufferParams& params);
- void zero();
-
- bool copy_from_device();
- bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels, const string &name);
- bool get_denoising_pass_rect(int offset, float exposure, int sample, int components, float *pixels);
+ public:
+ /* buffer parameters */
+ BufferParams params;
+
+ /* float buffer */
+ device_vector<float> buffer;
+ bool map_neighbor_copied;
+ double render_time;
+
+ explicit RenderBuffers(Device *device);
+ ~RenderBuffers();
+
+ void reset(BufferParams &params);
+ void zero();
+
+ bool copy_from_device();
+ bool get_pass_rect(PassType type,
+ float exposure,
+ int sample,
+ int components,
+ float *pixels,
+ const string &name);
+ bool get_denoising_pass_rect(
+ int offset, float exposure, int sample, int components, float *pixels);
};
/* Display Buffer
@@ -99,56 +105,56 @@ public:
* buffers to byte of half float storage */
class DisplayBuffer {
-public:
- /* buffer parameters */
- BufferParams params;
- /* dimensions for how much of the buffer is actually ready for display.
- * with progressive render we can be using only a subset of the buffer.
- * if these are zero, it means nothing can be drawn yet */
- int draw_width, draw_height;
- /* draw alpha channel? */
- bool transparent;
- /* use half float? */
- bool half_float;
- /* byte buffer for converted result */
- device_pixels<uchar4> rgba_byte;
- device_pixels<half4> rgba_half;
-
- DisplayBuffer(Device *device, bool linear = false);
- ~DisplayBuffer();
-
- void reset(BufferParams& params);
-
- void draw_set(int width, int height);
- void draw(Device *device, const DeviceDrawParams& draw_params);
- bool draw_ready();
+ public:
+ /* buffer parameters */
+ BufferParams params;
+ /* dimensions for how much of the buffer is actually ready for display.
+ * with progressive render we can be using only a subset of the buffer.
+ * if these are zero, it means nothing can be drawn yet */
+ int draw_width, draw_height;
+ /* draw alpha channel? */
+ bool transparent;
+ /* use half float? */
+ bool half_float;
+ /* byte buffer for converted result */
+ device_pixels<uchar4> rgba_byte;
+ device_pixels<half4> rgba_half;
+
+ DisplayBuffer(Device *device, bool linear = false);
+ ~DisplayBuffer();
+
+ void reset(BufferParams &params);
+
+ void draw_set(int width, int height);
+ void draw(Device *device, const DeviceDrawParams &draw_params);
+ bool draw_ready();
};
/* Render Tile
* Rendering task on a buffer */
class RenderTile {
-public:
- typedef enum { PATH_TRACE, DENOISE } Task;
+ public:
+ typedef enum { PATH_TRACE, DENOISE } Task;
- Task task;
- int x, y, w, h;
- int start_sample;
- int num_samples;
- int sample;
- int resolution;
- int offset;
- int stride;
- int tile_index;
+ Task task;
+ int x, y, w, h;
+ int start_sample;
+ int num_samples;
+ int sample;
+ int resolution;
+ int offset;
+ int stride;
+ int tile_index;
- device_ptr buffer;
- int device_size;
+ device_ptr buffer;
+ int device_size;
- RenderBuffers *buffers;
+ RenderBuffers *buffers;
- RenderTile();
+ RenderTile();
};
CCL_NAMESPACE_END
-#endif /* __BUFFERS_H__ */
+#endif /* __BUFFERS_H__ */
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index 82aeb324a00..9c9070c8a90 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -39,147 +39,148 @@
CCL_NAMESPACE_BEGIN
-static float shutter_curve_eval(float x,
- array<float>& shutter_curve)
+static float shutter_curve_eval(float x, array<float> &shutter_curve)
{
- if(shutter_curve.size() == 0) {
- return 1.0f;
- }
-
- x *= shutter_curve.size();
- int index = (int)x;
- float frac = x - index;
- if(index < shutter_curve.size() - 1) {
- return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
- }
- else {
- return shutter_curve[shutter_curve.size() - 1];
- }
+ if (shutter_curve.size() == 0) {
+ return 1.0f;
+ }
+
+ x *= shutter_curve.size();
+ int index = (int)x;
+ float frac = x - index;
+ if (index < shutter_curve.size() - 1) {
+ return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
+ }
+ else {
+ return shutter_curve[shutter_curve.size() - 1];
+ }
}
NODE_DEFINE(Camera)
{
- NodeType* type = NodeType::add("camera", create);
-
- SOCKET_FLOAT(shuttertime, "Shutter Time", 1.0f);
-
- static NodeEnum motion_position_enum;
- motion_position_enum.insert("start", MOTION_POSITION_START);
- motion_position_enum.insert("center", MOTION_POSITION_CENTER);
- motion_position_enum.insert("end", MOTION_POSITION_END);
- SOCKET_ENUM(motion_position, "Motion Position", motion_position_enum, MOTION_POSITION_CENTER);
-
- static NodeEnum rolling_shutter_type_enum;
- rolling_shutter_type_enum.insert("none", ROLLING_SHUTTER_NONE);
- rolling_shutter_type_enum.insert("top", ROLLING_SHUTTER_TOP);
- SOCKET_ENUM(rolling_shutter_type, "Rolling Shutter Type", rolling_shutter_type_enum, ROLLING_SHUTTER_NONE);
- SOCKET_FLOAT(rolling_shutter_duration, "Rolling Shutter Duration", 0.1f);
-
- SOCKET_FLOAT_ARRAY(shutter_curve, "Shutter Curve", array<float>());
-
- SOCKET_FLOAT(aperturesize, "Aperture Size", 0.0f);
- SOCKET_FLOAT(focaldistance, "Focal Distance", 10.0f);
- SOCKET_UINT(blades, "Blades", 0);
- SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f);
-
- SOCKET_TRANSFORM(matrix, "Matrix", transform_identity());
- SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
-
- SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f);
-
- static NodeEnum type_enum;
- type_enum.insert("perspective", CAMERA_PERSPECTIVE);
- type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC);
- type_enum.insert("panorama", CAMERA_PANORAMA);
- SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE);
-
- static NodeEnum panorama_type_enum;
- panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
- panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL);
- panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT);
- panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID);
- SOCKET_ENUM(panorama_type, "Panorama Type", panorama_type_enum, PANORAMA_EQUIRECTANGULAR);
-
- SOCKET_FLOAT(fisheye_fov, "Fisheye FOV", M_PI_F);
- SOCKET_FLOAT(fisheye_lens, "Fisheye Lens", 10.5f);
- SOCKET_FLOAT(latitude_min, "Latitude Min", -M_PI_2_F);
- SOCKET_FLOAT(latitude_max, "Latitude Max", M_PI_2_F);
- SOCKET_FLOAT(longitude_min, "Longitude Min", -M_PI_F);
- SOCKET_FLOAT(longitude_max, "Longitude Max", M_PI_F);
- SOCKET_FLOAT(fov, "FOV", M_PI_4_F);
- SOCKET_FLOAT(fov_pre, "FOV Pre", M_PI_4_F);
- SOCKET_FLOAT(fov_post, "FOV Post", M_PI_4_F);
-
- static NodeEnum stereo_eye_enum;
- stereo_eye_enum.insert("none", STEREO_NONE);
- stereo_eye_enum.insert("left", STEREO_LEFT);
- stereo_eye_enum.insert("right", STEREO_RIGHT);
- SOCKET_ENUM(stereo_eye, "Stereo Eye", stereo_eye_enum, STEREO_NONE);
-
- SOCKET_FLOAT(interocular_distance, "Interocular Distance", 0.065f);
- SOCKET_FLOAT(convergence_distance, "Convergence Distance", 30.0f * 0.065f);
-
- SOCKET_BOOLEAN(use_pole_merge, "Use Pole Merge", false);
- SOCKET_FLOAT(pole_merge_angle_from, "Pole Merge Angle From", 60.0f * M_PI_F / 180.0f);
- SOCKET_FLOAT(pole_merge_angle_to, "Pole Merge Angle To", 75.0f * M_PI_F / 180.0f);
-
- SOCKET_FLOAT(sensorwidth, "Sensor Width", 0.036f);
- SOCKET_FLOAT(sensorheight, "Sensor Height", 0.024f);
-
- SOCKET_FLOAT(nearclip, "Near Clip", 1e-5f);
- SOCKET_FLOAT(farclip, "Far Clip", 1e5f);
-
- SOCKET_FLOAT(viewplane.left, "Viewplane Left", 0);
- SOCKET_FLOAT(viewplane.right, "Viewplane Right", 0);
- SOCKET_FLOAT(viewplane.bottom, "Viewplane Bottom", 0);
- SOCKET_FLOAT(viewplane.top, "Viewplane Top", 0);
-
- SOCKET_FLOAT(border.left, "Border Left", 0);
- SOCKET_FLOAT(border.right, "Border Right", 0);
- SOCKET_FLOAT(border.bottom, "Border Bottom", 0);
- SOCKET_FLOAT(border.top, "Border Top", 0);
-
- SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f);
-
- return type;
+ NodeType *type = NodeType::add("camera", create);
+
+ SOCKET_FLOAT(shuttertime, "Shutter Time", 1.0f);
+
+ static NodeEnum motion_position_enum;
+ motion_position_enum.insert("start", MOTION_POSITION_START);
+ motion_position_enum.insert("center", MOTION_POSITION_CENTER);
+ motion_position_enum.insert("end", MOTION_POSITION_END);
+ SOCKET_ENUM(motion_position, "Motion Position", motion_position_enum, MOTION_POSITION_CENTER);
+
+ static NodeEnum rolling_shutter_type_enum;
+ rolling_shutter_type_enum.insert("none", ROLLING_SHUTTER_NONE);
+ rolling_shutter_type_enum.insert("top", ROLLING_SHUTTER_TOP);
+ SOCKET_ENUM(rolling_shutter_type,
+ "Rolling Shutter Type",
+ rolling_shutter_type_enum,
+ ROLLING_SHUTTER_NONE);
+ SOCKET_FLOAT(rolling_shutter_duration, "Rolling Shutter Duration", 0.1f);
+
+ SOCKET_FLOAT_ARRAY(shutter_curve, "Shutter Curve", array<float>());
+
+ SOCKET_FLOAT(aperturesize, "Aperture Size", 0.0f);
+ SOCKET_FLOAT(focaldistance, "Focal Distance", 10.0f);
+ SOCKET_UINT(blades, "Blades", 0);
+ SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f);
+
+ SOCKET_TRANSFORM(matrix, "Matrix", transform_identity());
+ SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
+
+ SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f);
+
+ static NodeEnum type_enum;
+ type_enum.insert("perspective", CAMERA_PERSPECTIVE);
+ type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC);
+ type_enum.insert("panorama", CAMERA_PANORAMA);
+ SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE);
+
+ static NodeEnum panorama_type_enum;
+ panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
+ panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL);
+ panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT);
+ panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID);
+ SOCKET_ENUM(panorama_type, "Panorama Type", panorama_type_enum, PANORAMA_EQUIRECTANGULAR);
+
+ SOCKET_FLOAT(fisheye_fov, "Fisheye FOV", M_PI_F);
+ SOCKET_FLOAT(fisheye_lens, "Fisheye Lens", 10.5f);
+ SOCKET_FLOAT(latitude_min, "Latitude Min", -M_PI_2_F);
+ SOCKET_FLOAT(latitude_max, "Latitude Max", M_PI_2_F);
+ SOCKET_FLOAT(longitude_min, "Longitude Min", -M_PI_F);
+ SOCKET_FLOAT(longitude_max, "Longitude Max", M_PI_F);
+ SOCKET_FLOAT(fov, "FOV", M_PI_4_F);
+ SOCKET_FLOAT(fov_pre, "FOV Pre", M_PI_4_F);
+ SOCKET_FLOAT(fov_post, "FOV Post", M_PI_4_F);
+
+ static NodeEnum stereo_eye_enum;
+ stereo_eye_enum.insert("none", STEREO_NONE);
+ stereo_eye_enum.insert("left", STEREO_LEFT);
+ stereo_eye_enum.insert("right", STEREO_RIGHT);
+ SOCKET_ENUM(stereo_eye, "Stereo Eye", stereo_eye_enum, STEREO_NONE);
+
+ SOCKET_FLOAT(interocular_distance, "Interocular Distance", 0.065f);
+ SOCKET_FLOAT(convergence_distance, "Convergence Distance", 30.0f * 0.065f);
+
+ SOCKET_BOOLEAN(use_pole_merge, "Use Pole Merge", false);
+ SOCKET_FLOAT(pole_merge_angle_from, "Pole Merge Angle From", 60.0f * M_PI_F / 180.0f);
+ SOCKET_FLOAT(pole_merge_angle_to, "Pole Merge Angle To", 75.0f * M_PI_F / 180.0f);
+
+ SOCKET_FLOAT(sensorwidth, "Sensor Width", 0.036f);
+ SOCKET_FLOAT(sensorheight, "Sensor Height", 0.024f);
+
+ SOCKET_FLOAT(nearclip, "Near Clip", 1e-5f);
+ SOCKET_FLOAT(farclip, "Far Clip", 1e5f);
+
+ SOCKET_FLOAT(viewplane.left, "Viewplane Left", 0);
+ SOCKET_FLOAT(viewplane.right, "Viewplane Right", 0);
+ SOCKET_FLOAT(viewplane.bottom, "Viewplane Bottom", 0);
+ SOCKET_FLOAT(viewplane.top, "Viewplane Top", 0);
+
+ SOCKET_FLOAT(border.left, "Border Left", 0);
+ SOCKET_FLOAT(border.right, "Border Right", 0);
+ SOCKET_FLOAT(border.bottom, "Border Bottom", 0);
+ SOCKET_FLOAT(border.top, "Border Top", 0);
+
+ SOCKET_FLOAT(offscreen_dicing_scale, "Offscreen Dicing Scale", 1.0f);
+
+ return type;
}
-Camera::Camera()
-: Node(node_type)
+Camera::Camera() : Node(node_type)
{
- shutter_table_offset = TABLE_OFFSET_INVALID;
+ shutter_table_offset = TABLE_OFFSET_INVALID;
- width = 1024;
- height = 512;
- resolution = 1;
+ width = 1024;
+ height = 512;
+ resolution = 1;
- use_perspective_motion = false;
+ use_perspective_motion = false;
- shutter_curve.resize(RAMP_TABLE_SIZE);
- for(int i = 0; i < shutter_curve.size(); ++i) {
- shutter_curve[i] = 1.0f;
- }
+ shutter_curve.resize(RAMP_TABLE_SIZE);
+ for (int i = 0; i < shutter_curve.size(); ++i) {
+ shutter_curve[i] = 1.0f;
+ }
- compute_auto_viewplane();
+ compute_auto_viewplane();
- screentoworld = projection_identity();
- rastertoworld = projection_identity();
- ndctoworld = projection_identity();
- rastertocamera = projection_identity();
- cameratoworld = transform_identity();
- worldtoraster = projection_identity();
+ screentoworld = projection_identity();
+ rastertoworld = projection_identity();
+ ndctoworld = projection_identity();
+ rastertocamera = projection_identity();
+ cameratoworld = transform_identity();
+ worldtoraster = projection_identity();
- full_rastertocamera = projection_identity();
+ full_rastertocamera = projection_identity();
- dx = make_float3(0.0f, 0.0f, 0.0f);
- dy = make_float3(0.0f, 0.0f, 0.0f);
+ dx = make_float3(0.0f, 0.0f, 0.0f);
+ dy = make_float3(0.0f, 0.0f, 0.0f);
- need_update = true;
- need_device_update = true;
- need_flags_update = true;
- previous_need_motion = -1;
+ need_update = true;
+ need_device_update = true;
+ need_flags_update = true;
+ previous_need_motion = -1;
- memset((void *)&kernel_camera, 0, sizeof(kernel_camera));
+ memset((void *)&kernel_camera, 0, sizeof(kernel_camera));
}
Camera::~Camera()
@@ -188,589 +189,577 @@ Camera::~Camera()
void Camera::compute_auto_viewplane()
{
- if(type == CAMERA_PANORAMA) {
- viewplane.left = 0.0f;
- viewplane.right = 1.0f;
- viewplane.bottom = 0.0f;
- viewplane.top = 1.0f;
- }
- else {
- float aspect = (float)width/(float)height;
- if(width >= height) {
- viewplane.left = -aspect;
- viewplane.right = aspect;
- viewplane.bottom = -1.0f;
- viewplane.top = 1.0f;
- }
- else {
- viewplane.left = -1.0f;
- viewplane.right = 1.0f;
- viewplane.bottom = -1.0f/aspect;
- viewplane.top = 1.0f/aspect;
- }
- }
+ if (type == CAMERA_PANORAMA) {
+ viewplane.left = 0.0f;
+ viewplane.right = 1.0f;
+ viewplane.bottom = 0.0f;
+ viewplane.top = 1.0f;
+ }
+ else {
+ float aspect = (float)width / (float)height;
+ if (width >= height) {
+ viewplane.left = -aspect;
+ viewplane.right = aspect;
+ viewplane.bottom = -1.0f;
+ viewplane.top = 1.0f;
+ }
+ else {
+ viewplane.left = -1.0f;
+ viewplane.right = 1.0f;
+ viewplane.bottom = -1.0f / aspect;
+ viewplane.top = 1.0f / aspect;
+ }
+ }
}
void Camera::update(Scene *scene)
{
- Scene::MotionType need_motion = scene->need_motion();
-
- if(previous_need_motion != need_motion) {
- /* scene's motion model could have been changed since previous device
- * camera update this could happen for example in case when one render
- * layer has got motion pass and another not */
- need_device_update = true;
- }
-
- if(!need_update)
- return;
-
- /* Full viewport to camera border in the viewport. */
- Transform fulltoborder = transform_from_viewplane(viewport_camera_border);
- Transform bordertofull = transform_inverse(fulltoborder);
-
- /* ndc to raster */
- Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull;
- Transform full_ndctoraster = transform_scale(full_width, full_height, 1.0f) * bordertofull;
-
- /* raster to screen */
- Transform screentondc = fulltoborder * transform_from_viewplane(viewplane);
-
- Transform screentoraster = ndctoraster * screentondc;
- Transform rastertoscreen = transform_inverse(screentoraster);
- Transform full_screentoraster = full_ndctoraster * screentondc;
- Transform full_rastertoscreen = transform_inverse(full_screentoraster);
-
- /* screen to camera */
- ProjectionTransform cameratoscreen;
- if(type == CAMERA_PERSPECTIVE)
- cameratoscreen = projection_perspective(fov, nearclip, farclip);
- else if(type == CAMERA_ORTHOGRAPHIC)
- cameratoscreen = projection_orthographic(nearclip, farclip);
- else
- cameratoscreen = projection_identity();
-
- ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
-
- rastertocamera = screentocamera * rastertoscreen;
- full_rastertocamera = screentocamera * full_rastertoscreen;
- cameratoraster = screentoraster * cameratoscreen;
-
- cameratoworld = matrix;
- screentoworld = cameratoworld * screentocamera;
- rastertoworld = cameratoworld * rastertocamera;
- ndctoworld = rastertoworld * ndctoraster;
-
- /* note we recompose matrices instead of taking inverses of the above, this
- * is needed to avoid inverting near degenerate matrices that happen due to
- * precision issues with large scenes */
- worldtocamera = transform_inverse(matrix);
- worldtoscreen = cameratoscreen * worldtocamera;
- worldtondc = screentondc * worldtoscreen;
- worldtoraster = ndctoraster * worldtondc;
-
- /* differentials */
- if(type == CAMERA_ORTHOGRAPHIC) {
- dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
- dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
- full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
- full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
- }
- else if(type == CAMERA_PERSPECTIVE) {
- dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
- transform_perspective(&rastertocamera, make_float3(0, 0, 0));
- dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
- transform_perspective(&rastertocamera, make_float3(0, 0, 0));
- full_dx = transform_perspective(&full_rastertocamera, make_float3(1, 0, 0)) -
- transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
- full_dy = transform_perspective(&full_rastertocamera, make_float3(0, 1, 0)) -
- transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
- }
- else {
- dx = make_float3(0.0f, 0.0f, 0.0f);
- dy = make_float3(0.0f, 0.0f, 0.0f);
- }
-
- dx = transform_direction(&cameratoworld, dx);
- dy = transform_direction(&cameratoworld, dy);
- full_dx = transform_direction(&cameratoworld, full_dx);
- full_dy = transform_direction(&cameratoworld, full_dy);
-
- if(type == CAMERA_PERSPECTIVE) {
- float3 v = transform_perspective(&full_rastertocamera, make_float3(full_width, full_height, 1.0f));
-
- frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x));
- frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y));
- }
-
- /* Compute kernel camera data. */
- KernelCamera *kcam = &kernel_camera;
-
- /* store matrices */
- kcam->screentoworld = screentoworld;
- kcam->rastertoworld = rastertoworld;
- kcam->rastertocamera = rastertocamera;
- kcam->cameratoworld = cameratoworld;
- kcam->worldtocamera = worldtocamera;
- kcam->worldtoscreen = worldtoscreen;
- kcam->worldtoraster = worldtoraster;
- kcam->worldtondc = worldtondc;
- kcam->ndctoworld = ndctoworld;
-
- /* camera motion */
- kcam->num_motion_steps = 0;
- kcam->have_perspective_motion = 0;
- kernel_camera_motion.clear();
-
- /* Test if any of the transforms are actually different. */
- bool have_motion = false;
- for(size_t i = 0; i < motion.size(); i++) {
- have_motion = have_motion || motion[i] != matrix;
- }
-
- if(need_motion == Scene::MOTION_PASS) {
- /* TODO(sergey): Support perspective (zoom, fov) motion. */
- if(type == CAMERA_PANORAMA) {
- if(have_motion) {
- kcam->motion_pass_pre = transform_inverse(motion[0]);
- kcam->motion_pass_post = transform_inverse(motion[motion.size()-1]);
- }
- else {
- kcam->motion_pass_pre = kcam->worldtocamera;
- kcam->motion_pass_post = kcam->worldtocamera;
- }
- }
- else {
- if(have_motion) {
- kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]);
- kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size()-1]);
- }
- else {
- kcam->perspective_pre = worldtoraster;
- kcam->perspective_post = worldtoraster;
- }
- }
- }
- else if(need_motion == Scene::MOTION_BLUR) {
- if(have_motion) {
- kernel_camera_motion.resize(motion.size());
- transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size());
- kcam->num_motion_steps = motion.size();
- }
-
- /* TODO(sergey): Support other types of camera. */
- if(use_perspective_motion && type == CAMERA_PERSPECTIVE) {
- /* TODO(sergey): Move to an utility function and de-duplicate with
- * calculation above.
- */
- ProjectionTransform screentocamera_pre =
- projection_inverse(projection_perspective(fov_pre,
- nearclip,
- farclip));
- ProjectionTransform screentocamera_post =
- projection_inverse(projection_perspective(fov_post,
- nearclip,
- farclip));
-
- kcam->perspective_pre = screentocamera_pre * rastertoscreen;
- kcam->perspective_post = screentocamera_post * rastertoscreen;
- kcam->have_perspective_motion = 1;
- }
- }
-
- /* depth of field */
- kcam->aperturesize = aperturesize;
- kcam->focaldistance = focaldistance;
- kcam->blades = (blades < 3)? 0.0f: blades;
- kcam->bladesrotation = bladesrotation;
-
- /* motion blur */
- kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f;
-
- /* type */
- kcam->type = type;
-
- /* anamorphic lens bokeh */
- kcam->inv_aperture_ratio = 1.0f / aperture_ratio;
-
- /* panorama */
- kcam->panorama_type = panorama_type;
- kcam->fisheye_fov = fisheye_fov;
- kcam->fisheye_lens = fisheye_lens;
- kcam->equirectangular_range = make_float4(longitude_min - longitude_max, -longitude_min,
- latitude_min - latitude_max, -latitude_min + M_PI_2_F);
-
- switch(stereo_eye) {
- case STEREO_LEFT:
- kcam->interocular_offset = -interocular_distance * 0.5f;
- break;
- case STEREO_RIGHT:
- kcam->interocular_offset = interocular_distance * 0.5f;
- break;
- case STEREO_NONE:
- default:
- kcam->interocular_offset = 0.0f;
- break;
- }
-
- kcam->convergence_distance = convergence_distance;
- if(use_pole_merge) {
- kcam->pole_merge_angle_from = pole_merge_angle_from;
- kcam->pole_merge_angle_to = pole_merge_angle_to;
- }
- else {
- kcam->pole_merge_angle_from = -1.0f;
- kcam->pole_merge_angle_to = -1.0f;
- }
-
- /* sensor size */
- kcam->sensorwidth = sensorwidth;
- kcam->sensorheight = sensorheight;
-
- /* render size */
- kcam->width = width;
- kcam->height = height;
- kcam->resolution = resolution;
-
- /* store differentials */
- kcam->dx = float3_to_float4(dx);
- kcam->dy = float3_to_float4(dy);
-
- /* clipping */
- kcam->nearclip = nearclip;
- kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
-
- /* Camera in volume. */
- kcam->is_inside_volume = 0;
-
- /* Rolling shutter effect */
- kcam->rolling_shutter_type = rolling_shutter_type;
- kcam->rolling_shutter_duration = rolling_shutter_duration;
-
- /* Set further update flags */
- need_update = false;
- need_device_update = true;
- need_flags_update = true;
- previous_need_motion = need_motion;
+ Scene::MotionType need_motion = scene->need_motion();
+
+ if (previous_need_motion != need_motion) {
+ /* scene's motion model could have been changed since previous device
+ * camera update this could happen for example in case when one render
+ * layer has got motion pass and another not */
+ need_device_update = true;
+ }
+
+ if (!need_update)
+ return;
+
+ /* Full viewport to camera border in the viewport. */
+ Transform fulltoborder = transform_from_viewplane(viewport_camera_border);
+ Transform bordertofull = transform_inverse(fulltoborder);
+
+ /* ndc to raster */
+ Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull;
+ Transform full_ndctoraster = transform_scale(full_width, full_height, 1.0f) * bordertofull;
+
+ /* raster to screen */
+ Transform screentondc = fulltoborder * transform_from_viewplane(viewplane);
+
+ Transform screentoraster = ndctoraster * screentondc;
+ Transform rastertoscreen = transform_inverse(screentoraster);
+ Transform full_screentoraster = full_ndctoraster * screentondc;
+ Transform full_rastertoscreen = transform_inverse(full_screentoraster);
+
+ /* screen to camera */
+ ProjectionTransform cameratoscreen;
+ if (type == CAMERA_PERSPECTIVE)
+ cameratoscreen = projection_perspective(fov, nearclip, farclip);
+ else if (type == CAMERA_ORTHOGRAPHIC)
+ cameratoscreen = projection_orthographic(nearclip, farclip);
+ else
+ cameratoscreen = projection_identity();
+
+ ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
+
+ rastertocamera = screentocamera * rastertoscreen;
+ full_rastertocamera = screentocamera * full_rastertoscreen;
+ cameratoraster = screentoraster * cameratoscreen;
+
+ cameratoworld = matrix;
+ screentoworld = cameratoworld * screentocamera;
+ rastertoworld = cameratoworld * rastertocamera;
+ ndctoworld = rastertoworld * ndctoraster;
+
+ /* note we recompose matrices instead of taking inverses of the above, this
+ * is needed to avoid inverting near degenerate matrices that happen due to
+ * precision issues with large scenes */
+ worldtocamera = transform_inverse(matrix);
+ worldtoscreen = cameratoscreen * worldtocamera;
+ worldtondc = screentondc * worldtoscreen;
+ worldtoraster = ndctoraster * worldtondc;
+
+ /* differentials */
+ if (type == CAMERA_ORTHOGRAPHIC) {
+ dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
+ dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
+ full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
+ full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
+ }
+ else if (type == CAMERA_PERSPECTIVE) {
+ dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
+ transform_perspective(&rastertocamera, make_float3(0, 0, 0));
+ dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
+ transform_perspective(&rastertocamera, make_float3(0, 0, 0));
+ full_dx = transform_perspective(&full_rastertocamera, make_float3(1, 0, 0)) -
+ transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
+ full_dy = transform_perspective(&full_rastertocamera, make_float3(0, 1, 0)) -
+ transform_perspective(&full_rastertocamera, make_float3(0, 0, 0));
+ }
+ else {
+ dx = make_float3(0.0f, 0.0f, 0.0f);
+ dy = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ dx = transform_direction(&cameratoworld, dx);
+ dy = transform_direction(&cameratoworld, dy);
+ full_dx = transform_direction(&cameratoworld, full_dx);
+ full_dy = transform_direction(&cameratoworld, full_dy);
+
+ if (type == CAMERA_PERSPECTIVE) {
+ float3 v = transform_perspective(&full_rastertocamera,
+ make_float3(full_width, full_height, 1.0f));
+
+ frustum_right_normal = normalize(make_float3(v.z, 0.0f, -v.x));
+ frustum_top_normal = normalize(make_float3(0.0f, v.z, -v.y));
+ }
+
+ /* Compute kernel camera data. */
+ KernelCamera *kcam = &kernel_camera;
+
+ /* store matrices */
+ kcam->screentoworld = screentoworld;
+ kcam->rastertoworld = rastertoworld;
+ kcam->rastertocamera = rastertocamera;
+ kcam->cameratoworld = cameratoworld;
+ kcam->worldtocamera = worldtocamera;
+ kcam->worldtoscreen = worldtoscreen;
+ kcam->worldtoraster = worldtoraster;
+ kcam->worldtondc = worldtondc;
+ kcam->ndctoworld = ndctoworld;
+
+ /* camera motion */
+ kcam->num_motion_steps = 0;
+ kcam->have_perspective_motion = 0;
+ kernel_camera_motion.clear();
+
+ /* Test if any of the transforms are actually different. */
+ bool have_motion = false;
+ for (size_t i = 0; i < motion.size(); i++) {
+ have_motion = have_motion || motion[i] != matrix;
+ }
+
+ if (need_motion == Scene::MOTION_PASS) {
+ /* TODO(sergey): Support perspective (zoom, fov) motion. */
+ if (type == CAMERA_PANORAMA) {
+ if (have_motion) {
+ kcam->motion_pass_pre = transform_inverse(motion[0]);
+ kcam->motion_pass_post = transform_inverse(motion[motion.size() - 1]);
+ }
+ else {
+ kcam->motion_pass_pre = kcam->worldtocamera;
+ kcam->motion_pass_post = kcam->worldtocamera;
+ }
+ }
+ else {
+ if (have_motion) {
+ kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]);
+ kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size() - 1]);
+ }
+ else {
+ kcam->perspective_pre = worldtoraster;
+ kcam->perspective_post = worldtoraster;
+ }
+ }
+ }
+ else if (need_motion == Scene::MOTION_BLUR) {
+ if (have_motion) {
+ kernel_camera_motion.resize(motion.size());
+ transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size());
+ kcam->num_motion_steps = motion.size();
+ }
+
+ /* TODO(sergey): Support other types of camera. */
+ if (use_perspective_motion && type == CAMERA_PERSPECTIVE) {
+ /* TODO(sergey): Move to an utility function and de-duplicate with
+ * calculation above.
+ */
+ ProjectionTransform screentocamera_pre = projection_inverse(
+ projection_perspective(fov_pre, nearclip, farclip));
+ ProjectionTransform screentocamera_post = projection_inverse(
+ projection_perspective(fov_post, nearclip, farclip));
+
+ kcam->perspective_pre = screentocamera_pre * rastertoscreen;
+ kcam->perspective_post = screentocamera_post * rastertoscreen;
+ kcam->have_perspective_motion = 1;
+ }
+ }
+
+ /* depth of field */
+ kcam->aperturesize = aperturesize;
+ kcam->focaldistance = focaldistance;
+ kcam->blades = (blades < 3) ? 0.0f : blades;
+ kcam->bladesrotation = bladesrotation;
+
+ /* motion blur */
+ kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime : -1.0f;
+
+ /* type */
+ kcam->type = type;
+
+ /* anamorphic lens bokeh */
+ kcam->inv_aperture_ratio = 1.0f / aperture_ratio;
+
+ /* panorama */
+ kcam->panorama_type = panorama_type;
+ kcam->fisheye_fov = fisheye_fov;
+ kcam->fisheye_lens = fisheye_lens;
+ kcam->equirectangular_range = make_float4(longitude_min - longitude_max,
+ -longitude_min,
+ latitude_min - latitude_max,
+ -latitude_min + M_PI_2_F);
+
+ switch (stereo_eye) {
+ case STEREO_LEFT:
+ kcam->interocular_offset = -interocular_distance * 0.5f;
+ break;
+ case STEREO_RIGHT:
+ kcam->interocular_offset = interocular_distance * 0.5f;
+ break;
+ case STEREO_NONE:
+ default:
+ kcam->interocular_offset = 0.0f;
+ break;
+ }
+
+ kcam->convergence_distance = convergence_distance;
+ if (use_pole_merge) {
+ kcam->pole_merge_angle_from = pole_merge_angle_from;
+ kcam->pole_merge_angle_to = pole_merge_angle_to;
+ }
+ else {
+ kcam->pole_merge_angle_from = -1.0f;
+ kcam->pole_merge_angle_to = -1.0f;
+ }
+
+ /* sensor size */
+ kcam->sensorwidth = sensorwidth;
+ kcam->sensorheight = sensorheight;
+
+ /* render size */
+ kcam->width = width;
+ kcam->height = height;
+ kcam->resolution = resolution;
+
+ /* store differentials */
+ kcam->dx = float3_to_float4(dx);
+ kcam->dy = float3_to_float4(dy);
+
+ /* clipping */
+ kcam->nearclip = nearclip;
+ kcam->cliplength = (farclip == FLT_MAX) ? FLT_MAX : farclip - nearclip;
+
+ /* Camera in volume. */
+ kcam->is_inside_volume = 0;
+
+ /* Rolling shutter effect */
+ kcam->rolling_shutter_type = rolling_shutter_type;
+ kcam->rolling_shutter_duration = rolling_shutter_duration;
+
+ /* Set further update flags */
+ need_update = false;
+ need_device_update = true;
+ need_flags_update = true;
+ previous_need_motion = need_motion;
}
-void Camera::device_update(Device * /* device */,
- DeviceScene *dscene,
- Scene *scene)
+void Camera::device_update(Device * /* device */, DeviceScene *dscene, Scene *scene)
{
- update(scene);
-
- if(!need_device_update)
- return;
-
- scene->lookup_tables->remove_table(&shutter_table_offset);
- if(kernel_camera.shuttertime != -1.0f) {
- vector<float> shutter_table;
- util_cdf_inverted(SHUTTER_TABLE_SIZE,
- 0.0f,
- 1.0f,
- function_bind(shutter_curve_eval, _1, shutter_curve),
- false,
- shutter_table);
- shutter_table_offset = scene->lookup_tables->add_table(dscene,
- shutter_table);
- kernel_camera.shutter_table_offset = (int)shutter_table_offset;
- }
-
- dscene->data.cam = kernel_camera;
-
- size_t num_motion_steps = kernel_camera_motion.size();
- if(num_motion_steps) {
- DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps);
- memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps);
- dscene->camera_motion.copy_to_device();
- }
- else {
- dscene->camera_motion.free();
- }
+ update(scene);
+
+ if (!need_device_update)
+ return;
+
+ scene->lookup_tables->remove_table(&shutter_table_offset);
+ if (kernel_camera.shuttertime != -1.0f) {
+ vector<float> shutter_table;
+ util_cdf_inverted(SHUTTER_TABLE_SIZE,
+ 0.0f,
+ 1.0f,
+ function_bind(shutter_curve_eval, _1, shutter_curve),
+ false,
+ shutter_table);
+ shutter_table_offset = scene->lookup_tables->add_table(dscene, shutter_table);
+ kernel_camera.shutter_table_offset = (int)shutter_table_offset;
+ }
+
+ dscene->data.cam = kernel_camera;
+
+ size_t num_motion_steps = kernel_camera_motion.size();
+ if (num_motion_steps) {
+ DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps);
+ memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps);
+ dscene->camera_motion.copy_to_device();
+ }
+ else {
+ dscene->camera_motion.free();
+ }
}
-void Camera::device_update_volume(Device * /*device*/,
- DeviceScene *dscene,
- Scene *scene)
+void Camera::device_update_volume(Device * /*device*/, DeviceScene *dscene, Scene *scene)
{
- if(!need_device_update && !need_flags_update) {
- return;
- }
- KernelCamera *kcam = &dscene->data.cam;
- BoundBox viewplane_boundbox = viewplane_bounds_get();
- for(size_t i = 0; i < scene->objects.size(); ++i) {
- Object *object = scene->objects[i];
- if(object->mesh->has_volume &&
- viewplane_boundbox.intersects(object->bounds))
- {
- /* TODO(sergey): Consider adding more grained check. */
- VLOG(1) << "Detected camera inside volume.";
- kcam->is_inside_volume = 1;
- break;
- }
- }
- if(!kcam->is_inside_volume) {
- VLOG(1) << "Camera is outside of the volume.";
- }
- need_device_update = false;
- need_flags_update = false;
+ if (!need_device_update && !need_flags_update) {
+ return;
+ }
+ KernelCamera *kcam = &dscene->data.cam;
+ BoundBox viewplane_boundbox = viewplane_bounds_get();
+ for (size_t i = 0; i < scene->objects.size(); ++i) {
+ Object *object = scene->objects[i];
+ if (object->mesh->has_volume && viewplane_boundbox.intersects(object->bounds)) {
+ /* TODO(sergey): Consider adding more grained check. */
+ VLOG(1) << "Detected camera inside volume.";
+ kcam->is_inside_volume = 1;
+ break;
+ }
+ }
+ if (!kcam->is_inside_volume) {
+ VLOG(1) << "Camera is outside of the volume.";
+ }
+ need_device_update = false;
+ need_flags_update = false;
}
-void Camera::device_free(Device * /*device*/,
- DeviceScene *dscene,
- Scene *scene)
+void Camera::device_free(Device * /*device*/, DeviceScene *dscene, Scene *scene)
{
- scene->lookup_tables->remove_table(&shutter_table_offset);
- dscene->camera_motion.free();
+ scene->lookup_tables->remove_table(&shutter_table_offset);
+ dscene->camera_motion.free();
}
-bool Camera::modified(const Camera& cam)
+bool Camera::modified(const Camera &cam)
{
- return !Node::equals(cam);
+ return !Node::equals(cam);
}
-bool Camera::motion_modified(const Camera& cam)
+bool Camera::motion_modified(const Camera &cam)
{
- return !((motion == cam.motion) &&
- (use_perspective_motion == cam.use_perspective_motion));
+ return !((motion == cam.motion) && (use_perspective_motion == cam.use_perspective_motion));
}
void Camera::tag_update()
{
- need_update = true;
+ need_update = true;
}
float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
{
- float3 D, P;
- if(type == CAMERA_PERSPECTIVE) {
- D = transform_perspective(&rastertocamera,
- make_float3(raster_x, raster_y, 0.0f));
- float3 Pclip = normalize(D);
- P = make_float3(0.0f, 0.0f, 0.0f);
- /* TODO(sergey): Aperture support? */
- P = transform_point(&cameratoworld, P);
- D = normalize(transform_direction(&cameratoworld, D));
- /* TODO(sergey): Clipping is conditional in kernel, and hence it could
- * be mistakes in here, currently leading to wrong camera-in-volume
- * detection.
- */
- P += nearclip * D / Pclip.z;
- }
- else if(type == CAMERA_ORTHOGRAPHIC) {
- D = make_float3(0.0f, 0.0f, 1.0f);
- /* TODO(sergey): Aperture support? */
- P = transform_perspective(&rastertocamera,
- make_float3(raster_x, raster_y, 0.0f));
- P = transform_point(&cameratoworld, P);
- D = normalize(transform_direction(&cameratoworld, D));
- }
- else {
- assert(!"unsupported camera type");
- }
- return P;
+ float3 D, P;
+ if (type == CAMERA_PERSPECTIVE) {
+ D = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ float3 Pclip = normalize(D);
+ P = make_float3(0.0f, 0.0f, 0.0f);
+ /* TODO(sergey): Aperture support? */
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
+ /* TODO(sergey): Clipping is conditional in kernel, and hence it could
+ * be mistakes in here, currently leading to wrong camera-in-volume
+ * detection.
+ */
+ P += nearclip * D / Pclip.z;
+ }
+ else if (type == CAMERA_ORTHOGRAPHIC) {
+ D = make_float3(0.0f, 0.0f, 1.0f);
+ /* TODO(sergey): Aperture support? */
+ P = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
+ P = transform_point(&cameratoworld, P);
+ D = normalize(transform_direction(&cameratoworld, D));
+ }
+ else {
+ assert(!"unsupported camera type");
+ }
+ return P;
}
BoundBox Camera::viewplane_bounds_get()
{
- /* TODO(sergey): This is all rather stupid, but is there a way to perform
- * checks we need in a more clear and smart fasion?
- */
- BoundBox bounds = BoundBox::empty;
-
- if(type == CAMERA_PANORAMA) {
- if(use_spherical_stereo == false) {
- bounds.grow(make_float3(cameratoworld.x.w,
- cameratoworld.y.w,
- cameratoworld.z.w));
- }
- else {
- float half_eye_distance = interocular_distance * 0.5f;
-
- bounds.grow(make_float3(cameratoworld.x.w + half_eye_distance,
- cameratoworld.y.w,
- cameratoworld.z.w));
-
- bounds.grow(make_float3(cameratoworld.z.w,
- cameratoworld.y.w + half_eye_distance,
- cameratoworld.z.w));
-
- bounds.grow(make_float3(cameratoworld.x.w - half_eye_distance,
- cameratoworld.y.w,
- cameratoworld.z.w));
-
- bounds.grow(make_float3(cameratoworld.x.w,
- cameratoworld.y.w - half_eye_distance,
- cameratoworld.z.w));
- }
- }
- else {
- bounds.grow(transform_raster_to_world(0.0f, 0.0f));
- bounds.grow(transform_raster_to_world(0.0f, (float)height));
- bounds.grow(transform_raster_to_world((float)width, (float)height));
- bounds.grow(transform_raster_to_world((float)width, 0.0f));
- if(type == CAMERA_PERSPECTIVE) {
- /* Center point has the most distance in local Z axis,
- * use it to construct bounding box/
- */
- bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
- }
- }
- return bounds;
+ /* TODO(sergey): This is all rather stupid, but is there a way to perform
+ * checks we need in a more clear and smart fasion?
+ */
+ BoundBox bounds = BoundBox::empty;
+
+ if (type == CAMERA_PANORAMA) {
+ if (use_spherical_stereo == false) {
+ bounds.grow(make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w));
+ }
+ else {
+ float half_eye_distance = interocular_distance * 0.5f;
+
+ bounds.grow(make_float3(
+ cameratoworld.x.w + half_eye_distance, cameratoworld.y.w, cameratoworld.z.w));
+
+ bounds.grow(make_float3(
+ cameratoworld.z.w, cameratoworld.y.w + half_eye_distance, cameratoworld.z.w));
+
+ bounds.grow(make_float3(
+ cameratoworld.x.w - half_eye_distance, cameratoworld.y.w, cameratoworld.z.w));
+
+ bounds.grow(make_float3(
+ cameratoworld.x.w, cameratoworld.y.w - half_eye_distance, cameratoworld.z.w));
+ }
+ }
+ else {
+ bounds.grow(transform_raster_to_world(0.0f, 0.0f));
+ bounds.grow(transform_raster_to_world(0.0f, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, (float)height));
+ bounds.grow(transform_raster_to_world((float)width, 0.0f));
+ if (type == CAMERA_PERSPECTIVE) {
+ /* Center point has the most distance in local Z axis,
+ * use it to construct bounding box/
+ */
+ bounds.grow(transform_raster_to_world(0.5f * width, 0.5f * height));
+ }
+ }
+ return bounds;
}
float Camera::world_to_raster_size(float3 P)
{
- float res = 1.0f;
-
- if(type == CAMERA_ORTHOGRAPHIC) {
- res = min(len(full_dx), len(full_dy));
-
- if(offscreen_dicing_scale > 1.0f) {
- float3 p = transform_point(&worldtocamera, P);
- float3 v = transform_perspective(&full_rastertocamera, make_float3(full_width, full_height, 0.0f));
-
- /* Create point clamped to frustum */
- float3 c;
- c.x = max(-v.x, min(v.x, p.x));
- c.y = max(-v.y, min(v.y, p.y));
- c.z = max(0.0f, p.z);
-
- float f_dist = len(p - c) / sqrtf((v.x*v.x+v.y*v.y)*0.5f);
-
- if(f_dist > 0.0f) {
- res += res * f_dist * (offscreen_dicing_scale - 1.0f);
- }
- }
- }
- else if(type == CAMERA_PERSPECTIVE) {
- /* Calculate as if point is directly ahead of the camera. */
- float3 raster = make_float3(0.5f*full_width, 0.5f*full_height, 0.0f);
- float3 Pcamera = transform_perspective(&full_rastertocamera, raster);
-
- /* dDdx */
- float3 Ddiff = transform_direction(&cameratoworld, Pcamera);
- float3 dx = len_squared(full_dx) < len_squared(full_dy) ? full_dx : full_dy;
- float3 dDdx = normalize(Ddiff + dx) - normalize(Ddiff);
-
- /* dPdx */
- float dist = len(transform_point(&worldtocamera, P));
- float3 D = normalize(Ddiff);
- res = len(dist*dDdx - dot(dist*dDdx, D)*D);
-
- /* Decent approx distance to frustum (doesn't handle corners correctly, but not that big of a deal) */
- float f_dist = 0.0f;
-
- if(offscreen_dicing_scale > 1.0f) {
- float3 p = transform_point(&worldtocamera, P);
-
- /* Distance from the four planes */
- float r = dot(p, frustum_right_normal);
- float t = dot(p, frustum_top_normal);
- p = make_float3(-p.x, -p.y, p.z);
- float l = dot(p, frustum_right_normal);
- float b = dot(p, frustum_top_normal);
- p = make_float3(-p.x, -p.y, p.z);
-
- if(r <= 0.0f && l <= 0.0f && t <= 0.0f && b <= 0.0f) {
- /* Point is inside frustum */
- f_dist = 0.0f;
- }
- else if(r > 0.0f && l > 0.0f && t > 0.0f && b > 0.0f) {
- /* Point is behind frustum */
- f_dist = len(p);
- }
- else {
- /* Point may be behind or off to the side, need to check */
- float3 along_right = make_float3(-frustum_right_normal.z, 0.0f, frustum_right_normal.x);
- float3 along_left = make_float3(frustum_right_normal.z, 0.0f, frustum_right_normal.x);
- float3 along_top = make_float3(0.0f, -frustum_top_normal.z, frustum_top_normal.y);
- float3 along_bottom = make_float3(0.0f, frustum_top_normal.z, frustum_top_normal.y);
-
- float dist[] = {r, l, t, b};
- float3 along[] = {along_right, along_left, along_top, along_bottom};
-
- bool test_o = false;
-
- float *d = dist;
- float3 *a = along;
- for(int i = 0; i < 4; i++, d++, a++) {
- /* Test if we should check this side at all */
- if(*d > 0.0f) {
- if(dot(p, *a) >= 0.0f) {
- /* We are in front of the back edge of this side of the frustum */
- f_dist = max(f_dist, *d);
- }
- else {
- /* Possibly far enough behind the frustum to use distance to origin instead of edge */
- test_o = true;
- }
- }
- }
-
- if(test_o) {
- f_dist = (f_dist > 0) ? min(f_dist, len(p)) : len(p);
- }
- }
-
- if(f_dist > 0.0f) {
- res += len(dDdx - dot(dDdx, D)*D) * f_dist * (offscreen_dicing_scale - 1.0f);
- }
- }
- }
- else if(type == CAMERA_PANORAMA) {
- float3 D = transform_point(&worldtocamera, P);
- float dist = len(D);
-
- Ray ray = {{0}};
-
- /* Distortion can become so great that the results become meaningless, there
- * may be a better way to do this, but calculating differentials from the
- * point directly ahead seems to produce good enough results. */
+ float res = 1.0f;
+
+ if (type == CAMERA_ORTHOGRAPHIC) {
+ res = min(len(full_dx), len(full_dy));
+
+ if (offscreen_dicing_scale > 1.0f) {
+ float3 p = transform_point(&worldtocamera, P);
+ float3 v = transform_perspective(&full_rastertocamera,
+ make_float3(full_width, full_height, 0.0f));
+
+ /* Create point clamped to frustum */
+ float3 c;
+ c.x = max(-v.x, min(v.x, p.x));
+ c.y = max(-v.y, min(v.y, p.y));
+ c.z = max(0.0f, p.z);
+
+ float f_dist = len(p - c) / sqrtf((v.x * v.x + v.y * v.y) * 0.5f);
+
+ if (f_dist > 0.0f) {
+ res += res * f_dist * (offscreen_dicing_scale - 1.0f);
+ }
+ }
+ }
+ else if (type == CAMERA_PERSPECTIVE) {
+ /* Calculate as if point is directly ahead of the camera. */
+ float3 raster = make_float3(0.5f * full_width, 0.5f * full_height, 0.0f);
+ float3 Pcamera = transform_perspective(&full_rastertocamera, raster);
+
+ /* dDdx */
+ float3 Ddiff = transform_direction(&cameratoworld, Pcamera);
+ float3 dx = len_squared(full_dx) < len_squared(full_dy) ? full_dx : full_dy;
+ float3 dDdx = normalize(Ddiff + dx) - normalize(Ddiff);
+
+ /* dPdx */
+ float dist = len(transform_point(&worldtocamera, P));
+ float3 D = normalize(Ddiff);
+ res = len(dist * dDdx - dot(dist * dDdx, D) * D);
+
+ /* Decent approx distance to frustum (doesn't handle corners correctly, but not that big of a deal) */
+ float f_dist = 0.0f;
+
+ if (offscreen_dicing_scale > 1.0f) {
+ float3 p = transform_point(&worldtocamera, P);
+
+ /* Distance from the four planes */
+ float r = dot(p, frustum_right_normal);
+ float t = dot(p, frustum_top_normal);
+ p = make_float3(-p.x, -p.y, p.z);
+ float l = dot(p, frustum_right_normal);
+ float b = dot(p, frustum_top_normal);
+ p = make_float3(-p.x, -p.y, p.z);
+
+ if (r <= 0.0f && l <= 0.0f && t <= 0.0f && b <= 0.0f) {
+ /* Point is inside frustum */
+ f_dist = 0.0f;
+ }
+ else if (r > 0.0f && l > 0.0f && t > 0.0f && b > 0.0f) {
+ /* Point is behind frustum */
+ f_dist = len(p);
+ }
+ else {
+ /* Point may be behind or off to the side, need to check */
+ float3 along_right = make_float3(-frustum_right_normal.z, 0.0f, frustum_right_normal.x);
+ float3 along_left = make_float3(frustum_right_normal.z, 0.0f, frustum_right_normal.x);
+ float3 along_top = make_float3(0.0f, -frustum_top_normal.z, frustum_top_normal.y);
+ float3 along_bottom = make_float3(0.0f, frustum_top_normal.z, frustum_top_normal.y);
+
+ float dist[] = {r, l, t, b};
+ float3 along[] = {along_right, along_left, along_top, along_bottom};
+
+ bool test_o = false;
+
+ float *d = dist;
+ float3 *a = along;
+ for (int i = 0; i < 4; i++, d++, a++) {
+ /* Test if we should check this side at all */
+ if (*d > 0.0f) {
+ if (dot(p, *a) >= 0.0f) {
+ /* We are in front of the back edge of this side of the frustum */
+ f_dist = max(f_dist, *d);
+ }
+ else {
+ /* Possibly far enough behind the frustum to use distance to origin instead of edge */
+ test_o = true;
+ }
+ }
+ }
+
+ if (test_o) {
+ f_dist = (f_dist > 0) ? min(f_dist, len(p)) : len(p);
+ }
+ }
+
+ if (f_dist > 0.0f) {
+ res += len(dDdx - dot(dDdx, D) * D) * f_dist * (offscreen_dicing_scale - 1.0f);
+ }
+ }
+ }
+ else if (type == CAMERA_PANORAMA) {
+ float3 D = transform_point(&worldtocamera, P);
+ float dist = len(D);
+
+ Ray ray = {{0}};
+
+ /* Distortion can become so great that the results become meaningless, there
+ * may be a better way to do this, but calculating differentials from the
+ * point directly ahead seems to produce good enough results. */
#if 0
- float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D));
- float3 raster = transform_perspective(&full_cameratoraster, make_float3(dir.x, dir.y, 0.0f));
-
- ray.t = 1.0f;
- camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray);
- if(ray.t == 0.0f) {
- /* No differentials, just use from directly ahead. */
- camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*full_width, 0.5f*full_height, 0.0f, 0.0f, &ray);
- }
+ float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D));
+ float3 raster = transform_perspective(&full_cameratoraster, make_float3(dir.x, dir.y, 0.0f));
+
+ ray.t = 1.0f;
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray);
+ if(ray.t == 0.0f) {
+ /* No differentials, just use from directly ahead. */
+ camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*full_width, 0.5f*full_height, 0.0f, 0.0f, &ray);
+ }
#else
- camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*full_width, 0.5f*full_height, 0.0f, 0.0f, &ray);
+ camera_sample_panorama(&kernel_camera,
+ kernel_camera_motion.data(),
+ 0.5f * full_width,
+ 0.5f * full_height,
+ 0.0f,
+ 0.0f,
+ &ray);
#endif
- differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist);
+ differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist);
- return max(len(ray.dP.dx),len(ray.dP.dy));
- }
+ return max(len(ray.dP.dx), len(ray.dP.dy));
+ }
- return res;
+ return res;
}
bool Camera::use_motion() const
{
- return motion.size() > 1;
+ return motion.size() > 1;
}
float Camera::motion_time(int step) const
{
- return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
+ return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
}
int Camera::motion_step(float time) const
{
- if(use_motion()) {
- for(int step = 0; step < motion.size(); step++) {
- if(time == motion_time(step)) {
- return step;
- }
- }
- }
-
- return -1;
+ if (use_motion()) {
+ for (int step = 0; step < motion.size(); step++) {
+ if (time == motion_time(step)) {
+ return step;
+ }
+ }
+ }
+
+ return -1;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 961e8f918ea..0e91fa44a5b 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -40,179 +40,179 @@ class Scene;
*/
class Camera : public Node {
-public:
- NODE_DECLARE
-
- /* Specifies an offset for the shutter's time interval. */
- enum MotionPosition {
- /* Shutter opens at the current frame. */
- MOTION_POSITION_START = 0,
- /* Shutter is fully open at the current frame. */
- MOTION_POSITION_CENTER = 1,
- /* Shutter closes at the current frame. */
- MOTION_POSITION_END = 2,
-
- MOTION_NUM_POSITIONS,
- };
-
- /* Specifies rolling shutter effect. */
- enum RollingShutterType {
- /* No rolling shutter effect. */
- ROLLING_SHUTTER_NONE = 0,
- /* Sensor is being scanned vertically from top to bottom. */
- ROLLING_SHUTTER_TOP = 1,
-
- ROLLING_SHUTTER_NUM_TYPES,
- };
-
- /* Stereo Type */
- enum StereoEye {
- STEREO_NONE,
- STEREO_LEFT,
- STEREO_RIGHT,
- };
-
- /* motion blur */
- float shuttertime;
- MotionPosition motion_position;
- array<float> shutter_curve;
- size_t shutter_table_offset;
-
- /* ** Rolling shutter effect. ** */
- /* Defines rolling shutter effect type. */
- RollingShutterType rolling_shutter_type;
- /* Specifies exposure time of scanlines when using
- * rolling shutter effect.
- */
- float rolling_shutter_duration;
-
- /* depth of field */
- float focaldistance;
- float aperturesize;
- uint blades;
- float bladesrotation;
-
- /* type */
- CameraType type;
- float fov;
-
- /* panorama */
- PanoramaType panorama_type;
- float fisheye_fov;
- float fisheye_lens;
- float latitude_min;
- float latitude_max;
- float longitude_min;
- float longitude_max;
-
- /* panorama stereo */
- StereoEye stereo_eye;
- bool use_spherical_stereo;
- float interocular_distance;
- float convergence_distance;
- bool use_pole_merge;
- float pole_merge_angle_from;
- float pole_merge_angle_to;
-
- /* anamorphic lens bokeh */
- float aperture_ratio;
-
- /* sensor */
- float sensorwidth;
- float sensorheight;
-
- /* clipping */
- float nearclip;
- float farclip;
-
- /* screen */
- int width, height;
- int resolution;
- BoundBox2D viewplane;
- /* width and height change during preview, so we need these for calculating dice rates. */
- int full_width, full_height;
- /* controls how fast the dicing rate falls off for geometry out side of view */
- float offscreen_dicing_scale;
-
- /* border */
- BoundBox2D border;
- BoundBox2D viewport_camera_border;
-
- /* transformation */
- Transform matrix;
-
- /* motion */
- array<Transform> motion;
- bool use_perspective_motion;
- float fov_pre, fov_post;
-
- /* computed camera parameters */
- ProjectionTransform screentoworld;
- ProjectionTransform rastertoworld;
- ProjectionTransform ndctoworld;
- Transform cameratoworld;
-
- ProjectionTransform worldtoraster;
- ProjectionTransform worldtoscreen;
- ProjectionTransform worldtondc;
- Transform worldtocamera;
-
- ProjectionTransform rastertocamera;
- ProjectionTransform cameratoraster;
-
- ProjectionTransform full_rastertocamera;
-
- float3 dx;
- float3 dy;
-
- float3 full_dx;
- float3 full_dy;
-
- float3 frustum_right_normal;
- float3 frustum_top_normal;
-
- /* update */
- bool need_update;
- bool need_device_update;
- bool need_flags_update;
- int previous_need_motion;
-
- /* Kernel camera data, copied here for dicing. */
- KernelCamera kernel_camera;
- array<DecomposedTransform> kernel_camera_motion;
-
- /* functions */
- Camera();
- ~Camera();
-
- void compute_auto_viewplane();
-
- void update(Scene *scene);
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
-
- bool modified(const Camera& cam);
- bool motion_modified(const Camera& cam);
- void tag_update();
-
- /* Public utility functions. */
- BoundBox viewplane_bounds_get();
-
- /* Calculates the width of a pixel at point in world space. */
- float world_to_raster_size(float3 P);
-
- /* Motion blur. */
- float motion_time(int step) const;
- int motion_step(float time) const;
- bool use_motion() const;
-
-private:
- /* Private utility functions. */
- float3 transform_raster_to_world(float raster_x, float raster_y);
+ public:
+ NODE_DECLARE
+
+ /* Specifies an offset for the shutter's time interval. */
+ enum MotionPosition {
+ /* Shutter opens at the current frame. */
+ MOTION_POSITION_START = 0,
+ /* Shutter is fully open at the current frame. */
+ MOTION_POSITION_CENTER = 1,
+ /* Shutter closes at the current frame. */
+ MOTION_POSITION_END = 2,
+
+ MOTION_NUM_POSITIONS,
+ };
+
+ /* Specifies rolling shutter effect. */
+ enum RollingShutterType {
+ /* No rolling shutter effect. */
+ ROLLING_SHUTTER_NONE = 0,
+ /* Sensor is being scanned vertically from top to bottom. */
+ ROLLING_SHUTTER_TOP = 1,
+
+ ROLLING_SHUTTER_NUM_TYPES,
+ };
+
+ /* Stereo Type */
+ enum StereoEye {
+ STEREO_NONE,
+ STEREO_LEFT,
+ STEREO_RIGHT,
+ };
+
+ /* motion blur */
+ float shuttertime;
+ MotionPosition motion_position;
+ array<float> shutter_curve;
+ size_t shutter_table_offset;
+
+ /* ** Rolling shutter effect. ** */
+ /* Defines rolling shutter effect type. */
+ RollingShutterType rolling_shutter_type;
+ /* Specifies exposure time of scanlines when using
+ * rolling shutter effect.
+ */
+ float rolling_shutter_duration;
+
+ /* depth of field */
+ float focaldistance;
+ float aperturesize;
+ uint blades;
+ float bladesrotation;
+
+ /* type */
+ CameraType type;
+ float fov;
+
+ /* panorama */
+ PanoramaType panorama_type;
+ float fisheye_fov;
+ float fisheye_lens;
+ float latitude_min;
+ float latitude_max;
+ float longitude_min;
+ float longitude_max;
+
+ /* panorama stereo */
+ StereoEye stereo_eye;
+ bool use_spherical_stereo;
+ float interocular_distance;
+ float convergence_distance;
+ bool use_pole_merge;
+ float pole_merge_angle_from;
+ float pole_merge_angle_to;
+
+ /* anamorphic lens bokeh */
+ float aperture_ratio;
+
+ /* sensor */
+ float sensorwidth;
+ float sensorheight;
+
+ /* clipping */
+ float nearclip;
+ float farclip;
+
+ /* screen */
+ int width, height;
+ int resolution;
+ BoundBox2D viewplane;
+ /* width and height change during preview, so we need these for calculating dice rates. */
+ int full_width, full_height;
+ /* controls how fast the dicing rate falls off for geometry out side of view */
+ float offscreen_dicing_scale;
+
+ /* border */
+ BoundBox2D border;
+ BoundBox2D viewport_camera_border;
+
+ /* transformation */
+ Transform matrix;
+
+ /* motion */
+ array<Transform> motion;
+ bool use_perspective_motion;
+ float fov_pre, fov_post;
+
+ /* computed camera parameters */
+ ProjectionTransform screentoworld;
+ ProjectionTransform rastertoworld;
+ ProjectionTransform ndctoworld;
+ Transform cameratoworld;
+
+ ProjectionTransform worldtoraster;
+ ProjectionTransform worldtoscreen;
+ ProjectionTransform worldtondc;
+ Transform worldtocamera;
+
+ ProjectionTransform rastertocamera;
+ ProjectionTransform cameratoraster;
+
+ ProjectionTransform full_rastertocamera;
+
+ float3 dx;
+ float3 dy;
+
+ float3 full_dx;
+ float3 full_dy;
+
+ float3 frustum_right_normal;
+ float3 frustum_top_normal;
+
+ /* update */
+ bool need_update;
+ bool need_device_update;
+ bool need_flags_update;
+ int previous_need_motion;
+
+ /* Kernel camera data, copied here for dicing. */
+ KernelCamera kernel_camera;
+ array<DecomposedTransform> kernel_camera_motion;
+
+ /* functions */
+ Camera();
+ ~Camera();
+
+ void compute_auto_viewplane();
+
+ void update(Scene *scene);
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_volume(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+
+ bool modified(const Camera &cam);
+ bool motion_modified(const Camera &cam);
+ void tag_update();
+
+ /* Public utility functions. */
+ BoundBox viewplane_bounds_get();
+
+ /* Calculates the width of a pixel at point in world space. */
+ float world_to_raster_size(float3 P);
+
+ /* Motion blur. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+ bool use_motion() const;
+
+ private:
+ /* Private utility functions. */
+ float3 transform_raster_to_world(float raster_x, float raster_y);
};
CCL_NAMESPACE_END
-#endif /* __CAMERA_H__ */
+#endif /* __CAMERA_H__ */
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
index 98c3e99996c..e475ff60eef 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -22,371 +22,374 @@
CCL_NAMESPACE_BEGIN
-ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene)
-: graph(graph), node(node), output(output), scene(scene)
+ConstantFolder::ConstantFolder(ShaderGraph *graph,
+ ShaderNode *node,
+ ShaderOutput *output,
+ Scene *scene)
+ : graph(graph), node(node), output(output), scene(scene)
{
}
bool ConstantFolder::all_inputs_constant() const
{
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- return false;
- }
- }
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
void ConstantFolder::make_constant(float value) const
{
- VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant (" << value << ").";
+ VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant (" << value
+ << ").";
- foreach(ShaderInput *sock, output->links) {
- sock->set(value);
- }
+ foreach (ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
- graph->disconnect(output);
+ graph->disconnect(output);
}
void ConstantFolder::make_constant(float3 value) const
{
- VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant " << value << ".";
+ VLOG(1) << "Folding " << node->name << "::" << output->name() << " to constant " << value << ".";
- foreach(ShaderInput *sock, output->links) {
- sock->set(value);
- }
+ foreach (ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
- graph->disconnect(output);
+ graph->disconnect(output);
}
void ConstantFolder::make_constant_clamp(float value, bool clamp) const
{
- make_constant(clamp ? saturate(value) : value);
+ make_constant(clamp ? saturate(value) : value);
}
void ConstantFolder::make_constant_clamp(float3 value, bool clamp) const
{
- if(clamp) {
- value.x = saturate(value.x);
- value.y = saturate(value.y);
- value.z = saturate(value.z);
- }
+ if (clamp) {
+ value.x = saturate(value.x);
+ value.y = saturate(value.y);
+ value.z = saturate(value.z);
+ }
- make_constant(value);
+ make_constant(value);
}
void ConstantFolder::make_zero() const
{
- if(output->type() == SocketType::FLOAT) {
- make_constant(0.0f);
- }
- else if(SocketType::is_float3(output->type())) {
- make_constant(make_float3(0.0f, 0.0f, 0.0f));
- }
- else {
- assert(0);
- }
+ if (output->type() == SocketType::FLOAT) {
+ make_constant(0.0f);
+ }
+ else if (SocketType::is_float3(output->type())) {
+ make_constant(make_float3(0.0f, 0.0f, 0.0f));
+ }
+ else {
+ assert(0);
+ }
}
void ConstantFolder::make_one() const
{
- if(output->type() == SocketType::FLOAT) {
- make_constant(1.0f);
- }
- else if(SocketType::is_float3(output->type())) {
- make_constant(make_float3(1.0f, 1.0f, 1.0f));
- }
- else {
- assert(0);
- }
+ if (output->type() == SocketType::FLOAT) {
+ make_constant(1.0f);
+ }
+ else if (SocketType::is_float3(output->type())) {
+ make_constant(make_float3(1.0f, 1.0f, 1.0f));
+ }
+ else {
+ assert(0);
+ }
}
void ConstantFolder::bypass(ShaderOutput *new_output) const
{
- assert(new_output);
+ assert(new_output);
- VLOG(1) << "Folding " << node->name << "::" << output->name() << " to socket " << new_output->parent->name << "::" << new_output->name() << ".";
+ VLOG(1) << "Folding " << node->name << "::" << output->name() << " to socket "
+ << new_output->parent->name << "::" << new_output->name() << ".";
- /* Remove all outgoing links from socket and connect them to new_output instead.
- * The graph->relink method affects node inputs, so it's not safe to use in constant
- * folding if the node has multiple outputs and will thus be folded multiple times. */
- vector<ShaderInput*> outputs = output->links;
+ /* Remove all outgoing links from socket and connect them to new_output instead.
+ * The graph->relink method affects node inputs, so it's not safe to use in constant
+ * folding if the node has multiple outputs and will thus be folded multiple times. */
+ vector<ShaderInput *> outputs = output->links;
- graph->disconnect(output);
+ graph->disconnect(output);
- foreach(ShaderInput *sock, outputs) {
- graph->connect(new_output, sock);
- }
+ foreach (ShaderInput *sock, outputs) {
+ graph->connect(new_output, sock);
+ }
}
void ConstantFolder::discard() const
{
- assert(output->type() == SocketType::CLOSURE);
+ assert(output->type() == SocketType::CLOSURE);
- VLOG(1) << "Discarding closure " << node->name << ".";
+ VLOG(1) << "Discarding closure " << node->name << ".";
- graph->disconnect(output);
+ graph->disconnect(output);
}
void ConstantFolder::bypass_or_discard(ShaderInput *input) const
{
- assert(input->type() == SocketType::CLOSURE);
-
- if(input->link) {
- bypass(input->link);
- }
- else {
- discard();
- }
+ assert(input->type() == SocketType::CLOSURE);
+
+ if (input->link) {
+ bypass(input->link);
+ }
+ else {
+ discard();
+ }
}
bool ConstantFolder::try_bypass_or_make_constant(ShaderInput *input, bool clamp) const
{
- if(input->type() != output->type()) {
- return false;
- }
- else if(!input->link) {
- if(input->type() == SocketType::FLOAT) {
- make_constant_clamp(node->get_float(input->socket_type), clamp);
- return true;
- }
- else if(SocketType::is_float3(input->type())) {
- make_constant_clamp(node->get_float3(input->socket_type), clamp);
- return true;
- }
- }
- else if(!clamp) {
- bypass(input->link);
- return true;
- }
- else {
- /* disconnect other inputs if we can't fully bypass due to clamp */
- foreach(ShaderInput *other, node->inputs) {
- if(other != input && other->link) {
- graph->disconnect(other);
- }
- }
- }
-
- return false;
+ if (input->type() != output->type()) {
+ return false;
+ }
+ else if (!input->link) {
+ if (input->type() == SocketType::FLOAT) {
+ make_constant_clamp(node->get_float(input->socket_type), clamp);
+ return true;
+ }
+ else if (SocketType::is_float3(input->type())) {
+ make_constant_clamp(node->get_float3(input->socket_type), clamp);
+ return true;
+ }
+ }
+ else if (!clamp) {
+ bypass(input->link);
+ return true;
+ }
+ else {
+ /* disconnect other inputs if we can't fully bypass due to clamp */
+ foreach (ShaderInput *other, node->inputs) {
+ if (other != input && other->link) {
+ graph->disconnect(other);
+ }
+ }
+ }
+
+ return false;
}
bool ConstantFolder::is_zero(ShaderInput *input) const
{
- if(!input->link) {
- if(input->type() == SocketType::FLOAT) {
- return node->get_float(input->socket_type) == 0.0f;
- }
- else if(SocketType::is_float3(input->type())) {
- return node->get_float3(input->socket_type) ==
- make_float3(0.0f, 0.0f, 0.0f);
- }
- }
-
- return false;
+ if (!input->link) {
+ if (input->type() == SocketType::FLOAT) {
+ return node->get_float(input->socket_type) == 0.0f;
+ }
+ else if (SocketType::is_float3(input->type())) {
+ return node->get_float3(input->socket_type) == make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+
+ return false;
}
bool ConstantFolder::is_one(ShaderInput *input) const
{
- if(!input->link) {
- if(input->type() == SocketType::FLOAT) {
- return node->get_float(input->socket_type) == 1.0f;
- }
- else if(SocketType::is_float3(input->type())) {
- return node->get_float3(input->socket_type) ==
- make_float3(1.0f, 1.0f, 1.0f);
- }
- }
-
- return false;
+ if (!input->link) {
+ if (input->type() == SocketType::FLOAT) {
+ return node->get_float(input->socket_type) == 1.0f;
+ }
+ else if (SocketType::is_float3(input->type())) {
+ return node->get_float3(input->socket_type) == make_float3(1.0f, 1.0f, 1.0f);
+ }
+ }
+
+ return false;
}
/* Specific nodes */
void ConstantFolder::fold_mix(NodeMix type, bool clamp) const
{
- ShaderInput *fac_in = node->input("Fac");
- ShaderInput *color1_in = node->input("Color1");
- ShaderInput *color2_in = node->input("Color2");
-
- float fac = saturate(node->get_float(fac_in->socket_type));
- bool fac_is_zero = !fac_in->link && fac == 0.0f;
- bool fac_is_one = !fac_in->link && fac == 1.0f;
-
- /* remove no-op node when factor is 0.0 */
- if(fac_is_zero) {
- /* note that some of the modes will clamp out of bounds values even without use_clamp */
- if(!(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN)) {
- if(try_bypass_or_make_constant(color1_in, clamp)) {
- return;
- }
- }
- }
-
- switch(type) {
- case NODE_MIX_BLEND:
- /* remove useless mix colors nodes */
- if(color1_in->link && color2_in->link) {
- if(color1_in->link == color2_in->link) {
- try_bypass_or_make_constant(color1_in, clamp);
- break;
- }
- }
- else if(!color1_in->link && !color2_in->link) {
- float3 color1 = node->get_float3(color1_in->socket_type);
- float3 color2 = node->get_float3(color2_in->socket_type);
- if(color1 == color2) {
- try_bypass_or_make_constant(color1_in, clamp);
- break;
- }
- }
- /* remove no-op mix color node when factor is 1.0 */
- if(fac_is_one) {
- try_bypass_or_make_constant(color2_in, clamp);
- break;
- }
- break;
- case NODE_MIX_ADD:
- /* 0 + X (fac 1) == X */
- if(is_zero(color1_in) && fac_is_one) {
- try_bypass_or_make_constant(color2_in, clamp);
- }
- /* X + 0 (fac ?) == X */
- else if(is_zero(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- break;
- case NODE_MIX_SUB:
- /* X - 0 (fac ?) == X */
- if(is_zero(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- /* X - X (fac 1) == 0 */
- else if(color1_in->link && color1_in->link == color2_in->link && fac_is_one) {
- make_zero();
- }
- break;
- case NODE_MIX_MUL:
- /* X * 1 (fac ?) == X, 1 * X (fac 1) == X */
- if(is_one(color1_in) && fac_is_one) {
- try_bypass_or_make_constant(color2_in, clamp);
- }
- else if(is_one(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- /* 0 * ? (fac ?) == 0, ? * 0 (fac 1) == 0 */
- else if(is_zero(color1_in)) {
- make_zero();
- }
- else if(is_zero(color2_in) && fac_is_one) {
- make_zero();
- }
- break;
- case NODE_MIX_DIV:
- /* X / 1 (fac ?) == X */
- if(is_one(color2_in)) {
- try_bypass_or_make_constant(color1_in, clamp);
- }
- /* 0 / ? (fac ?) == 0 */
- else if(is_zero(color1_in)) {
- make_zero();
- }
- break;
- default:
- break;
- }
+ ShaderInput *fac_in = node->input("Fac");
+ ShaderInput *color1_in = node->input("Color1");
+ ShaderInput *color2_in = node->input("Color2");
+
+ float fac = saturate(node->get_float(fac_in->socket_type));
+ bool fac_is_zero = !fac_in->link && fac == 0.0f;
+ bool fac_is_one = !fac_in->link && fac == 1.0f;
+
+ /* remove no-op node when factor is 0.0 */
+ if (fac_is_zero) {
+ /* note that some of the modes will clamp out of bounds values even without use_clamp */
+ if (!(type == NODE_MIX_LIGHT || type == NODE_MIX_DODGE || type == NODE_MIX_BURN)) {
+ if (try_bypass_or_make_constant(color1_in, clamp)) {
+ return;
+ }
+ }
+ }
+
+ switch (type) {
+ case NODE_MIX_BLEND:
+ /* remove useless mix colors nodes */
+ if (color1_in->link && color2_in->link) {
+ if (color1_in->link == color2_in->link) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ break;
+ }
+ }
+ else if (!color1_in->link && !color2_in->link) {
+ float3 color1 = node->get_float3(color1_in->socket_type);
+ float3 color2 = node->get_float3(color2_in->socket_type);
+ if (color1 == color2) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ break;
+ }
+ }
+ /* remove no-op mix color node when factor is 1.0 */
+ if (fac_is_one) {
+ try_bypass_or_make_constant(color2_in, clamp);
+ break;
+ }
+ break;
+ case NODE_MIX_ADD:
+ /* 0 + X (fac 1) == X */
+ if (is_zero(color1_in) && fac_is_one) {
+ try_bypass_or_make_constant(color2_in, clamp);
+ }
+ /* X + 0 (fac ?) == X */
+ else if (is_zero(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ break;
+ case NODE_MIX_SUB:
+ /* X - 0 (fac ?) == X */
+ if (is_zero(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ /* X - X (fac 1) == 0 */
+ else if (color1_in->link && color1_in->link == color2_in->link && fac_is_one) {
+ make_zero();
+ }
+ break;
+ case NODE_MIX_MUL:
+ /* X * 1 (fac ?) == X, 1 * X (fac 1) == X */
+ if (is_one(color1_in) && fac_is_one) {
+ try_bypass_or_make_constant(color2_in, clamp);
+ }
+ else if (is_one(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ /* 0 * ? (fac ?) == 0, ? * 0 (fac 1) == 0 */
+ else if (is_zero(color1_in)) {
+ make_zero();
+ }
+ else if (is_zero(color2_in) && fac_is_one) {
+ make_zero();
+ }
+ break;
+ case NODE_MIX_DIV:
+ /* X / 1 (fac ?) == X */
+ if (is_one(color2_in)) {
+ try_bypass_or_make_constant(color1_in, clamp);
+ }
+ /* 0 / ? (fac ?) == 0 */
+ else if (is_zero(color1_in)) {
+ make_zero();
+ }
+ break;
+ default:
+ break;
+ }
}
void ConstantFolder::fold_math(NodeMath type, bool clamp) const
{
- ShaderInput *value1_in = node->input("Value1");
- ShaderInput *value2_in = node->input("Value2");
-
- switch(type) {
- case NODE_MATH_ADD:
- /* X + 0 == 0 + X == X */
- if(is_zero(value1_in)) {
- try_bypass_or_make_constant(value2_in, clamp);
- }
- else if(is_zero(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- break;
- case NODE_MATH_SUBTRACT:
- /* X - 0 == X */
- if(is_zero(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- break;
- case NODE_MATH_MULTIPLY:
- /* X * 1 == 1 * X == X */
- if(is_one(value1_in)) {
- try_bypass_or_make_constant(value2_in, clamp);
- }
- else if(is_one(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- /* X * 0 == 0 * X == 0 */
- else if(is_zero(value1_in) || is_zero(value2_in)) {
- make_zero();
- }
- break;
- case NODE_MATH_DIVIDE:
- /* X / 1 == X */
- if(is_one(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- /* 0 / X == 0 */
- else if(is_zero(value1_in)) {
- make_zero();
- }
- break;
- case NODE_MATH_POWER:
- /* 1 ^ X == X ^ 0 == 1 */
- if(is_one(value1_in) || is_zero(value2_in)) {
- make_one();
- }
- /* X ^ 1 == X */
- else if(is_one(value2_in)) {
- try_bypass_or_make_constant(value1_in, clamp);
- }
- default:
- break;
- }
+ ShaderInput *value1_in = node->input("Value1");
+ ShaderInput *value2_in = node->input("Value2");
+
+ switch (type) {
+ case NODE_MATH_ADD:
+ /* X + 0 == 0 + X == X */
+ if (is_zero(value1_in)) {
+ try_bypass_or_make_constant(value2_in, clamp);
+ }
+ else if (is_zero(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ break;
+ case NODE_MATH_SUBTRACT:
+ /* X - 0 == X */
+ if (is_zero(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ break;
+ case NODE_MATH_MULTIPLY:
+ /* X * 1 == 1 * X == X */
+ if (is_one(value1_in)) {
+ try_bypass_or_make_constant(value2_in, clamp);
+ }
+ else if (is_one(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ /* X * 0 == 0 * X == 0 */
+ else if (is_zero(value1_in) || is_zero(value2_in)) {
+ make_zero();
+ }
+ break;
+ case NODE_MATH_DIVIDE:
+ /* X / 1 == X */
+ if (is_one(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ /* 0 / X == 0 */
+ else if (is_zero(value1_in)) {
+ make_zero();
+ }
+ break;
+ case NODE_MATH_POWER:
+ /* 1 ^ X == X ^ 0 == 1 */
+ if (is_one(value1_in) || is_zero(value2_in)) {
+ make_one();
+ }
+ /* X ^ 1 == X */
+ else if (is_one(value2_in)) {
+ try_bypass_or_make_constant(value1_in, clamp);
+ }
+ default:
+ break;
+ }
}
void ConstantFolder::fold_vector_math(NodeVectorMath type) const
{
- ShaderInput *vector1_in = node->input("Vector1");
- ShaderInput *vector2_in = node->input("Vector2");
-
- switch(type) {
- case NODE_VECTOR_MATH_ADD:
- /* X + 0 == 0 + X == X */
- if(is_zero(vector1_in)) {
- try_bypass_or_make_constant(vector2_in);
- }
- else if(is_zero(vector2_in)) {
- try_bypass_or_make_constant(vector1_in);
- }
- break;
- case NODE_VECTOR_MATH_SUBTRACT:
- /* X - 0 == X */
- if(is_zero(vector2_in)) {
- try_bypass_or_make_constant(vector1_in);
- }
- break;
- case NODE_VECTOR_MATH_DOT_PRODUCT:
- case NODE_VECTOR_MATH_CROSS_PRODUCT:
- /* X * 0 == 0 * X == 0 */
- if(is_zero(vector1_in) || is_zero(vector2_in)) {
- make_zero();
- }
- break;
- default:
- break;
- }
+ ShaderInput *vector1_in = node->input("Vector1");
+ ShaderInput *vector2_in = node->input("Vector2");
+
+ switch (type) {
+ case NODE_VECTOR_MATH_ADD:
+ /* X + 0 == 0 + X == X */
+ if (is_zero(vector1_in)) {
+ try_bypass_or_make_constant(vector2_in);
+ }
+ else if (is_zero(vector2_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
+ case NODE_VECTOR_MATH_SUBTRACT:
+ /* X - 0 == X */
+ if (is_zero(vector2_in)) {
+ try_bypass_or_make_constant(vector1_in);
+ }
+ break;
+ case NODE_VECTOR_MATH_DOT_PRODUCT:
+ case NODE_VECTOR_MATH_CROSS_PRODUCT:
+ /* X * 0 == 0 * X == 0 */
+ if (is_zero(vector1_in) || is_zero(vector2_in)) {
+ make_zero();
+ }
+ break;
+ default:
+ break;
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
index 6ec94b055e3..c14b94868dc 100644
--- a/intern/cycles/render/constant_fold.h
+++ b/intern/cycles/render/constant_fold.h
@@ -29,45 +29,45 @@ class ShaderNode;
class ShaderOutput;
class ConstantFolder {
-public:
- ShaderGraph *const graph;
- ShaderNode *const node;
- ShaderOutput *const output;
+ public:
+ ShaderGraph *const graph;
+ ShaderNode *const node;
+ ShaderOutput *const output;
- Scene *scene;
+ Scene *scene;
- ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene);
+ ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output, Scene *scene);
- bool all_inputs_constant() const;
+ bool all_inputs_constant() const;
- /* Constant folding helpers */
- void make_constant(float value) const;
- void make_constant(float3 value) const;
- void make_constant_clamp(float value, bool clamp) const;
- void make_constant_clamp(float3 value, bool clamp) const;
- void make_zero() const;
- void make_one() const;
+ /* Constant folding helpers */
+ void make_constant(float value) const;
+ void make_constant(float3 value) const;
+ void make_constant_clamp(float value, bool clamp) const;
+ void make_constant_clamp(float3 value, bool clamp) const;
+ void make_zero() const;
+ void make_one() const;
- /* Bypass node, relinking to another output socket. */
- void bypass(ShaderOutput *output) const;
+ /* Bypass node, relinking to another output socket. */
+ void bypass(ShaderOutput *output) const;
- /* For closure nodes, discard node entirely or bypass to one of its inputs. */
- void discard() const;
- void bypass_or_discard(ShaderInput *input) const;
+ /* For closure nodes, discard node entirely or bypass to one of its inputs. */
+ void discard() const;
+ void bypass_or_discard(ShaderInput *input) const;
- /* Bypass or make constant, unless we can't due to clamp being true. */
- bool try_bypass_or_make_constant(ShaderInput *input, bool clamp = false) const;
+ /* Bypass or make constant, unless we can't due to clamp being true. */
+ bool try_bypass_or_make_constant(ShaderInput *input, bool clamp = false) const;
- /* Test if shader inputs of the current nodes have fixed values. */
- bool is_zero(ShaderInput *input) const;
- bool is_one(ShaderInput *input) const;
+ /* Test if shader inputs of the current nodes have fixed values. */
+ bool is_zero(ShaderInput *input) const;
+ bool is_one(ShaderInput *input) const;
- /* Specific nodes. */
- void fold_mix(NodeMix type, bool clamp) const;
- void fold_math(NodeMath type, bool clamp) const;
- void fold_vector_math(NodeVectorMath type) const;
+ /* Specific nodes. */
+ void fold_mix(NodeMix type, bool clamp) const;
+ void fold_math(NodeMath type, bool clamp) const;
+ void fold_vector_math(NodeVectorMath type) const;
};
CCL_NAMESPACE_END
-#endif /* __CONSTANT_FOLD_H__ */
+#endif /* __CONSTANT_FOLD_H__ */
diff --git a/intern/cycles/render/coverage.cpp b/intern/cycles/render/coverage.cpp
index 72ef4cda3ff..0a29903728a 100644
--- a/intern/cycles/render/coverage.cpp
+++ b/intern/cycles/render/coverage.cpp
@@ -25,119 +25,128 @@
CCL_NAMESPACE_BEGIN
-static bool crypomatte_comp(const pair<float, float>& i, const pair<float, float> j) { return i.first > j.first; }
+static bool crypomatte_comp(const pair<float, float> &i, const pair<float, float> j)
+{
+ return i.first > j.first;
+}
void Coverage::finalize()
{
- int pass_offset = 0;
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- finalize_buffer(coverage_object, pass_offset);
- pass_offset += kernel_data.film.cryptomatte_depth * 4;
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- finalize_buffer(coverage_material, pass_offset);
- pass_offset += kernel_data.film.cryptomatte_depth * 4;
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- finalize_buffer(coverage_asset, pass_offset);
- }
+ int pass_offset = 0;
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ finalize_buffer(coverage_object, pass_offset);
+ pass_offset += kernel_data.film.cryptomatte_depth * 4;
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ finalize_buffer(coverage_material, pass_offset);
+ pass_offset += kernel_data.film.cryptomatte_depth * 4;
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ finalize_buffer(coverage_asset, pass_offset);
+ }
}
void Coverage::init_path_trace()
{
- kg->coverage_object = kg->coverage_material = kg->coverage_asset = NULL;
+ kg->coverage_object = kg->coverage_material = kg->coverage_asset = NULL;
- if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- coverage_object.clear();
- coverage_object.resize(tile.w * tile.h);
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- coverage_material.clear();
- coverage_material.resize(tile.w * tile.h);
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- coverage_asset.clear();
- coverage_asset.resize(tile.w * tile.h);
- }
- }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ coverage_object.clear();
+ coverage_object.resize(tile.w * tile.h);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ coverage_material.clear();
+ coverage_material.resize(tile.w * tile.h);
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ coverage_asset.clear();
+ coverage_asset.resize(tile.w * tile.h);
+ }
+ }
}
void Coverage::init_pixel(int x, int y)
{
- if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
- const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
- if(kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
- kg->coverage_object = &coverage_object[pixel_index];
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
- kg->coverage_material = &coverage_material[pixel_index];
- }
- if(kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
- kg->coverage_asset = &coverage_asset[pixel_index];
- }
- }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ const int pixel_index = tile.w * (y - tile.y) + x - tile.x;
+ if (kernel_data.film.cryptomatte_passes & CRYPT_OBJECT) {
+ kg->coverage_object = &coverage_object[pixel_index];
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_MATERIAL) {
+ kg->coverage_material = &coverage_material[pixel_index];
+ }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ASSET) {
+ kg->coverage_asset = &coverage_asset[pixel_index];
+ }
+ }
}
-void Coverage::finalize_buffer(vector<CoverageMap> & coverage, const int pass_offset)
+void Coverage::finalize_buffer(vector<CoverageMap> &coverage, const int pass_offset)
{
- if(kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
- flatten_buffer(coverage, pass_offset);
- }
- else {
- sort_buffer(pass_offset);
- }
+ if (kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE) {
+ flatten_buffer(coverage, pass_offset);
+ }
+ else {
+ sort_buffer(pass_offset);
+ }
}
void Coverage::flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset)
{
- /* Sort the coverage map and write it to the output */
- int pixel_index = 0;
- int pass_stride = tile.buffers->params.get_passes_size();
- for(int y = 0; y < tile.h; ++y) {
- for(int x = 0; x < tile.w; ++x) {
- const CoverageMap& pixel = coverage[pixel_index];
- if(!pixel.empty()) {
- /* buffer offset */
- int index = x + y * tile.stride;
- float *buffer = (float*)tile.buffer + index*pass_stride;
+ /* Sort the coverage map and write it to the output */
+ int pixel_index = 0;
+ int pass_stride = tile.buffers->params.get_passes_size();
+ for (int y = 0; y < tile.h; ++y) {
+ for (int x = 0; x < tile.w; ++x) {
+ const CoverageMap &pixel = coverage[pixel_index];
+ if (!pixel.empty()) {
+ /* buffer offset */
+ int index = x + y * tile.stride;
+ float *buffer = (float *)tile.buffer + index * pass_stride;
- /* sort the cryptomatte pixel */
- vector<pair<float, float> > sorted_pixel;
- for(CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
- sorted_pixel.push_back(std::make_pair(it->second, it->first));
- }
- sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
- int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
- if(sorted_pixel.size() > num_slots) {
- float leftover = 0.0f;
- for(vector<pair<float, float> >::iterator it = sorted_pixel.begin()+num_slots; it != sorted_pixel.end(); ++it) {
- leftover += it->first;
- }
- sorted_pixel[num_slots-1].first += leftover;
- }
- int limit = min(num_slots, sorted_pixel.size());
- for(int i = 0; i < limit; ++i) {
- kernel_write_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth), sorted_pixel[i].second, sorted_pixel[i].first);
- }
- }
- ++pixel_index;
- }
- }
+ /* sort the cryptomatte pixel */
+ vector<pair<float, float>> sorted_pixel;
+ for (CoverageMap::const_iterator it = pixel.begin(); it != pixel.end(); ++it) {
+ sorted_pixel.push_back(std::make_pair(it->second, it->first));
+ }
+ sort(sorted_pixel.begin(), sorted_pixel.end(), crypomatte_comp);
+ int num_slots = 2 * (kernel_data.film.cryptomatte_depth);
+ if (sorted_pixel.size() > num_slots) {
+ float leftover = 0.0f;
+ for (vector<pair<float, float>>::iterator it = sorted_pixel.begin() + num_slots;
+ it != sorted_pixel.end();
+ ++it) {
+ leftover += it->first;
+ }
+ sorted_pixel[num_slots - 1].first += leftover;
+ }
+ int limit = min(num_slots, sorted_pixel.size());
+ for (int i = 0; i < limit; ++i) {
+ kernel_write_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset,
+ 2 * (kernel_data.film.cryptomatte_depth),
+ sorted_pixel[i].second,
+ sorted_pixel[i].first);
+ }
+ }
+ ++pixel_index;
+ }
+ }
}
void Coverage::sort_buffer(const int pass_offset)
{
- /* Sort the coverage map and write it to the output */
- int pass_stride = tile.buffers->params.get_passes_size();
- for(int y = 0; y < tile.h; ++y) {
- for(int x = 0; x < tile.w; ++x) {
- /* buffer offset */
- int index = x + y*tile.stride;
- float *buffer = (float*)tile.buffer + index*pass_stride;
- kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset, 2 * (kernel_data.film.cryptomatte_depth));
- }
- }
+ /* Sort the coverage map and write it to the output */
+ int pass_stride = tile.buffers->params.get_passes_size();
+ for (int y = 0; y < tile.h; ++y) {
+ for (int x = 0; x < tile.w; ++x) {
+ /* buffer offset */
+ int index = x + y * tile.stride;
+ float *buffer = (float *)tile.buffer + index * pass_stride;
+ kernel_sort_id_slots(buffer + kernel_data.film.pass_cryptomatte + pass_offset,
+ 2 * (kernel_data.film.cryptomatte_depth));
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/coverage.h b/intern/cycles/render/coverage.h
index 9ee0bce7517..3d1f6a2b040 100644
--- a/intern/cycles/render/coverage.h
+++ b/intern/cycles/render/coverage.h
@@ -22,28 +22,30 @@
#include "util/util_vector.h"
#ifndef __COVERAGE_H__
-#define __COVERAGE_H__
+# define __COVERAGE_H__
CCL_NAMESPACE_BEGIN
class Coverage {
-public:
- Coverage(KernelGlobals *kg_, RenderTile &tile_) : kg(kg_), tile(tile_) { }
- void init_path_trace();
- void init_pixel(int x, int y);
- void finalize();
-private:
- vector<CoverageMap>coverage_object;
- vector<CoverageMap>coverage_material;
- vector<CoverageMap>coverage_asset;
- KernelGlobals *kg;
- RenderTile &tile;
- void finalize_buffer(vector<CoverageMap>&coverage, const int pass_offset);
- void flatten_buffer(vector<CoverageMap>&coverage, const int pass_offset);
- void sort_buffer(const int pass_offset);
-};
+ public:
+ Coverage(KernelGlobals *kg_, RenderTile &tile_) : kg(kg_), tile(tile_)
+ {
+ }
+ void init_path_trace();
+ void init_pixel(int x, int y);
+ void finalize();
+ private:
+ vector<CoverageMap> coverage_object;
+ vector<CoverageMap> coverage_material;
+ vector<CoverageMap> coverage_asset;
+ KernelGlobals *kg;
+ RenderTile &tile;
+ void finalize_buffer(vector<CoverageMap> &coverage, const int pass_offset);
+ void flatten_buffer(vector<CoverageMap> &coverage, const int pass_offset);
+ void sort_buffer(const int pass_offset);
+};
CCL_NAMESPACE_END
-#endif /* __COVERAGE_H__ */
+#endif /* __COVERAGE_H__ */
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index 58b71d3e122..49ab70541c2 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -31,72 +31,73 @@ CCL_NAMESPACE_BEGIN
void curvebounds(float *lower, float *upper, float3 *p, int dim)
{
- float *p0 = &p[0].x;
- float *p1 = &p[1].x;
- float *p2 = &p[2].x;
- float *p3 = &p[3].x;
-
- float fc = 0.71f;
- float curve_coef[4];
- curve_coef[0] = p1[dim];
- curve_coef[1] = -fc*p0[dim] + fc*p2[dim];
- curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] - fc * p3[dim];
- curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim];
-
- float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1];
- float ta = -1.0f;
- float tb = -1.0f;
-
- if(discroot >= 0) {
- discroot = sqrtf(discroot);
- ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
- tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
- ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta;
- tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb;
- }
-
- *upper = max(p1[dim],p2[dim]);
- *lower = min(p1[dim],p2[dim]);
-
- float exa = p1[dim];
- float exb = p2[dim];
-
- if(ta >= 0.0f) {
- float t2 = ta * ta;
- float t3 = t2 * ta;
- exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0];
- }
- if(tb >= 0.0f) {
- float t2 = tb * tb;
- float t3 = t2 * tb;
- exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0];
- }
-
- *upper = max(*upper, max(exa,exb));
- *lower = min(*lower, min(exa,exb));
+ float *p0 = &p[0].x;
+ float *p1 = &p[1].x;
+ float *p2 = &p[2].x;
+ float *p3 = &p[3].x;
+
+ float fc = 0.71f;
+ float curve_coef[4];
+ curve_coef[0] = p1[dim];
+ curve_coef[1] = -fc * p0[dim] + fc * p2[dim];
+ curve_coef[2] = 2.0f * fc * p0[dim] + (fc - 3.0f) * p1[dim] + (3.0f - 2.0f * fc) * p2[dim] -
+ fc * p3[dim];
+ curve_coef[3] = -fc * p0[dim] + (2.0f - fc) * p1[dim] + (fc - 2.0f) * p2[dim] + fc * p3[dim];
+
+ float discroot = curve_coef[2] * curve_coef[2] - 3 * curve_coef[3] * curve_coef[1];
+ float ta = -1.0f;
+ float tb = -1.0f;
+
+ if (discroot >= 0) {
+ discroot = sqrtf(discroot);
+ ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
+ tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
+ ta = (ta > 1.0f || ta < 0.0f) ? -1.0f : ta;
+ tb = (tb > 1.0f || tb < 0.0f) ? -1.0f : tb;
+ }
+
+ *upper = max(p1[dim], p2[dim]);
+ *lower = min(p1[dim], p2[dim]);
+
+ float exa = p1[dim];
+ float exb = p2[dim];
+
+ if (ta >= 0.0f) {
+ float t2 = ta * ta;
+ float t3 = t2 * ta;
+ exa = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * ta + curve_coef[0];
+ }
+ if (tb >= 0.0f) {
+ float t2 = tb * tb;
+ float t3 = t2 * tb;
+ exb = curve_coef[3] * t3 + curve_coef[2] * t2 + curve_coef[1] * tb + curve_coef[0];
+ }
+
+ *upper = max(*upper, max(exa, exb));
+ *lower = min(*lower, min(exa, exb));
}
/* Hair System Manager */
CurveSystemManager::CurveSystemManager()
{
- primitive = CURVE_LINE_SEGMENTS;
- curve_shape = CURVE_THICK;
- line_method = CURVE_CORRECTED;
- triangle_method = CURVE_CAMERA_TRIANGLES;
- resolution = 3;
- subdivisions = 3;
-
- minimum_width = 0.0f;
- maximum_width = 0.0f;
-
- use_curves = true;
- use_encasing = true;
- use_backfacing = false;
- use_tangent_normal_geometry = false;
-
- need_update = true;
- need_mesh_update = false;
+ primitive = CURVE_LINE_SEGMENTS;
+ curve_shape = CURVE_THICK;
+ line_method = CURVE_CORRECTED;
+ triangle_method = CURVE_CAMERA_TRIANGLES;
+ resolution = 3;
+ subdivisions = 3;
+
+ minimum_width = 0.0f;
+ maximum_width = 0.0f;
+
+ use_curves = true;
+ use_encasing = true;
+ use_backfacing = false;
+ use_tangent_normal_geometry = false;
+
+ need_update = true;
+ need_mesh_update = false;
}
CurveSystemManager::~CurveSystemManager()
@@ -106,85 +107,82 @@ CurveSystemManager::~CurveSystemManager()
void CurveSystemManager::device_update(Device *device,
DeviceScene *dscene,
Scene * /*scene*/,
- Progress& progress)
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- device_free(device, dscene);
+ device_free(device, dscene);
- progress.set_status("Updating Hair settings", "Copying Hair settings to device");
+ progress.set_status("Updating Hair settings", "Copying Hair settings to device");
- KernelCurves *kcurve = &dscene->data.curve;
+ KernelCurves *kcurve = &dscene->data.curve;
- kcurve->curveflags = 0;
+ kcurve->curveflags = 0;
- if(use_curves) {
- if(primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS)
- kcurve->curveflags |= CURVE_KN_INTERPOLATE;
- if(primitive == CURVE_RIBBONS)
- kcurve->curveflags |= CURVE_KN_RIBBONS;
+ if (use_curves) {
+ if (primitive == CURVE_SEGMENTS || primitive == CURVE_RIBBONS)
+ kcurve->curveflags |= CURVE_KN_INTERPOLATE;
+ if (primitive == CURVE_RIBBONS)
+ kcurve->curveflags |= CURVE_KN_RIBBONS;
- if(line_method == CURVE_ACCURATE)
- kcurve->curveflags |= CURVE_KN_ACCURATE;
- else if(line_method == CURVE_CORRECTED)
- kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
+ if (line_method == CURVE_ACCURATE)
+ kcurve->curveflags |= CURVE_KN_ACCURATE;
+ else if (line_method == CURVE_CORRECTED)
+ kcurve->curveflags |= CURVE_KN_INTERSECTCORRECTION;
- if(use_tangent_normal_geometry)
- kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
- if(use_backfacing)
- kcurve->curveflags |= CURVE_KN_BACKFACING;
- if(use_encasing)
- kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
+ if (use_tangent_normal_geometry)
+ kcurve->curveflags |= CURVE_KN_TRUETANGENTGNORMAL;
+ if (use_backfacing)
+ kcurve->curveflags |= CURVE_KN_BACKFACING;
+ if (use_encasing)
+ kcurve->curveflags |= CURVE_KN_ENCLOSEFILTER;
- kcurve->minimum_width = minimum_width;
- kcurve->maximum_width = maximum_width;
- kcurve->subdivisions = subdivisions;
- }
+ kcurve->minimum_width = minimum_width;
+ kcurve->maximum_width = maximum_width;
+ kcurve->subdivisions = subdivisions;
+ }
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- need_update = false;
+ need_update = false;
}
-void CurveSystemManager::device_free(Device * /*device*/,
- DeviceScene * /*dscene*/)
+void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
-
}
-bool CurveSystemManager::modified(const CurveSystemManager& CurveSystemManager)
+bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager)
{
- return !(curve_shape == CurveSystemManager.curve_shape &&
- line_method == CurveSystemManager.line_method &&
- primitive == CurveSystemManager.primitive &&
- use_encasing == CurveSystemManager.use_encasing &&
- use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
- minimum_width == CurveSystemManager.minimum_width &&
- maximum_width == CurveSystemManager.maximum_width &&
- use_backfacing == CurveSystemManager.use_backfacing &&
- triangle_method == CurveSystemManager.triangle_method &&
- resolution == CurveSystemManager.resolution &&
- use_curves == CurveSystemManager.use_curves &&
- subdivisions == CurveSystemManager.subdivisions);
+ return !(
+ curve_shape == CurveSystemManager.curve_shape &&
+ line_method == CurveSystemManager.line_method && primitive == CurveSystemManager.primitive &&
+ use_encasing == CurveSystemManager.use_encasing &&
+ use_tangent_normal_geometry == CurveSystemManager.use_tangent_normal_geometry &&
+ minimum_width == CurveSystemManager.minimum_width &&
+ maximum_width == CurveSystemManager.maximum_width &&
+ use_backfacing == CurveSystemManager.use_backfacing &&
+ triangle_method == CurveSystemManager.triangle_method &&
+ resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves &&
+ subdivisions == CurveSystemManager.subdivisions);
}
-bool CurveSystemManager::modified_mesh(const CurveSystemManager& CurveSystemManager)
+bool CurveSystemManager::modified_mesh(const CurveSystemManager &CurveSystemManager)
{
- return !(primitive == CurveSystemManager.primitive &&
- curve_shape == CurveSystemManager.curve_shape &&
- triangle_method == CurveSystemManager.triangle_method &&
- resolution == CurveSystemManager.resolution &&
- use_curves == CurveSystemManager.use_curves);
+ return !(
+ primitive == CurveSystemManager.primitive && curve_shape == CurveSystemManager.curve_shape &&
+ triangle_method == CurveSystemManager.triangle_method &&
+ resolution == CurveSystemManager.resolution && use_curves == CurveSystemManager.use_curves);
}
void CurveSystemManager::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
void CurveSystemManager::tag_update_mesh()
{
- need_mesh_update = true;
+ need_mesh_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 9db411bc04b..81e7b4ac88d 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -30,93 +30,91 @@ class Scene;
void curvebounds(float *lower, float *upper, float3 *p, int dim);
typedef enum CurvePrimitiveType {
- CURVE_TRIANGLES = 0,
- CURVE_LINE_SEGMENTS = 1,
- CURVE_SEGMENTS = 2,
- CURVE_RIBBONS = 3,
+ CURVE_TRIANGLES = 0,
+ CURVE_LINE_SEGMENTS = 1,
+ CURVE_SEGMENTS = 2,
+ CURVE_RIBBONS = 3,
- CURVE_NUM_PRIMITIVE_TYPES,
+ CURVE_NUM_PRIMITIVE_TYPES,
} CurvePrimitiveType;
typedef enum CurveShapeType {
- CURVE_RIBBON = 0,
- CURVE_THICK = 1,
+ CURVE_RIBBON = 0,
+ CURVE_THICK = 1,
- CURVE_NUM_SHAPE_TYPES,
+ CURVE_NUM_SHAPE_TYPES,
} CurveShapeType;
typedef enum CurveTriangleMethod {
- CURVE_CAMERA_TRIANGLES,
- CURVE_TESSELATED_TRIANGLES
+ CURVE_CAMERA_TRIANGLES,
+ CURVE_TESSELATED_TRIANGLES
} CurveTriangleMethod;
typedef enum CurveLineMethod {
- CURVE_ACCURATE,
- CURVE_CORRECTED,
- CURVE_UNCORRECTED
+ CURVE_ACCURATE,
+ CURVE_CORRECTED,
+ CURVE_UNCORRECTED
} CurveLineMethod;
class ParticleCurveData {
-public:
+ public:
+ ParticleCurveData();
+ ~ParticleCurveData();
- ParticleCurveData();
- ~ParticleCurveData();
+ array<int> psys_firstcurve;
+ array<int> psys_curvenum;
+ array<int> psys_shader;
- array<int> psys_firstcurve;
- array<int> psys_curvenum;
- array<int> psys_shader;
+ array<float> psys_rootradius;
+ array<float> psys_tipradius;
+ array<float> psys_shape;
+ array<bool> psys_closetip;
- array<float> psys_rootradius;
- array<float> psys_tipradius;
- array<float> psys_shape;
- array<bool> psys_closetip;
+ array<int> curve_firstkey;
+ array<int> curve_keynum;
+ array<float> curve_length;
+ array<float2> curve_uv;
+ array<float3> curve_vcol;
- array<int> curve_firstkey;
- array<int> curve_keynum;
- array<float> curve_length;
- array<float2> curve_uv;
- array<float3> curve_vcol;
-
- array<float3> curvekey_co;
- array<float> curvekey_time;
+ array<float3> curvekey_co;
+ array<float> curvekey_time;
};
/* HairSystem Manager */
class CurveSystemManager {
-public:
-
- CurvePrimitiveType primitive;
- CurveShapeType curve_shape;
- CurveLineMethod line_method;
- CurveTriangleMethod triangle_method;
- int resolution;
- int subdivisions;
-
- float minimum_width;
- float maximum_width;
-
- bool use_curves;
- bool use_encasing;
- bool use_backfacing;
- bool use_tangent_normal_geometry;
-
- bool need_update;
- bool need_mesh_update;
-
- CurveSystemManager();
- ~CurveSystemManager();
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
- bool modified(const CurveSystemManager& CurveSystemManager);
- bool modified_mesh(const CurveSystemManager& CurveSystemManager);
-
- void tag_update(Scene *scene);
- void tag_update_mesh();
+ public:
+ CurvePrimitiveType primitive;
+ CurveShapeType curve_shape;
+ CurveLineMethod line_method;
+ CurveTriangleMethod triangle_method;
+ int resolution;
+ int subdivisions;
+
+ float minimum_width;
+ float maximum_width;
+
+ bool use_curves;
+ bool use_encasing;
+ bool use_backfacing;
+ bool use_tangent_normal_geometry;
+
+ bool need_update;
+ bool need_mesh_update;
+
+ CurveSystemManager();
+ ~CurveSystemManager();
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
+ bool modified(const CurveSystemManager &CurveSystemManager);
+ bool modified_mesh(const CurveSystemManager &CurveSystemManager);
+
+ void tag_update(Scene *scene);
+ void tag_update_mesh();
};
CCL_NAMESPACE_END
-#endif /* __CURVES_H__ */
+#endif /* __CURVES_H__ */
diff --git a/intern/cycles/render/denoising.cpp b/intern/cycles/render/denoising.cpp
index ab74fd8fd38..c4f21d9c771 100644
--- a/intern/cycles/render/denoising.cpp
+++ b/intern/cycles/render/denoising.cpp
@@ -31,55 +31,55 @@ CCL_NAMESPACE_BEGIN
static void print_progress(int num, int total, int frame, int num_frames)
{
- const char *label = "Denoise Frame ";
- int cols = system_console_width();
-
- cols -= strlen(label);
-
- int len = 1;
- for(int x = total; x > 9; x /= 10) {
- len++;
- }
-
- int bars = cols - 2*len - 6;
-
- printf("\r%s", label);
-
- if(num_frames > 1) {
- int frame_len = 1;
- for(int x = num_frames - 1; x > 9; x /= 10) {
- frame_len++;
- }
- bars -= frame_len + 2;
- printf("%*d ", frame_len, frame);
- }
-
- int v = int(float(num)*bars/total);
- printf("[");
- for(int i = 0; i < v; i++) {
- printf("=");
- }
- if(v < bars) {
- printf(">");
- }
- for(int i = v+1; i < bars; i++) {
- printf(" ");
- }
- printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
- fflush(stdout);
+ const char *label = "Denoise Frame ";
+ int cols = system_console_width();
+
+ cols -= strlen(label);
+
+ int len = 1;
+ for (int x = total; x > 9; x /= 10) {
+ len++;
+ }
+
+ int bars = cols - 2 * len - 6;
+
+ printf("\r%s", label);
+
+ if (num_frames > 1) {
+ int frame_len = 1;
+ for (int x = num_frames - 1; x > 9; x /= 10) {
+ frame_len++;
+ }
+ bars -= frame_len + 2;
+ printf("%*d ", frame_len, frame);
+ }
+
+ int v = int(float(num) * bars / total);
+ printf("[");
+ for (int i = 0; i < v; i++) {
+ printf("=");
+ }
+ if (v < bars) {
+ printf(">");
+ }
+ for (int i = v + 1; i < bars; i++) {
+ printf(" ");
+ }
+ printf(string_printf("] %%%dd / %d", len, total).c_str(), num);
+ fflush(stdout);
}
/* Splits in at its last dot, setting suffix to the part after the dot and in to the part before it.
* Returns whether a dot was found. */
static bool split_last_dot(string &in, string &suffix)
{
- size_t pos = in.rfind(".");
- if(pos == string::npos) {
- return false;
- }
- suffix = in.substr(pos+1);
- in = in.substr(0, pos);
- return true;
+ size_t pos = in.rfind(".");
+ if (pos == string::npos) {
+ return false;
+ }
+ suffix = in.substr(pos + 1);
+ in = in.substr(0, pos);
+ return true;
}
/* Separate channel names as generated by Blender.
@@ -87,39 +87,40 @@ static bool split_last_dot(string &in, string &suffix)
* Inputs are expected in the form RenderLayer.Pass.View.Channel, sets renderlayer to "RenderLayer.View"
* Otherwise:
* Inputs are expected in the form RenderLayer.Pass.Channel */
-static bool parse_channel_name(string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
+static bool parse_channel_name(
+ string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
{
- if(!split_last_dot(name, channel)) {
- return false;
- }
- string view;
- if(multiview_channels && !split_last_dot(name, view)) {
- return false;
- }
- if(!split_last_dot(name, pass)) {
- return false;
- }
- renderlayer = name;
+ if (!split_last_dot(name, channel)) {
+ return false;
+ }
+ string view;
+ if (multiview_channels && !split_last_dot(name, view)) {
+ return false;
+ }
+ if (!split_last_dot(name, pass)) {
+ return false;
+ }
+ renderlayer = name;
- if(multiview_channels) {
- renderlayer += "." + view;
- }
+ if (multiview_channels) {
+ renderlayer += "." + view;
+ }
- return true;
+ return true;
}
/* Channel Mapping */
struct ChannelMapping {
- int channel;
- string name;
+ int channel;
+ string name;
};
static void fill_mapping(vector<ChannelMapping> &map, int pos, string name, string channels)
{
- for(const char *chan = channels.c_str(); *chan; chan++) {
- map.push_back({pos++, name + "." + *chan});
- }
+ for (const char *chan = channels.c_str(); *chan; chan++) {
+ map.push_back({pos++, name + "." + *chan});
+ }
}
static const int INPUT_NUM_CHANNELS = 15;
@@ -132,131 +133,135 @@ static const int INPUT_DENOISING_VARIANCE = 11;
static const int INPUT_DENOISING_INTENSITY = 14;
static vector<ChannelMapping> input_channels()
{
- vector<ChannelMapping> map;
- fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
- fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
- fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
- fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
- fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
- fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
- fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
- return map;
+ vector<ChannelMapping> map;
+ fill_mapping(map, INPUT_DENOISING_DEPTH, "Denoising Depth", "Z");
+ fill_mapping(map, INPUT_DENOISING_NORMAL, "Denoising Normal", "XYZ");
+ fill_mapping(map, INPUT_DENOISING_SHADOWING, "Denoising Shadowing", "X");
+ fill_mapping(map, INPUT_DENOISING_ALBEDO, "Denoising Albedo", "RGB");
+ fill_mapping(map, INPUT_NOISY_IMAGE, "Noisy Image", "RGB");
+ fill_mapping(map, INPUT_DENOISING_VARIANCE, "Denoising Variance", "RGB");
+ fill_mapping(map, INPUT_DENOISING_INTENSITY, "Denoising Intensity", "X");
+ return map;
}
static const int OUTPUT_NUM_CHANNELS = 3;
static vector<ChannelMapping> output_channels()
{
- vector<ChannelMapping> map;
- fill_mapping(map, 0, "Combined", "RGB");
- return map;
+ vector<ChannelMapping> map;
+ fill_mapping(map, 0, "Combined", "RGB");
+ return map;
}
/* Renderlayer Handling */
bool DenoiseImageLayer::detect_denoising_channels()
{
- /* Map device input to image channels. */
- input_to_image_channel.clear();
- input_to_image_channel.resize(INPUT_NUM_CHANNELS, -1);
+ /* Map device input to image channels. */
+ input_to_image_channel.clear();
+ input_to_image_channel.resize(INPUT_NUM_CHANNELS, -1);
- foreach(const ChannelMapping& mapping, input_channels()) {
- vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
- if(i == channels.end()) {
- return false;
- }
+ foreach (const ChannelMapping &mapping, input_channels()) {
+ vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
+ if (i == channels.end()) {
+ return false;
+ }
- size_t input_channel = mapping.channel;
- size_t layer_channel = i - channels.begin();
- input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
- }
+ size_t input_channel = mapping.channel;
+ size_t layer_channel = i - channels.begin();
+ input_to_image_channel[input_channel] = layer_to_image_channel[layer_channel];
+ }
- /* Map device output to image channels. */
- output_to_image_channel.clear();
- output_to_image_channel.resize(OUTPUT_NUM_CHANNELS, -1);
+ /* Map device output to image channels. */
+ output_to_image_channel.clear();
+ output_to_image_channel.resize(OUTPUT_NUM_CHANNELS, -1);
- foreach(const ChannelMapping& mapping, output_channels()) {
- vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
- if(i == channels.end()) {
- return false;
- }
+ foreach (const ChannelMapping &mapping, output_channels()) {
+ vector<string>::iterator i = find(channels.begin(), channels.end(), mapping.name);
+ if (i == channels.end()) {
+ return false;
+ }
- size_t output_channel = mapping.channel;
- size_t layer_channel = i - channels.begin();
- output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
- }
+ size_t output_channel = mapping.channel;
+ size_t layer_channel = i - channels.begin();
+ output_to_image_channel[output_channel] = layer_to_image_channel[layer_channel];
+ }
- /* Check that all buffer channels are correctly set. */
- for(int i = 0; i < INPUT_NUM_CHANNELS; i++) {
- assert(input_to_image_channel[i] >= 0);
- }
- for(int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
- assert(output_to_image_channel[i] >= 0);
- }
+ /* Check that all buffer channels are correctly set. */
+ for (int i = 0; i < INPUT_NUM_CHANNELS; i++) {
+ assert(input_to_image_channel[i] >= 0);
+ }
+ for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
+ assert(output_to_image_channel[i] >= 0);
+ }
- return true;
+ return true;
}
bool DenoiseImageLayer::match_channels(int neighbor,
const std::vector<string> &channelnames,
const std::vector<string> &neighbor_channelnames)
{
- neighbor_input_to_image_channel.resize(neighbor + 1);
- vector<int>& mapping = neighbor_input_to_image_channel[neighbor];
+ neighbor_input_to_image_channel.resize(neighbor + 1);
+ vector<int> &mapping = neighbor_input_to_image_channel[neighbor];
- assert(mapping.size() == 0);
- mapping.resize(input_to_image_channel.size(), -1);
+ assert(mapping.size() == 0);
+ mapping.resize(input_to_image_channel.size(), -1);
- for(int i = 0; i < input_to_image_channel.size(); i++) {
- const string& channel = channelnames[input_to_image_channel[i]];
- std::vector<string>::const_iterator frame_channel = find(neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
+ for (int i = 0; i < input_to_image_channel.size(); i++) {
+ const string &channel = channelnames[input_to_image_channel[i]];
+ std::vector<string>::const_iterator frame_channel = find(
+ neighbor_channelnames.begin(), neighbor_channelnames.end(), channel);
- if(frame_channel == neighbor_channelnames.end()) {
- return false;
- }
+ if (frame_channel == neighbor_channelnames.end()) {
+ return false;
+ }
- mapping[i] = frame_channel - neighbor_channelnames.begin();
- }
+ mapping[i] = frame_channel - neighbor_channelnames.begin();
+ }
- return true;
+ return true;
}
/* Denoise Task */
-DenoiseTask::DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int>& neighbor_frames)
-: denoiser(denoiser),
- device(device),
- frame(frame),
- neighbor_frames(neighbor_frames),
- current_layer(0),
- input_pixels(device, "filter input buffer", MEM_READ_ONLY),
- num_tiles(0)
+DenoiseTask::DenoiseTask(Device *device,
+ Denoiser *denoiser,
+ int frame,
+ const vector<int> &neighbor_frames)
+ : denoiser(denoiser),
+ device(device),
+ frame(frame),
+ neighbor_frames(neighbor_frames),
+ current_layer(0),
+ input_pixels(device, "filter input buffer", MEM_READ_ONLY),
+ num_tiles(0)
{
- image.samples = denoiser->samples_override;
+ image.samples = denoiser->samples_override;
}
DenoiseTask::~DenoiseTask()
{
- free();
+ free();
}
/* Device callbacks */
bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &tile)
{
- thread_scoped_lock tile_lock(tiles_mutex);
+ thread_scoped_lock tile_lock(tiles_mutex);
- if(tiles.empty()) {
- return false;
- }
+ if (tiles.empty()) {
+ return false;
+ }
- tile = tiles.front();
- tiles.pop_front();
+ tile = tiles.front();
+ tiles.pop_front();
- device->map_tile(tile_device, tile);
+ device->map_tile(tile_device, tile);
- print_progress(num_tiles - tiles.size(), num_tiles, frame, denoiser->num_frames);
+ print_progress(num_tiles - tiles.size(), num_tiles, frame, denoiser->num_frames);
- return true;
+ return true;
}
/* Mapping tiles is required for regular rendering since each tile has its separate memory
@@ -268,87 +273,89 @@ bool DenoiseTask::acquire_tile(Device *device, Device *tile_device, RenderTile &
* a different buffer to avoid having to copy an entire horizontal slice of the image. */
void DenoiseTask::map_neighboring_tiles(RenderTile *tiles, Device *tile_device)
{
- /* Fill tile information. */
- for(int i = 0; i < 9; i++) {
- if(i == 4) {
- continue;
- }
-
- int dx = (i%3)-1;
- int dy = (i/3)-1;
- tiles[i].x = clamp(tiles[4].x + dx *denoiser->tile_size.x, 0, image.width);
- tiles[i].w = clamp(tiles[4].x + (dx+1)*denoiser->tile_size.x, 0, image.width) - tiles[i].x;
- tiles[i].y = clamp(tiles[4].y + dy *denoiser->tile_size.y, 0, image.height);
- tiles[i].h = clamp(tiles[4].y + (dy+1)*denoiser->tile_size.y, 0, image.height) - tiles[i].y;
-
- tiles[i].buffer = tiles[4].buffer;
- tiles[i].offset = tiles[4].offset;
- tiles[i].stride = image.width;
- }
-
- /* Allocate output buffer. */
- device_vector<float> *output_mem = new device_vector<float>(tile_device, "denoising_output", MEM_READ_WRITE);
- output_mem->alloc(OUTPUT_NUM_CHANNELS*tiles[4].w*tiles[4].h);
-
- /* Fill output buffer with noisy image, assumed by kernel_filter_finalize
- * when skipping denoising of some pixels. */
- float *result = output_mem->data();
- float *in = &image.pixels[image.num_channels*(tiles[4].y*image.width + tiles[4].x)];
-
- const DenoiseImageLayer& layer = image.layers[current_layer];
- const int *input_to_image_channel = layer.input_to_image_channel.data();
-
- for(int y = 0; y < tiles[4].h; y++) {
- for(int x = 0; x < tiles[4].w; x++, result += OUTPUT_NUM_CHANNELS) {
- for(int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
- result[i] = in[image.num_channels*x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
- }
- }
- in += image.num_channels * image.width;
- }
-
- output_mem->copy_to_device();
-
- /* Fill output tile info. */
- tiles[9] = tiles[4];
- tiles[9].buffer = output_mem->device_pointer;
- tiles[9].stride = tiles[9].w;
- tiles[9].offset -= tiles[9].x + tiles[9].y*tiles[9].stride;
-
- thread_scoped_lock output_lock(output_mutex);
- assert(output_pixels.count(tiles[4].tile_index) == 0);
- output_pixels[tiles[9].tile_index] = output_mem;
+ /* Fill tile information. */
+ for (int i = 0; i < 9; i++) {
+ if (i == 4) {
+ continue;
+ }
+
+ int dx = (i % 3) - 1;
+ int dy = (i / 3) - 1;
+ tiles[i].x = clamp(tiles[4].x + dx * denoiser->tile_size.x, 0, image.width);
+ tiles[i].w = clamp(tiles[4].x + (dx + 1) * denoiser->tile_size.x, 0, image.width) - tiles[i].x;
+ tiles[i].y = clamp(tiles[4].y + dy * denoiser->tile_size.y, 0, image.height);
+ tiles[i].h = clamp(tiles[4].y + (dy + 1) * denoiser->tile_size.y, 0, image.height) -
+ tiles[i].y;
+
+ tiles[i].buffer = tiles[4].buffer;
+ tiles[i].offset = tiles[4].offset;
+ tiles[i].stride = image.width;
+ }
+
+ /* Allocate output buffer. */
+ device_vector<float> *output_mem = new device_vector<float>(
+ tile_device, "denoising_output", MEM_READ_WRITE);
+ output_mem->alloc(OUTPUT_NUM_CHANNELS * tiles[4].w * tiles[4].h);
+
+ /* Fill output buffer with noisy image, assumed by kernel_filter_finalize
+ * when skipping denoising of some pixels. */
+ float *result = output_mem->data();
+ float *in = &image.pixels[image.num_channels * (tiles[4].y * image.width + tiles[4].x)];
+
+ const DenoiseImageLayer &layer = image.layers[current_layer];
+ const int *input_to_image_channel = layer.input_to_image_channel.data();
+
+ for (int y = 0; y < tiles[4].h; y++) {
+ for (int x = 0; x < tiles[4].w; x++, result += OUTPUT_NUM_CHANNELS) {
+ for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
+ result[i] = in[image.num_channels * x + input_to_image_channel[INPUT_NOISY_IMAGE + i]];
+ }
+ }
+ in += image.num_channels * image.width;
+ }
+
+ output_mem->copy_to_device();
+
+ /* Fill output tile info. */
+ tiles[9] = tiles[4];
+ tiles[9].buffer = output_mem->device_pointer;
+ tiles[9].stride = tiles[9].w;
+ tiles[9].offset -= tiles[9].x + tiles[9].y * tiles[9].stride;
+
+ thread_scoped_lock output_lock(output_mutex);
+ assert(output_pixels.count(tiles[4].tile_index) == 0);
+ output_pixels[tiles[9].tile_index] = output_mem;
}
void DenoiseTask::unmap_neighboring_tiles(RenderTile *tiles)
{
- thread_scoped_lock output_lock(output_mutex);
- assert(output_pixels.count(tiles[4].tile_index) == 1);
- device_vector<float> *output_mem = output_pixels[tiles[9].tile_index];
- output_pixels.erase(tiles[4].tile_index);
- output_lock.unlock();
+ thread_scoped_lock output_lock(output_mutex);
+ assert(output_pixels.count(tiles[4].tile_index) == 1);
+ device_vector<float> *output_mem = output_pixels[tiles[9].tile_index];
+ output_pixels.erase(tiles[4].tile_index);
+ output_lock.unlock();
- /* Copy denoised pixels from device. */
- output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS*tiles[9].w, tiles[9].h);
+ /* Copy denoised pixels from device. */
+ output_mem->copy_from_device(0, OUTPUT_NUM_CHANNELS * tiles[9].w, tiles[9].h);
- float *result = output_mem->data();
- float *out = &image.pixels[image.num_channels*(tiles[9].y*image.width + tiles[9].x)];
+ float *result = output_mem->data();
+ float *out = &image.pixels[image.num_channels * (tiles[9].y * image.width + tiles[9].x)];
- const DenoiseImageLayer& layer = image.layers[current_layer];
- const int *output_to_image_channel = layer.output_to_image_channel.data();
+ const DenoiseImageLayer &layer = image.layers[current_layer];
+ const int *output_to_image_channel = layer.output_to_image_channel.data();
- for(int y = 0; y < tiles[9].h; y++) {
- for(int x = 0; x < tiles[9].w; x++, result += OUTPUT_NUM_CHANNELS) {
- for(int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
- out[image.num_channels*x + output_to_image_channel[i]] = result[i];
- }
- }
- out += image.num_channels * image.width;
- }
+ for (int y = 0; y < tiles[9].h; y++) {
+ for (int x = 0; x < tiles[9].w; x++, result += OUTPUT_NUM_CHANNELS) {
+ for (int i = 0; i < OUTPUT_NUM_CHANNELS; i++) {
+ out[image.num_channels * x + output_to_image_channel[i]] = result[i];
+ }
+ }
+ out += image.num_channels * image.width;
+ }
- /* Free device buffer. */
- output_mem->free();
- delete output_mem;
+ /* Free device buffer. */
+ output_mem->free();
+ delete output_mem;
}
void DenoiseTask::release_tile()
@@ -357,542 +364,547 @@ void DenoiseTask::release_tile()
bool DenoiseTask::get_cancel()
{
- return false;
-}
-
-void DenoiseTask::create_task(DeviceTask& task)
-{
- /* Callback functions. */
- task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
- task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
- task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
- task.release_tile = function_bind(&DenoiseTask::release_tile, this);
- task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
-
- /* Denoising parameters. */
- task.denoising = denoiser->params;
- task.denoising_do_filter = true;
- task.denoising_write_passes = false;
- task.denoising_from_render = false;
-
- task.denoising_frames.resize(neighbor_frames.size());
- for(int i = 0; i < neighbor_frames.size(); i++) {
- task.denoising_frames[i] = neighbor_frames[i] - frame;
- }
-
- /* Buffer parameters. */
- task.pass_stride = INPUT_NUM_CHANNELS;
- task.target_pass_stride = OUTPUT_NUM_CHANNELS;
- task.pass_denoising_data = 0;
- task.pass_denoising_clean = -1;
- task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
-
- /* Create tiles. */
- thread_scoped_lock tile_lock(tiles_mutex);
- thread_scoped_lock output_lock(output_mutex);
-
- tiles.clear();
- assert(output_pixels.empty());
- output_pixels.clear();
-
- int tiles_x = divide_up(image.width, denoiser->tile_size.x);
- int tiles_y = divide_up(image.height, denoiser->tile_size.y);
-
- for(int ty = 0; ty < tiles_y; ty++) {
- for(int tx = 0; tx < tiles_x; tx++) {
- RenderTile tile;
- tile.x = tx * denoiser->tile_size.x;
- tile.y = ty * denoiser->tile_size.y;
- tile.w = min(image.width - tile.x, denoiser->tile_size.x);
- tile.h = min(image.height - tile.y, denoiser->tile_size.y);
- tile.start_sample = 0;
- tile.num_samples = image.layers[current_layer].samples;
- tile.sample = 0;
- tile.offset = 0;
- tile.stride = image.width;
- tile.tile_index = ty*tiles_x + tx;
- tile.task = RenderTile::DENOISE;
- tile.buffers = NULL;
- tile.buffer = input_pixels.device_pointer;
- tiles.push_back(tile);
- }
- }
-
- num_tiles = tiles.size();
+ return false;
+}
+
+void DenoiseTask::create_task(DeviceTask &task)
+{
+ /* Callback functions. */
+ task.acquire_tile = function_bind(&DenoiseTask::acquire_tile, this, device, _1, _2);
+ task.map_neighbor_tiles = function_bind(&DenoiseTask::map_neighboring_tiles, this, _1, _2);
+ task.unmap_neighbor_tiles = function_bind(&DenoiseTask::unmap_neighboring_tiles, this, _1);
+ task.release_tile = function_bind(&DenoiseTask::release_tile, this);
+ task.get_cancel = function_bind(&DenoiseTask::get_cancel, this);
+
+ /* Denoising parameters. */
+ task.denoising = denoiser->params;
+ task.denoising_do_filter = true;
+ task.denoising_write_passes = false;
+ task.denoising_from_render = false;
+
+ task.denoising_frames.resize(neighbor_frames.size());
+ for (int i = 0; i < neighbor_frames.size(); i++) {
+ task.denoising_frames[i] = neighbor_frames[i] - frame;
+ }
+
+ /* Buffer parameters. */
+ task.pass_stride = INPUT_NUM_CHANNELS;
+ task.target_pass_stride = OUTPUT_NUM_CHANNELS;
+ task.pass_denoising_data = 0;
+ task.pass_denoising_clean = -1;
+ task.frame_stride = image.width * image.height * INPUT_NUM_CHANNELS;
+
+ /* Create tiles. */
+ thread_scoped_lock tile_lock(tiles_mutex);
+ thread_scoped_lock output_lock(output_mutex);
+
+ tiles.clear();
+ assert(output_pixels.empty());
+ output_pixels.clear();
+
+ int tiles_x = divide_up(image.width, denoiser->tile_size.x);
+ int tiles_y = divide_up(image.height, denoiser->tile_size.y);
+
+ for (int ty = 0; ty < tiles_y; ty++) {
+ for (int tx = 0; tx < tiles_x; tx++) {
+ RenderTile tile;
+ tile.x = tx * denoiser->tile_size.x;
+ tile.y = ty * denoiser->tile_size.y;
+ tile.w = min(image.width - tile.x, denoiser->tile_size.x);
+ tile.h = min(image.height - tile.y, denoiser->tile_size.y);
+ tile.start_sample = 0;
+ tile.num_samples = image.layers[current_layer].samples;
+ tile.sample = 0;
+ tile.offset = 0;
+ tile.stride = image.width;
+ tile.tile_index = ty * tiles_x + tx;
+ tile.task = RenderTile::DENOISE;
+ tile.buffers = NULL;
+ tile.buffer = input_pixels.device_pointer;
+ tiles.push_back(tile);
+ }
+ }
+
+ num_tiles = tiles.size();
}
/* Denoiser Operations */
bool DenoiseTask::load_input_pixels(int layer)
{
- int w = image.width;
- int h = image.height;
- int num_pixels = image.width * image.height;
- int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
-
- /* Load center image */
- DenoiseImageLayer& image_layer = image.layers[layer];
-
- float *buffer_data = input_pixels.data();
- image.read_pixels(image_layer, buffer_data);
- buffer_data += frame_stride;
-
- /* Load neighbor images */
- for(int i = 0; i < image.in_neighbors.size(); i++) {
- if(!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
- error = "Failed to read neighbor frame pixels";
- return false;
- }
- buffer_data += frame_stride;
- }
-
- /* Preprocess */
- buffer_data = input_pixels.data();
- for(int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
- /* Clamp */
- if(denoiser->params.clamp_input) {
- for(int i = 0; i < num_pixels*INPUT_NUM_CHANNELS; i++) {
- buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
- }
- }
-
- /* Box blur */
- int r = 5 * denoiser->params.radius;
- float *data = buffer_data + 14;
- array<float> temp(num_pixels);
-
- for(int y = 0; y < h; y++) {
- for(int x = 0; x < w; x++) {
- int n = 0;
- float sum = 0.0f;
- for(int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
- sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
- }
- temp[y * w + x] = sum/n;
- }
- }
-
- for(int y = 0; y < h; y++) {
- for(int x = 0; x < w; x++) {
- int n = 0;
- float sum = 0.0f;
-
- for(int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
- sum += temp[dy * w + x];
- }
-
- data[INPUT_NUM_CHANNELS * (y * w + x)] = sum/n;
- }
- }
-
- buffer_data += frame_stride;
- }
-
- /* Copy to device */
- input_pixels.copy_to_device();
-
- return true;
+ int w = image.width;
+ int h = image.height;
+ int num_pixels = image.width * image.height;
+ int frame_stride = num_pixels * INPUT_NUM_CHANNELS;
+
+ /* Load center image */
+ DenoiseImageLayer &image_layer = image.layers[layer];
+
+ float *buffer_data = input_pixels.data();
+ image.read_pixels(image_layer, buffer_data);
+ buffer_data += frame_stride;
+
+ /* Load neighbor images */
+ for (int i = 0; i < image.in_neighbors.size(); i++) {
+ if (!image.read_neighbor_pixels(i, image_layer, buffer_data)) {
+ error = "Failed to read neighbor frame pixels";
+ return false;
+ }
+ buffer_data += frame_stride;
+ }
+
+ /* Preprocess */
+ buffer_data = input_pixels.data();
+ for (int neighbor = 0; neighbor < image.in_neighbors.size() + 1; neighbor++) {
+ /* Clamp */
+ if (denoiser->params.clamp_input) {
+ for (int i = 0; i < num_pixels * INPUT_NUM_CHANNELS; i++) {
+ buffer_data[i] = clamp(buffer_data[i], -1e8f, 1e8f);
+ }
+ }
+
+ /* Box blur */
+ int r = 5 * denoiser->params.radius;
+ float *data = buffer_data + 14;
+ array<float> temp(num_pixels);
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int n = 0;
+ float sum = 0.0f;
+ for (int dx = max(x - r, 0); dx < min(x + r + 1, w); dx++, n++) {
+ sum += data[INPUT_NUM_CHANNELS * (y * w + dx)];
+ }
+ temp[y * w + x] = sum / n;
+ }
+ }
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int n = 0;
+ float sum = 0.0f;
+
+ for (int dy = max(y - r, 0); dy < min(y + r + 1, h); dy++, n++) {
+ sum += temp[dy * w + x];
+ }
+
+ data[INPUT_NUM_CHANNELS * (y * w + x)] = sum / n;
+ }
+ }
+
+ buffer_data += frame_stride;
+ }
+
+ /* Copy to device */
+ input_pixels.copy_to_device();
+
+ return true;
}
/* Task stages */
bool DenoiseTask::load()
{
- string center_filepath = denoiser->input[frame];
- if(!image.load(center_filepath, error)) {
- return false;
- }
+ string center_filepath = denoiser->input[frame];
+ if (!image.load(center_filepath, error)) {
+ return false;
+ }
- if(!image.load_neighbors(denoiser->input, neighbor_frames, error)) {
- return false;
- }
+ if (!image.load_neighbors(denoiser->input, neighbor_frames, error)) {
+ return false;
+ }
- if(image.layers.empty()) {
- error = "No image layers found to denoise in " + center_filepath;
- return false;
- }
+ if (image.layers.empty()) {
+ error = "No image layers found to denoise in " + center_filepath;
+ return false;
+ }
- /* Allocate device buffer. */
- int num_frames = image.in_neighbors.size() + 1;
- input_pixels.alloc(image.width * INPUT_NUM_CHANNELS, image.height * num_frames);
- input_pixels.zero_to_device();
+ /* Allocate device buffer. */
+ int num_frames = image.in_neighbors.size() + 1;
+ input_pixels.alloc(image.width * INPUT_NUM_CHANNELS, image.height * num_frames);
+ input_pixels.zero_to_device();
- /* Read pixels for first layer. */
- current_layer = 0;
- if(!load_input_pixels(current_layer)) {
- return false;
- }
+ /* Read pixels for first layer. */
+ current_layer = 0;
+ if (!load_input_pixels(current_layer)) {
+ return false;
+ }
- return true;
+ return true;
}
bool DenoiseTask::exec()
{
- for(current_layer = 0; current_layer < image.layers.size(); current_layer++) {
- /* Read pixels for secondary layers, first was already loaded. */
- if(current_layer > 0) {
- if(!load_input_pixels(current_layer)) {
- return false;
- }
- }
+ for (current_layer = 0; current_layer < image.layers.size(); current_layer++) {
+ /* Read pixels for secondary layers, first was already loaded. */
+ if (current_layer > 0) {
+ if (!load_input_pixels(current_layer)) {
+ return false;
+ }
+ }
- /* Run task on device. */
- DeviceTask task(DeviceTask::RENDER);
- create_task(task);
- device->task_add(task);
- device->task_wait();
+ /* Run task on device. */
+ DeviceTask task(DeviceTask::RENDER);
+ create_task(task);
+ device->task_add(task);
+ device->task_wait();
- printf("\n");
- }
+ printf("\n");
+ }
- return true;
+ return true;
}
bool DenoiseTask::save()
{
- bool ok = image.save_output(denoiser->output[frame], error);
- free();
- return ok;
+ bool ok = image.save_output(denoiser->output[frame], error);
+ free();
+ return ok;
}
void DenoiseTask::free()
{
- image.free();
- input_pixels.free();
- assert(output_pixels.empty());
+ image.free();
+ input_pixels.free();
+ assert(output_pixels.empty());
}
/* Denoise Image Storage */
DenoiseImage::DenoiseImage()
{
- width = 0;
- height = 0;
- num_channels = 0;
- samples = 0;
+ width = 0;
+ height = 0;
+ num_channels = 0;
+ samples = 0;
}
DenoiseImage::~DenoiseImage()
{
- free();
+ free();
}
void DenoiseImage::close_input()
{
- in_neighbors.clear();
+ in_neighbors.clear();
}
void DenoiseImage::free()
{
- close_input();
- pixels.clear();
-}
-
-bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string& error)
+ close_input();
+ pixels.clear();
+}
+
+bool DenoiseImage::parse_channels(const ImageSpec &in_spec, string &error)
{
- const std::vector<string> &channels = in_spec.channelnames;
- const ParamValue *multiview = in_spec.find_attribute("multiView");
- const bool multiview_channels = (multiview &&
- multiview->type().basetype == TypeDesc::STRING &&
- multiview->type().arraylen >= 2);
-
- layers.clear();
-
- /* Loop over all the channels in the file, parse their name and sort them
- * by RenderLayer.
- * Channels that can't be parsed are directly passed through to the output. */
- map<string, DenoiseImageLayer> file_layers;
- for(int i = 0; i < channels.size(); i++) {
- string layer, pass, channel;
- if(parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
- file_layers[layer].channels.push_back(pass + "." + channel);
- file_layers[layer].layer_to_image_channel.push_back(i);
- }
- }
-
- /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
- * Any channels that won't be processed internally are also passed through. */
- for(map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end(); ++i) {
- const string& name = i->first;
- DenoiseImageLayer& layer = i->second;
-
- /* Check for full pass set. */
- if(!layer.detect_denoising_channels()) {
- continue;
- }
-
- layer.name = name;
- layer.samples = samples;
-
- /* If the sample value isn't set yet, check if there is a layer-specific one in the input file. */
- if(layer.samples < 1) {
- string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
- if(sample_string != "") {
- if(!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
- error = "Failed to parse samples metadata: " + sample_string;
- return false;
- }
- }
- }
-
- if(layer.samples < 1) {
- error = string_printf("No sample number specified in the file for layer %s or on the command line", name.c_str());
- return false;
- }
-
- layers.push_back(layer);
- }
-
- return true;
-}
-
-void DenoiseImage::read_pixels(const DenoiseImageLayer& layer, float *input_pixels)
-{
- /* Pixels from center file have already been loaded into pixels.
- * We copy a subset into the device input buffer with channels reshuffled. */
- const int *input_to_image_channel = layer.input_to_image_channel.data();
-
- for(int i = 0; i < width * height; i++) {
- for(int j = 0; j < INPUT_NUM_CHANNELS; j++) {
- int image_channel = input_to_image_channel[j];
- input_pixels[i*INPUT_NUM_CHANNELS + j] = pixels[((size_t)i)*num_channels + image_channel];
- }
- }
-}
-
-bool DenoiseImage::read_neighbor_pixels(int neighbor, const DenoiseImageLayer& layer, float *input_pixels)
-{
- /* Load pixels from neighboring frames, and copy them into device buffer
- * with channels reshuffled. */
- size_t num_pixels = (size_t)width * (size_t)height;
- array<float> neighbor_pixels(num_pixels * num_channels);
- if(!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
- return false;
- }
-
- const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
-
- for(int i = 0; i < width * height; i++) {
- for(int j = 0; j < INPUT_NUM_CHANNELS; j++) {
- int image_channel = input_to_image_channel[j];
- input_pixels[i*INPUT_NUM_CHANNELS + j] = neighbor_pixels[((size_t)i)*num_channels + image_channel];
- }
- }
-
- return true;
-}
-
-bool DenoiseImage::load(const string& in_filepath, string& error)
-{
- if(!Filesystem::is_regular(in_filepath)) {
- error = "Couldn't find file: " + in_filepath;
- return false;
- }
-
- unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
- if(!in) {
- error = "Couldn't open file: " + in_filepath;
- return false;
- }
-
- in_spec = in->spec();
- width = in_spec.width;
- height = in_spec.height;
- num_channels = in_spec.nchannels;
-
- if(!parse_channels(in_spec, error)) {
- return false;
- }
-
- if(layers.size() == 0) {
- error = "Could not find a render layer containing denoising info";
- return false;
- }
-
- size_t num_pixels = (size_t)width * (size_t)height;
- pixels.resize(num_pixels * num_channels);
-
- /* Read all channels into buffer. Reading all channels at once is faster
- * than individually due to interleaved EXR channel storage. */
- if(!in->read_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to read image: " + in_filepath;
- return false;
- }
-
- return true;
-}
-
-bool DenoiseImage::load_neighbors(const vector<string>& filepaths, const vector<int>& frames, string& error)
-{
- if(frames.size() > DENOISE_MAX_FRAMES - 1) {
- error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
- return false;
- }
-
- for(int neighbor = 0; neighbor < frames.size(); neighbor++) {
- int frame = frames[neighbor];
- const string& filepath = filepaths[frame];
-
- if(!Filesystem::is_regular(filepath)) {
- error = "Couldn't find neighbor frame: " + filepath;
- return false;
- }
-
- unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
- if(!in_neighbor) {
- error = "Couldn't open neighbor frame: " + filepath;
- return false;
- }
+ const std::vector<string> &channels = in_spec.channelnames;
+ const ParamValue *multiview = in_spec.find_attribute("multiView");
+ const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
+ multiview->type().arraylen >= 2);
+
+ layers.clear();
+
+ /* Loop over all the channels in the file, parse their name and sort them
+ * by RenderLayer.
+ * Channels that can't be parsed are directly passed through to the output. */
+ map<string, DenoiseImageLayer> file_layers;
+ for (int i = 0; i < channels.size(); i++) {
+ string layer, pass, channel;
+ if (parse_channel_name(channels[i], layer, pass, channel, multiview_channels)) {
+ file_layers[layer].channels.push_back(pass + "." + channel);
+ file_layers[layer].layer_to_image_channel.push_back(i);
+ }
+ }
+
+ /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
+ * Any channels that won't be processed internally are also passed through. */
+ for (map<string, DenoiseImageLayer>::iterator i = file_layers.begin(); i != file_layers.end();
+ ++i) {
+ const string &name = i->first;
+ DenoiseImageLayer &layer = i->second;
+
+ /* Check for full pass set. */
+ if (!layer.detect_denoising_channels()) {
+ continue;
+ }
+
+ layer.name = name;
+ layer.samples = samples;
+
+ /* If the sample value isn't set yet, check if there is a layer-specific one in the input file. */
+ if (layer.samples < 1) {
+ string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
+ if (sample_string != "") {
+ if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
+ error = "Failed to parse samples metadata: " + sample_string;
+ return false;
+ }
+ }
+ }
+
+ if (layer.samples < 1) {
+ error = string_printf(
+ "No sample number specified in the file for layer %s or on the command line",
+ name.c_str());
+ return false;
+ }
+
+ layers.push_back(layer);
+ }
+
+ return true;
+}
+
+void DenoiseImage::read_pixels(const DenoiseImageLayer &layer, float *input_pixels)
+{
+ /* Pixels from center file have already been loaded into pixels.
+ * We copy a subset into the device input buffer with channels reshuffled. */
+ const int *input_to_image_channel = layer.input_to_image_channel.data();
+
+ for (int i = 0; i < width * height; i++) {
+ for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
+ int image_channel = input_to_image_channel[j];
+ input_pixels[i * INPUT_NUM_CHANNELS + j] =
+ pixels[((size_t)i) * num_channels + image_channel];
+ }
+ }
+}
+
+bool DenoiseImage::read_neighbor_pixels(int neighbor,
+ const DenoiseImageLayer &layer,
+ float *input_pixels)
+{
+ /* Load pixels from neighboring frames, and copy them into device buffer
+ * with channels reshuffled. */
+ size_t num_pixels = (size_t)width * (size_t)height;
+ array<float> neighbor_pixels(num_pixels * num_channels);
+ if (!in_neighbors[neighbor]->read_image(TypeDesc::FLOAT, neighbor_pixels.data())) {
+ return false;
+ }
+
+ const int *input_to_image_channel = layer.neighbor_input_to_image_channel[neighbor].data();
+
+ for (int i = 0; i < width * height; i++) {
+ for (int j = 0; j < INPUT_NUM_CHANNELS; j++) {
+ int image_channel = input_to_image_channel[j];
+ input_pixels[i * INPUT_NUM_CHANNELS + j] =
+ neighbor_pixels[((size_t)i) * num_channels + image_channel];
+ }
+ }
+
+ return true;
+}
+
+bool DenoiseImage::load(const string &in_filepath, string &error)
+{
+ if (!Filesystem::is_regular(in_filepath)) {
+ error = "Couldn't find file: " + in_filepath;
+ return false;
+ }
+
+ unique_ptr<ImageInput> in(ImageInput::open(in_filepath));
+ if (!in) {
+ error = "Couldn't open file: " + in_filepath;
+ return false;
+ }
+
+ in_spec = in->spec();
+ width = in_spec.width;
+ height = in_spec.height;
+ num_channels = in_spec.nchannels;
+
+ if (!parse_channels(in_spec, error)) {
+ return false;
+ }
+
+ if (layers.size() == 0) {
+ error = "Could not find a render layer containing denoising info";
+ return false;
+ }
+
+ size_t num_pixels = (size_t)width * (size_t)height;
+ pixels.resize(num_pixels * num_channels);
+
+ /* Read all channels into buffer. Reading all channels at once is faster
+ * than individually due to interleaved EXR channel storage. */
+ if (!in->read_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to read image: " + in_filepath;
+ return false;
+ }
+
+ return true;
+}
+
+bool DenoiseImage::load_neighbors(const vector<string> &filepaths,
+ const vector<int> &frames,
+ string &error)
+{
+ if (frames.size() > DENOISE_MAX_FRAMES - 1) {
+ error = string_printf("Maximum number of neighbors (%d) exceeded\n", DENOISE_MAX_FRAMES - 1);
+ return false;
+ }
+
+ for (int neighbor = 0; neighbor < frames.size(); neighbor++) {
+ int frame = frames[neighbor];
+ const string &filepath = filepaths[frame];
- const ImageSpec &neighbor_spec = in_neighbor->spec();
- if(neighbor_spec.width != width || neighbor_spec.height != height) {
- error = "Neighbor frame has different dimensions: " + filepath;
- return false;
- }
-
- foreach(DenoiseImageLayer& layer, layers) {
- if(!layer.match_channels(neighbor,
- in_spec.channelnames,
- neighbor_spec.channelnames))
- {
- error = "Neighbor frame misses denoising data passes: " + filepath;
- return false;
- }
- }
-
- in_neighbors.push_back(std::move(in_neighbor));
- }
-
- return true;
-}
-
-bool DenoiseImage::save_output(const string& out_filepath, string& error)
-{
- /* Save image with identical dimensions, channels and metadata. */
- ImageSpec out_spec = in_spec;
-
- /* Ensure that the output frame contains sample information even if the input didn't. */
- for(int i = 0; i < layers.size(); i++) {
- string name = "cycles." + layers[i].name + ".samples";
- if(!out_spec.find_attribute(name, TypeDesc::STRING)) {
- out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
- }
- }
+ if (!Filesystem::is_regular(filepath)) {
+ error = "Couldn't find neighbor frame: " + filepath;
+ return false;
+ }
+
+ unique_ptr<ImageInput> in_neighbor(ImageInput::open(filepath));
+ if (!in_neighbor) {
+ error = "Couldn't open neighbor frame: " + filepath;
+ return false;
+ }
+
+ const ImageSpec &neighbor_spec = in_neighbor->spec();
+ if (neighbor_spec.width != width || neighbor_spec.height != height) {
+ error = "Neighbor frame has different dimensions: " + filepath;
+ return false;
+ }
+
+ foreach (DenoiseImageLayer &layer, layers) {
+ if (!layer.match_channels(neighbor, in_spec.channelnames, neighbor_spec.channelnames)) {
+ error = "Neighbor frame misses denoising data passes: " + filepath;
+ return false;
+ }
+ }
+
+ in_neighbors.push_back(std::move(in_neighbor));
+ }
+
+ return true;
+}
+
+bool DenoiseImage::save_output(const string &out_filepath, string &error)
+{
+ /* Save image with identical dimensions, channels and metadata. */
+ ImageSpec out_spec = in_spec;
+
+ /* Ensure that the output frame contains sample information even if the input didn't. */
+ for (int i = 0; i < layers.size(); i++) {
+ string name = "cycles." + layers[i].name + ".samples";
+ if (!out_spec.find_attribute(name, TypeDesc::STRING)) {
+ out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", layers[i].samples));
+ }
+ }
- /* We don't need input anymore at this point, and will possibly
- * overwrite the same file. */
- close_input();
-
- /* Write to temporary file path, so we denoise images in place and don't
- * risk destroying files when something goes wrong in file saving. */
- string extension = OIIO::Filesystem::extension(out_filepath);
- string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
- string tmp_filepath = out_filepath + unique_name + extension;
- unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
-
- if(!out) {
- error = "Failed to open temporary file " + tmp_filepath + " for writing";
- return false;
- }
-
- /* Open temporary file and write image buffers. */
- if(!out->open(tmp_filepath, out_spec)) {
- error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
- return false;
- }
-
- bool ok = true;
- if(!out->write_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- if(!out->close()) {
- error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- out.reset();
-
- /* Copy temporary file to outputput filepath. */
- string rename_error;
- if(ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
- error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
- ok = false;
- }
-
- if(!ok) {
- OIIO::Filesystem::remove(tmp_filepath);
- }
-
- return ok;
+ /* We don't need input anymore at this point, and will possibly
+ * overwrite the same file. */
+ close_input();
+
+ /* Write to temporary file path, so we denoise images in place and don't
+ * risk destroying files when something goes wrong in file saving. */
+ string extension = OIIO::Filesystem::extension(out_filepath);
+ string unique_name = ".denoise-tmp-" + OIIO::Filesystem::unique_path();
+ string tmp_filepath = out_filepath + unique_name + extension;
+ unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
+
+ if (!out) {
+ error = "Failed to open temporary file " + tmp_filepath + " for writing";
+ return false;
+ }
+
+ /* Open temporary file and write image buffers. */
+ if (!out->open(tmp_filepath, out_spec)) {
+ error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
+ return false;
+ }
+
+ bool ok = true;
+ if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ if (!out->close()) {
+ error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ out.reset();
+
+ /* Copy temporary file to outputput filepath. */
+ string rename_error;
+ if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) {
+ error = "Failed to move denoised image to " + out_filepath + ": " + rename_error;
+ ok = false;
+ }
+
+ if (!ok) {
+ OIIO::Filesystem::remove(tmp_filepath);
+ }
+
+ return ok;
}
/* File pattern handling and outer loop over frames */
-Denoiser::Denoiser(DeviceInfo& device_info)
+Denoiser::Denoiser(DeviceInfo &device_info)
{
- samples_override = 0;
- tile_size = make_int2(64, 64);
+ samples_override = 0;
+ tile_size = make_int2(64, 64);
- num_frames = 0;
+ num_frames = 0;
- /* Initialize task scheduler. */
- TaskScheduler::init();
+ /* Initialize task scheduler. */
+ TaskScheduler::init();
- /* Initialize device. */
- DeviceRequestedFeatures req;
- device = Device::create(device_info, stats, profiler, true);
- device->load_kernels(req);
+ /* Initialize device. */
+ DeviceRequestedFeatures req;
+ device = Device::create(device_info, stats, profiler, true);
+ device->load_kernels(req);
}
Denoiser::~Denoiser()
{
- delete device;
- TaskScheduler::exit();
+ delete device;
+ TaskScheduler::exit();
}
bool Denoiser::run()
{
- assert(input.size() == output.size());
-
- num_frames = output.size();
-
- for(int frame = 0; frame < num_frames; frame++) {
- /* Skip empty output paths. */
- if(output[frame].empty()) {
- continue;
- }
-
- /* Determine neighbor frame numbers that should be used for filtering. */
- vector<int> neighbor_frames;
- for(int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
- if (f >= 0 && f < num_frames && f != frame) {
- neighbor_frames.push_back(f);
- }
- }
-
- /* Execute task. */
- DenoiseTask task(device, this, frame, neighbor_frames);
- if(!task.load()) {
- error = task.error;
- return false;
- }
-
- if(!task.exec()) {
- error = task.error;
- return false;
- }
-
- if(!task.save()) {
- error = task.error;
- return false;
- }
-
- task.free();
- }
-
- return true;
+ assert(input.size() == output.size());
+
+ num_frames = output.size();
+
+ for (int frame = 0; frame < num_frames; frame++) {
+ /* Skip empty output paths. */
+ if (output[frame].empty()) {
+ continue;
+ }
+
+ /* Determine neighbor frame numbers that should be used for filtering. */
+ vector<int> neighbor_frames;
+ for (int f = frame - params.neighbor_frames; f <= frame + params.neighbor_frames; f++) {
+ if (f >= 0 && f < num_frames && f != frame) {
+ neighbor_frames.push_back(f);
+ }
+ }
+
+ /* Execute task. */
+ DenoiseTask task(device, this, frame, neighbor_frames);
+ if (!task.load()) {
+ error = task.error;
+ return false;
+ }
+
+ if (!task.exec()) {
+ error = task.error;
+ return false;
+ }
+
+ if (!task.save()) {
+ error = task.error;
+ return false;
+ }
+
+ task.free();
+ }
+
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/denoising.h b/intern/cycles/render/denoising.h
index 5bf1a8dd0fa..dcb842a4603 100644
--- a/intern/cycles/render/denoising.h
+++ b/intern/cycles/render/denoising.h
@@ -35,166 +35,166 @@ CCL_NAMESPACE_BEGIN
/* Denoiser */
class Denoiser {
-public:
- Denoiser(DeviceInfo& device_info);
- ~Denoiser();
+ public:
+ Denoiser(DeviceInfo &device_info);
+ ~Denoiser();
- bool run();
+ bool run();
- /* Error message after running, in case of failure. */
- string error;
+ /* Error message after running, in case of failure. */
+ string error;
- /* Sequential list of frame filepaths to denoise. */
- vector<string> input;
- /* Sequential list of frame filepaths to write result to. Empty entries
- * are skipped, so only a subset of the sequence can be denoised while
- * taking into account all input frames. */
- vector<string> output;
+ /* Sequential list of frame filepaths to denoise. */
+ vector<string> input;
+ /* Sequential list of frame filepaths to write result to. Empty entries
+ * are skipped, so only a subset of the sequence can be denoised while
+ * taking into account all input frames. */
+ vector<string> output;
- /* Sample number override, takes precedence over values from input frames. */
- int samples_override;
- /* Tile size for processing on device. */
- int2 tile_size;
+ /* Sample number override, takes precedence over values from input frames. */
+ int samples_override;
+ /* Tile size for processing on device. */
+ int2 tile_size;
- /* Equivalent to the settings in the regular denoiser. */
- DenoiseParams params;
+ /* Equivalent to the settings in the regular denoiser. */
+ DenoiseParams params;
-protected:
- friend class DenoiseTask;
+ protected:
+ friend class DenoiseTask;
- Stats stats;
- Profiler profiler;
- Device *device;
+ Stats stats;
+ Profiler profiler;
+ Device *device;
- int num_frames;
+ int num_frames;
};
/* Denoise Image Layer */
struct DenoiseImageLayer {
- string name;
- /* All channels belonging to this DenoiseImageLayer. */
- vector<string> channels;
- /* Layer to image channel mapping. */
- vector<int> layer_to_image_channel;
+ string name;
+ /* All channels belonging to this DenoiseImageLayer. */
+ vector<string> channels;
+ /* Layer to image channel mapping. */
+ vector<int> layer_to_image_channel;
- /* Sample amount that was used for rendering this layer. */
- int samples;
+ /* Sample amount that was used for rendering this layer. */
+ int samples;
- /* Device input channel will be copied from image channel input_to_image_channel[i]. */
- vector<int> input_to_image_channel;
+ /* Device input channel will be copied from image channel input_to_image_channel[i]. */
+ vector<int> input_to_image_channel;
- /* input_to_image_channel of the secondary frames, if any are used. */
- vector<vector<int>> neighbor_input_to_image_channel;
+ /* input_to_image_channel of the secondary frames, if any are used. */
+ vector<vector<int>> neighbor_input_to_image_channel;
- /* Write i-th channel of the processing output to output_to_image_channel[i]-th channel of the file. */
- vector<int> output_to_image_channel;
+ /* Write i-th channel of the processing output to output_to_image_channel[i]-th channel of the file. */
+ vector<int> output_to_image_channel;
- /* Detect whether this layer contains a full set of channels and set up the offsets accordingly. */
- bool detect_denoising_channels();
+ /* Detect whether this layer contains a full set of channels and set up the offsets accordingly. */
+ bool detect_denoising_channels();
- /* Map the channels of a secondary frame to the channels that are required for processing,
- * fill neighbor_input_to_image_channel if all are present or return false if a channel are missing. */
- bool match_channels(int neighbor,
- const std::vector<string> &channelnames,
- const std::vector<string> &neighbor_channelnames);
+ /* Map the channels of a secondary frame to the channels that are required for processing,
+ * fill neighbor_input_to_image_channel if all are present or return false if a channel are missing. */
+ bool match_channels(int neighbor,
+ const std::vector<string> &channelnames,
+ const std::vector<string> &neighbor_channelnames);
};
/* Denoise Image Data */
class DenoiseImage {
-public:
- DenoiseImage();
- ~DenoiseImage();
+ public:
+ DenoiseImage();
+ ~DenoiseImage();
- /* Dimensions */
- int width, height, num_channels;
+ /* Dimensions */
+ int width, height, num_channels;
- /* Samples */
- int samples;
+ /* Samples */
+ int samples;
- /* Pixel buffer with interleaved channels. */
- array<float> pixels;
+ /* Pixel buffer with interleaved channels. */
+ array<float> pixels;
- /* Image file handles */
- ImageSpec in_spec;
- vector<unique_ptr<ImageInput>> in_neighbors;
+ /* Image file handles */
+ ImageSpec in_spec;
+ vector<unique_ptr<ImageInput>> in_neighbors;
- /* Render layers */
- vector<DenoiseImageLayer> layers;
+ /* Render layers */
+ vector<DenoiseImageLayer> layers;
- void free();
+ void free();
- /* Open the input image, parse its channels, open the output image and allocate the output buffer. */
- bool load(const string& in_filepath, string& error);
+ /* Open the input image, parse its channels, open the output image and allocate the output buffer. */
+ bool load(const string &in_filepath, string &error);
- /* Load neighboring frames. */
- bool load_neighbors(const vector<string>& filepaths, const vector<int>& frames, string& error);
+ /* Load neighboring frames. */
+ bool load_neighbors(const vector<string> &filepaths, const vector<int> &frames, string &error);
- /* Load subset of pixels from file buffer into input buffer, as needed for denoising
- * on the device. Channels are reshuffled following the provided mapping. */
- void read_pixels(const DenoiseImageLayer& layer, float *input_pixels);
- bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer& layer, float *input_pixels);
+ /* Load subset of pixels from file buffer into input buffer, as needed for denoising
+ * on the device. Channels are reshuffled following the provided mapping. */
+ void read_pixels(const DenoiseImageLayer &layer, float *input_pixels);
+ bool read_neighbor_pixels(int neighbor, const DenoiseImageLayer &layer, float *input_pixels);
- bool save_output(const string& out_filepath, string& error);
+ bool save_output(const string &out_filepath, string &error);
-protected:
- /* Parse input file channels, separate them into DenoiseImageLayers, detect DenoiseImageLayers with full channel sets,
- * fill layers and set up the output channels and passthrough map. */
- bool parse_channels(const ImageSpec &in_spec, string& error);
+ protected:
+ /* Parse input file channels, separate them into DenoiseImageLayers, detect DenoiseImageLayers with full channel sets,
+ * fill layers and set up the output channels and passthrough map. */
+ bool parse_channels(const ImageSpec &in_spec, string &error);
- void close_input();
+ void close_input();
};
/* Denoise Task */
class DenoiseTask {
-public:
- DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int>& neighbor_frames);
- ~DenoiseTask();
-
- /* Task stages */
- bool load();
- bool exec();
- bool save();
- void free();
-
- string error;
-
-protected:
- /* Denoiser parameters and device */
- Denoiser *denoiser;
- Device *device;
-
- /* Frame number to be denoised */
- int frame;
- vector<int> neighbor_frames;
-
- /* Image file data */
- DenoiseImage image;
- int current_layer;
-
- /* Device input buffer */
- device_vector<float> input_pixels;
-
- /* Tiles */
- thread_mutex tiles_mutex;
- list<RenderTile> tiles;
- int num_tiles;
-
- thread_mutex output_mutex;
- map<int, device_vector<float>*> output_pixels;
-
- /* Task handling */
- bool load_input_pixels(int layer);
- void create_task(DeviceTask& task);
-
- /* Device task callbacks */
- bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
- void map_neighboring_tiles(RenderTile *tiles, Device *tile_device);
- void unmap_neighboring_tiles(RenderTile *tiles);
- void release_tile();
- bool get_cancel();
+ public:
+ DenoiseTask(Device *device, Denoiser *denoiser, int frame, const vector<int> &neighbor_frames);
+ ~DenoiseTask();
+
+ /* Task stages */
+ bool load();
+ bool exec();
+ bool save();
+ void free();
+
+ string error;
+
+ protected:
+ /* Denoiser parameters and device */
+ Denoiser *denoiser;
+ Device *device;
+
+ /* Frame number to be denoised */
+ int frame;
+ vector<int> neighbor_frames;
+
+ /* Image file data */
+ DenoiseImage image;
+ int current_layer;
+
+ /* Device input buffer */
+ device_vector<float> input_pixels;
+
+ /* Tiles */
+ thread_mutex tiles_mutex;
+ list<RenderTile> tiles;
+ int num_tiles;
+
+ thread_mutex output_mutex;
+ map<int, device_vector<float> *> output_pixels;
+
+ /* Task handling */
+ bool load_input_pixels(int layer);
+ void create_task(DeviceTask &task);
+
+ /* Device task callbacks */
+ bool acquire_tile(Device *device, Device *tile_device, RenderTile &tile);
+ void map_neighboring_tiles(RenderTile *tiles, Device *tile_device);
+ void unmap_neighboring_tiles(RenderTile *tiles);
+ void release_tile();
+ bool get_cancel();
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 1d1668a20d1..d6c44b66117 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -31,277 +31,275 @@ CCL_NAMESPACE_BEGIN
/* Pass */
-static bool compare_pass_order(const Pass& a, const Pass& b)
+static bool compare_pass_order(const Pass &a, const Pass &b)
{
- if(a.components == b.components)
- return (a.type < b.type);
- return (a.components > b.components);
+ if (a.components == b.components)
+ return (a.type < b.type);
+ return (a.components > b.components);
}
-void Pass::add(PassType type, vector<Pass>& passes, const char *name)
+void Pass::add(PassType type, vector<Pass> &passes, const char *name)
{
- for(size_t i = 0; i < passes.size(); i++) {
- if(passes[i].type == type &&
- (name ? (passes[i].name == name) : passes[i].name.empty())) {
- return;
- }
- }
-
- Pass pass;
-
- pass.type = type;
- pass.filter = true;
- pass.exposure = false;
- pass.divide_type = PASS_NONE;
- if(name) {
- pass.name = name;
- }
-
- switch(type) {
- case PASS_NONE:
- pass.components = 0;
- break;
- case PASS_COMBINED:
- pass.components = 4;
- pass.exposure = true;
- break;
- case PASS_DEPTH:
- pass.components = 1;
- pass.filter = false;
- break;
- case PASS_MIST:
- pass.components = 1;
- break;
- case PASS_NORMAL:
- pass.components = 4;
- break;
- case PASS_UV:
- pass.components = 4;
- break;
- case PASS_MOTION:
- pass.components = 4;
- pass.divide_type = PASS_MOTION_WEIGHT;
- break;
- case PASS_MOTION_WEIGHT:
- pass.components = 1;
- break;
- case PASS_OBJECT_ID:
- case PASS_MATERIAL_ID:
- pass.components = 1;
- pass.filter = false;
- break;
-
- case PASS_EMISSION:
- case PASS_BACKGROUND:
- pass.components = 4;
- pass.exposure = true;
- break;
- case PASS_AO:
- pass.components = 4;
- break;
- case PASS_SHADOW:
- pass.components = 4;
- pass.exposure = false;
- break;
- case PASS_LIGHT:
- /* This isn't a real pass, used by baking to see whether
- * light data is needed or not.
- *
- * Set components to 0 so pass sort below happens in a
- * determined way.
- */
- pass.components = 0;
- break;
+ for (size_t i = 0; i < passes.size(); i++) {
+ if (passes[i].type == type && (name ? (passes[i].name == name) : passes[i].name.empty())) {
+ return;
+ }
+ }
+
+ Pass pass;
+
+ pass.type = type;
+ pass.filter = true;
+ pass.exposure = false;
+ pass.divide_type = PASS_NONE;
+ if (name) {
+ pass.name = name;
+ }
+
+ switch (type) {
+ case PASS_NONE:
+ pass.components = 0;
+ break;
+ case PASS_COMBINED:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
+ case PASS_DEPTH:
+ pass.components = 1;
+ pass.filter = false;
+ break;
+ case PASS_MIST:
+ pass.components = 1;
+ break;
+ case PASS_NORMAL:
+ pass.components = 4;
+ break;
+ case PASS_UV:
+ pass.components = 4;
+ break;
+ case PASS_MOTION:
+ pass.components = 4;
+ pass.divide_type = PASS_MOTION_WEIGHT;
+ break;
+ case PASS_MOTION_WEIGHT:
+ pass.components = 1;
+ break;
+ case PASS_OBJECT_ID:
+ case PASS_MATERIAL_ID:
+ pass.components = 1;
+ pass.filter = false;
+ break;
+
+ case PASS_EMISSION:
+ case PASS_BACKGROUND:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
+ case PASS_AO:
+ pass.components = 4;
+ break;
+ case PASS_SHADOW:
+ pass.components = 4;
+ pass.exposure = false;
+ break;
+ case PASS_LIGHT:
+ /* This isn't a real pass, used by baking to see whether
+ * light data is needed or not.
+ *
+ * Set components to 0 so pass sort below happens in a
+ * determined way.
+ */
+ pass.components = 0;
+ break;
#ifdef WITH_CYCLES_DEBUG
- case PASS_BVH_TRAVERSED_NODES:
- case PASS_BVH_TRAVERSED_INSTANCES:
- case PASS_BVH_INTERSECTIONS:
- case PASS_RAY_BOUNCES:
- pass.components = 1;
- pass.exposure = false;
- break;
+ case PASS_BVH_TRAVERSED_NODES:
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ case PASS_BVH_INTERSECTIONS:
+ case PASS_RAY_BOUNCES:
+ pass.components = 1;
+ pass.exposure = false;
+ break;
#endif
- case PASS_RENDER_TIME:
- /* This pass is handled entirely on the host side. */
- pass.components = 0;
- break;
-
- case PASS_DIFFUSE_COLOR:
- case PASS_GLOSSY_COLOR:
- case PASS_TRANSMISSION_COLOR:
- case PASS_SUBSURFACE_COLOR:
- pass.components = 4;
- break;
- case PASS_DIFFUSE_DIRECT:
- case PASS_DIFFUSE_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_DIFFUSE_COLOR;
- break;
- case PASS_GLOSSY_DIRECT:
- case PASS_GLOSSY_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_GLOSSY_COLOR;
- break;
- case PASS_TRANSMISSION_DIRECT:
- case PASS_TRANSMISSION_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_TRANSMISSION_COLOR;
- break;
- case PASS_SUBSURFACE_DIRECT:
- case PASS_SUBSURFACE_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- pass.divide_type = PASS_SUBSURFACE_COLOR;
- break;
- case PASS_VOLUME_DIRECT:
- case PASS_VOLUME_INDIRECT:
- pass.components = 4;
- pass.exposure = true;
- break;
- case PASS_CRYPTOMATTE:
- pass.components = 4;
- break;
- default:
- assert(false);
- break;
- }
-
- passes.push_back(pass);
-
- /* order from by components, to ensure alignment so passes with size 4
- * come first and then passes with size 1 */
- sort(&passes[0], &passes[0] + passes.size(), compare_pass_order);
-
- if(pass.divide_type != PASS_NONE)
- Pass::add(pass.divide_type, passes);
+ case PASS_RENDER_TIME:
+ /* This pass is handled entirely on the host side. */
+ pass.components = 0;
+ break;
+
+ case PASS_DIFFUSE_COLOR:
+ case PASS_GLOSSY_COLOR:
+ case PASS_TRANSMISSION_COLOR:
+ case PASS_SUBSURFACE_COLOR:
+ pass.components = 4;
+ break;
+ case PASS_DIFFUSE_DIRECT:
+ case PASS_DIFFUSE_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_DIFFUSE_COLOR;
+ break;
+ case PASS_GLOSSY_DIRECT:
+ case PASS_GLOSSY_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_GLOSSY_COLOR;
+ break;
+ case PASS_TRANSMISSION_DIRECT:
+ case PASS_TRANSMISSION_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_TRANSMISSION_COLOR;
+ break;
+ case PASS_SUBSURFACE_DIRECT:
+ case PASS_SUBSURFACE_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ pass.divide_type = PASS_SUBSURFACE_COLOR;
+ break;
+ case PASS_VOLUME_DIRECT:
+ case PASS_VOLUME_INDIRECT:
+ pass.components = 4;
+ pass.exposure = true;
+ break;
+ case PASS_CRYPTOMATTE:
+ pass.components = 4;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ passes.push_back(pass);
+
+ /* order from by components, to ensure alignment so passes with size 4
+ * come first and then passes with size 1 */
+ sort(&passes[0], &passes[0] + passes.size(), compare_pass_order);
+
+ if (pass.divide_type != PASS_NONE)
+ Pass::add(pass.divide_type, passes);
}
-bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
+bool Pass::equals(const vector<Pass> &A, const vector<Pass> &B)
{
- if(A.size() != B.size())
- return false;
+ if (A.size() != B.size())
+ return false;
- for(int i = 0; i < A.size(); i++)
- if(A[i].type != B[i].type || A[i].name != B[i].name)
- return false;
+ for (int i = 0; i < A.size(); i++)
+ if (A[i].type != B[i].type || A[i].name != B[i].name)
+ return false;
- return true;
+ return true;
}
-bool Pass::contains(const vector<Pass>& passes, PassType type)
+bool Pass::contains(const vector<Pass> &passes, PassType type)
{
- for(size_t i = 0; i < passes.size(); i++)
- if(passes[i].type == type)
- return true;
+ for (size_t i = 0; i < passes.size(); i++)
+ if (passes[i].type == type)
+ return true;
- return false;
+ return false;
}
/* Pixel Filter */
static float filter_func_box(float /*v*/, float /*width*/)
{
- return 1.0f;
+ return 1.0f;
}
static float filter_func_gaussian(float v, float width)
{
- v *= 6.0f/width;
- return expf(-2.0f*v*v);
+ v *= 6.0f / width;
+ return expf(-2.0f * v * v);
}
static float filter_func_blackman_harris(float v, float width)
{
- v = M_2PI_F * (v / width + 0.5f);
- return 0.35875f - 0.48829f*cosf(v) + 0.14128f*cosf(2.0f*v) - 0.01168f*cosf(3.0f*v);
+ v = M_2PI_F * (v / width + 0.5f);
+ return 0.35875f - 0.48829f * cosf(v) + 0.14128f * cosf(2.0f * v) - 0.01168f * cosf(3.0f * v);
}
static vector<float> filter_table(FilterType type, float width)
{
- vector<float> filter_table(FILTER_TABLE_SIZE);
- float (*filter_func)(float, float) = NULL;
-
- switch(type) {
- case FILTER_BOX:
- filter_func = filter_func_box;
- break;
- case FILTER_GAUSSIAN:
- filter_func = filter_func_gaussian;
- width *= 3.0f;
- break;
- case FILTER_BLACKMAN_HARRIS:
- filter_func = filter_func_blackman_harris;
- width *= 2.0f;
- break;
- default:
- assert(0);
- }
-
- /* Create importance sampling table. */
-
- /* TODO(sergey): With the even filter table size resolution we can not
- * really make it nice symmetric importance map without sampling full range
- * (meaning, we would need to sample full filter range and not use the
- * make_symmetric argument).
- *
- * Current code matches exactly initial filter table code, but we should
- * consider either making FILTER_TABLE_SIZE odd value or sample full filter.
- */
-
- util_cdf_inverted(FILTER_TABLE_SIZE,
- 0.0f,
- width * 0.5f,
- function_bind(filter_func, _1, width),
- true,
- filter_table);
-
- return filter_table;
+ vector<float> filter_table(FILTER_TABLE_SIZE);
+ float (*filter_func)(float, float) = NULL;
+
+ switch (type) {
+ case FILTER_BOX:
+ filter_func = filter_func_box;
+ break;
+ case FILTER_GAUSSIAN:
+ filter_func = filter_func_gaussian;
+ width *= 3.0f;
+ break;
+ case FILTER_BLACKMAN_HARRIS:
+ filter_func = filter_func_blackman_harris;
+ width *= 2.0f;
+ break;
+ default:
+ assert(0);
+ }
+
+ /* Create importance sampling table. */
+
+ /* TODO(sergey): With the even filter table size resolution we can not
+ * really make it nice symmetric importance map without sampling full range
+ * (meaning, we would need to sample full filter range and not use the
+ * make_symmetric argument).
+ *
+ * Current code matches exactly initial filter table code, but we should
+ * consider either making FILTER_TABLE_SIZE odd value or sample full filter.
+ */
+
+ util_cdf_inverted(FILTER_TABLE_SIZE,
+ 0.0f,
+ width * 0.5f,
+ function_bind(filter_func, _1, width),
+ true,
+ filter_table);
+
+ return filter_table;
}
/* Film */
NODE_DEFINE(Film)
{
- NodeType* type = NodeType::add("film", create);
+ NodeType *type = NodeType::add("film", create);
- SOCKET_FLOAT(exposure, "Exposure", 0.8f);
- SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.5f);
+ SOCKET_FLOAT(exposure, "Exposure", 0.8f);
+ SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.5f);
- static NodeEnum filter_enum;
- filter_enum.insert("box", FILTER_BOX);
- filter_enum.insert("gaussian", FILTER_GAUSSIAN);
- filter_enum.insert("blackman_harris", FILTER_BLACKMAN_HARRIS);
+ static NodeEnum filter_enum;
+ filter_enum.insert("box", FILTER_BOX);
+ filter_enum.insert("gaussian", FILTER_GAUSSIAN);
+ filter_enum.insert("blackman_harris", FILTER_BLACKMAN_HARRIS);
- SOCKET_ENUM(filter_type, "Filter Type", filter_enum, FILTER_BOX);
- SOCKET_FLOAT(filter_width, "Filter Width", 1.0f);
+ SOCKET_ENUM(filter_type, "Filter Type", filter_enum, FILTER_BOX);
+ SOCKET_FLOAT(filter_width, "Filter Width", 1.0f);
- SOCKET_FLOAT(mist_start, "Mist Start", 0.0f);
- SOCKET_FLOAT(mist_depth, "Mist Depth", 100.0f);
- SOCKET_FLOAT(mist_falloff, "Mist Falloff", 1.0f);
+ SOCKET_FLOAT(mist_start, "Mist Start", 0.0f);
+ SOCKET_FLOAT(mist_depth, "Mist Depth", 100.0f);
+ SOCKET_FLOAT(mist_falloff, "Mist Falloff", 1.0f);
- SOCKET_BOOLEAN(use_sample_clamp, "Use Sample Clamp", false);
+ SOCKET_BOOLEAN(use_sample_clamp, "Use Sample Clamp", false);
- SOCKET_BOOLEAN(denoising_data_pass, "Generate Denoising Data Pass", false);
- SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
- SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
- SOCKET_INT(denoising_flags, "Denoising Flags", 0);
+ SOCKET_BOOLEAN(denoising_data_pass, "Generate Denoising Data Pass", false);
+ SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
+ SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
+ SOCKET_INT(denoising_flags, "Denoising Flags", 0);
- return type;
+ return type;
}
-Film::Film()
-: Node(node_type)
+Film::Film() : Node(node_type)
{
- Pass::add(PASS_COMBINED, passes);
+ Pass::add(PASS_COMBINED, passes);
- use_light_visibility = false;
- filter_table_offset = TABLE_OFFSET_INVALID;
- cryptomatte_passes = CRYPT_NONE;
+ use_light_visibility = false;
+ filter_table_offset = TABLE_OFFSET_INVALID;
+ cryptomatte_passes = CRYPT_NONE;
- need_update = true;
+ need_update = true;
}
Film::~Film()
@@ -310,233 +308,233 @@ Film::~Film()
void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(!need_update)
- return;
-
- device_free(device, dscene, scene);
-
- KernelFilm *kfilm = &dscene->data.film;
-
- /* update __data */
- kfilm->exposure = exposure;
- kfilm->pass_flag = 0;
- kfilm->light_pass_flag = 0;
- kfilm->pass_stride = 0;
- kfilm->use_light_pass = use_light_visibility || use_sample_clamp;
-
- bool have_cryptomatte = false;
-
- for(size_t i = 0; i < passes.size(); i++) {
- Pass& pass = passes[i];
-
- if(pass.type == PASS_NONE) {
- continue;
- }
-
- /* Can't do motion pass if no motion vectors are available. */
- if (pass.type == PASS_MOTION || pass.type == PASS_MOTION_WEIGHT) {
- if (scene->need_motion() != Scene::MOTION_PASS) {
- kfilm->pass_stride += pass.components;
- continue;
- }
- }
-
- int pass_flag = (1 << (pass.type % 32));
- if(pass.type <= PASS_CATEGORY_MAIN_END) {
- kfilm->pass_flag |= pass_flag;
- }
- else {
- assert(pass.type <= PASS_CATEGORY_LIGHT_END);
- kfilm->use_light_pass = 1;
- kfilm->light_pass_flag |= pass_flag;
- }
-
- switch(pass.type) {
- case PASS_COMBINED:
- kfilm->pass_combined = kfilm->pass_stride;
- break;
- case PASS_DEPTH:
- kfilm->pass_depth = kfilm->pass_stride;
- break;
- case PASS_NORMAL:
- kfilm->pass_normal = kfilm->pass_stride;
- break;
- case PASS_UV:
- kfilm->pass_uv = kfilm->pass_stride;
- break;
- case PASS_MOTION:
- kfilm->pass_motion = kfilm->pass_stride;
- break;
- case PASS_MOTION_WEIGHT:
- kfilm->pass_motion_weight = kfilm->pass_stride;
- break;
- case PASS_OBJECT_ID:
- kfilm->pass_object_id = kfilm->pass_stride;
- break;
- case PASS_MATERIAL_ID:
- kfilm->pass_material_id = kfilm->pass_stride;
- break;
-
- case PASS_MIST:
- kfilm->pass_mist = kfilm->pass_stride;
- break;
- case PASS_EMISSION:
- kfilm->pass_emission = kfilm->pass_stride;
- break;
- case PASS_BACKGROUND:
- kfilm->pass_background = kfilm->pass_stride;
- break;
- case PASS_AO:
- kfilm->pass_ao = kfilm->pass_stride;
- break;
- case PASS_SHADOW:
- kfilm->pass_shadow = kfilm->pass_stride;
- break;
-
- case PASS_LIGHT:
- break;
-
- case PASS_DIFFUSE_COLOR:
- kfilm->pass_diffuse_color = kfilm->pass_stride;
- break;
- case PASS_GLOSSY_COLOR:
- kfilm->pass_glossy_color = kfilm->pass_stride;
- break;
- case PASS_TRANSMISSION_COLOR:
- kfilm->pass_transmission_color = kfilm->pass_stride;
- break;
- case PASS_SUBSURFACE_COLOR:
- kfilm->pass_subsurface_color = kfilm->pass_stride;
- break;
- case PASS_DIFFUSE_INDIRECT:
- kfilm->pass_diffuse_indirect = kfilm->pass_stride;
- break;
- case PASS_GLOSSY_INDIRECT:
- kfilm->pass_glossy_indirect = kfilm->pass_stride;
- break;
- case PASS_TRANSMISSION_INDIRECT:
- kfilm->pass_transmission_indirect = kfilm->pass_stride;
- break;
- case PASS_SUBSURFACE_INDIRECT:
- kfilm->pass_subsurface_indirect = kfilm->pass_stride;
- break;
- case PASS_VOLUME_INDIRECT:
- kfilm->pass_volume_indirect = kfilm->pass_stride;
- break;
- case PASS_DIFFUSE_DIRECT:
- kfilm->pass_diffuse_direct = kfilm->pass_stride;
- break;
- case PASS_GLOSSY_DIRECT:
- kfilm->pass_glossy_direct = kfilm->pass_stride;
- break;
- case PASS_TRANSMISSION_DIRECT:
- kfilm->pass_transmission_direct = kfilm->pass_stride;
- break;
- case PASS_SUBSURFACE_DIRECT:
- kfilm->pass_subsurface_direct = kfilm->pass_stride;
- break;
- case PASS_VOLUME_DIRECT:
- kfilm->pass_volume_direct = kfilm->pass_stride;
- break;
+ if (!need_update)
+ return;
+
+ device_free(device, dscene, scene);
+
+ KernelFilm *kfilm = &dscene->data.film;
+
+ /* update __data */
+ kfilm->exposure = exposure;
+ kfilm->pass_flag = 0;
+ kfilm->light_pass_flag = 0;
+ kfilm->pass_stride = 0;
+ kfilm->use_light_pass = use_light_visibility || use_sample_clamp;
+
+ bool have_cryptomatte = false;
+
+ for (size_t i = 0; i < passes.size(); i++) {
+ Pass &pass = passes[i];
+
+ if (pass.type == PASS_NONE) {
+ continue;
+ }
+
+ /* Can't do motion pass if no motion vectors are available. */
+ if (pass.type == PASS_MOTION || pass.type == PASS_MOTION_WEIGHT) {
+ if (scene->need_motion() != Scene::MOTION_PASS) {
+ kfilm->pass_stride += pass.components;
+ continue;
+ }
+ }
+
+ int pass_flag = (1 << (pass.type % 32));
+ if (pass.type <= PASS_CATEGORY_MAIN_END) {
+ kfilm->pass_flag |= pass_flag;
+ }
+ else {
+ assert(pass.type <= PASS_CATEGORY_LIGHT_END);
+ kfilm->use_light_pass = 1;
+ kfilm->light_pass_flag |= pass_flag;
+ }
+
+ switch (pass.type) {
+ case PASS_COMBINED:
+ kfilm->pass_combined = kfilm->pass_stride;
+ break;
+ case PASS_DEPTH:
+ kfilm->pass_depth = kfilm->pass_stride;
+ break;
+ case PASS_NORMAL:
+ kfilm->pass_normal = kfilm->pass_stride;
+ break;
+ case PASS_UV:
+ kfilm->pass_uv = kfilm->pass_stride;
+ break;
+ case PASS_MOTION:
+ kfilm->pass_motion = kfilm->pass_stride;
+ break;
+ case PASS_MOTION_WEIGHT:
+ kfilm->pass_motion_weight = kfilm->pass_stride;
+ break;
+ case PASS_OBJECT_ID:
+ kfilm->pass_object_id = kfilm->pass_stride;
+ break;
+ case PASS_MATERIAL_ID:
+ kfilm->pass_material_id = kfilm->pass_stride;
+ break;
+
+ case PASS_MIST:
+ kfilm->pass_mist = kfilm->pass_stride;
+ break;
+ case PASS_EMISSION:
+ kfilm->pass_emission = kfilm->pass_stride;
+ break;
+ case PASS_BACKGROUND:
+ kfilm->pass_background = kfilm->pass_stride;
+ break;
+ case PASS_AO:
+ kfilm->pass_ao = kfilm->pass_stride;
+ break;
+ case PASS_SHADOW:
+ kfilm->pass_shadow = kfilm->pass_stride;
+ break;
+
+ case PASS_LIGHT:
+ break;
+
+ case PASS_DIFFUSE_COLOR:
+ kfilm->pass_diffuse_color = kfilm->pass_stride;
+ break;
+ case PASS_GLOSSY_COLOR:
+ kfilm->pass_glossy_color = kfilm->pass_stride;
+ break;
+ case PASS_TRANSMISSION_COLOR:
+ kfilm->pass_transmission_color = kfilm->pass_stride;
+ break;
+ case PASS_SUBSURFACE_COLOR:
+ kfilm->pass_subsurface_color = kfilm->pass_stride;
+ break;
+ case PASS_DIFFUSE_INDIRECT:
+ kfilm->pass_diffuse_indirect = kfilm->pass_stride;
+ break;
+ case PASS_GLOSSY_INDIRECT:
+ kfilm->pass_glossy_indirect = kfilm->pass_stride;
+ break;
+ case PASS_TRANSMISSION_INDIRECT:
+ kfilm->pass_transmission_indirect = kfilm->pass_stride;
+ break;
+ case PASS_SUBSURFACE_INDIRECT:
+ kfilm->pass_subsurface_indirect = kfilm->pass_stride;
+ break;
+ case PASS_VOLUME_INDIRECT:
+ kfilm->pass_volume_indirect = kfilm->pass_stride;
+ break;
+ case PASS_DIFFUSE_DIRECT:
+ kfilm->pass_diffuse_direct = kfilm->pass_stride;
+ break;
+ case PASS_GLOSSY_DIRECT:
+ kfilm->pass_glossy_direct = kfilm->pass_stride;
+ break;
+ case PASS_TRANSMISSION_DIRECT:
+ kfilm->pass_transmission_direct = kfilm->pass_stride;
+ break;
+ case PASS_SUBSURFACE_DIRECT:
+ kfilm->pass_subsurface_direct = kfilm->pass_stride;
+ break;
+ case PASS_VOLUME_DIRECT:
+ kfilm->pass_volume_direct = kfilm->pass_stride;
+ break;
#ifdef WITH_CYCLES_DEBUG
- case PASS_BVH_TRAVERSED_NODES:
- kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
- break;
- case PASS_BVH_TRAVERSED_INSTANCES:
- kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
- break;
- case PASS_BVH_INTERSECTIONS:
- kfilm->pass_bvh_intersections = kfilm->pass_stride;
- break;
- case PASS_RAY_BOUNCES:
- kfilm->pass_ray_bounces = kfilm->pass_stride;
- break;
+ case PASS_BVH_TRAVERSED_NODES:
+ kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
+ break;
+ case PASS_BVH_TRAVERSED_INSTANCES:
+ kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
+ break;
+ case PASS_BVH_INTERSECTIONS:
+ kfilm->pass_bvh_intersections = kfilm->pass_stride;
+ break;
+ case PASS_RAY_BOUNCES:
+ kfilm->pass_ray_bounces = kfilm->pass_stride;
+ break;
#endif
- case PASS_RENDER_TIME:
- break;
- case PASS_CRYPTOMATTE:
- kfilm->pass_cryptomatte = have_cryptomatte ? min(kfilm->pass_cryptomatte, kfilm->pass_stride) : kfilm->pass_stride;
- have_cryptomatte = true;
- break;
- default:
- assert(false);
- break;
- }
-
- kfilm->pass_stride += pass.components;
- }
-
- kfilm->pass_denoising_data = 0;
- kfilm->pass_denoising_clean = 0;
- kfilm->denoising_flags = 0;
- if(denoising_data_pass) {
- kfilm->pass_denoising_data = kfilm->pass_stride;
- kfilm->pass_stride += DENOISING_PASS_SIZE_BASE;
- kfilm->denoising_flags = denoising_flags;
- if(denoising_clean_pass) {
- kfilm->pass_denoising_clean = kfilm->pass_stride;
- kfilm->pass_stride += DENOISING_PASS_SIZE_CLEAN;
- kfilm->use_light_pass = 1;
- }
- if(denoising_prefiltered_pass) {
- kfilm->pass_stride += DENOISING_PASS_SIZE_PREFILTERED;
- }
- }
-
- kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
- kfilm->pass_alpha_threshold = pass_alpha_threshold;
-
- /* update filter table */
- vector<float> table = filter_table(filter_type, filter_width);
- scene->lookup_tables->remove_table(&filter_table_offset);
- filter_table_offset = scene->lookup_tables->add_table(dscene, table);
- kfilm->filter_table_offset = (int)filter_table_offset;
-
- /* mist pass parameters */
- kfilm->mist_start = mist_start;
- kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f;
- kfilm->mist_falloff = mist_falloff;
-
- kfilm->cryptomatte_passes = cryptomatte_passes;
- kfilm->cryptomatte_depth = cryptomatte_depth;
-
- pass_stride = kfilm->pass_stride;
- denoising_data_offset = kfilm->pass_denoising_data;
- denoising_clean_offset = kfilm->pass_denoising_clean;
-
- need_update = false;
+ case PASS_RENDER_TIME:
+ break;
+ case PASS_CRYPTOMATTE:
+ kfilm->pass_cryptomatte = have_cryptomatte ?
+ min(kfilm->pass_cryptomatte, kfilm->pass_stride) :
+ kfilm->pass_stride;
+ have_cryptomatte = true;
+ break;
+ default:
+ assert(false);
+ break;
+ }
+
+ kfilm->pass_stride += pass.components;
+ }
+
+ kfilm->pass_denoising_data = 0;
+ kfilm->pass_denoising_clean = 0;
+ kfilm->denoising_flags = 0;
+ if (denoising_data_pass) {
+ kfilm->pass_denoising_data = kfilm->pass_stride;
+ kfilm->pass_stride += DENOISING_PASS_SIZE_BASE;
+ kfilm->denoising_flags = denoising_flags;
+ if (denoising_clean_pass) {
+ kfilm->pass_denoising_clean = kfilm->pass_stride;
+ kfilm->pass_stride += DENOISING_PASS_SIZE_CLEAN;
+ kfilm->use_light_pass = 1;
+ }
+ if (denoising_prefiltered_pass) {
+ kfilm->pass_stride += DENOISING_PASS_SIZE_PREFILTERED;
+ }
+ }
+
+ kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
+ kfilm->pass_alpha_threshold = pass_alpha_threshold;
+
+ /* update filter table */
+ vector<float> table = filter_table(filter_type, filter_width);
+ scene->lookup_tables->remove_table(&filter_table_offset);
+ filter_table_offset = scene->lookup_tables->add_table(dscene, table);
+ kfilm->filter_table_offset = (int)filter_table_offset;
+
+ /* mist pass parameters */
+ kfilm->mist_start = mist_start;
+ kfilm->mist_inv_depth = (mist_depth > 0.0f) ? 1.0f / mist_depth : 0.0f;
+ kfilm->mist_falloff = mist_falloff;
+
+ kfilm->cryptomatte_passes = cryptomatte_passes;
+ kfilm->cryptomatte_depth = cryptomatte_depth;
+
+ pass_stride = kfilm->pass_stride;
+ denoising_data_offset = kfilm->pass_denoising_data;
+ denoising_clean_offset = kfilm->pass_denoising_clean;
+
+ need_update = false;
}
-void Film::device_free(Device * /*device*/,
- DeviceScene * /*dscene*/,
- Scene *scene)
+void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *scene)
{
- scene->lookup_tables->remove_table(&filter_table_offset);
+ scene->lookup_tables->remove_table(&filter_table_offset);
}
-bool Film::modified(const Film& film)
+bool Film::modified(const Film &film)
{
- return !Node::equals(film) || !Pass::equals(passes, film.passes);
+ return !Node::equals(film) || !Pass::equals(passes, film.passes);
}
-void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
+void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_)
{
- if(Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
- scene->mesh_manager->tag_update(scene);
+ if (Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
+ scene->mesh_manager->tag_update(scene);
- foreach(Shader *shader, scene->shaders)
- shader->need_update_mesh = true;
- }
- else if(Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
- scene->mesh_manager->tag_update(scene);
+ foreach (Shader *shader, scene->shaders)
+ shader->need_update_mesh = true;
+ }
+ else if (Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
+ scene->mesh_manager->tag_update(scene);
- passes = passes_;
+ passes = passes_;
}
void Film::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index 8330a4cf413..1cfa7c3b77d 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -31,69 +31,69 @@ class DeviceScene;
class Scene;
typedef enum FilterType {
- FILTER_BOX,
- FILTER_GAUSSIAN,
- FILTER_BLACKMAN_HARRIS,
+ FILTER_BOX,
+ FILTER_GAUSSIAN,
+ FILTER_BLACKMAN_HARRIS,
- FILTER_NUM_TYPES,
+ FILTER_NUM_TYPES,
} FilterType;
class Pass {
-public:
- PassType type;
- int components;
- bool filter;
- bool exposure;
- PassType divide_type;
- string name;
-
- static void add(PassType type, vector<Pass>& passes, const char* name = NULL);
- static bool equals(const vector<Pass>& A, const vector<Pass>& B);
- static bool contains(const vector<Pass>& passes, PassType);
+ public:
+ PassType type;
+ int components;
+ bool filter;
+ bool exposure;
+ PassType divide_type;
+ string name;
+
+ static void add(PassType type, vector<Pass> &passes, const char *name = NULL);
+ static bool equals(const vector<Pass> &A, const vector<Pass> &B);
+ static bool contains(const vector<Pass> &passes, PassType);
};
class Film : public Node {
-public:
- NODE_DECLARE
+ public:
+ NODE_DECLARE
- float exposure;
- vector<Pass> passes;
- bool denoising_data_pass;
- bool denoising_clean_pass;
- bool denoising_prefiltered_pass;
- int denoising_flags;
- float pass_alpha_threshold;
+ float exposure;
+ vector<Pass> passes;
+ bool denoising_data_pass;
+ bool denoising_clean_pass;
+ bool denoising_prefiltered_pass;
+ int denoising_flags;
+ float pass_alpha_threshold;
- int pass_stride;
- int denoising_data_offset;
- int denoising_clean_offset;
+ int pass_stride;
+ int denoising_data_offset;
+ int denoising_clean_offset;
- FilterType filter_type;
- float filter_width;
- size_t filter_table_offset;
+ FilterType filter_type;
+ float filter_width;
+ size_t filter_table_offset;
- float mist_start;
- float mist_depth;
- float mist_falloff;
+ float mist_start;
+ float mist_depth;
+ float mist_falloff;
- bool use_light_visibility;
- bool use_sample_clamp;
- CryptomatteType cryptomatte_passes;
- int cryptomatte_depth;
+ bool use_light_visibility;
+ bool use_sample_clamp;
+ CryptomatteType cryptomatte_passes;
+ int cryptomatte_depth;
- bool need_update;
+ bool need_update;
- Film();
- ~Film();
+ Film();
+ ~Film();
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
- bool modified(const Film& film);
- void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
- void tag_update(Scene *scene);
+ bool modified(const Film &film);
+ void tag_passes_update(Scene *scene, const vector<Pass> &passes_);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __FILM_H__ */
+#endif /* __FILM_H__ */
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index eea1bed58dc..c284c64b5bf 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -33,388 +33,385 @@ namespace {
bool check_node_inputs_has_links(const ShaderNode *node)
{
- foreach(const ShaderInput *in, node->inputs) {
- if(in->link) {
- return true;
- }
- }
- return false;
+ foreach (const ShaderInput *in, node->inputs) {
+ if (in->link) {
+ return true;
+ }
+ }
+ return false;
}
-bool check_node_inputs_traversed(const ShaderNode *node,
- const ShaderNodeSet& done)
+bool check_node_inputs_traversed(const ShaderNode *node, const ShaderNodeSet &done)
{
- foreach(const ShaderInput *in, node->inputs) {
- if(in->link) {
- if(done.find(in->link->parent) == done.end()) {
- return false;
- }
- }
- }
- return true;
+ foreach (const ShaderInput *in, node->inputs) {
+ if (in->link) {
+ if (done.find(in->link->parent) == done.end()) {
+ return false;
+ }
+ }
+ }
+ return true;
}
-} /* namespace */
+} /* namespace */
/* Node */
-ShaderNode::ShaderNode(const NodeType *type)
-: Node(type)
+ShaderNode::ShaderNode(const NodeType *type) : Node(type)
{
- name = type->name;
- id = -1;
- bump = SHADER_BUMP_NONE;
- special_type = SHADER_SPECIAL_TYPE_NONE;
+ name = type->name;
+ id = -1;
+ bump = SHADER_BUMP_NONE;
+ special_type = SHADER_SPECIAL_TYPE_NONE;
- create_inputs_outputs(type);
+ create_inputs_outputs(type);
}
ShaderNode::~ShaderNode()
{
- foreach(ShaderInput *socket, inputs)
- delete socket;
+ foreach (ShaderInput *socket, inputs)
+ delete socket;
- foreach(ShaderOutput *socket, outputs)
- delete socket;
+ foreach (ShaderOutput *socket, outputs)
+ delete socket;
}
void ShaderNode::create_inputs_outputs(const NodeType *type)
{
- foreach(const SocketType& socket, type->inputs) {
- if(socket.flags & SocketType::LINKABLE) {
- inputs.push_back(new ShaderInput(socket, this));
- }
- }
-
- foreach(const SocketType& socket, type->outputs) {
- outputs.push_back(new ShaderOutput(socket, this));
- }
+ foreach (const SocketType &socket, type->inputs) {
+ if (socket.flags & SocketType::LINKABLE) {
+ inputs.push_back(new ShaderInput(socket, this));
+ }
+ }
+
+ foreach (const SocketType &socket, type->outputs) {
+ outputs.push_back(new ShaderOutput(socket, this));
+ }
}
ShaderInput *ShaderNode::input(const char *name)
{
- foreach(ShaderInput *socket, inputs) {
- if(socket->name() == name)
- return socket;
- }
+ foreach (ShaderInput *socket, inputs) {
+ if (socket->name() == name)
+ return socket;
+ }
- return NULL;
+ return NULL;
}
ShaderOutput *ShaderNode::output(const char *name)
{
- foreach(ShaderOutput *socket, outputs)
- if(socket->name() == name)
- return socket;
+ foreach (ShaderOutput *socket, outputs)
+ if (socket->name() == name)
+ return socket;
- return NULL;
+ return NULL;
}
ShaderInput *ShaderNode::input(ustring name)
{
- foreach(ShaderInput *socket, inputs) {
- if(socket->name() == name)
- return socket;
- }
+ foreach (ShaderInput *socket, inputs) {
+ if (socket->name() == name)
+ return socket;
+ }
- return NULL;
+ return NULL;
}
ShaderOutput *ShaderNode::output(ustring name)
{
- foreach(ShaderOutput *socket, outputs)
- if(socket->name() == name)
- return socket;
+ foreach (ShaderOutput *socket, outputs)
+ if (socket->name() == name)
+ return socket;
- return NULL;
+ return NULL;
}
void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- foreach(ShaderInput *input, inputs) {
- if(!input->link) {
- if(input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
- if(shader->has_surface)
- attributes->add(ATTR_STD_GENERATED);
- if(shader->has_volume)
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
- else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
- if(shader->has_surface)
- attributes->add(ATTR_STD_UV);
- }
- }
- }
+ foreach (ShaderInput *input, inputs) {
+ if (!input->link) {
+ if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
+ if (shader->has_surface)
+ attributes->add(ATTR_STD_GENERATED);
+ if (shader->has_volume)
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+ else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
+ if (shader->has_surface)
+ attributes->add(ATTR_STD_UV);
+ }
+ }
+ }
}
-bool ShaderNode::equals(const ShaderNode& other)
+bool ShaderNode::equals(const ShaderNode &other)
{
- if(type != other.type || bump != other.bump) {
- return false;
- }
-
- assert(inputs.size() == other.inputs.size());
-
- /* Compare unlinkable sockets */
- foreach(const SocketType& socket, type->inputs) {
- if(!(socket.flags & SocketType::LINKABLE)) {
- if(!Node::equals_value(other, socket)) {
- return false;
- }
- }
- }
-
- /* Compare linkable input sockets */
- for(int i = 0; i < inputs.size(); ++i) {
- ShaderInput *input_a = inputs[i],
- *input_b = other.inputs[i];
- if(input_a->link == NULL && input_b->link == NULL) {
- /* Unconnected inputs are expected to have the same value. */
- if(!Node::equals_value(other, input_a->socket_type)) {
- return false;
- }
- }
- else if(input_a->link != NULL && input_b->link != NULL) {
- /* Expect links are to come from the same exact socket. */
- if(input_a->link != input_b->link) {
- return false;
- }
- }
- else {
- /* One socket has a link and another has not, inputs can't be
- * considered equal.
- */
- return false;
- }
- }
-
- return true;
+ if (type != other.type || bump != other.bump) {
+ return false;
+ }
+
+ assert(inputs.size() == other.inputs.size());
+
+ /* Compare unlinkable sockets */
+ foreach (const SocketType &socket, type->inputs) {
+ if (!(socket.flags & SocketType::LINKABLE)) {
+ if (!Node::equals_value(other, socket)) {
+ return false;
+ }
+ }
+ }
+
+ /* Compare linkable input sockets */
+ for (int i = 0; i < inputs.size(); ++i) {
+ ShaderInput *input_a = inputs[i], *input_b = other.inputs[i];
+ if (input_a->link == NULL && input_b->link == NULL) {
+ /* Unconnected inputs are expected to have the same value. */
+ if (!Node::equals_value(other, input_a->socket_type)) {
+ return false;
+ }
+ }
+ else if (input_a->link != NULL && input_b->link != NULL) {
+ /* Expect links are to come from the same exact socket. */
+ if (input_a->link != input_b->link) {
+ return false;
+ }
+ }
+ else {
+ /* One socket has a link and another has not, inputs can't be
+ * considered equal.
+ */
+ return false;
+ }
+ }
+
+ return true;
}
/* Graph */
ShaderGraph::ShaderGraph()
{
- finalized = false;
- simplified = false;
- num_node_ids = 0;
- add(new OutputNode());
+ finalized = false;
+ simplified = false;
+ num_node_ids = 0;
+ add(new OutputNode());
}
ShaderGraph::~ShaderGraph()
{
- clear_nodes();
+ clear_nodes();
}
ShaderNode *ShaderGraph::add(ShaderNode *node)
{
- assert(!finalized);
- simplified = false;
+ assert(!finalized);
+ simplified = false;
- node->id = num_node_ids++;
- nodes.push_back(node);
- return node;
+ node->id = num_node_ids++;
+ nodes.push_back(node);
+ return node;
}
OutputNode *ShaderGraph::output()
{
- return (OutputNode*)nodes.front();
+ return (OutputNode *)nodes.front();
}
void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
{
- assert(!finalized);
- assert(from && to);
-
- if(to->link) {
- fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
- return;
- }
-
- if(from->type() != to->type()) {
- /* can't do automatic conversion from closure */
- if(from->type() == SocketType::CLOSURE) {
- fprintf(stderr, "Cycles shader graph connect: can only connect closure to closure "
- "(%s.%s to %s.%s).\n",
- from->parent->name.c_str(), from->name().c_str(),
- to->parent->name.c_str(), to->name().c_str());
- return;
- }
-
- /* add automatic conversion node in case of type mismatch */
- ShaderNode *convert;
- ShaderInput *convert_in;
-
- if(to->type() == SocketType::CLOSURE) {
- EmissionNode *emission = new EmissionNode();
- emission->color = make_float3(1.0f, 1.0f, 1.0f);
- emission->strength = 1.0f;
- convert = add(emission);
- /* Connect float inputs to Strength to save an additional Falue->Color conversion. */
- if(from->type() == SocketType::FLOAT) {
- convert_in = convert->input("Strength");
- }
- else {
- convert_in = convert->input("Color");
- }
- }
- else {
- convert = add(new ConvertNode(from->type(), to->type(), true));
- convert_in = convert->inputs[0];
- }
-
- connect(from, convert_in);
- connect(convert->outputs[0], to);
- }
- else {
- /* types match, just connect */
- to->link = from;
- from->links.push_back(to);
- }
+ assert(!finalized);
+ assert(from && to);
+
+ if (to->link) {
+ fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
+ return;
+ }
+
+ if (from->type() != to->type()) {
+ /* can't do automatic conversion from closure */
+ if (from->type() == SocketType::CLOSURE) {
+ fprintf(stderr,
+ "Cycles shader graph connect: can only connect closure to closure "
+ "(%s.%s to %s.%s).\n",
+ from->parent->name.c_str(),
+ from->name().c_str(),
+ to->parent->name.c_str(),
+ to->name().c_str());
+ return;
+ }
+
+ /* add automatic conversion node in case of type mismatch */
+ ShaderNode *convert;
+ ShaderInput *convert_in;
+
+ if (to->type() == SocketType::CLOSURE) {
+ EmissionNode *emission = new EmissionNode();
+ emission->color = make_float3(1.0f, 1.0f, 1.0f);
+ emission->strength = 1.0f;
+ convert = add(emission);
+ /* Connect float inputs to Strength to save an additional Falue->Color conversion. */
+ if (from->type() == SocketType::FLOAT) {
+ convert_in = convert->input("Strength");
+ }
+ else {
+ convert_in = convert->input("Color");
+ }
+ }
+ else {
+ convert = add(new ConvertNode(from->type(), to->type(), true));
+ convert_in = convert->inputs[0];
+ }
+
+ connect(from, convert_in);
+ connect(convert->outputs[0], to);
+ }
+ else {
+ /* types match, just connect */
+ to->link = from;
+ from->links.push_back(to);
+ }
}
void ShaderGraph::disconnect(ShaderOutput *from)
{
- assert(!finalized);
- simplified = false;
+ assert(!finalized);
+ simplified = false;
- foreach(ShaderInput *sock, from->links) {
- sock->link = NULL;
- }
+ foreach (ShaderInput *sock, from->links) {
+ sock->link = NULL;
+ }
- from->links.clear();
+ from->links.clear();
}
void ShaderGraph::disconnect(ShaderInput *to)
{
- assert(!finalized);
- assert(to->link);
- simplified = false;
+ assert(!finalized);
+ assert(to->link);
+ simplified = false;
- ShaderOutput *from = to->link;
+ ShaderOutput *from = to->link;
- to->link = NULL;
- from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
+ to->link = NULL;
+ from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
}
void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
{
- simplified = false;
-
- /* Copy because disconnect modifies this list */
- vector<ShaderInput*> outputs = from->links;
-
- /* Bypass node by moving all links from "from" to "to" */
- foreach(ShaderInput *sock, node->inputs) {
- if(sock->link)
- disconnect(sock);
- }
-
- foreach(ShaderInput *sock, outputs) {
- disconnect(sock);
- if(to)
- connect(to, sock);
- }
+ simplified = false;
+
+ /* Copy because disconnect modifies this list */
+ vector<ShaderInput *> outputs = from->links;
+
+ /* Bypass node by moving all links from "from" to "to" */
+ foreach (ShaderInput *sock, node->inputs) {
+ if (sock->link)
+ disconnect(sock);
+ }
+
+ foreach (ShaderInput *sock, outputs) {
+ disconnect(sock);
+ if (to)
+ connect(to, sock);
+ }
}
void ShaderGraph::simplify(Scene *scene)
{
- if(!simplified) {
- default_inputs(scene->shader_manager->use_osl());
- clean(scene);
- refine_bump_nodes();
+ if (!simplified) {
+ default_inputs(scene->shader_manager->use_osl());
+ clean(scene);
+ refine_bump_nodes();
- simplified = true;
- }
+ simplified = true;
+ }
}
-void ShaderGraph::finalize(Scene *scene,
- bool do_bump,
- bool do_simplify,
- bool bump_in_object_space)
+void ShaderGraph::finalize(Scene *scene, bool do_bump, bool do_simplify, bool bump_in_object_space)
{
- /* before compiling, the shader graph may undergo a number of modifications.
- * currently we set default geometry shader inputs, and create automatic bump
- * from displacement. a graph can be finalized only once, and should not be
- * modified afterwards. */
+ /* before compiling, the shader graph may undergo a number of modifications.
+ * currently we set default geometry shader inputs, and create automatic bump
+ * from displacement. a graph can be finalized only once, and should not be
+ * modified afterwards. */
- if(!finalized) {
- simplify(scene);
+ if (!finalized) {
+ simplify(scene);
- if(do_bump)
- bump_from_displacement(bump_in_object_space);
+ if (do_bump)
+ bump_from_displacement(bump_in_object_space);
- ShaderInput *surface_in = output()->input("Surface");
- ShaderInput *volume_in = output()->input("Volume");
+ ShaderInput *surface_in = output()->input("Surface");
+ ShaderInput *volume_in = output()->input("Volume");
- /* todo: make this work when surface and volume closures are tangled up */
+ /* todo: make this work when surface and volume closures are tangled up */
- if(surface_in->link)
- transform_multi_closure(surface_in->link->parent, NULL, false);
- if(volume_in->link)
- transform_multi_closure(volume_in->link->parent, NULL, true);
+ if (surface_in->link)
+ transform_multi_closure(surface_in->link->parent, NULL, false);
+ if (volume_in->link)
+ transform_multi_closure(volume_in->link->parent, NULL, true);
- finalized = true;
- }
- else if(do_simplify) {
- simplify_settings(scene);
- }
+ finalized = true;
+ }
+ else if (do_simplify) {
+ simplify_settings(scene);
+ }
}
-void ShaderGraph::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
+void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
{
- /* find all nodes that this input depends on directly and indirectly */
- ShaderNode *node = (input->link)? input->link->parent: NULL;
+ /* find all nodes that this input depends on directly and indirectly */
+ ShaderNode *node = (input->link) ? input->link->parent : NULL;
- if(node != NULL && dependencies.find(node) == dependencies.end()) {
- foreach(ShaderInput *in, node->inputs)
- find_dependencies(dependencies, in);
+ if (node != NULL && dependencies.find(node) == dependencies.end()) {
+ foreach (ShaderInput *in, node->inputs)
+ find_dependencies(dependencies, in);
- dependencies.insert(node);
- }
+ dependencies.insert(node);
+ }
}
void ShaderGraph::clear_nodes()
{
- foreach(ShaderNode *node, nodes) {
- delete node;
- }
- nodes.clear();
+ foreach (ShaderNode *node, nodes) {
+ delete node;
+ }
+ nodes.clear();
}
-void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
+void ShaderGraph::copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
{
- /* copy a set of nodes, and the links between them. the assumption is
- * made that all nodes that inputs are linked to are in the set too. */
-
- /* copy nodes */
- foreach(ShaderNode *node, nodes) {
- ShaderNode *nnode = node->clone();
- nnodemap[node] = nnode;
-
- /* create new inputs and outputs to recreate links and ensure
- * that we still point to valid SocketType if the NodeType
- * changed in cloning, as it does for OSL nodes */
- nnode->inputs.clear();
- nnode->outputs.clear();
- nnode->create_inputs_outputs(nnode->type);
- }
-
- /* recreate links */
- foreach(ShaderNode *node, nodes) {
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- /* find new input and output */
- ShaderNode *nfrom = nnodemap[input->link->parent];
- ShaderNode *nto = nnodemap[input->parent];
- ShaderOutput *noutput = nfrom->output(input->link->name());
- ShaderInput *ninput = nto->input(input->name());
-
- /* connect */
- connect(noutput, ninput);
- }
- }
- }
+ /* copy a set of nodes, and the links between them. the assumption is
+ * made that all nodes that inputs are linked to are in the set too. */
+
+ /* copy nodes */
+ foreach (ShaderNode *node, nodes) {
+ ShaderNode *nnode = node->clone();
+ nnodemap[node] = nnode;
+
+ /* create new inputs and outputs to recreate links and ensure
+ * that we still point to valid SocketType if the NodeType
+ * changed in cloning, as it does for OSL nodes */
+ nnode->inputs.clear();
+ nnode->outputs.clear();
+ nnode->create_inputs_outputs(nnode->type);
+ }
+
+ /* recreate links */
+ foreach (ShaderNode *node, nodes) {
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ /* find new input and output */
+ ShaderNode *nfrom = nnodemap[input->link->parent];
+ ShaderNode *nto = nnodemap[input->parent];
+ ShaderOutput *noutput = nfrom->output(input->link->name());
+ ShaderInput *ninput = nto->input(input->name());
+
+ /* connect */
+ connect(noutput, ninput);
+ }
+ }
+ }
}
/* Graph simplification */
@@ -427,68 +424,68 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
*/
void ShaderGraph::remove_proxy_nodes()
{
- vector<bool> removed(num_node_ids, false);
- bool any_node_removed = false;
-
- foreach(ShaderNode *node, nodes) {
- if(node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
- ConvertNode *proxy = static_cast<ConvertNode*>(node);
- ShaderInput *input = proxy->inputs[0];
- ShaderOutput *output = proxy->outputs[0];
-
- /* bypass the proxy node */
- if(input->link) {
- relink(proxy, output, input->link);
- }
- else {
- /* Copy because disconnect modifies this list */
- vector<ShaderInput*> links(output->links);
-
- foreach(ShaderInput *to, links) {
- /* remove any autoconvert nodes too if they lead to
- * sockets with an automatically set default value */
- ShaderNode *tonode = to->parent;
-
- if(tonode->special_type == SHADER_SPECIAL_TYPE_AUTOCONVERT) {
- bool all_links_removed = true;
- vector<ShaderInput*> links = tonode->outputs[0]->links;
-
- foreach(ShaderInput *autoin, links) {
- if(autoin->flags() & SocketType::DEFAULT_LINK_MASK)
- disconnect(autoin);
- else
- all_links_removed = false;
- }
-
- if(all_links_removed)
- removed[tonode->id] = true;
- }
-
- disconnect(to);
-
- /* transfer the default input value to the target socket */
- tonode->copy_value(to->socket_type, *proxy, input->socket_type);
- }
- }
-
- removed[proxy->id] = true;
- any_node_removed = true;
- }
- }
-
- /* remove nodes */
- if(any_node_removed) {
- list<ShaderNode*> newnodes;
-
- foreach(ShaderNode *node, nodes) {
- if(!removed[node->id])
- newnodes.push_back(node);
- else
- delete node;
- }
-
- nodes = newnodes;
- }
+ vector<bool> removed(num_node_ids, false);
+ bool any_node_removed = false;
+
+ foreach (ShaderNode *node, nodes) {
+ if (node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
+ ConvertNode *proxy = static_cast<ConvertNode *>(node);
+ ShaderInput *input = proxy->inputs[0];
+ ShaderOutput *output = proxy->outputs[0];
+
+ /* bypass the proxy node */
+ if (input->link) {
+ relink(proxy, output, input->link);
+ }
+ else {
+ /* Copy because disconnect modifies this list */
+ vector<ShaderInput *> links(output->links);
+
+ foreach (ShaderInput *to, links) {
+ /* remove any autoconvert nodes too if they lead to
+ * sockets with an automatically set default value */
+ ShaderNode *tonode = to->parent;
+
+ if (tonode->special_type == SHADER_SPECIAL_TYPE_AUTOCONVERT) {
+ bool all_links_removed = true;
+ vector<ShaderInput *> links = tonode->outputs[0]->links;
+
+ foreach (ShaderInput *autoin, links) {
+ if (autoin->flags() & SocketType::DEFAULT_LINK_MASK)
+ disconnect(autoin);
+ else
+ all_links_removed = false;
+ }
+
+ if (all_links_removed)
+ removed[tonode->id] = true;
+ }
+
+ disconnect(to);
+
+ /* transfer the default input value to the target socket */
+ tonode->copy_value(to->socket_type, *proxy, input->socket_type);
+ }
+ }
+
+ removed[proxy->id] = true;
+ any_node_removed = true;
+ }
+ }
+
+ /* remove nodes */
+ if (any_node_removed) {
+ list<ShaderNode *> newnodes;
+
+ foreach (ShaderNode *node, nodes) {
+ if (!removed[node->id])
+ newnodes.push_back(node);
+ else
+ delete node;
+ }
+
+ nodes = newnodes;
+ }
}
/* Constant folding.
@@ -498,143 +495,143 @@ void ShaderGraph::remove_proxy_nodes()
*/
void ShaderGraph::constant_fold(Scene *scene)
{
- ShaderNodeSet done, scheduled;
- queue<ShaderNode*> traverse_queue;
-
- bool has_displacement = (output()->input("Displacement")->link != NULL);
-
- /* Schedule nodes which doesn't have any dependencies. */
- foreach(ShaderNode *node, nodes) {
- if(!check_node_inputs_has_links(node)) {
- traverse_queue.push(node);
- scheduled.insert(node);
- }
- }
-
- while(!traverse_queue.empty()) {
- ShaderNode *node = traverse_queue.front();
- traverse_queue.pop();
- done.insert(node);
- foreach(ShaderOutput *output, node->outputs) {
- if(output->links.size() == 0) {
- continue;
- }
- /* Schedule node which was depending on the value,
- * when possible. Do it before disconnect.
- */
- foreach(ShaderInput *input, output->links) {
- if(scheduled.find(input->parent) != scheduled.end()) {
- /* Node might not be optimized yet but scheduled already
- * by other dependencies. No need to re-schedule it.
- */
- continue;
- }
- /* Schedule node if its inputs are fully done. */
- if(check_node_inputs_traversed(input->parent, done)) {
- traverse_queue.push(input->parent);
- scheduled.insert(input->parent);
- }
- }
- /* Optimize current node. */
- ConstantFolder folder(this, node, output, scene);
- node->constant_fold(folder);
- }
- }
-
- /* Folding might have removed all nodes connected to the displacement output
- * even tho there is displacement to be applied, so add in a value node if
- * that happens to ensure there is still a valid graph for displacement.
- */
- if(has_displacement && !output()->input("Displacement")->link) {
- ColorNode *value = (ColorNode*)add(new ColorNode());
- value->value = output()->displacement;
-
- connect(value->output("Color"), output()->input("Displacement"));
- }
+ ShaderNodeSet done, scheduled;
+ queue<ShaderNode *> traverse_queue;
+
+ bool has_displacement = (output()->input("Displacement")->link != NULL);
+
+ /* Schedule nodes which doesn't have any dependencies. */
+ foreach (ShaderNode *node, nodes) {
+ if (!check_node_inputs_has_links(node)) {
+ traverse_queue.push(node);
+ scheduled.insert(node);
+ }
+ }
+
+ while (!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ done.insert(node);
+ foreach (ShaderOutput *output, node->outputs) {
+ if (output->links.size() == 0) {
+ continue;
+ }
+ /* Schedule node which was depending on the value,
+ * when possible. Do it before disconnect.
+ */
+ foreach (ShaderInput *input, output->links) {
+ if (scheduled.find(input->parent) != scheduled.end()) {
+ /* Node might not be optimized yet but scheduled already
+ * by other dependencies. No need to re-schedule it.
+ */
+ continue;
+ }
+ /* Schedule node if its inputs are fully done. */
+ if (check_node_inputs_traversed(input->parent, done)) {
+ traverse_queue.push(input->parent);
+ scheduled.insert(input->parent);
+ }
+ }
+ /* Optimize current node. */
+ ConstantFolder folder(this, node, output, scene);
+ node->constant_fold(folder);
+ }
+ }
+
+ /* Folding might have removed all nodes connected to the displacement output
+ * even tho there is displacement to be applied, so add in a value node if
+ * that happens to ensure there is still a valid graph for displacement.
+ */
+ if (has_displacement && !output()->input("Displacement")->link) {
+ ColorNode *value = (ColorNode *)add(new ColorNode());
+ value->value = output()->displacement;
+
+ connect(value->output("Color"), output()->input("Displacement"));
+ }
}
/* Simplification. */
void ShaderGraph::simplify_settings(Scene *scene)
{
- foreach(ShaderNode *node, nodes) {
- node->simplify_settings(scene);
- }
+ foreach (ShaderNode *node, nodes) {
+ node->simplify_settings(scene);
+ }
}
/* Deduplicate nodes with same settings. */
void ShaderGraph::deduplicate_nodes()
{
- /* NOTES:
- * - Deduplication happens for nodes which has same exact settings and same
- * exact input links configuration (either connected to same output or has
- * the same exact default value).
- * - Deduplication happens in the bottom-top manner, so we know for fact that
- * all traversed nodes are either can not be deduplicated at all or were
- * already deduplicated.
- */
-
- ShaderNodeSet scheduled, done;
- map<ustring, ShaderNodeSet> candidates;
- queue<ShaderNode*> traverse_queue;
- int num_deduplicated = 0;
-
- /* Schedule nodes which doesn't have any dependencies. */
- foreach(ShaderNode *node, nodes) {
- if(!check_node_inputs_has_links(node)) {
- traverse_queue.push(node);
- scheduled.insert(node);
- }
- }
-
- while(!traverse_queue.empty()) {
- ShaderNode *node = traverse_queue.front();
- traverse_queue.pop();
- done.insert(node);
- /* Schedule the nodes which were depending on the current node. */
- bool has_output_links = false;
- foreach(ShaderOutput *output, node->outputs) {
- foreach(ShaderInput *input, output->links) {
- has_output_links = true;
- if(scheduled.find(input->parent) != scheduled.end()) {
- /* Node might not be optimized yet but scheduled already
- * by other dependencies. No need to re-schedule it.
- */
- continue;
- }
- /* Schedule node if its inputs are fully done. */
- if(check_node_inputs_traversed(input->parent, done)) {
- traverse_queue.push(input->parent);
- scheduled.insert(input->parent);
- }
- }
- }
- /* Only need to care about nodes that are actually used */
- if(!has_output_links) {
- continue;
- }
- /* Try to merge this node with another one. */
- ShaderNode *merge_with = NULL;
- foreach(ShaderNode *other_node, candidates[node->type->name]) {
- if(node != other_node && node->equals(*other_node)) {
- merge_with = other_node;
- break;
- }
- }
- /* If found an equivalent, merge; otherwise keep node for later merges */
- if(merge_with != NULL) {
- for(int i = 0; i < node->outputs.size(); ++i) {
- relink(node, node->outputs[i], merge_with->outputs[i]);
- }
- num_deduplicated++;
- }
- else {
- candidates[node->type->name].insert(node);
- }
- }
-
- if(num_deduplicated > 0) {
- VLOG(1) << "Deduplicated " << num_deduplicated << " nodes.";
- }
+ /* NOTES:
+ * - Deduplication happens for nodes which has same exact settings and same
+ * exact input links configuration (either connected to same output or has
+ * the same exact default value).
+ * - Deduplication happens in the bottom-top manner, so we know for fact that
+ * all traversed nodes are either can not be deduplicated at all or were
+ * already deduplicated.
+ */
+
+ ShaderNodeSet scheduled, done;
+ map<ustring, ShaderNodeSet> candidates;
+ queue<ShaderNode *> traverse_queue;
+ int num_deduplicated = 0;
+
+ /* Schedule nodes which doesn't have any dependencies. */
+ foreach (ShaderNode *node, nodes) {
+ if (!check_node_inputs_has_links(node)) {
+ traverse_queue.push(node);
+ scheduled.insert(node);
+ }
+ }
+
+ while (!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ done.insert(node);
+ /* Schedule the nodes which were depending on the current node. */
+ bool has_output_links = false;
+ foreach (ShaderOutput *output, node->outputs) {
+ foreach (ShaderInput *input, output->links) {
+ has_output_links = true;
+ if (scheduled.find(input->parent) != scheduled.end()) {
+ /* Node might not be optimized yet but scheduled already
+ * by other dependencies. No need to re-schedule it.
+ */
+ continue;
+ }
+ /* Schedule node if its inputs are fully done. */
+ if (check_node_inputs_traversed(input->parent, done)) {
+ traverse_queue.push(input->parent);
+ scheduled.insert(input->parent);
+ }
+ }
+ }
+ /* Only need to care about nodes that are actually used */
+ if (!has_output_links) {
+ continue;
+ }
+ /* Try to merge this node with another one. */
+ ShaderNode *merge_with = NULL;
+ foreach (ShaderNode *other_node, candidates[node->type->name]) {
+ if (node != other_node && node->equals(*other_node)) {
+ merge_with = other_node;
+ break;
+ }
+ }
+ /* If found an equivalent, merge; otherwise keep node for later merges */
+ if (merge_with != NULL) {
+ for (int i = 0; i < node->outputs.size(); ++i) {
+ relink(node, node->outputs[i], merge_with->outputs[i]);
+ }
+ num_deduplicated++;
+ }
+ else {
+ candidates[node->type->name].insert(node);
+ }
+ }
+
+ if (num_deduplicated > 0) {
+ VLOG(1) << "Deduplicated " << num_deduplicated << " nodes.";
+ }
}
/* Check whether volume output has meaningful nodes, otherwise
@@ -642,535 +639,536 @@ void ShaderGraph::deduplicate_nodes()
*/
void ShaderGraph::verify_volume_output()
{
- /* Check whether we can optimize the whole volume graph out. */
- ShaderInput *volume_in = output()->input("Volume");
- if(volume_in->link == NULL) {
- return;
- }
- bool has_valid_volume = false;
- ShaderNodeSet scheduled;
- queue<ShaderNode*> traverse_queue;
- /* Schedule volume output. */
- traverse_queue.push(volume_in->link->parent);
- scheduled.insert(volume_in->link->parent);
- /* Traverse down the tree. */
- while(!traverse_queue.empty()) {
- ShaderNode *node = traverse_queue.front();
- traverse_queue.pop();
- /* Node is fully valid for volume, can't optimize anything out. */
- if(node->has_volume_support()) {
- has_valid_volume = true;
- break;
- }
- foreach(ShaderInput *input, node->inputs) {
- if(input->link == NULL) {
- continue;
- }
- if(scheduled.find(input->link->parent) != scheduled.end()) {
- continue;
- }
- traverse_queue.push(input->link->parent);
- scheduled.insert(input->link->parent);
- }
- }
- if(!has_valid_volume) {
- VLOG(1) << "Disconnect meaningless volume output.";
- disconnect(volume_in->link);
- }
+ /* Check whether we can optimize the whole volume graph out. */
+ ShaderInput *volume_in = output()->input("Volume");
+ if (volume_in->link == NULL) {
+ return;
+ }
+ bool has_valid_volume = false;
+ ShaderNodeSet scheduled;
+ queue<ShaderNode *> traverse_queue;
+ /* Schedule volume output. */
+ traverse_queue.push(volume_in->link->parent);
+ scheduled.insert(volume_in->link->parent);
+ /* Traverse down the tree. */
+ while (!traverse_queue.empty()) {
+ ShaderNode *node = traverse_queue.front();
+ traverse_queue.pop();
+ /* Node is fully valid for volume, can't optimize anything out. */
+ if (node->has_volume_support()) {
+ has_valid_volume = true;
+ break;
+ }
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link == NULL) {
+ continue;
+ }
+ if (scheduled.find(input->link->parent) != scheduled.end()) {
+ continue;
+ }
+ traverse_queue.push(input->link->parent);
+ scheduled.insert(input->link->parent);
+ }
+ }
+ if (!has_valid_volume) {
+ VLOG(1) << "Disconnect meaningless volume output.";
+ disconnect(volume_in->link);
+ }
}
-void ShaderGraph::break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack)
+void ShaderGraph::break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack)
{
- visited[node->id] = true;
- on_stack[node->id] = true;
-
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- ShaderNode *depnode = input->link->parent;
-
- if(on_stack[depnode->id]) {
- /* break cycle */
- disconnect(input);
- fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
- }
- else if(!visited[depnode->id]) {
- /* visit dependencies */
- break_cycles(depnode, visited, on_stack);
- }
- }
- }
-
- on_stack[node->id] = false;
+ visited[node->id] = true;
+ on_stack[node->id] = true;
+
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ ShaderNode *depnode = input->link->parent;
+
+ if (on_stack[depnode->id]) {
+ /* break cycle */
+ disconnect(input);
+ fprintf(stderr, "Cycles shader graph: detected cycle in graph, connection removed.\n");
+ }
+ else if (!visited[depnode->id]) {
+ /* visit dependencies */
+ break_cycles(depnode, visited, on_stack);
+ }
+ }
+ }
+
+ on_stack[node->id] = false;
}
void ShaderGraph::compute_displacement_hash()
{
- /* Compute hash of all nodes linked to displacement, to detect if we need
- * to recompute displacement when shader nodes change. */
- ShaderInput *displacement_in = output()->input("Displacement");
-
- if(!displacement_in->link) {
- displacement_hash = "";
- return;
- }
-
- ShaderNodeSet nodes_displace;
- find_dependencies(nodes_displace, displacement_in);
-
- MD5Hash md5;
- foreach(ShaderNode *node, nodes_displace) {
- node->hash(md5);
- foreach(ShaderInput *input, node->inputs) {
- int link_id = (input->link) ? input->link->parent->id : 0;
- md5.append((uint8_t*)&link_id, sizeof(link_id));
- }
- }
-
- displacement_hash = md5.get_hex();
+ /* Compute hash of all nodes linked to displacement, to detect if we need
+ * to recompute displacement when shader nodes change. */
+ ShaderInput *displacement_in = output()->input("Displacement");
+
+ if (!displacement_in->link) {
+ displacement_hash = "";
+ return;
+ }
+
+ ShaderNodeSet nodes_displace;
+ find_dependencies(nodes_displace, displacement_in);
+
+ MD5Hash md5;
+ foreach (ShaderNode *node, nodes_displace) {
+ node->hash(md5);
+ foreach (ShaderInput *input, node->inputs) {
+ int link_id = (input->link) ? input->link->parent->id : 0;
+ md5.append((uint8_t *)&link_id, sizeof(link_id));
+ }
+ }
+
+ displacement_hash = md5.get_hex();
}
void ShaderGraph::clean(Scene *scene)
{
- /* Graph simplification */
-
- /* NOTE: Remove proxy nodes was already done. */
- constant_fold(scene);
- simplify_settings(scene);
- deduplicate_nodes();
- verify_volume_output();
-
- /* we do two things here: find cycles and break them, and remove unused
- * nodes that don't feed into the output. how cycles are broken is
- * undefined, they are invalid input, the important thing is to not crash */
-
- vector<bool> visited(num_node_ids, false);
- vector<bool> on_stack(num_node_ids, false);
-
- /* break cycles */
- break_cycles(output(), visited, on_stack);
-
- /* disconnect unused nodes */
- foreach(ShaderNode *node, nodes) {
- if(!visited[node->id]) {
- foreach(ShaderInput *to, node->inputs) {
- ShaderOutput *from = to->link;
-
- if(from) {
- to->link = NULL;
- from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
- }
- }
- }
- }
-
- /* remove unused nodes */
- list<ShaderNode*> newnodes;
-
- foreach(ShaderNode *node, nodes) {
- if(visited[node->id])
- newnodes.push_back(node);
- else
- delete node;
- }
-
- nodes = newnodes;
+ /* Graph simplification */
+
+ /* NOTE: Remove proxy nodes was already done. */
+ constant_fold(scene);
+ simplify_settings(scene);
+ deduplicate_nodes();
+ verify_volume_output();
+
+ /* we do two things here: find cycles and break them, and remove unused
+ * nodes that don't feed into the output. how cycles are broken is
+ * undefined, they are invalid input, the important thing is to not crash */
+
+ vector<bool> visited(num_node_ids, false);
+ vector<bool> on_stack(num_node_ids, false);
+
+ /* break cycles */
+ break_cycles(output(), visited, on_stack);
+
+ /* disconnect unused nodes */
+ foreach (ShaderNode *node, nodes) {
+ if (!visited[node->id]) {
+ foreach (ShaderInput *to, node->inputs) {
+ ShaderOutput *from = to->link;
+
+ if (from) {
+ to->link = NULL;
+ from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
+ }
+ }
+ }
+ }
+
+ /* remove unused nodes */
+ list<ShaderNode *> newnodes;
+
+ foreach (ShaderNode *node, nodes) {
+ if (visited[node->id])
+ newnodes.push_back(node);
+ else
+ delete node;
+ }
+
+ nodes = newnodes;
}
void ShaderGraph::default_inputs(bool do_osl)
{
- /* nodes can specify default texture coordinates, for now we give
- * everything the position by default, except for the sky texture */
-
- ShaderNode *geom = NULL;
- ShaderNode *texco = NULL;
-
- foreach(ShaderNode *node, nodes) {
- foreach(ShaderInput *input, node->inputs) {
- if(!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
- if(input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
- if(!texco)
- texco = new TextureCoordinateNode();
-
- connect(texco->output("Generated"), input);
- }
- if(input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
- if(!texco)
- texco = new TextureCoordinateNode();
-
- connect(texco->output("Normal"), input);
- }
- else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
- if(!texco)
- texco = new TextureCoordinateNode();
-
- connect(texco->output("UV"), input);
- }
- else if(input->flags() & SocketType::LINK_INCOMING) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Incoming"), input);
- }
- else if(input->flags() & SocketType::LINK_NORMAL) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Normal"), input);
- }
- else if(input->flags() & SocketType::LINK_POSITION) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Position"), input);
- }
- else if(input->flags() & SocketType::LINK_TANGENT) {
- if(!geom)
- geom = new GeometryNode();
-
- connect(geom->output("Tangent"), input);
- }
- }
- }
- }
-
- if(geom)
- add(geom);
- if(texco)
- add(texco);
+ /* nodes can specify default texture coordinates, for now we give
+ * everything the position by default, except for the sky texture */
+
+ ShaderNode *geom = NULL;
+ ShaderNode *texco = NULL;
+
+ foreach (ShaderNode *node, nodes) {
+ foreach (ShaderInput *input, node->inputs) {
+ if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
+ if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
+ if (!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("Generated"), input);
+ }
+ if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
+ if (!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("Normal"), input);
+ }
+ else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
+ if (!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("UV"), input);
+ }
+ else if (input->flags() & SocketType::LINK_INCOMING) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Incoming"), input);
+ }
+ else if (input->flags() & SocketType::LINK_NORMAL) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Normal"), input);
+ }
+ else if (input->flags() & SocketType::LINK_POSITION) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Position"), input);
+ }
+ else if (input->flags() & SocketType::LINK_TANGENT) {
+ if (!geom)
+ geom = new GeometryNode();
+
+ connect(geom->output("Tangent"), input);
+ }
+ }
+ }
+ }
+
+ if (geom)
+ add(geom);
+ if (texco)
+ add(texco);
}
void ShaderGraph::refine_bump_nodes()
{
- /* we transverse the node graph looking for bump nodes, when we find them,
- * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
- * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
- * to "center" input. */
-
- foreach(ShaderNode *node, nodes) {
- if(node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
- ShaderInput *bump_input = node->input("Height");
- ShaderNodeSet nodes_bump;
-
- /* make 2 extra copies of the subgraph defined in Bump input */
- ShaderNodeMap nodes_dx;
- ShaderNodeMap nodes_dy;
-
- /* find dependencies for the given input */
- find_dependencies(nodes_bump, bump_input);
-
- copy_nodes(nodes_bump, nodes_dx);
- copy_nodes(nodes_bump, nodes_dy);
-
- /* mark nodes to indicate they are use for bump computation, so
- that any texture coordinates are shifted by dx/dy when sampling */
- foreach(ShaderNode *node, nodes_bump)
- node->bump = SHADER_BUMP_CENTER;
- foreach(NodePair& pair, nodes_dx)
- pair.second->bump = SHADER_BUMP_DX;
- foreach(NodePair& pair, nodes_dy)
- pair.second->bump = SHADER_BUMP_DY;
-
- ShaderOutput *out = bump_input->link;
- ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
- ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
-
- connect(out_dx, node->input("SampleX"));
- connect(out_dy, node->input("SampleY"));
-
- /* add generated nodes */
- foreach(NodePair& pair, nodes_dx)
- add(pair.second);
- foreach(NodePair& pair, nodes_dy)
- add(pair.second);
-
- /* connect what is connected is bump to samplecenter input*/
- connect(out , node->input("SampleCenter"));
-
- /* bump input is just for connectivity purpose for the graph input,
- * we re-connected this input to samplecenter, so lets disconnect it
- * from bump input */
- disconnect(bump_input);
- }
- }
+ /* we transverse the node graph looking for bump nodes, when we find them,
+ * like in bump_from_displacement(), we copy the sub-graph defined from "bump"
+ * input to the inputs "center","dx" and "dy" What is in "bump" input is moved
+ * to "center" input. */
+
+ foreach (ShaderNode *node, nodes) {
+ if (node->special_type == SHADER_SPECIAL_TYPE_BUMP && node->input("Height")->link) {
+ ShaderInput *bump_input = node->input("Height");
+ ShaderNodeSet nodes_bump;
+
+ /* make 2 extra copies of the subgraph defined in Bump input */
+ ShaderNodeMap nodes_dx;
+ ShaderNodeMap nodes_dy;
+
+ /* find dependencies for the given input */
+ find_dependencies(nodes_bump, bump_input);
+
+ copy_nodes(nodes_bump, nodes_dx);
+ copy_nodes(nodes_bump, nodes_dy);
+
+ /* mark nodes to indicate they are use for bump computation, so
+ that any texture coordinates are shifted by dx/dy when sampling */
+ foreach (ShaderNode *node, nodes_bump)
+ node->bump = SHADER_BUMP_CENTER;
+ foreach (NodePair &pair, nodes_dx)
+ pair.second->bump = SHADER_BUMP_DX;
+ foreach (NodePair &pair, nodes_dy)
+ pair.second->bump = SHADER_BUMP_DY;
+
+ ShaderOutput *out = bump_input->link;
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
+
+ connect(out_dx, node->input("SampleX"));
+ connect(out_dy, node->input("SampleY"));
+
+ /* add generated nodes */
+ foreach (NodePair &pair, nodes_dx)
+ add(pair.second);
+ foreach (NodePair &pair, nodes_dy)
+ add(pair.second);
+
+ /* connect what is connected is bump to samplecenter input*/
+ connect(out, node->input("SampleCenter"));
+
+ /* bump input is just for connectivity purpose for the graph input,
+ * we re-connected this input to samplecenter, so lets disconnect it
+ * from bump input */
+ disconnect(bump_input);
+ }
+ }
}
void ShaderGraph::bump_from_displacement(bool use_object_space)
{
- /* generate bump mapping automatically from displacement. bump mapping is
- * done using a 3-tap filter, computing the displacement at the center,
- * and two other positions shifted by ray differentials.
- *
- * since the input to displacement is a node graph, we need to ensure that
- * all texture coordinates use are shift by the ray differentials. for this
- * reason we make 3 copies of the node subgraph defining the displacement,
- * with each different geometry and texture coordinate nodes that generate
- * different shifted coordinates.
- *
- * these 3 displacement values are then fed into the bump node, which will
- * output the perturbed normal. */
-
- ShaderInput *displacement_in = output()->input("Displacement");
-
- if(!displacement_in->link)
- return;
-
- /* find dependencies for the given input */
- ShaderNodeSet nodes_displace;
- find_dependencies(nodes_displace, displacement_in);
-
- /* copy nodes for 3 bump samples */
- ShaderNodeMap nodes_center;
- ShaderNodeMap nodes_dx;
- ShaderNodeMap nodes_dy;
-
- copy_nodes(nodes_displace, nodes_center);
- copy_nodes(nodes_displace, nodes_dx);
- copy_nodes(nodes_displace, nodes_dy);
-
- /* mark nodes to indicate they are use for bump computation, so
- * that any texture coordinates are shifted by dx/dy when sampling */
- foreach(NodePair& pair, nodes_center)
- pair.second->bump = SHADER_BUMP_CENTER;
- foreach(NodePair& pair, nodes_dx)
- pair.second->bump = SHADER_BUMP_DX;
- foreach(NodePair& pair, nodes_dy)
- pair.second->bump = SHADER_BUMP_DY;
-
- /* add set normal node and connect the bump normal ouput to the set normal
- * output, so it can finally set the shader normal, note we are only doing
- * this for bump from displacement, this will be the only bump allowed to
- * overwrite the shader normal */
- ShaderNode *set_normal = add(new SetNormalNode());
-
- /* add bump node and connect copied graphs to it */
- BumpNode *bump = (BumpNode*)add(new BumpNode());
- bump->use_object_space = use_object_space;
- bump->distance = 1.0f;
-
- ShaderOutput *out = displacement_in->link;
- ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
- ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
- ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
-
- /* convert displacement vector to height */
- VectorMathNode *dot_center = (VectorMathNode*)add(new VectorMathNode());
- VectorMathNode *dot_dx = (VectorMathNode*)add(new VectorMathNode());
- VectorMathNode *dot_dy = (VectorMathNode*)add(new VectorMathNode());
-
- dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT;
- dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT;
- dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT;
-
- GeometryNode *geom = (GeometryNode*)add(new GeometryNode());
- connect(geom->output("Normal"), dot_center->input("Vector2"));
- connect(geom->output("Normal"), dot_dx->input("Vector2"));
- connect(geom->output("Normal"), dot_dy->input("Vector2"));
-
- connect(out_center, dot_center->input("Vector1"));
- connect(out_dx, dot_dx->input("Vector1"));
- connect(out_dy, dot_dy->input("Vector1"));
-
- connect(dot_center->output("Value"), bump->input("SampleCenter"));
- connect(dot_dx->output("Value"), bump->input("SampleX"));
- connect(dot_dy->output("Value"), bump->input("SampleY"));
-
- /* connect the bump out to the set normal in: */
- connect(bump->output("Normal"), set_normal->input("Direction"));
-
- /* connect to output node */
- connect(set_normal->output("Normal"), output()->input("Normal"));
-
- /* finally, add the copied nodes to the graph. we can't do this earlier
- * because we would create dependency cycles in the above loop */
- foreach(NodePair& pair, nodes_center)
- add(pair.second);
- foreach(NodePair& pair, nodes_dx)
- add(pair.second);
- foreach(NodePair& pair, nodes_dy)
- add(pair.second);
+ /* generate bump mapping automatically from displacement. bump mapping is
+ * done using a 3-tap filter, computing the displacement at the center,
+ * and two other positions shifted by ray differentials.
+ *
+ * since the input to displacement is a node graph, we need to ensure that
+ * all texture coordinates use are shift by the ray differentials. for this
+ * reason we make 3 copies of the node subgraph defining the displacement,
+ * with each different geometry and texture coordinate nodes that generate
+ * different shifted coordinates.
+ *
+ * these 3 displacement values are then fed into the bump node, which will
+ * output the perturbed normal. */
+
+ ShaderInput *displacement_in = output()->input("Displacement");
+
+ if (!displacement_in->link)
+ return;
+
+ /* find dependencies for the given input */
+ ShaderNodeSet nodes_displace;
+ find_dependencies(nodes_displace, displacement_in);
+
+ /* copy nodes for 3 bump samples */
+ ShaderNodeMap nodes_center;
+ ShaderNodeMap nodes_dx;
+ ShaderNodeMap nodes_dy;
+
+ copy_nodes(nodes_displace, nodes_center);
+ copy_nodes(nodes_displace, nodes_dx);
+ copy_nodes(nodes_displace, nodes_dy);
+
+ /* mark nodes to indicate they are use for bump computation, so
+ * that any texture coordinates are shifted by dx/dy when sampling */
+ foreach (NodePair &pair, nodes_center)
+ pair.second->bump = SHADER_BUMP_CENTER;
+ foreach (NodePair &pair, nodes_dx)
+ pair.second->bump = SHADER_BUMP_DX;
+ foreach (NodePair &pair, nodes_dy)
+ pair.second->bump = SHADER_BUMP_DY;
+
+ /* add set normal node and connect the bump normal ouput to the set normal
+ * output, so it can finally set the shader normal, note we are only doing
+ * this for bump from displacement, this will be the only bump allowed to
+ * overwrite the shader normal */
+ ShaderNode *set_normal = add(new SetNormalNode());
+
+ /* add bump node and connect copied graphs to it */
+ BumpNode *bump = (BumpNode *)add(new BumpNode());
+ bump->use_object_space = use_object_space;
+ bump->distance = 1.0f;
+
+ ShaderOutput *out = displacement_in->link;
+ ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
+
+ /* convert displacement vector to height */
+ VectorMathNode *dot_center = (VectorMathNode *)add(new VectorMathNode());
+ VectorMathNode *dot_dx = (VectorMathNode *)add(new VectorMathNode());
+ VectorMathNode *dot_dy = (VectorMathNode *)add(new VectorMathNode());
+
+ dot_center->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dot_dx->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dot_dy->type = NODE_VECTOR_MATH_DOT_PRODUCT;
+
+ GeometryNode *geom = (GeometryNode *)add(new GeometryNode());
+ connect(geom->output("Normal"), dot_center->input("Vector2"));
+ connect(geom->output("Normal"), dot_dx->input("Vector2"));
+ connect(geom->output("Normal"), dot_dy->input("Vector2"));
+
+ connect(out_center, dot_center->input("Vector1"));
+ connect(out_dx, dot_dx->input("Vector1"));
+ connect(out_dy, dot_dy->input("Vector1"));
+
+ connect(dot_center->output("Value"), bump->input("SampleCenter"));
+ connect(dot_dx->output("Value"), bump->input("SampleX"));
+ connect(dot_dy->output("Value"), bump->input("SampleY"));
+
+ /* connect the bump out to the set normal in: */
+ connect(bump->output("Normal"), set_normal->input("Direction"));
+
+ /* connect to output node */
+ connect(set_normal->output("Normal"), output()->input("Normal"));
+
+ /* finally, add the copied nodes to the graph. we can't do this earlier
+ * because we would create dependency cycles in the above loop */
+ foreach (NodePair &pair, nodes_center)
+ add(pair.second);
+ foreach (NodePair &pair, nodes_dx)
+ add(pair.second);
+ foreach (NodePair &pair, nodes_dy)
+ add(pair.second);
}
void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume)
{
- /* for SVM in multi closure mode, this transforms the shader mix/add part of
- * the graph into nodes that feed weights into closure nodes. this is too
- * avoid building a closure tree and then flattening it, and instead write it
- * directly to an array */
-
- if(node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
- ShaderInput *fin = node->input("Fac");
- ShaderInput *cl1in = node->input("Closure1");
- ShaderInput *cl2in = node->input("Closure2");
- ShaderOutput *weight1_out, *weight2_out;
-
- if(fin) {
- /* mix closure: add node to mix closure weights */
- MixClosureWeightNode *mix_node = new MixClosureWeightNode();
- add(mix_node);
- ShaderInput *fac_in = mix_node->input("Fac");
- ShaderInput *weight_in = mix_node->input("Weight");
-
- if(fin->link)
- connect(fin->link, fac_in);
- else
- mix_node->fac = node->get_float(fin->socket_type);
-
- if(weight_out)
- connect(weight_out, weight_in);
-
- weight1_out = mix_node->output("Weight1");
- weight2_out = mix_node->output("Weight2");
- }
- else {
- /* add closure: just pass on any weights */
- weight1_out = weight_out;
- weight2_out = weight_out;
- }
-
- if(cl1in->link)
- transform_multi_closure(cl1in->link->parent, weight1_out, volume);
- if(cl2in->link)
- transform_multi_closure(cl2in->link->parent, weight2_out, volume);
- }
- else {
- ShaderInput *weight_in = node->input((volume)? "VolumeMixWeight": "SurfaceMixWeight");
-
- /* not a closure node? */
- if(!weight_in)
- return;
-
- /* already has a weight connected to it? add weights */
- float weight_value = node->get_float(weight_in->socket_type);
- if(weight_in->link || weight_value != 0.0f) {
- MathNode *math_node = new MathNode();
- add(math_node);
-
- if(weight_in->link)
- connect(weight_in->link, math_node->input("Value1"));
- else
- math_node->value1 = weight_value;
-
- if(weight_out)
- connect(weight_out, math_node->input("Value2"));
- else
- math_node->value2 = 1.0f;
-
- weight_out = math_node->output("Value");
- if(weight_in->link)
- disconnect(weight_in);
- }
-
- /* connected to closure mix weight */
- if(weight_out)
- connect(weight_out, weight_in);
- else
- node->set(weight_in->socket_type, weight_value + 1.0f);
- }
+ /* for SVM in multi closure mode, this transforms the shader mix/add part of
+ * the graph into nodes that feed weights into closure nodes. this is too
+ * avoid building a closure tree and then flattening it, and instead write it
+ * directly to an array */
+
+ if (node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
+ ShaderInput *fin = node->input("Fac");
+ ShaderInput *cl1in = node->input("Closure1");
+ ShaderInput *cl2in = node->input("Closure2");
+ ShaderOutput *weight1_out, *weight2_out;
+
+ if (fin) {
+ /* mix closure: add node to mix closure weights */
+ MixClosureWeightNode *mix_node = new MixClosureWeightNode();
+ add(mix_node);
+ ShaderInput *fac_in = mix_node->input("Fac");
+ ShaderInput *weight_in = mix_node->input("Weight");
+
+ if (fin->link)
+ connect(fin->link, fac_in);
+ else
+ mix_node->fac = node->get_float(fin->socket_type);
+
+ if (weight_out)
+ connect(weight_out, weight_in);
+
+ weight1_out = mix_node->output("Weight1");
+ weight2_out = mix_node->output("Weight2");
+ }
+ else {
+ /* add closure: just pass on any weights */
+ weight1_out = weight_out;
+ weight2_out = weight_out;
+ }
+
+ if (cl1in->link)
+ transform_multi_closure(cl1in->link->parent, weight1_out, volume);
+ if (cl2in->link)
+ transform_multi_closure(cl2in->link->parent, weight2_out, volume);
+ }
+ else {
+ ShaderInput *weight_in = node->input((volume) ? "VolumeMixWeight" : "SurfaceMixWeight");
+
+ /* not a closure node? */
+ if (!weight_in)
+ return;
+
+ /* already has a weight connected to it? add weights */
+ float weight_value = node->get_float(weight_in->socket_type);
+ if (weight_in->link || weight_value != 0.0f) {
+ MathNode *math_node = new MathNode();
+ add(math_node);
+
+ if (weight_in->link)
+ connect(weight_in->link, math_node->input("Value1"));
+ else
+ math_node->value1 = weight_value;
+
+ if (weight_out)
+ connect(weight_out, math_node->input("Value2"));
+ else
+ math_node->value2 = 1.0f;
+
+ weight_out = math_node->output("Value");
+ if (weight_in->link)
+ disconnect(weight_in);
+ }
+
+ /* connected to closure mix weight */
+ if (weight_out)
+ connect(weight_out, weight_in);
+ else
+ node->set(weight_in->socket_type, weight_value + 1.0f);
+ }
}
int ShaderGraph::get_num_closures()
{
- int num_closures = 0;
- foreach(ShaderNode *node, nodes) {
- ClosureType closure_type = node->get_closure_type();
- if(closure_type == CLOSURE_NONE_ID) {
- continue;
- }
- else if(CLOSURE_IS_BSSRDF(closure_type)) {
- num_closures += 3;
- }
- else if(CLOSURE_IS_GLASS(closure_type)) {
- num_closures += 2;
- }
- else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
- num_closures += 2;
- }
- else if(CLOSURE_IS_PRINCIPLED(closure_type)) {
- num_closures += 8;
- }
- else if(CLOSURE_IS_VOLUME(closure_type)) {
- num_closures += VOLUME_STACK_SIZE;
- }
- else if(closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
- num_closures += 4;
- }
- else {
- ++num_closures;
- }
- }
- return num_closures;
+ int num_closures = 0;
+ foreach (ShaderNode *node, nodes) {
+ ClosureType closure_type = node->get_closure_type();
+ if (closure_type == CLOSURE_NONE_ID) {
+ continue;
+ }
+ else if (CLOSURE_IS_BSSRDF(closure_type)) {
+ num_closures += 3;
+ }
+ else if (CLOSURE_IS_GLASS(closure_type)) {
+ num_closures += 2;
+ }
+ else if (CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
+ num_closures += 2;
+ }
+ else if (CLOSURE_IS_PRINCIPLED(closure_type)) {
+ num_closures += 8;
+ }
+ else if (CLOSURE_IS_VOLUME(closure_type)) {
+ num_closures += VOLUME_STACK_SIZE;
+ }
+ else if (closure_type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) {
+ num_closures += 4;
+ }
+ else {
+ ++num_closures;
+ }
+ }
+ return num_closures;
}
void ShaderGraph::dump_graph(const char *filename)
{
- FILE *fd = fopen(filename, "w");
-
- if(fd == NULL) {
- printf("Error opening file for dumping the graph: %s\n", filename);
- return;
- }
-
- fprintf(fd, "digraph shader_graph {\n");
- fprintf(fd, "ranksep=1.5\n");
- fprintf(fd, "rankdir=LR\n");
- fprintf(fd, "splines=false\n");
-
- foreach(ShaderNode *node, nodes) {
- fprintf(fd, "// NODE: %p\n", node);
- fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
- if(node->inputs.size()) {
- fprintf(fd, "{");
- foreach(ShaderInput *socket, node->inputs) {
- if(socket != node->inputs[0]) {
- fprintf(fd, "|");
- }
- fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
- }
- fprintf(fd, "}|");
- }
- fprintf(fd, "%s", node->name.c_str());
- if(node->bump == SHADER_BUMP_CENTER) {
- fprintf(fd, " (bump:center)");
- }
- else if(node->bump == SHADER_BUMP_DX) {
- fprintf(fd, " (bump:dx)");
- }
- else if(node->bump == SHADER_BUMP_DY) {
- fprintf(fd, " (bump:dy)");
- }
- if(node->outputs.size()) {
- fprintf(fd, "|{");
- foreach(ShaderOutput *socket, node->outputs) {
- if(socket != node->outputs[0]) {
- fprintf(fd, "|");
- }
- fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
- }
- fprintf(fd, "}");
- }
- fprintf(fd, "}\"]");
- }
-
- foreach(ShaderNode *node, nodes) {
- foreach(ShaderOutput *output, node->outputs) {
- foreach(ShaderInput *input, output->links) {
- fprintf(fd,
- "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
- output,
- input,
- output->name().c_str(), input->name().c_str());
- fprintf(fd,
- "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
- output->parent,
- output,
- input->parent,
- input);
- }
- }
- }
-
- fprintf(fd, "}\n");
- fclose(fd);
+ FILE *fd = fopen(filename, "w");
+
+ if (fd == NULL) {
+ printf("Error opening file for dumping the graph: %s\n", filename);
+ return;
+ }
+
+ fprintf(fd, "digraph shader_graph {\n");
+ fprintf(fd, "ranksep=1.5\n");
+ fprintf(fd, "rankdir=LR\n");
+ fprintf(fd, "splines=false\n");
+
+ foreach (ShaderNode *node, nodes) {
+ fprintf(fd, "// NODE: %p\n", node);
+ fprintf(fd, "\"%p\" [shape=record,label=\"{", node);
+ if (node->inputs.size()) {
+ fprintf(fd, "{");
+ foreach (ShaderInput *socket, node->inputs) {
+ if (socket != node->inputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
+ }
+ fprintf(fd, "}|");
+ }
+ fprintf(fd, "%s", node->name.c_str());
+ if (node->bump == SHADER_BUMP_CENTER) {
+ fprintf(fd, " (bump:center)");
+ }
+ else if (node->bump == SHADER_BUMP_DX) {
+ fprintf(fd, " (bump:dx)");
+ }
+ else if (node->bump == SHADER_BUMP_DY) {
+ fprintf(fd, " (bump:dy)");
+ }
+ if (node->outputs.size()) {
+ fprintf(fd, "|{");
+ foreach (ShaderOutput *socket, node->outputs) {
+ if (socket != node->outputs[0]) {
+ fprintf(fd, "|");
+ }
+ fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
+ }
+ fprintf(fd, "}");
+ }
+ fprintf(fd, "}\"]");
+ }
+
+ foreach (ShaderNode *node, nodes) {
+ foreach (ShaderOutput *output, node->outputs) {
+ foreach (ShaderInput *input, output->links) {
+ fprintf(fd,
+ "// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
+ output,
+ input,
+ output->name().c_str(),
+ input->name().c_str());
+ fprintf(fd,
+ "\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
+ output->parent,
+ output,
+ input->parent,
+ input);
+ }
+ }
+ }
+
+ fprintf(fd, "}\n");
+ fclose(fd);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index d14a59b4900..a2c030fd226 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -49,12 +49,7 @@ class MD5Hash;
* For bump mapping, a node may be evaluated multiple times, using different
* samples to reconstruct the normal, this indicates the sample position */
-enum ShaderBump {
- SHADER_BUMP_NONE,
- SHADER_BUMP_CENTER,
- SHADER_BUMP_DX,
- SHADER_BUMP_DY
-};
+enum ShaderBump { SHADER_BUMP_NONE, SHADER_BUMP_CENTER, SHADER_BUMP_DX, SHADER_BUMP_DY };
/* Identifiers for some special node types.
*
@@ -62,16 +57,16 @@ enum ShaderBump {
* Cannot use dynamic_cast, as this is disabled for OSL. */
enum ShaderNodeSpecialType {
- SHADER_SPECIAL_TYPE_NONE,
- SHADER_SPECIAL_TYPE_PROXY,
- SHADER_SPECIAL_TYPE_AUTOCONVERT,
- SHADER_SPECIAL_TYPE_GEOMETRY,
- SHADER_SPECIAL_TYPE_SCRIPT,
- SHADER_SPECIAL_TYPE_IMAGE_SLOT,
- SHADER_SPECIAL_TYPE_CLOSURE,
- SHADER_SPECIAL_TYPE_COMBINE_CLOSURE,
- SHADER_SPECIAL_TYPE_OUTPUT,
- SHADER_SPECIAL_TYPE_BUMP,
+ SHADER_SPECIAL_TYPE_NONE,
+ SHADER_SPECIAL_TYPE_PROXY,
+ SHADER_SPECIAL_TYPE_AUTOCONVERT,
+ SHADER_SPECIAL_TYPE_GEOMETRY,
+ SHADER_SPECIAL_TYPE_SCRIPT,
+ SHADER_SPECIAL_TYPE_IMAGE_SLOT,
+ SHADER_SPECIAL_TYPE_CLOSURE,
+ SHADER_SPECIAL_TYPE_COMBINE_CLOSURE,
+ SHADER_SPECIAL_TYPE_OUTPUT,
+ SHADER_SPECIAL_TYPE_BUMP,
};
/* Input
@@ -81,22 +76,38 @@ enum ShaderNodeSpecialType {
* coordinate. */
class ShaderInput {
-public:
- ShaderInput(const SocketType& socket_type_, ShaderNode* parent_)
- : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
- {}
-
- ustring name() { return socket_type.ui_name; }
- int flags() { return socket_type.flags; }
- SocketType::Type type() { return socket_type.type; }
-
- void set(float f) { ((Node*)parent)->set(socket_type, f); }
- void set(float3 f) { ((Node*)parent)->set(socket_type, f); }
-
- const SocketType& socket_type;
- ShaderNode *parent;
- ShaderOutput *link;
- int stack_offset; /* for SVM compiler */
+ public:
+ ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
+ : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
+ {
+ }
+
+ ustring name()
+ {
+ return socket_type.ui_name;
+ }
+ int flags()
+ {
+ return socket_type.flags;
+ }
+ SocketType::Type type()
+ {
+ return socket_type.type;
+ }
+
+ void set(float f)
+ {
+ ((Node *)parent)->set(socket_type, f);
+ }
+ void set(float3 f)
+ {
+ ((Node *)parent)->set(socket_type, f);
+ }
+
+ const SocketType &socket_type;
+ ShaderNode *parent;
+ ShaderOutput *link;
+ int stack_offset; /* for SVM compiler */
};
/* Output
@@ -104,18 +115,25 @@ public:
* Output socket for a shader node. */
class ShaderOutput {
-public:
- ShaderOutput(const SocketType& socket_type_, ShaderNode* parent_)
- : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
- {}
-
- ustring name() { return socket_type.ui_name; }
- SocketType::Type type() { return socket_type.type; }
-
- const SocketType& socket_type;
- ShaderNode *parent;
- vector<ShaderInput*> links;
- int stack_offset; /* for SVM compiler */
+ public:
+ ShaderOutput(const SocketType &socket_type_, ShaderNode *parent_)
+ : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
+ {
+ }
+
+ ustring name()
+ {
+ return socket_type.ui_name;
+ }
+ SocketType::Type type()
+ {
+ return socket_type.type;
+ }
+
+ const SocketType &socket_type;
+ ShaderNode *parent;
+ vector<ShaderInput *> links;
+ int stack_offset; /* for SVM compiler */
};
/* Node
@@ -124,115 +142,163 @@ public:
* base class for all node types. */
class ShaderNode : public Node {
-public:
- explicit ShaderNode(const NodeType *type);
- virtual ~ShaderNode();
-
- void create_inputs_outputs(const NodeType *type);
-
- ShaderInput *input(const char *name);
- ShaderOutput *output(const char *name);
- ShaderInput *input(ustring name);
- ShaderOutput *output(ustring name);
-
- virtual ShaderNode *clone() const = 0;
- virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
- virtual void compile(SVMCompiler& compiler) = 0;
- virtual void compile(OSLCompiler& compiler) = 0;
-
- /* ** Node optimization ** */
- /* Check whether the node can be replaced with single constant. */
- virtual void constant_fold(const ConstantFolder& /*folder*/) {}
-
- /* Simplify settings used by artists to the ones which are simpler to
- * evaluate in the kernel but keep the final result unchanged.
- */
- virtual void simplify_settings(Scene * /*scene*/) {};
-
- virtual bool has_surface_emission() { return false; }
- virtual bool has_surface_transparent() { return false; }
- virtual bool has_surface_bssrdf() { return false; }
- virtual bool has_bump() { return false; }
- virtual bool has_bssrdf_bump() { return false; }
- virtual bool has_spatial_varying() { return false; }
- virtual bool has_object_dependency() { return false; }
- virtual bool has_attribute_dependency() { return false; }
- virtual bool has_integrator_dependency() { return false; }
- virtual bool has_volume_support() { return false; }
- virtual bool has_raytrace() { return false; }
- vector<ShaderInput*> inputs;
- vector<ShaderOutput*> outputs;
-
- int id; /* index in graph node array */
- ShaderBump bump; /* for bump mapping utility */
-
- ShaderNodeSpecialType special_type; /* special node type */
-
- /* ** Selective nodes compilation ** */
-
- /* TODO(sergey): More explicitly mention in the function names
- * that those functions are for selective compilation only?
- */
-
- /* Nodes are split into several groups, group of level 0 contains
- * nodes which are most commonly used, further levels are extension
- * of previous one and includes less commonly used nodes.
- */
- virtual int get_group() { return NODE_GROUP_LEVEL_0; }
-
- /* Node feature are used to disable huge nodes inside the group,
- * so it's possible to disable huge nodes inside of the required
- * nodes group.
- */
- virtual int get_feature() { return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP; }
-
- /* Get closure ID to which the node compiles into. */
- virtual ClosureType get_closure_type() { return CLOSURE_NONE_ID; }
-
- /* Check whether settings of the node equals to another one.
- *
- * This is mainly used to check whether two nodes can be merged
- * together. Meaning, runtime stuff like node id and unbound slots
- * will be ignored for comparison.
- *
- * NOTE: If some node can't be de-duplicated for whatever reason it
- * is to be handled in the subclass.
- */
- virtual bool equals(const ShaderNode& other);
+ public:
+ explicit ShaderNode(const NodeType *type);
+ virtual ~ShaderNode();
+
+ void create_inputs_outputs(const NodeType *type);
+
+ ShaderInput *input(const char *name);
+ ShaderOutput *output(const char *name);
+ ShaderInput *input(ustring name);
+ ShaderOutput *output(ustring name);
+
+ virtual ShaderNode *clone() const = 0;
+ virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
+ virtual void compile(SVMCompiler &compiler) = 0;
+ virtual void compile(OSLCompiler &compiler) = 0;
+
+ /* ** Node optimization ** */
+ /* Check whether the node can be replaced with single constant. */
+ virtual void constant_fold(const ConstantFolder & /*folder*/)
+ {
+ }
+
+ /* Simplify settings used by artists to the ones which are simpler to
+ * evaluate in the kernel but keep the final result unchanged.
+ */
+ virtual void simplify_settings(Scene * /*scene*/){};
+
+ virtual bool has_surface_emission()
+ {
+ return false;
+ }
+ virtual bool has_surface_transparent()
+ {
+ return false;
+ }
+ virtual bool has_surface_bssrdf()
+ {
+ return false;
+ }
+ virtual bool has_bump()
+ {
+ return false;
+ }
+ virtual bool has_bssrdf_bump()
+ {
+ return false;
+ }
+ virtual bool has_spatial_varying()
+ {
+ return false;
+ }
+ virtual bool has_object_dependency()
+ {
+ return false;
+ }
+ virtual bool has_attribute_dependency()
+ {
+ return false;
+ }
+ virtual bool has_integrator_dependency()
+ {
+ return false;
+ }
+ virtual bool has_volume_support()
+ {
+ return false;
+ }
+ virtual bool has_raytrace()
+ {
+ return false;
+ }
+ vector<ShaderInput *> inputs;
+ vector<ShaderOutput *> outputs;
+
+ int id; /* index in graph node array */
+ ShaderBump bump; /* for bump mapping utility */
+
+ ShaderNodeSpecialType special_type; /* special node type */
+
+ /* ** Selective nodes compilation ** */
+
+ /* TODO(sergey): More explicitly mention in the function names
+ * that those functions are for selective compilation only?
+ */
+
+ /* Nodes are split into several groups, group of level 0 contains
+ * nodes which are most commonly used, further levels are extension
+ * of previous one and includes less commonly used nodes.
+ */
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_0;
+ }
+
+ /* Node feature are used to disable huge nodes inside the group,
+ * so it's possible to disable huge nodes inside of the required
+ * nodes group.
+ */
+ virtual int get_feature()
+ {
+ return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP;
+ }
+
+ /* Get closure ID to which the node compiles into. */
+ virtual ClosureType get_closure_type()
+ {
+ return CLOSURE_NONE_ID;
+ }
+
+ /* Check whether settings of the node equals to another one.
+ *
+ * This is mainly used to check whether two nodes can be merged
+ * together. Meaning, runtime stuff like node id and unbound slots
+ * will be ignored for comparison.
+ *
+ * NOTE: If some node can't be de-duplicated for whatever reason it
+ * is to be handled in the subclass.
+ */
+ virtual bool equals(const ShaderNode &other);
};
-
/* Node definition utility macros */
#define SHADER_NODE_CLASS(type) \
- NODE_DECLARE \
- type(); \
- virtual ShaderNode *clone() const { return new type(*this); } \
- virtual void compile(SVMCompiler& compiler); \
- virtual void compile(OSLCompiler& compiler); \
+ NODE_DECLARE \
+ type(); \
+ virtual ShaderNode *clone() const \
+ { \
+ return new type(*this); \
+ } \
+ virtual void compile(SVMCompiler &compiler); \
+ virtual void compile(OSLCompiler &compiler);
#define SHADER_NODE_NO_CLONE_CLASS(type) \
- NODE_DECLARE \
- type(); \
- virtual void compile(SVMCompiler& compiler); \
- virtual void compile(OSLCompiler& compiler); \
+ NODE_DECLARE \
+ type(); \
+ virtual void compile(SVMCompiler &compiler); \
+ virtual void compile(OSLCompiler &compiler);
#define SHADER_NODE_BASE_CLASS(type) \
- virtual ShaderNode *clone() const { return new type(*this); } \
- virtual void compile(SVMCompiler& compiler); \
- virtual void compile(OSLCompiler& compiler); \
-
-class ShaderNodeIDComparator
-{
-public:
- bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
- {
- return n1->id < n2->id;
- }
+ virtual ShaderNode *clone() const \
+ { \
+ return new type(*this); \
+ } \
+ virtual void compile(SVMCompiler &compiler); \
+ virtual void compile(OSLCompiler &compiler);
+
+class ShaderNodeIDComparator {
+ public:
+ bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
+ {
+ return n1->id < n2->id;
+ }
};
-typedef set<ShaderNode*, ShaderNodeIDComparator> ShaderNodeSet;
-typedef map<ShaderNode*, ShaderNode*, ShaderNodeIDComparator> ShaderNodeMap;
+typedef set<ShaderNode *, ShaderNodeIDComparator> ShaderNodeSet;
+typedef map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator> ShaderNodeMap;
/* Graph
*
@@ -240,57 +306,57 @@ typedef map<ShaderNode*, ShaderNode*, ShaderNodeIDComparator> ShaderNodeMap;
* bump mapping from displacement, and possibly other things in the future. */
class ShaderGraph {
-public:
- list<ShaderNode*> nodes;
- size_t num_node_ids;
- bool finalized;
- bool simplified;
- string displacement_hash;
-
- ShaderGraph();
- ~ShaderGraph();
-
- ShaderNode *add(ShaderNode *node);
- OutputNode *output();
-
- void connect(ShaderOutput *from, ShaderInput *to);
- void disconnect(ShaderOutput *from);
- void disconnect(ShaderInput *to);
- void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
-
- void remove_proxy_nodes();
- void compute_displacement_hash();
- void simplify(Scene *scene);
- void finalize(Scene *scene,
- bool do_bump = false,
- bool do_simplify = false,
- bool bump_in_object_space = false);
-
- int get_num_closures();
-
- void dump_graph(const char *filename);
-
-protected:
- typedef pair<ShaderNode* const, ShaderNode*> NodePair;
-
- void find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input);
- void clear_nodes();
- void copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap);
-
- void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack);
- void bump_from_displacement(bool use_object_space);
- void refine_bump_nodes();
- void default_inputs(bool do_osl);
- void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
-
- /* Graph simplification routines. */
- void clean(Scene *scene);
- void constant_fold(Scene *scene);
- void simplify_settings(Scene *scene);
- void deduplicate_nodes();
- void verify_volume_output();
+ public:
+ list<ShaderNode *> nodes;
+ size_t num_node_ids;
+ bool finalized;
+ bool simplified;
+ string displacement_hash;
+
+ ShaderGraph();
+ ~ShaderGraph();
+
+ ShaderNode *add(ShaderNode *node);
+ OutputNode *output();
+
+ void connect(ShaderOutput *from, ShaderInput *to);
+ void disconnect(ShaderOutput *from);
+ void disconnect(ShaderInput *to);
+ void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
+
+ void remove_proxy_nodes();
+ void compute_displacement_hash();
+ void simplify(Scene *scene);
+ void finalize(Scene *scene,
+ bool do_bump = false,
+ bool do_simplify = false,
+ bool bump_in_object_space = false);
+
+ int get_num_closures();
+
+ void dump_graph(const char *filename);
+
+ protected:
+ typedef pair<ShaderNode *const, ShaderNode *> NodePair;
+
+ void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
+ void clear_nodes();
+ void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap);
+
+ void break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack);
+ void bump_from_displacement(bool use_object_space);
+ void refine_bump_nodes();
+ void default_inputs(bool do_osl);
+ void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
+
+ /* Graph simplification routines. */
+ void clean(Scene *scene);
+ void constant_fold(Scene *scene);
+ void simplify_settings(Scene *scene);
+ void deduplicate_nodes();
+ void verify_volume_output();
};
CCL_NAMESPACE_END
-#endif /* __GRAPH_H__ */
+#endif /* __GRAPH_H__ */
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 1edd5865836..ae219e912e0 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -27,7 +27,7 @@
#include "util/util_unique_ptr.h"
#ifdef WITH_OSL
-#include <OSL/oslexec.h>
+# include <OSL/oslexec.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -37,15 +37,15 @@ namespace {
/* Some helpers to silence warning in templated function. */
bool isfinite(uchar /*value*/)
{
- return true;
+ return true;
}
bool isfinite(half /*value*/)
{
- return true;
+ return true;
}
-bool isfinite(uint16_t /*value*/)
+bool isfinite(uint16_t /*value*/)
{
- return true;
+ return true;
}
/* The lower three bits of a device texture slot number indicate its type.
@@ -54,946 +54,888 @@ bool isfinite(uint16_t /*value*/)
*/
int type_index_to_flattened_slot(int slot, ImageDataType type)
{
- return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
+ return (slot << IMAGE_DATA_TYPE_SHIFT) | (type);
}
int flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
{
- *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
- return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
+ *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK);
+ return flat_slot >> IMAGE_DATA_TYPE_SHIFT;
}
-const char* name_from_type(ImageDataType type)
+const char *name_from_type(ImageDataType type)
{
- switch(type) {
- case IMAGE_DATA_TYPE_FLOAT4: return "float4";
- case IMAGE_DATA_TYPE_BYTE4: return "byte4";
- case IMAGE_DATA_TYPE_HALF4: return "half4";
- case IMAGE_DATA_TYPE_FLOAT: return "float";
- case IMAGE_DATA_TYPE_BYTE: return "byte";
- case IMAGE_DATA_TYPE_HALF: return "half";
- case IMAGE_DATA_TYPE_USHORT4: return "ushort4";
- case IMAGE_DATA_TYPE_USHORT: return "ushort";
- case IMAGE_DATA_NUM_TYPES:
- assert(!"System enumerator type, should never be used");
- return "";
- }
- assert(!"Unhandled image data type");
- return "";
+ switch (type) {
+ case IMAGE_DATA_TYPE_FLOAT4:
+ return "float4";
+ case IMAGE_DATA_TYPE_BYTE4:
+ return "byte4";
+ case IMAGE_DATA_TYPE_HALF4:
+ return "half4";
+ case IMAGE_DATA_TYPE_FLOAT:
+ return "float";
+ case IMAGE_DATA_TYPE_BYTE:
+ return "byte";
+ case IMAGE_DATA_TYPE_HALF:
+ return "half";
+ case IMAGE_DATA_TYPE_USHORT4:
+ return "ushort4";
+ case IMAGE_DATA_TYPE_USHORT:
+ return "ushort";
+ case IMAGE_DATA_NUM_TYPES:
+ assert(!"System enumerator type, should never be used");
+ return "";
+ }
+ assert(!"Unhandled image data type");
+ return "";
}
} // namespace
-ImageManager::ImageManager(const DeviceInfo& info)
+ImageManager::ImageManager(const DeviceInfo &info)
{
- need_update = true;
- osl_texture_system = NULL;
- animation_frame = 0;
+ need_update = true;
+ osl_texture_system = NULL;
+ animation_frame = 0;
- /* Set image limits */
- max_num_images = TEX_NUM_MAX;
- has_half_images = info.has_half_images;
+ /* Set image limits */
+ max_num_images = TEX_NUM_MAX;
+ has_half_images = info.has_half_images;
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- tex_num_images[type] = 0;
- }
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ tex_num_images[type] = 0;
+ }
}
ImageManager::~ImageManager()
{
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++)
- assert(!images[type][slot]);
- }
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++)
+ assert(!images[type][slot]);
+ }
}
void ImageManager::set_osl_texture_system(void *texture_system)
{
- osl_texture_system = texture_system;
+ osl_texture_system = texture_system;
}
bool ImageManager::set_animation_frame_update(int frame)
{
- if(frame != animation_frame) {
- animation_frame = frame;
-
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && images[type][slot]->animated)
- return true;
- }
- }
- }
-
- return false;
+ if (frame != animation_frame) {
+ animation_frame = frame;
+
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] && images[type][slot]->animated)
+ return true;
+ }
+ }
+ }
+
+ return false;
}
device_memory *ImageManager::image_memory(int flat_slot)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *img = images[type][slot];
+ Image *img = images[type][slot];
- return img->mem;
+ return img->mem;
}
-bool ImageManager::get_image_metadata(int flat_slot,
- ImageMetaData& metadata)
+bool ImageManager::get_image_metadata(int flat_slot, ImageMetaData &metadata)
{
- if(flat_slot == -1) {
- return false;
- }
+ if (flat_slot == -1) {
+ return false;
+ }
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *img = images[type][slot];
- if(img) {
- metadata = img->metadata;
- return true;
- }
+ Image *img = images[type][slot];
+ if (img) {
+ metadata = img->metadata;
+ return true;
+ }
- return false;
+ return false;
}
-bool ImageManager::get_image_metadata(const string& filename,
+bool ImageManager::get_image_metadata(const string &filename,
void *builtin_data,
- ImageMetaData& metadata)
+ ImageMetaData &metadata)
{
- memset(&metadata, 0, sizeof(metadata));
-
- if(builtin_data) {
- if(builtin_image_info_cb) {
- builtin_image_info_cb(filename, builtin_data, metadata);
- }
- else {
- return false;
- }
-
- if(metadata.is_float) {
- metadata.is_linear = true;
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4
- : IMAGE_DATA_TYPE_FLOAT;
- }
- else {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4
- : IMAGE_DATA_TYPE_BYTE;
- }
-
- return true;
- }
-
- /* Perform preliminary checks, with meaningful logging. */
- if(!path_exists(filename)) {
- VLOG(1) << "File '" << filename << "' does not exist.";
- return false;
- }
- if(path_is_directory(filename)) {
- VLOG(1) << "File '" << filename
- << "' is a directory, can't use as image.";
- return false;
- }
-
- unique_ptr<ImageInput> in(ImageInput::create(filename));
-
- if(!in) {
- return false;
- }
-
- ImageSpec spec;
- if(!in->open(filename, spec)) {
- return false;
- }
-
- metadata.width = spec.width;
- metadata.height = spec.height;
- metadata.depth = spec.depth;
-
-
- /* Check the main format, and channel formats. */
- size_t channel_size = spec.format.basesize();
-
- if(spec.format.is_floating_point()) {
- metadata.is_float = true;
- metadata.is_linear = true;
- }
-
- for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
- channel_size = max(channel_size, spec.channelformats[channel].basesize());
- if(spec.channelformats[channel].is_floating_point()) {
- metadata.is_float = true;
- metadata.is_linear = true;
- }
- }
-
- /* check if it's half float */
- if(spec.format == TypeDesc::HALF) {
- metadata.is_half = true;
- }
-
- /* basic color space detection, not great but better than nothing
- * before we do OpenColorIO integration */
- if(metadata.is_float) {
- string colorspace = spec.get_string_attribute("oiio:ColorSpace");
-
- metadata.is_linear = !(colorspace == "sRGB" ||
- colorspace == "GammaCorrected" ||
- (colorspace == "" &&
- (strcmp(in->format_name(), "png") == 0 ||
- strcmp(in->format_name(), "tiff") == 0 ||
- strcmp(in->format_name(), "dpx") == 0 ||
- strcmp(in->format_name(), "jpeg2000") == 0)));
- }
- else {
- metadata.is_linear = false;
- }
-
- /* set type and channels */
- metadata.channels = spec.nchannels;
-
- if(metadata.is_half) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4
- : IMAGE_DATA_TYPE_HALF;
- }
- else if(metadata.is_float) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4
- : IMAGE_DATA_TYPE_FLOAT;
- }
- else if(spec.format == TypeDesc::USHORT) {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4
- : IMAGE_DATA_TYPE_USHORT;
- }
- else {
- metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4
- : IMAGE_DATA_TYPE_BYTE;
- }
-
- in->close();
-
- return true;
+ memset(&metadata, 0, sizeof(metadata));
+
+ if (builtin_data) {
+ if (builtin_image_info_cb) {
+ builtin_image_info_cb(filename, builtin_data, metadata);
+ }
+ else {
+ return false;
+ }
+
+ if (metadata.is_float) {
+ metadata.is_linear = true;
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
+ }
+ else {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
+ }
+
+ return true;
+ }
+
+ /* Perform preliminary checks, with meaningful logging. */
+ if (!path_exists(filename)) {
+ VLOG(1) << "File '" << filename << "' does not exist.";
+ return false;
+ }
+ if (path_is_directory(filename)) {
+ VLOG(1) << "File '" << filename << "' is a directory, can't use as image.";
+ return false;
+ }
+
+ unique_ptr<ImageInput> in(ImageInput::create(filename));
+
+ if (!in) {
+ return false;
+ }
+
+ ImageSpec spec;
+ if (!in->open(filename, spec)) {
+ return false;
+ }
+
+ metadata.width = spec.width;
+ metadata.height = spec.height;
+ metadata.depth = spec.depth;
+
+ /* Check the main format, and channel formats. */
+ size_t channel_size = spec.format.basesize();
+
+ if (spec.format.is_floating_point()) {
+ metadata.is_float = true;
+ metadata.is_linear = true;
+ }
+
+ for (size_t channel = 0; channel < spec.channelformats.size(); channel++) {
+ channel_size = max(channel_size, spec.channelformats[channel].basesize());
+ if (spec.channelformats[channel].is_floating_point()) {
+ metadata.is_float = true;
+ metadata.is_linear = true;
+ }
+ }
+
+ /* check if it's half float */
+ if (spec.format == TypeDesc::HALF) {
+ metadata.is_half = true;
+ }
+
+ /* basic color space detection, not great but better than nothing
+ * before we do OpenColorIO integration */
+ if (metadata.is_float) {
+ string colorspace = spec.get_string_attribute("oiio:ColorSpace");
+
+ metadata.is_linear = !(
+ colorspace == "sRGB" || colorspace == "GammaCorrected" ||
+ (colorspace == "" &&
+ (strcmp(in->format_name(), "png") == 0 || strcmp(in->format_name(), "tiff") == 0 ||
+ strcmp(in->format_name(), "dpx") == 0 || strcmp(in->format_name(), "jpeg2000") == 0)));
+ }
+ else {
+ metadata.is_linear = false;
+ }
+
+ /* set type and channels */
+ metadata.channels = spec.nchannels;
+
+ if (metadata.is_half) {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
+ }
+ else if (metadata.is_float) {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
+ }
+ else if (spec.format == TypeDesc::USHORT) {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT;
+ }
+ else {
+ metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
+ }
+
+ in->close();
+
+ return true;
}
static bool image_equals(ImageManager::Image *image,
- const string& filename,
+ const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha)
{
- return image->filename == filename &&
- image->builtin_data == builtin_data &&
- image->interpolation == interpolation &&
- image->extension == extension &&
- image->use_alpha == use_alpha;
+ return image->filename == filename && image->builtin_data == builtin_data &&
+ image->interpolation == interpolation && image->extension == extension &&
+ image->use_alpha == use_alpha;
}
-int ImageManager::add_image(const string& filename,
+int ImageManager::add_image(const string &filename,
void *builtin_data,
bool animated,
float frame,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha,
- ImageMetaData& metadata)
+ ImageMetaData &metadata)
{
- Image *img;
- size_t slot;
-
- get_image_metadata(filename, builtin_data, metadata);
- ImageDataType type = metadata.type;
-
- thread_scoped_lock device_lock(device_mutex);
-
- /* No half textures on OpenCL, use full float instead. */
- if(!has_half_images) {
- if(type == IMAGE_DATA_TYPE_HALF4) {
- type = IMAGE_DATA_TYPE_FLOAT4;
- }
- else if(type == IMAGE_DATA_TYPE_HALF) {
- type = IMAGE_DATA_TYPE_FLOAT;
- }
- }
-
- /* Fnd existing image. */
- for(slot = 0; slot < images[type].size(); slot++) {
- img = images[type][slot];
- if(img && image_equals(img,
- filename,
- builtin_data,
- interpolation,
- extension,
- use_alpha))
- {
- if(img->frame != frame) {
- img->frame = frame;
- img->need_load = true;
- }
- if(img->use_alpha != use_alpha) {
- img->use_alpha = use_alpha;
- img->need_load = true;
- }
- if(!(img->metadata == metadata)) {
- img->metadata = metadata;
- img->need_load = true;
- }
- img->users++;
- return type_index_to_flattened_slot(slot, type);
- }
- }
-
- /* Find free slot. */
- for(slot = 0; slot < images[type].size(); slot++) {
- if(!images[type][slot])
- break;
- }
-
- /* Count if we're over the limit.
- * Very unlikely, since max_num_images is insanely big. But better safe
- * than sorry.
- */
- int tex_count = 0;
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- tex_count += tex_num_images[type];
- }
- if(tex_count > max_num_images) {
- printf("ImageManager::add_image: Reached image limit (%d), "
- "skipping '%s'\n", max_num_images, filename.c_str());
- return -1;
- }
-
- if(slot == images[type].size()) {
- images[type].resize(images[type].size() + 1);
- }
-
- /* Add new image. */
- img = new Image();
- img->filename = filename;
- img->builtin_data = builtin_data;
- img->metadata = metadata;
- img->need_load = true;
- img->animated = animated;
- img->frame = frame;
- img->interpolation = interpolation;
- img->extension = extension;
- img->users = 1;
- img->use_alpha = use_alpha;
- img->mem = NULL;
-
- images[type][slot] = img;
-
- ++tex_num_images[type];
-
- need_update = true;
-
- return type_index_to_flattened_slot(slot, type);
+ Image *img;
+ size_t slot;
+
+ get_image_metadata(filename, builtin_data, metadata);
+ ImageDataType type = metadata.type;
+
+ thread_scoped_lock device_lock(device_mutex);
+
+ /* No half textures on OpenCL, use full float instead. */
+ if (!has_half_images) {
+ if (type == IMAGE_DATA_TYPE_HALF4) {
+ type = IMAGE_DATA_TYPE_FLOAT4;
+ }
+ else if (type == IMAGE_DATA_TYPE_HALF) {
+ type = IMAGE_DATA_TYPE_FLOAT;
+ }
+ }
+
+ /* Fnd existing image. */
+ for (slot = 0; slot < images[type].size(); slot++) {
+ img = images[type][slot];
+ if (img && image_equals(img, filename, builtin_data, interpolation, extension, use_alpha)) {
+ if (img->frame != frame) {
+ img->frame = frame;
+ img->need_load = true;
+ }
+ if (img->use_alpha != use_alpha) {
+ img->use_alpha = use_alpha;
+ img->need_load = true;
+ }
+ if (!(img->metadata == metadata)) {
+ img->metadata = metadata;
+ img->need_load = true;
+ }
+ img->users++;
+ return type_index_to_flattened_slot(slot, type);
+ }
+ }
+
+ /* Find free slot. */
+ for (slot = 0; slot < images[type].size(); slot++) {
+ if (!images[type][slot])
+ break;
+ }
+
+ /* Count if we're over the limit.
+ * Very unlikely, since max_num_images is insanely big. But better safe
+ * than sorry.
+ */
+ int tex_count = 0;
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ tex_count += tex_num_images[type];
+ }
+ if (tex_count > max_num_images) {
+ printf(
+ "ImageManager::add_image: Reached image limit (%d), "
+ "skipping '%s'\n",
+ max_num_images,
+ filename.c_str());
+ return -1;
+ }
+
+ if (slot == images[type].size()) {
+ images[type].resize(images[type].size() + 1);
+ }
+
+ /* Add new image. */
+ img = new Image();
+ img->filename = filename;
+ img->builtin_data = builtin_data;
+ img->metadata = metadata;
+ img->need_load = true;
+ img->animated = animated;
+ img->frame = frame;
+ img->interpolation = interpolation;
+ img->extension = extension;
+ img->users = 1;
+ img->use_alpha = use_alpha;
+ img->mem = NULL;
+
+ images[type][slot] = img;
+
+ ++tex_num_images[type];
+
+ need_update = true;
+
+ return type_index_to_flattened_slot(slot, type);
}
void ImageManager::remove_image(int flat_slot)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
- Image *image = images[type][slot];
- assert(image && image->users >= 1);
+ Image *image = images[type][slot];
+ assert(image && image->users >= 1);
- /* decrement user count */
- image->users--;
+ /* decrement user count */
+ image->users--;
- /* don't remove immediately, rather do it all together later on. one of
- * the reasons for this is that on shader changes we add and remove nodes
- * that use them, but we do not want to reload the image all the time. */
- if(image->users == 0)
- need_update = true;
+ /* don't remove immediately, rather do it all together later on. one of
+ * the reasons for this is that on shader changes we add and remove nodes
+ * that use them, but we do not want to reload the image all the time. */
+ if (image->users == 0)
+ need_update = true;
}
-void ImageManager::remove_image(const string& filename,
+void ImageManager::remove_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha)
{
- size_t slot;
-
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && image_equals(images[type][slot],
- filename,
- builtin_data,
- interpolation,
- extension,
- use_alpha))
- {
- remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
- return;
- }
- }
- }
+ size_t slot;
+
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] &&
+ image_equals(
+ images[type][slot], filename, builtin_data, interpolation, extension, use_alpha)) {
+ remove_image(type_index_to_flattened_slot(slot, (ImageDataType)type));
+ return;
+ }
+ }
+ }
}
/* TODO(sergey): Deduplicate with the iteration above, but make it pretty,
* without bunch of arguments passing around making code readability even
* more cluttered.
*/
-void ImageManager::tag_reload_image(const string& filename,
+void ImageManager::tag_reload_image(const string &filename,
void *builtin_data,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha)
{
- for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && image_equals(images[type][slot],
- filename,
- builtin_data,
- interpolation,
- extension,
- use_alpha))
- {
- images[type][slot]->need_load = true;
- break;
- }
- }
- }
+ for (size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] &&
+ image_equals(
+ images[type][slot], filename, builtin_data, interpolation, extension, use_alpha)) {
+ images[type][slot]->need_load = true;
+ break;
+ }
+ }
+ }
}
-bool ImageManager::file_load_image_generic(Image *img,
- unique_ptr<ImageInput> *in)
+bool ImageManager::file_load_image_generic(Image *img, unique_ptr<ImageInput> *in)
{
- if(img->filename == "")
- return false;
-
- if(!img->builtin_data) {
- /* NOTE: Error logging is done in meta data acquisition. */
- if(!path_exists(img->filename) || path_is_directory(img->filename)) {
- return false;
- }
-
- /* load image from file through OIIO */
- *in = unique_ptr<ImageInput>(ImageInput::create(img->filename));
-
- if(!*in)
- return false;
-
- ImageSpec spec = ImageSpec();
- ImageSpec config = ImageSpec();
-
- if(img->use_alpha == false)
- config.attribute("oiio:UnassociatedAlpha", 1);
-
- if(!(*in)->open(img->filename, spec, config)) {
- return false;
- }
- }
- else {
- /* load image using builtin images callbacks */
- if(!builtin_image_info_cb || !builtin_image_pixels_cb)
- return false;
- }
-
- /* we only handle certain number of components */
- if(!(img->metadata.channels >= 1 && img->metadata.channels <= 4)) {
- if(*in) {
- (*in)->close();
- }
- return false;
- }
-
- return true;
+ if (img->filename == "")
+ return false;
+
+ if (!img->builtin_data) {
+ /* NOTE: Error logging is done in meta data acquisition. */
+ if (!path_exists(img->filename) || path_is_directory(img->filename)) {
+ return false;
+ }
+
+ /* load image from file through OIIO */
+ *in = unique_ptr<ImageInput>(ImageInput::create(img->filename));
+
+ if (!*in)
+ return false;
+
+ ImageSpec spec = ImageSpec();
+ ImageSpec config = ImageSpec();
+
+ if (img->use_alpha == false)
+ config.attribute("oiio:UnassociatedAlpha", 1);
+
+ if (!(*in)->open(img->filename, spec, config)) {
+ return false;
+ }
+ }
+ else {
+ /* load image using builtin images callbacks */
+ if (!builtin_image_info_cb || !builtin_image_pixels_cb)
+ return false;
+ }
+
+ /* we only handle certain number of components */
+ if (!(img->metadata.channels >= 1 && img->metadata.channels <= 4)) {
+ if (*in) {
+ (*in)->close();
+ }
+ return false;
+ }
+
+ return true;
}
-template<TypeDesc::BASETYPE FileFormat,
- typename StorageType,
- typename DeviceType>
+template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType>
bool ImageManager::file_load_image(Image *img,
ImageDataType type,
int texture_limit,
- device_vector<DeviceType>& tex_img)
+ device_vector<DeviceType> &tex_img)
{
- unique_ptr<ImageInput> in = NULL;
- if(!file_load_image_generic(img, &in)) {
- return false;
- }
-
- /* Get metadata. */
- int width = img->metadata.width;
- int height = img->metadata.height;
- int depth = img->metadata.depth;
- int components = img->metadata.channels;
-
- /* Read RGBA pixels. */
- vector<StorageType> pixels_storage;
- StorageType *pixels;
- const size_t max_size = max(max(width, height), depth);
- if(max_size == 0) {
- /* Don't bother with invalid images. */
- return false;
- }
- if(texture_limit > 0 && max_size > texture_limit) {
- pixels_storage.resize(((size_t)width)*height*depth*4);
- pixels = &pixels_storage[0];
- }
- else {
- thread_scoped_lock device_lock(device_mutex);
- pixels = (StorageType*)tex_img.alloc(width, height, depth);
- }
- if(pixels == NULL) {
- /* Could be that we've run out of memory. */
- return false;
- }
- bool cmyk = false;
- const size_t num_pixels = ((size_t)width) * height * depth;
- if(in) {
- StorageType *readpixels = pixels;
- vector<StorageType> tmppixels;
- if(components > 4) {
- tmppixels.resize(((size_t)width)*height*components);
- readpixels = &tmppixels[0];
- }
- if(depth <= 1) {
- size_t scanlinesize = ((size_t)width)*components*sizeof(StorageType);
- in->read_image(FileFormat,
- (uchar*)readpixels + (height-1)*scanlinesize,
- AutoStride,
- -scanlinesize,
- AutoStride);
- }
- else {
- in->read_image(FileFormat, (uchar*)readpixels);
- }
- if(components > 4) {
- size_t dimensions = ((size_t)width)*height;
- for(size_t i = dimensions-1, pixel = 0; pixel < dimensions; pixel++, i--) {
- pixels[i*4+3] = tmppixels[i*components+3];
- pixels[i*4+2] = tmppixels[i*components+2];
- pixels[i*4+1] = tmppixels[i*components+1];
- pixels[i*4+0] = tmppixels[i*components+0];
- }
- tmppixels.clear();
- }
- cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
- in->close();
- }
- else {
- if(FileFormat == TypeDesc::FLOAT) {
- builtin_image_float_pixels_cb(img->filename,
- img->builtin_data,
- (float*)&pixels[0],
- num_pixels * components,
- img->metadata.builtin_free_cache);
- }
- else if(FileFormat == TypeDesc::UINT8) {
- builtin_image_pixels_cb(img->filename,
- img->builtin_data,
- (uchar*)&pixels[0],
- num_pixels * components,
- img->metadata.builtin_free_cache);
- }
- else {
- /* TODO(dingto): Support half for ImBuf. */
- }
- }
- /* Check if we actually have a float4 slot, in case components == 1,
- * but device doesn't support single channel textures.
- */
- bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 ||
- type == IMAGE_DATA_TYPE_HALF4 ||
- type == IMAGE_DATA_TYPE_BYTE4 ||
- type == IMAGE_DATA_TYPE_USHORT4);
- if(is_rgba) {
- const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
-
- if(cmyk) {
- /* CMYK */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- float c = util_image_cast_to_float(pixels[i*4+0]);
- float m = util_image_cast_to_float(pixels[i*4+1]);
- float y = util_image_cast_to_float(pixels[i*4+2]);
- float k = util_image_cast_to_float(pixels[i*4+3]);
- pixels[i*4+0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
- pixels[i*4+1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
- pixels[i*4+2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
- pixels[i*4+3] = one;
- }
- }
- else if(components == 2) {
- /* grayscale + alpha */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = pixels[i*2+1];
- pixels[i*4+2] = pixels[i*2+0];
- pixels[i*4+1] = pixels[i*2+0];
- pixels[i*4+0] = pixels[i*2+0];
- }
- }
- else if(components == 3) {
- /* RGB */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = one;
- pixels[i*4+2] = pixels[i*3+2];
- pixels[i*4+1] = pixels[i*3+1];
- pixels[i*4+0] = pixels[i*3+0];
- }
- }
- else if(components == 1) {
- /* grayscale */
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = one;
- pixels[i*4+2] = pixels[i];
- pixels[i*4+1] = pixels[i];
- pixels[i*4+0] = pixels[i];
- }
- }
- if(img->use_alpha == false) {
- for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
- pixels[i*4+3] = one;
- }
- }
- }
- /* Make sure we don't have buggy values. */
- if(FileFormat == TypeDesc::FLOAT) {
- /* For RGBA buffers we put all channels to 0 if either of them is not
- * finite. This way we avoid possible artifacts caused by fully changed
- * hue.
- */
- if(is_rgba) {
- for(size_t i = 0; i < num_pixels; i += 4) {
- StorageType *pixel = &pixels[i*4];
- if(!isfinite(pixel[0]) ||
- !isfinite(pixel[1]) ||
- !isfinite(pixel[2]) ||
- !isfinite(pixel[3]))
- {
- pixel[0] = 0;
- pixel[1] = 0;
- pixel[2] = 0;
- pixel[3] = 0;
- }
- }
- }
- else {
- for(size_t i = 0; i < num_pixels; ++i) {
- StorageType *pixel = &pixels[i];
- if(!isfinite(pixel[0])) {
- pixel[0] = 0;
- }
- }
- }
- }
- /* Scale image down if needed. */
- if(pixels_storage.size() > 0) {
- float scale_factor = 1.0f;
- while(max_size * scale_factor > texture_limit) {
- scale_factor *= 0.5f;
- }
- VLOG(1) << "Scaling image " << img->filename
- << " by a factor of " << scale_factor << ".";
- vector<StorageType> scaled_pixels;
- size_t scaled_width, scaled_height, scaled_depth;
- util_image_resize_pixels(pixels_storage,
- width, height, depth,
- is_rgba ? 4 : 1,
- scale_factor,
- &scaled_pixels,
- &scaled_width, &scaled_height, &scaled_depth);
-
- StorageType *texture_pixels;
-
- {
- thread_scoped_lock device_lock(device_mutex);
- texture_pixels = (StorageType*)tex_img.alloc(scaled_width,
- scaled_height,
- scaled_depth);
- }
-
- memcpy(texture_pixels,
- &scaled_pixels[0],
- scaled_pixels.size() * sizeof(StorageType));
- }
- return true;
+ unique_ptr<ImageInput> in = NULL;
+ if (!file_load_image_generic(img, &in)) {
+ return false;
+ }
+
+ /* Get metadata. */
+ int width = img->metadata.width;
+ int height = img->metadata.height;
+ int depth = img->metadata.depth;
+ int components = img->metadata.channels;
+
+ /* Read RGBA pixels. */
+ vector<StorageType> pixels_storage;
+ StorageType *pixels;
+ const size_t max_size = max(max(width, height), depth);
+ if (max_size == 0) {
+ /* Don't bother with invalid images. */
+ return false;
+ }
+ if (texture_limit > 0 && max_size > texture_limit) {
+ pixels_storage.resize(((size_t)width) * height * depth * 4);
+ pixels = &pixels_storage[0];
+ }
+ else {
+ thread_scoped_lock device_lock(device_mutex);
+ pixels = (StorageType *)tex_img.alloc(width, height, depth);
+ }
+ if (pixels == NULL) {
+ /* Could be that we've run out of memory. */
+ return false;
+ }
+ bool cmyk = false;
+ const size_t num_pixels = ((size_t)width) * height * depth;
+ if (in) {
+ StorageType *readpixels = pixels;
+ vector<StorageType> tmppixels;
+ if (components > 4) {
+ tmppixels.resize(((size_t)width) * height * components);
+ readpixels = &tmppixels[0];
+ }
+ if (depth <= 1) {
+ size_t scanlinesize = ((size_t)width) * components * sizeof(StorageType);
+ in->read_image(FileFormat,
+ (uchar *)readpixels + (height - 1) * scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
+ }
+ else {
+ in->read_image(FileFormat, (uchar *)readpixels);
+ }
+ if (components > 4) {
+ size_t dimensions = ((size_t)width) * height;
+ for (size_t i = dimensions - 1, pixel = 0; pixel < dimensions; pixel++, i--) {
+ pixels[i * 4 + 3] = tmppixels[i * components + 3];
+ pixels[i * 4 + 2] = tmppixels[i * components + 2];
+ pixels[i * 4 + 1] = tmppixels[i * components + 1];
+ pixels[i * 4 + 0] = tmppixels[i * components + 0];
+ }
+ tmppixels.clear();
+ }
+ cmyk = strcmp(in->format_name(), "jpeg") == 0 && components == 4;
+ in->close();
+ }
+ else {
+ if (FileFormat == TypeDesc::FLOAT) {
+ builtin_image_float_pixels_cb(img->filename,
+ img->builtin_data,
+ (float *)&pixels[0],
+ num_pixels * components,
+ img->metadata.builtin_free_cache);
+ }
+ else if (FileFormat == TypeDesc::UINT8) {
+ builtin_image_pixels_cb(img->filename,
+ img->builtin_data,
+ (uchar *)&pixels[0],
+ num_pixels * components,
+ img->metadata.builtin_free_cache);
+ }
+ else {
+ /* TODO(dingto): Support half for ImBuf. */
+ }
+ }
+ /* Check if we actually have a float4 slot, in case components == 1,
+ * but device doesn't support single channel textures.
+ */
+ bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 || type == IMAGE_DATA_TYPE_HALF4 ||
+ type == IMAGE_DATA_TYPE_BYTE4 || type == IMAGE_DATA_TYPE_USHORT4);
+ if (is_rgba) {
+ const StorageType one = util_image_cast_from_float<StorageType>(1.0f);
+
+ if (cmyk) {
+ /* CMYK */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ float c = util_image_cast_to_float(pixels[i * 4 + 0]);
+ float m = util_image_cast_to_float(pixels[i * 4 + 1]);
+ float y = util_image_cast_to_float(pixels[i * 4 + 2]);
+ float k = util_image_cast_to_float(pixels[i * 4 + 3]);
+ pixels[i * 4 + 0] = util_image_cast_from_float<StorageType>((1.0f - c) * (1.0f - k));
+ pixels[i * 4 + 1] = util_image_cast_from_float<StorageType>((1.0f - m) * (1.0f - k));
+ pixels[i * 4 + 2] = util_image_cast_from_float<StorageType>((1.0f - y) * (1.0f - k));
+ pixels[i * 4 + 3] = one;
+ }
+ }
+ else if (components == 2) {
+ /* grayscale + alpha */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = pixels[i * 2 + 1];
+ pixels[i * 4 + 2] = pixels[i * 2 + 0];
+ pixels[i * 4 + 1] = pixels[i * 2 + 0];
+ pixels[i * 4 + 0] = pixels[i * 2 + 0];
+ }
+ }
+ else if (components == 3) {
+ /* RGB */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = one;
+ pixels[i * 4 + 2] = pixels[i * 3 + 2];
+ pixels[i * 4 + 1] = pixels[i * 3 + 1];
+ pixels[i * 4 + 0] = pixels[i * 3 + 0];
+ }
+ }
+ else if (components == 1) {
+ /* grayscale */
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = one;
+ pixels[i * 4 + 2] = pixels[i];
+ pixels[i * 4 + 1] = pixels[i];
+ pixels[i * 4 + 0] = pixels[i];
+ }
+ }
+ if (img->use_alpha == false) {
+ for (size_t i = num_pixels - 1, pixel = 0; pixel < num_pixels; pixel++, i--) {
+ pixels[i * 4 + 3] = one;
+ }
+ }
+ }
+ /* Make sure we don't have buggy values. */
+ if (FileFormat == TypeDesc::FLOAT) {
+ /* For RGBA buffers we put all channels to 0 if either of them is not
+ * finite. This way we avoid possible artifacts caused by fully changed
+ * hue.
+ */
+ if (is_rgba) {
+ for (size_t i = 0; i < num_pixels; i += 4) {
+ StorageType *pixel = &pixels[i * 4];
+ if (!isfinite(pixel[0]) || !isfinite(pixel[1]) || !isfinite(pixel[2]) ||
+ !isfinite(pixel[3])) {
+ pixel[0] = 0;
+ pixel[1] = 0;
+ pixel[2] = 0;
+ pixel[3] = 0;
+ }
+ }
+ }
+ else {
+ for (size_t i = 0; i < num_pixels; ++i) {
+ StorageType *pixel = &pixels[i];
+ if (!isfinite(pixel[0])) {
+ pixel[0] = 0;
+ }
+ }
+ }
+ }
+ /* Scale image down if needed. */
+ if (pixels_storage.size() > 0) {
+ float scale_factor = 1.0f;
+ while (max_size * scale_factor > texture_limit) {
+ scale_factor *= 0.5f;
+ }
+ VLOG(1) << "Scaling image " << img->filename << " by a factor of " << scale_factor << ".";
+ vector<StorageType> scaled_pixels;
+ size_t scaled_width, scaled_height, scaled_depth;
+ util_image_resize_pixels(pixels_storage,
+ width,
+ height,
+ depth,
+ is_rgba ? 4 : 1,
+ scale_factor,
+ &scaled_pixels,
+ &scaled_width,
+ &scaled_height,
+ &scaled_depth);
+
+ StorageType *texture_pixels;
+
+ {
+ thread_scoped_lock device_lock(device_mutex);
+ texture_pixels = (StorageType *)tex_img.alloc(scaled_width, scaled_height, scaled_depth);
+ }
+
+ memcpy(texture_pixels, &scaled_pixels[0], scaled_pixels.size() * sizeof(StorageType));
+ }
+ return true;
}
-void ImageManager::device_load_image(Device *device,
- Scene *scene,
- ImageDataType type,
- int slot,
- Progress *progress)
+void ImageManager::device_load_image(
+ Device *device, Scene *scene, ImageDataType type, int slot, Progress *progress)
{
- if(progress->get_cancel())
- return;
-
- Image *img = images[type][slot];
-
- if(osl_texture_system && !img->builtin_data)
- return;
-
- string filename = path_filename(images[type][slot]->filename);
- progress->set_status("Updating Images", "Loading " + filename);
-
- const int texture_limit = scene->params.texture_limit;
-
- /* Slot assignment */
- int flat_slot = type_index_to_flattened_slot(slot, type);
- img->mem_name = string_printf("__tex_image_%s_%03d",
- name_from_type(type), flat_slot);
-
- /* Free previous texture in slot. */
- if(img->mem) {
- thread_scoped_lock device_lock(device_mutex);
- delete img->mem;
- img->mem = NULL;
- }
-
- /* Create new texture. */
- if(type == IMAGE_DATA_TYPE_FLOAT4) {
- device_vector<float4> *tex_img
- = new device_vector<float4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_FLOAT) {
- device_vector<float> *tex_img
- = new device_vector<float>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_BYTE4) {
- device_vector<uchar4> *tex_img
- = new device_vector<uchar4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::UINT8, uchar>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 255);
- pixels[1] = (TEX_IMAGE_MISSING_G * 255);
- pixels[2] = (TEX_IMAGE_MISSING_B * 255);
- pixels[3] = (TEX_IMAGE_MISSING_A * 255);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_BYTE) {
- device_vector<uchar> *tex_img
- = new device_vector<uchar>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::UINT8, uchar>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 255);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_HALF4) {
- device_vector<half4> *tex_img
- = new device_vector<half4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::HALF, half>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_USHORT) {
- device_vector<uint16_t> *tex_img
- = new device_vector<uint16_t>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::USHORT, uint16_t>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_USHORT4) {
- device_vector<ushort4> *tex_img
- = new device_vector<ushort4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::USHORT, uint16_t>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uint16_t *pixels = (uint16_t*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
- pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
- pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
- pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_HALF) {
- device_vector<half> *tex_img
- = new device_vector<half>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::HALF, half>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- img->need_load = false;
+ if (progress->get_cancel())
+ return;
+
+ Image *img = images[type][slot];
+
+ if (osl_texture_system && !img->builtin_data)
+ return;
+
+ string filename = path_filename(images[type][slot]->filename);
+ progress->set_status("Updating Images", "Loading " + filename);
+
+ const int texture_limit = scene->params.texture_limit;
+
+ /* Slot assignment */
+ int flat_slot = type_index_to_flattened_slot(slot, type);
+ img->mem_name = string_printf("__tex_image_%s_%03d", name_from_type(type), flat_slot);
+
+ /* Free previous texture in slot. */
+ if (img->mem) {
+ thread_scoped_lock device_lock(device_mutex);
+ delete img->mem;
+ img->mem = NULL;
+ }
+
+ /* Create new texture. */
+ if (type == IMAGE_DATA_TYPE_FLOAT4) {
+ device_vector<float4> *tex_img = new device_vector<float4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::FLOAT, float>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ float *pixels = (float *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_FLOAT) {
+ device_vector<float> *tex_img = new device_vector<float>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::FLOAT, float>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ float *pixels = (float *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_BYTE4) {
+ device_vector<uchar4> *tex_img = new device_vector<uchar4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::UINT8, uchar>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uchar *pixels = (uchar *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 255);
+ pixels[1] = (TEX_IMAGE_MISSING_G * 255);
+ pixels[2] = (TEX_IMAGE_MISSING_B * 255);
+ pixels[3] = (TEX_IMAGE_MISSING_A * 255);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_BYTE) {
+ device_vector<uchar> *tex_img = new device_vector<uchar>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::UINT8, uchar>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uchar *pixels = (uchar *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 255);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_HALF4) {
+ device_vector<half4> *tex_img = new device_vector<half4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::HALF, half>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ half *pixels = (half *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_USHORT) {
+ device_vector<uint16_t> *tex_img = new device_vector<uint16_t>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uint16_t *pixels = (uint16_t *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_USHORT4) {
+ device_vector<ushort4> *tex_img = new device_vector<ushort4>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::USHORT, uint16_t>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ uint16_t *pixels = (uint16_t *)tex_img->alloc(1, 1);
+
+ pixels[0] = (TEX_IMAGE_MISSING_R * 65535);
+ pixels[1] = (TEX_IMAGE_MISSING_G * 65535);
+ pixels[2] = (TEX_IMAGE_MISSING_B * 65535);
+ pixels[3] = (TEX_IMAGE_MISSING_A * 65535);
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ else if (type == IMAGE_DATA_TYPE_HALF) {
+ device_vector<half> *tex_img = new device_vector<half>(
+ device, img->mem_name.c_str(), MEM_TEXTURE);
+
+ if (!file_load_image<TypeDesc::HALF, half>(img, type, texture_limit, *tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ thread_scoped_lock device_lock(device_mutex);
+ half *pixels = (half *)tex_img->alloc(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ }
+
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+ img->need_load = false;
}
void ImageManager::device_free_image(Device *, ImageDataType type, int slot)
{
- Image *img = images[type][slot];
+ Image *img = images[type][slot];
- if(img) {
- if(osl_texture_system && !img->builtin_data) {
+ if (img) {
+ if (osl_texture_system && !img->builtin_data) {
#ifdef WITH_OSL
- ustring filename(images[type][slot]->filename);
- ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
+ ustring filename(images[type][slot]->filename);
+ ((OSL::TextureSystem *)osl_texture_system)->invalidate(filename);
#endif
- }
+ }
- if(img->mem) {
- thread_scoped_lock device_lock(device_mutex);
- delete img->mem;
- }
+ if (img->mem) {
+ thread_scoped_lock device_lock(device_mutex);
+ delete img->mem;
+ }
- delete img;
- images[type][slot] = NULL;
- --tex_num_images[type];
- }
+ delete img;
+ images[type][slot] = NULL;
+ --tex_num_images[type];
+ }
}
-void ImageManager::device_update(Device *device,
- Scene *scene,
- Progress& progress)
+void ImageManager::device_update(Device *device, Scene *scene, Progress &progress)
{
- if(!need_update) {
- return;
- }
-
- TaskPool pool;
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(!images[type][slot])
- continue;
-
- if(images[type][slot]->users == 0) {
- device_free_image(device, (ImageDataType)type, slot);
- }
- else if(images[type][slot]->need_load) {
- if(!osl_texture_system || images[type][slot]->builtin_data)
- pool.push(function_bind(&ImageManager::device_load_image,
- this,
- device,
- scene,
- (ImageDataType)type,
- slot,
- &progress));
- }
- }
- }
-
- pool.wait_work();
-
- need_update = false;
+ if (!need_update) {
+ return;
+ }
+
+ TaskPool pool;
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (!images[type][slot])
+ continue;
+
+ if (images[type][slot]->users == 0) {
+ device_free_image(device, (ImageDataType)type, slot);
+ }
+ else if (images[type][slot]->need_load) {
+ if (!osl_texture_system || images[type][slot]->builtin_data)
+ pool.push(function_bind(&ImageManager::device_load_image,
+ this,
+ device,
+ scene,
+ (ImageDataType)type,
+ slot,
+ &progress));
+ }
+ }
+ }
+
+ pool.wait_work();
+
+ need_update = false;
}
void ImageManager::device_update_slot(Device *device,
@@ -1001,87 +943,80 @@ void ImageManager::device_update_slot(Device *device,
int flat_slot,
Progress *progress)
{
- ImageDataType type;
- int slot = flattened_slot_to_type_index(flat_slot, &type);
-
- Image *image = images[type][slot];
- assert(image != NULL);
-
- if(image->users == 0) {
- device_free_image(device, type, slot);
- }
- else if(image->need_load) {
- if(!osl_texture_system || image->builtin_data)
- device_load_image(device,
- scene,
- type,
- slot,
- progress);
- }
+ ImageDataType type;
+ int slot = flattened_slot_to_type_index(flat_slot, &type);
+
+ Image *image = images[type][slot];
+ assert(image != NULL);
+
+ if (image->users == 0) {
+ device_free_image(device, type, slot);
+ }
+ else if (image->need_load) {
+ if (!osl_texture_system || image->builtin_data)
+ device_load_image(device, scene, type, slot, progress);
+ }
}
-void ImageManager::device_load_builtin(Device *device,
- Scene *scene,
- Progress& progress)
+void ImageManager::device_load_builtin(Device *device, Scene *scene, Progress &progress)
{
- /* Load only builtin images, Blender needs this to load evaluated
- * scene data from depsgraph before it is freed. */
- if(!need_update) {
- return;
- }
-
- TaskPool pool;
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(!images[type][slot])
- continue;
-
- if(images[type][slot]->need_load) {
- if(images[type][slot]->builtin_data) {
- pool.push(function_bind(&ImageManager::device_load_image,
- this,
- device,
- scene,
- (ImageDataType)type,
- slot,
- &progress));
- }
- }
- }
- }
-
- pool.wait_work();
+ /* Load only builtin images, Blender needs this to load evaluated
+ * scene data from depsgraph before it is freed. */
+ if (!need_update) {
+ return;
+ }
+
+ TaskPool pool;
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (!images[type][slot])
+ continue;
+
+ if (images[type][slot]->need_load) {
+ if (images[type][slot]->builtin_data) {
+ pool.push(function_bind(&ImageManager::device_load_image,
+ this,
+ device,
+ scene,
+ (ImageDataType)type,
+ slot,
+ &progress));
+ }
+ }
+ }
+ }
+
+ pool.wait_work();
}
void ImageManager::device_free_builtin(Device *device)
{
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- if(images[type][slot] && images[type][slot]->builtin_data)
- device_free_image(device, (ImageDataType)type, slot);
- }
- }
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ if (images[type][slot] && images[type][slot]->builtin_data)
+ device_free_image(device, (ImageDataType)type, slot);
+ }
+ }
}
void ImageManager::device_free(Device *device)
{
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- for(size_t slot = 0; slot < images[type].size(); slot++) {
- device_free_image(device, (ImageDataType)type, slot);
- }
- images[type].clear();
- }
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ for (size_t slot = 0; slot < images[type].size(); slot++) {
+ device_free_image(device, (ImageDataType)type, slot);
+ }
+ images[type].clear();
+ }
}
void ImageManager::collect_statistics(RenderStats *stats)
{
- for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
- foreach(const Image *image, images[type]) {
- stats->image.textures.add_entry(
- NamedSizeEntry(path_filename(image->filename),
- image->mem->memory_size()));
- }
- }
+ for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) {
+ foreach (const Image *image, images[type]) {
+ stats->image.textures.add_entry(
+ NamedSizeEntry(path_filename(image->filename), image->mem->memory_size()));
+ }
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 1403b9050fd..34f046692f6 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -34,150 +34,129 @@ class RenderStats;
class Scene;
class ImageMetaData {
-public:
- /* Must be set by image file or builtin callback. */
- bool is_float, is_half;
- int channels;
- size_t width, height, depth;
- bool builtin_free_cache;
-
- /* Automatically set. */
- ImageDataType type;
- bool is_linear;
-
- bool operator==(const ImageMetaData& other) const
- {
- return is_float == other.is_float &&
- is_half == other.is_half &&
- channels == other.channels &&
- width == other.width &&
- height == other.height &&
- depth == other.depth &&
- type == other.type &&
- is_linear == other.is_linear;
- }
+ public:
+ /* Must be set by image file or builtin callback. */
+ bool is_float, is_half;
+ int channels;
+ size_t width, height, depth;
+ bool builtin_free_cache;
+
+ /* Automatically set. */
+ ImageDataType type;
+ bool is_linear;
+
+ bool operator==(const ImageMetaData &other) const
+ {
+ return is_float == other.is_float && is_half == other.is_half && channels == other.channels &&
+ width == other.width && height == other.height && depth == other.depth &&
+ type == other.type && is_linear == other.is_linear;
+ }
};
class ImageManager {
-public:
- explicit ImageManager(const DeviceInfo& info);
- ~ImageManager();
-
- int add_image(const string& filename,
- void *builtin_data,
- bool animated,
- float frame,
- InterpolationType interpolation,
- ExtensionType extension,
- bool use_alpha,
- ImageMetaData& metadata);
- void remove_image(int flat_slot);
- void remove_image(const string& filename,
- void *builtin_data,
- InterpolationType interpolation,
- ExtensionType extension,
- bool use_alpha);
- void tag_reload_image(const string& filename,
- void *builtin_data,
- InterpolationType interpolation,
- ExtensionType extension,
- bool use_alpha);
- bool get_image_metadata(const string& filename,
- void *builtin_data,
- ImageMetaData& metadata);
- bool get_image_metadata(int flat_slot,
- ImageMetaData& metadata);
-
- void device_update(Device *device,
- Scene *scene,
- Progress& progress);
- void device_update_slot(Device *device,
- Scene *scene,
- int flat_slot,
- Progress *progress);
- void device_free(Device *device);
-
- void device_load_builtin(Device *device,
- Scene *scene,
- Progress& progress);
- void device_free_builtin(Device *device);
-
- void set_osl_texture_system(void *texture_system);
- bool set_animation_frame_update(int frame);
-
- device_memory *image_memory(int flat_slot);
-
- void collect_statistics(RenderStats *stats);
-
- bool need_update;
-
- /* NOTE: Here pixels_size is a size of storage, which equals to
- * width * height * depth.
- * Use this to avoid some nasty memory corruptions.
- */
- function<void(const string &filename,
- void *data,
- ImageMetaData& metadata)> builtin_image_info_cb;
- function<bool(const string &filename,
- void *data,
- unsigned char *pixels,
- const size_t pixels_size,
- const bool free_cache)> builtin_image_pixels_cb;
- function<bool(const string &filename,
- void *data,
- float *pixels,
- const size_t pixels_size,
- const bool free_cache)> builtin_image_float_pixels_cb;
-
- struct Image {
- string filename;
- void *builtin_data;
- ImageMetaData metadata;
-
- bool use_alpha;
- bool need_load;
- bool animated;
- float frame;
- InterpolationType interpolation;
- ExtensionType extension;
-
- string mem_name;
- device_memory *mem;
-
- int users;
- };
-
-private:
- int tex_num_images[IMAGE_DATA_NUM_TYPES];
- int max_num_images;
- bool has_half_images;
-
- thread_mutex device_mutex;
- int animation_frame;
-
- vector<Image*> images[IMAGE_DATA_NUM_TYPES];
- void *osl_texture_system;
-
- bool file_load_image_generic(Image *img, unique_ptr<ImageInput> *in);
-
- template<TypeDesc::BASETYPE FileFormat,
- typename StorageType,
- typename DeviceType>
- bool file_load_image(Image *img,
- ImageDataType type,
- int texture_limit,
- device_vector<DeviceType>& tex_img);
-
- void device_load_image(Device *device,
- Scene *scene,
- ImageDataType type,
- int slot,
- Progress *progress);
- void device_free_image(Device *device,
- ImageDataType type,
- int slot);
+ public:
+ explicit ImageManager(const DeviceInfo &info);
+ ~ImageManager();
+
+ int add_image(const string &filename,
+ void *builtin_data,
+ bool animated,
+ float frame,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha,
+ ImageMetaData &metadata);
+ void remove_image(int flat_slot);
+ void remove_image(const string &filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha);
+ void tag_reload_image(const string &filename,
+ void *builtin_data,
+ InterpolationType interpolation,
+ ExtensionType extension,
+ bool use_alpha);
+ bool get_image_metadata(const string &filename, void *builtin_data, ImageMetaData &metadata);
+ bool get_image_metadata(int flat_slot, ImageMetaData &metadata);
+
+ void device_update(Device *device, Scene *scene, Progress &progress);
+ void device_update_slot(Device *device, Scene *scene, int flat_slot, Progress *progress);
+ void device_free(Device *device);
+
+ void device_load_builtin(Device *device, Scene *scene, Progress &progress);
+ void device_free_builtin(Device *device);
+
+ void set_osl_texture_system(void *texture_system);
+ bool set_animation_frame_update(int frame);
+
+ device_memory *image_memory(int flat_slot);
+
+ void collect_statistics(RenderStats *stats);
+
+ bool need_update;
+
+ /* NOTE: Here pixels_size is a size of storage, which equals to
+ * width * height * depth.
+ * Use this to avoid some nasty memory corruptions.
+ */
+ function<void(const string &filename, void *data, ImageMetaData &metadata)>
+ builtin_image_info_cb;
+ function<bool(const string &filename,
+ void *data,
+ unsigned char *pixels,
+ const size_t pixels_size,
+ const bool free_cache)>
+ builtin_image_pixels_cb;
+ function<bool(const string &filename,
+ void *data,
+ float *pixels,
+ const size_t pixels_size,
+ const bool free_cache)>
+ builtin_image_float_pixels_cb;
+
+ struct Image {
+ string filename;
+ void *builtin_data;
+ ImageMetaData metadata;
+
+ bool use_alpha;
+ bool need_load;
+ bool animated;
+ float frame;
+ InterpolationType interpolation;
+ ExtensionType extension;
+
+ string mem_name;
+ device_memory *mem;
+
+ int users;
+ };
+
+ private:
+ int tex_num_images[IMAGE_DATA_NUM_TYPES];
+ int max_num_images;
+ bool has_half_images;
+
+ thread_mutex device_mutex;
+ int animation_frame;
+
+ vector<Image *> images[IMAGE_DATA_NUM_TYPES];
+ void *osl_texture_system;
+
+ bool file_load_image_generic(Image *img, unique_ptr<ImageInput> *in);
+
+ template<TypeDesc::BASETYPE FileFormat, typename StorageType, typename DeviceType>
+ bool file_load_image(Image *img,
+ ImageDataType type,
+ int texture_limit,
+ device_vector<DeviceType> &tex_img);
+
+ void device_load_image(
+ Device *device, Scene *scene, ImageDataType type, int slot, Progress *progress);
+ void device_free_image(Device *device, ImageDataType type, int slot);
};
CCL_NAMESPACE_END
-#endif /* __IMAGE_H__ */
+#endif /* __IMAGE_H__ */
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index d86eb8fc5d3..d3873dcfe46 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -30,61 +30,60 @@ CCL_NAMESPACE_BEGIN
NODE_DEFINE(Integrator)
{
- NodeType *type = NodeType::add("integrator", create);
-
- SOCKET_INT(max_bounce, "Max Bounce", 7);
-
- SOCKET_INT(max_diffuse_bounce, "Max Diffuse Bounce", 7);
- SOCKET_INT(max_glossy_bounce, "Max Glossy Bounce", 7);
- SOCKET_INT(max_transmission_bounce, "Max Transmission Bounce", 7);
- SOCKET_INT(max_volume_bounce, "Max Volume Bounce", 7);
-
- SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
-
- SOCKET_INT(ao_bounces, "AO Bounces", 0);
-
- SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024);
- SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f);
-
- SOCKET_BOOLEAN(caustics_reflective, "Reflective Caustics", true);
- SOCKET_BOOLEAN(caustics_refractive, "Refractive Caustics", true);
- SOCKET_FLOAT(filter_glossy, "Filter Glossy", 0.0f);
- SOCKET_INT(seed, "Seed", 0);
- SOCKET_FLOAT(sample_clamp_direct, "Sample Clamp Direct", 0.0f);
- SOCKET_FLOAT(sample_clamp_indirect, "Sample Clamp Indirect", 0.0f);
- SOCKET_BOOLEAN(motion_blur, "Motion Blur", false);
-
- SOCKET_INT(aa_samples, "AA Samples", 0);
- SOCKET_INT(diffuse_samples, "Diffuse Samples", 1);
- SOCKET_INT(glossy_samples, "Glossy Samples", 1);
- SOCKET_INT(transmission_samples, "Transmission Samples", 1);
- SOCKET_INT(ao_samples, "AO Samples", 1);
- SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1);
- SOCKET_INT(subsurface_samples, "Subsurface Samples", 1);
- SOCKET_INT(volume_samples, "Volume Samples", 1);
- SOCKET_INT(start_sample, "Start Sample", 0);
-
- SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
- SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
- SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.05f);
-
- static NodeEnum method_enum;
- method_enum.insert("path", PATH);
- method_enum.insert("branched_path", BRANCHED_PATH);
- SOCKET_ENUM(method, "Method", method_enum, PATH);
-
- static NodeEnum sampling_pattern_enum;
- sampling_pattern_enum.insert("sobol", SAMPLING_PATTERN_SOBOL);
- sampling_pattern_enum.insert("cmj", SAMPLING_PATTERN_CMJ);
- SOCKET_ENUM(sampling_pattern, "Sampling Pattern", sampling_pattern_enum, SAMPLING_PATTERN_SOBOL);
-
- return type;
+ NodeType *type = NodeType::add("integrator", create);
+
+ SOCKET_INT(max_bounce, "Max Bounce", 7);
+
+ SOCKET_INT(max_diffuse_bounce, "Max Diffuse Bounce", 7);
+ SOCKET_INT(max_glossy_bounce, "Max Glossy Bounce", 7);
+ SOCKET_INT(max_transmission_bounce, "Max Transmission Bounce", 7);
+ SOCKET_INT(max_volume_bounce, "Max Volume Bounce", 7);
+
+ SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
+
+ SOCKET_INT(ao_bounces, "AO Bounces", 0);
+
+ SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024);
+ SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f);
+
+ SOCKET_BOOLEAN(caustics_reflective, "Reflective Caustics", true);
+ SOCKET_BOOLEAN(caustics_refractive, "Refractive Caustics", true);
+ SOCKET_FLOAT(filter_glossy, "Filter Glossy", 0.0f);
+ SOCKET_INT(seed, "Seed", 0);
+ SOCKET_FLOAT(sample_clamp_direct, "Sample Clamp Direct", 0.0f);
+ SOCKET_FLOAT(sample_clamp_indirect, "Sample Clamp Indirect", 0.0f);
+ SOCKET_BOOLEAN(motion_blur, "Motion Blur", false);
+
+ SOCKET_INT(aa_samples, "AA Samples", 0);
+ SOCKET_INT(diffuse_samples, "Diffuse Samples", 1);
+ SOCKET_INT(glossy_samples, "Glossy Samples", 1);
+ SOCKET_INT(transmission_samples, "Transmission Samples", 1);
+ SOCKET_INT(ao_samples, "AO Samples", 1);
+ SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1);
+ SOCKET_INT(subsurface_samples, "Subsurface Samples", 1);
+ SOCKET_INT(volume_samples, "Volume Samples", 1);
+ SOCKET_INT(start_sample, "Start Sample", 0);
+
+ SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true);
+ SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true);
+ SOCKET_FLOAT(light_sampling_threshold, "Light Sampling Threshold", 0.05f);
+
+ static NodeEnum method_enum;
+ method_enum.insert("path", PATH);
+ method_enum.insert("branched_path", BRANCHED_PATH);
+ SOCKET_ENUM(method, "Method", method_enum, PATH);
+
+ static NodeEnum sampling_pattern_enum;
+ sampling_pattern_enum.insert("sobol", SAMPLING_PATTERN_SOBOL);
+ sampling_pattern_enum.insert("cmj", SAMPLING_PATTERN_CMJ);
+ SOCKET_ENUM(sampling_pattern, "Sampling Pattern", sampling_pattern_enum, SAMPLING_PATTERN_SOBOL);
+
+ return type;
}
-Integrator::Integrator()
-: Node(node_type)
+Integrator::Integrator() : Node(node_type)
{
- need_update = true;
+ need_update = true;
}
Integrator::~Integrator()
@@ -93,146 +92,148 @@ Integrator::~Integrator()
void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene)
{
- if(!need_update)
- return;
-
- device_free(device, dscene);
-
- KernelIntegrator *kintegrator = &dscene->data.integrator;
-
- /* integrator parameters */
- kintegrator->max_bounce = max_bounce + 1;
-
- kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
- kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
- kintegrator->max_transmission_bounce = max_transmission_bounce + 1;
- kintegrator->max_volume_bounce = max_volume_bounce + 1;
-
- kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
-
- if(ao_bounces == 0) {
- kintegrator->ao_bounces = INT_MAX;
- }
- else {
- kintegrator->ao_bounces = ao_bounces - 1;
- }
-
- /* Transparent Shadows
- * We only need to enable transparent shadows, if we actually have
- * transparent shaders in the scene. Otherwise we can disable it
- * to improve performance a bit. */
- kintegrator->transparent_shadows = false;
- foreach(Shader *shader, scene->shaders) {
- /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
- if((shader->has_surface_transparent && shader->use_transparent_shadow) || shader->has_volume) {
- kintegrator->transparent_shadows = true;
- break;
- }
- }
-
- kintegrator->volume_max_steps = volume_max_steps;
- kintegrator->volume_step_size = volume_step_size;
-
- kintegrator->caustics_reflective = caustics_reflective;
- kintegrator->caustics_refractive = caustics_refractive;
- kintegrator->filter_glossy = (filter_glossy == 0.0f)? FLT_MAX: 1.0f/filter_glossy;
-
- kintegrator->seed = hash_int(seed);
-
- kintegrator->use_ambient_occlusion =
- ((Pass::contains(scene->film->passes, PASS_AO)) || dscene->data.background.ao_factor != 0.0f);
-
- kintegrator->sample_clamp_direct = (sample_clamp_direct == 0.0f)? FLT_MAX: sample_clamp_direct*3.0f;
- kintegrator->sample_clamp_indirect = (sample_clamp_indirect == 0.0f)? FLT_MAX: sample_clamp_indirect*3.0f;
-
- kintegrator->branched = (method == BRANCHED_PATH);
- kintegrator->volume_decoupled = device->info.has_volume_decoupled;
- kintegrator->diffuse_samples = diffuse_samples;
- kintegrator->glossy_samples = glossy_samples;
- kintegrator->transmission_samples = transmission_samples;
- kintegrator->ao_samples = ao_samples;
- kintegrator->mesh_light_samples = mesh_light_samples;
- kintegrator->subsurface_samples = subsurface_samples;
- kintegrator->volume_samples = volume_samples;
- kintegrator->start_sample = start_sample;
-
- if(method == BRANCHED_PATH) {
- kintegrator->sample_all_lights_direct = sample_all_lights_direct;
- kintegrator->sample_all_lights_indirect = sample_all_lights_indirect;
- }
- else {
- kintegrator->sample_all_lights_direct = false;
- kintegrator->sample_all_lights_indirect = false;
- }
-
- kintegrator->sampling_pattern = sampling_pattern;
- kintegrator->aa_samples = aa_samples;
-
- if(light_sampling_threshold > 0.0f) {
- kintegrator->light_inv_rr_threshold = 1.0f / light_sampling_threshold;
- }
- else {
- kintegrator->light_inv_rr_threshold = 0.0f;
- }
-
- /* sobol directions table */
- int max_samples = 1;
-
- if(method == BRANCHED_PATH) {
- foreach(Light *light, scene->lights)
- max_samples = max(max_samples, light->samples);
-
- max_samples = max(max_samples, max(diffuse_samples, max(glossy_samples, transmission_samples)));
- max_samples = max(max_samples, max(ao_samples, max(mesh_light_samples, subsurface_samples)));
- max_samples = max(max_samples, volume_samples);
- }
-
- uint total_bounces = max_bounce +
- transparent_max_bounce + 3 +
- VOLUME_BOUNDS_MAX +
- max(BSSRDF_MAX_HITS, BSSRDF_MAX_BOUNCES);
-
- max_samples *= total_bounces;
-
- int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM;
- dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
-
- uint *directions = dscene->sobol_directions.alloc(SOBOL_BITS*dimensions);
-
- sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
-
- dscene->sobol_directions.copy_to_device();
-
- /* Clamping. */
- bool use_sample_clamp = (sample_clamp_direct != 0.0f ||
- sample_clamp_indirect != 0.0f);
- if(use_sample_clamp != scene->film->use_sample_clamp) {
- scene->film->use_sample_clamp = use_sample_clamp;
- scene->film->tag_update(scene);
- }
-
- need_update = false;
+ if (!need_update)
+ return;
+
+ device_free(device, dscene);
+
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+
+ /* integrator parameters */
+ kintegrator->max_bounce = max_bounce + 1;
+
+ kintegrator->max_diffuse_bounce = max_diffuse_bounce + 1;
+ kintegrator->max_glossy_bounce = max_glossy_bounce + 1;
+ kintegrator->max_transmission_bounce = max_transmission_bounce + 1;
+ kintegrator->max_volume_bounce = max_volume_bounce + 1;
+
+ kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
+
+ if (ao_bounces == 0) {
+ kintegrator->ao_bounces = INT_MAX;
+ }
+ else {
+ kintegrator->ao_bounces = ao_bounces - 1;
+ }
+
+ /* Transparent Shadows
+ * We only need to enable transparent shadows, if we actually have
+ * transparent shaders in the scene. Otherwise we can disable it
+ * to improve performance a bit. */
+ kintegrator->transparent_shadows = false;
+ foreach (Shader *shader, scene->shaders) {
+ /* keep this in sync with SD_HAS_TRANSPARENT_SHADOW in shader.cpp */
+ if ((shader->has_surface_transparent && shader->use_transparent_shadow) ||
+ shader->has_volume) {
+ kintegrator->transparent_shadows = true;
+ break;
+ }
+ }
+
+ kintegrator->volume_max_steps = volume_max_steps;
+ kintegrator->volume_step_size = volume_step_size;
+
+ kintegrator->caustics_reflective = caustics_reflective;
+ kintegrator->caustics_refractive = caustics_refractive;
+ kintegrator->filter_glossy = (filter_glossy == 0.0f) ? FLT_MAX : 1.0f / filter_glossy;
+
+ kintegrator->seed = hash_int(seed);
+
+ kintegrator->use_ambient_occlusion = ((Pass::contains(scene->film->passes, PASS_AO)) ||
+ dscene->data.background.ao_factor != 0.0f);
+
+ kintegrator->sample_clamp_direct = (sample_clamp_direct == 0.0f) ? FLT_MAX :
+ sample_clamp_direct * 3.0f;
+ kintegrator->sample_clamp_indirect = (sample_clamp_indirect == 0.0f) ?
+ FLT_MAX :
+ sample_clamp_indirect * 3.0f;
+
+ kintegrator->branched = (method == BRANCHED_PATH);
+ kintegrator->volume_decoupled = device->info.has_volume_decoupled;
+ kintegrator->diffuse_samples = diffuse_samples;
+ kintegrator->glossy_samples = glossy_samples;
+ kintegrator->transmission_samples = transmission_samples;
+ kintegrator->ao_samples = ao_samples;
+ kintegrator->mesh_light_samples = mesh_light_samples;
+ kintegrator->subsurface_samples = subsurface_samples;
+ kintegrator->volume_samples = volume_samples;
+ kintegrator->start_sample = start_sample;
+
+ if (method == BRANCHED_PATH) {
+ kintegrator->sample_all_lights_direct = sample_all_lights_direct;
+ kintegrator->sample_all_lights_indirect = sample_all_lights_indirect;
+ }
+ else {
+ kintegrator->sample_all_lights_direct = false;
+ kintegrator->sample_all_lights_indirect = false;
+ }
+
+ kintegrator->sampling_pattern = sampling_pattern;
+ kintegrator->aa_samples = aa_samples;
+
+ if (light_sampling_threshold > 0.0f) {
+ kintegrator->light_inv_rr_threshold = 1.0f / light_sampling_threshold;
+ }
+ else {
+ kintegrator->light_inv_rr_threshold = 0.0f;
+ }
+
+ /* sobol directions table */
+ int max_samples = 1;
+
+ if (method == BRANCHED_PATH) {
+ foreach (Light *light, scene->lights)
+ max_samples = max(max_samples, light->samples);
+
+ max_samples = max(max_samples,
+ max(diffuse_samples, max(glossy_samples, transmission_samples)));
+ max_samples = max(max_samples, max(ao_samples, max(mesh_light_samples, subsurface_samples)));
+ max_samples = max(max_samples, volume_samples);
+ }
+
+ uint total_bounces = max_bounce + transparent_max_bounce + 3 + VOLUME_BOUNDS_MAX +
+ max(BSSRDF_MAX_HITS, BSSRDF_MAX_BOUNCES);
+
+ max_samples *= total_bounces;
+
+ int dimensions = PRNG_BASE_NUM + max_samples * PRNG_BOUNCE_NUM;
+ dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
+
+ uint *directions = dscene->sobol_directions.alloc(SOBOL_BITS * dimensions);
+
+ sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions);
+
+ dscene->sobol_directions.copy_to_device();
+
+ /* Clamping. */
+ bool use_sample_clamp = (sample_clamp_direct != 0.0f || sample_clamp_indirect != 0.0f);
+ if (use_sample_clamp != scene->film->use_sample_clamp) {
+ scene->film->use_sample_clamp = use_sample_clamp;
+ scene->film->tag_update(scene);
+ }
+
+ need_update = false;
}
void Integrator::device_free(Device *, DeviceScene *dscene)
{
- dscene->sobol_directions.free();
+ dscene->sobol_directions.free();
}
-bool Integrator::modified(const Integrator& integrator)
+bool Integrator::modified(const Integrator &integrator)
{
- return !Node::equals(integrator);
+ return !Node::equals(integrator);
}
void Integrator::tag_update(Scene *scene)
{
- foreach(Shader *shader, scene->shaders) {
- if(shader->has_integrator_dependency) {
- scene->shader_manager->need_update = true;
- break;
- }
- }
- need_update = true;
+ foreach (Shader *shader, scene->shaders) {
+ if (shader->has_integrator_dependency) {
+ scene->shader_manager->need_update = true;
+ break;
+ }
+ }
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index da4e61d8153..6acc68a7402 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -28,74 +28,74 @@ class DeviceScene;
class Scene;
class Integrator : public Node {
-public:
- NODE_DECLARE
+ public:
+ NODE_DECLARE
- int max_bounce;
+ int max_bounce;
- int max_diffuse_bounce;
- int max_glossy_bounce;
- int max_transmission_bounce;
- int max_volume_bounce;
+ int max_diffuse_bounce;
+ int max_glossy_bounce;
+ int max_transmission_bounce;
+ int max_volume_bounce;
- int transparent_max_bounce;
+ int transparent_max_bounce;
- int ao_bounces;
+ int ao_bounces;
- int volume_max_steps;
- float volume_step_size;
+ int volume_max_steps;
+ float volume_step_size;
- bool caustics_reflective;
- bool caustics_refractive;
- float filter_glossy;
+ bool caustics_reflective;
+ bool caustics_refractive;
+ float filter_glossy;
- int seed;
+ int seed;
- float sample_clamp_direct;
- float sample_clamp_indirect;
- bool motion_blur;
+ float sample_clamp_direct;
+ float sample_clamp_indirect;
+ bool motion_blur;
- /* Maximum number of samples, beyond which we are likely to run into
- * precision issues for sampling patterns. */
- static const int MAX_SAMPLES = (1 << 24);
+ /* Maximum number of samples, beyond which we are likely to run into
+ * precision issues for sampling patterns. */
+ static const int MAX_SAMPLES = (1 << 24);
- int aa_samples;
- int diffuse_samples;
- int glossy_samples;
- int transmission_samples;
- int ao_samples;
- int mesh_light_samples;
- int subsurface_samples;
- int volume_samples;
- int start_sample;
+ int aa_samples;
+ int diffuse_samples;
+ int glossy_samples;
+ int transmission_samples;
+ int ao_samples;
+ int mesh_light_samples;
+ int subsurface_samples;
+ int volume_samples;
+ int start_sample;
- bool sample_all_lights_direct;
- bool sample_all_lights_indirect;
- float light_sampling_threshold;
+ bool sample_all_lights_direct;
+ bool sample_all_lights_indirect;
+ float light_sampling_threshold;
- enum Method {
- BRANCHED_PATH = 0,
- PATH = 1,
+ enum Method {
+ BRANCHED_PATH = 0,
+ PATH = 1,
- NUM_METHODS,
- };
+ NUM_METHODS,
+ };
- Method method;
+ Method method;
- SamplingPattern sampling_pattern;
+ SamplingPattern sampling_pattern;
- bool need_update;
+ bool need_update;
- Integrator();
- ~Integrator();
+ Integrator();
+ ~Integrator();
- void device_update(Device *device, DeviceScene *dscene, Scene *scene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_free(Device *device, DeviceScene *dscene);
- bool modified(const Integrator& integrator);
- void tag_update(Scene *scene);
+ bool modified(const Integrator &integrator);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __INTEGRATOR_H__ */
+#endif /* __INTEGRATOR_H__ */
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 56d60adf71d..d4c233e3bb3 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -34,1002 +34,1016 @@
CCL_NAMESPACE_BEGIN
-static void shade_background_pixels(Device *device, DeviceScene *dscene, int width, int height, vector<float3>& pixels, Progress& progress)
+static void shade_background_pixels(Device *device,
+ DeviceScene *dscene,
+ int width,
+ int height,
+ vector<float3> &pixels,
+ Progress &progress)
{
- /* create input */
- device_vector<uint4> d_input(device, "background_input", MEM_READ_ONLY);
- device_vector<float4> d_output(device, "background_output", MEM_READ_WRITE);
-
- uint4 *d_input_data = d_input.alloc(width*height);
-
- for(int y = 0; y < height; y++) {
- for(int x = 0; x < width; x++) {
- float u = (x + 0.5f)/width;
- float v = (y + 0.5f)/height;
-
- uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
- d_input_data[x + y*width] = in;
- }
- }
-
- /* compute on device */
- d_output.alloc(width*height);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- DeviceTask main_task(DeviceTask::SHADER);
- main_task.shader_input = d_input.device_pointer;
- main_task.shader_output = d_output.device_pointer;
- main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
- main_task.shader_x = 0;
- main_task.shader_w = width*height;
- main_task.num_samples = 1;
- main_task.get_cancel = function_bind(&Progress::get_cancel, &progress);
-
- /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
- list<DeviceTask> split_tasks;
- main_task.split(split_tasks, 1, 128*128);
-
- foreach(DeviceTask& task, split_tasks) {
- device->task_add(task);
- device->task_wait();
- d_output.copy_from_device(task.shader_x, 1, task.shader_w);
- }
-
- d_input.free();
-
- float4 *d_output_data = d_output.data();
-
- pixels.resize(width*height);
-
- for(int y = 0; y < height; y++) {
- for(int x = 0; x < width; x++) {
- pixels[y*width + x].x = d_output_data[y*width + x].x;
- pixels[y*width + x].y = d_output_data[y*width + x].y;
- pixels[y*width + x].z = d_output_data[y*width + x].z;
- }
- }
-
- d_output.free();
+ /* create input */
+ device_vector<uint4> d_input(device, "background_input", MEM_READ_ONLY);
+ device_vector<float4> d_output(device, "background_output", MEM_READ_WRITE);
+
+ uint4 *d_input_data = d_input.alloc(width * height);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ float u = (x + 0.5f) / width;
+ float v = (y + 0.5f) / height;
+
+ uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
+ d_input_data[x + y * width] = in;
+ }
+ }
+
+ /* compute on device */
+ d_output.alloc(width * height);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ DeviceTask main_task(DeviceTask::SHADER);
+ main_task.shader_input = d_input.device_pointer;
+ main_task.shader_output = d_output.device_pointer;
+ main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
+ main_task.shader_x = 0;
+ main_task.shader_w = width * height;
+ main_task.num_samples = 1;
+ main_task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+
+ /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
+ list<DeviceTask> split_tasks;
+ main_task.split(split_tasks, 1, 128 * 128);
+
+ foreach (DeviceTask &task, split_tasks) {
+ device->task_add(task);
+ device->task_wait();
+ d_output.copy_from_device(task.shader_x, 1, task.shader_w);
+ }
+
+ d_input.free();
+
+ float4 *d_output_data = d_output.data();
+
+ pixels.resize(width * height);
+
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ pixels[y * width + x].x = d_output_data[y * width + x].x;
+ pixels[y * width + x].y = d_output_data[y * width + x].y;
+ pixels[y * width + x].z = d_output_data[y * width + x].z;
+ }
+ }
+
+ d_output.free();
}
/* Light */
NODE_DEFINE(Light)
{
- NodeType* type = NodeType::add("light", create);
+ NodeType *type = NodeType::add("light", create);
- static NodeEnum type_enum;
- type_enum.insert("point", LIGHT_POINT);
- type_enum.insert("distant", LIGHT_DISTANT);
- type_enum.insert("background", LIGHT_BACKGROUND);
- type_enum.insert("area", LIGHT_AREA);
- type_enum.insert("spot", LIGHT_SPOT);
- SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT);
+ static NodeEnum type_enum;
+ type_enum.insert("point", LIGHT_POINT);
+ type_enum.insert("distant", LIGHT_DISTANT);
+ type_enum.insert("background", LIGHT_BACKGROUND);
+ type_enum.insert("area", LIGHT_AREA);
+ type_enum.insert("spot", LIGHT_SPOT);
+ SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT);
- SOCKET_POINT(co, "Co", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_POINT(co, "Co", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_FLOAT(size, "Size", 0.0f);
+ SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_FLOAT(size, "Size", 0.0f);
- SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_FLOAT(sizeu, "Size U", 1.0f);
- SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_FLOAT(sizev, "Size V", 1.0f);
- SOCKET_BOOLEAN(round, "Round", false);
+ SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_FLOAT(sizeu, "Size U", 1.0f);
+ SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_FLOAT(sizev, "Size V", 1.0f);
+ SOCKET_BOOLEAN(round, "Round", false);
- SOCKET_INT(map_resolution, "Map Resolution", 0);
+ SOCKET_INT(map_resolution, "Map Resolution", 0);
- SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
- SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
+ SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
+ SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
- SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
- SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
- SOCKET_BOOLEAN(use_mis, "Use Mis", false);
- SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
- SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
- SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
- SOCKET_BOOLEAN(use_scatter, "Use Scatter", true);
+ SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
+ SOCKET_BOOLEAN(use_mis, "Use Mis", false);
+ SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
+ SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
+ SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
+ SOCKET_BOOLEAN(use_scatter, "Use Scatter", true);
- SOCKET_INT(samples, "Samples", 1);
- SOCKET_INT(max_bounces, "Max Bounces", 1024);
- SOCKET_UINT(random_id, "Random ID", 0);
+ SOCKET_INT(samples, "Samples", 1);
+ SOCKET_INT(max_bounces, "Max Bounces", 1024);
+ SOCKET_UINT(random_id, "Random ID", 0);
- SOCKET_BOOLEAN(is_portal, "Is Portal", false);
- SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
+ SOCKET_BOOLEAN(is_portal, "Is Portal", false);
+ SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
- SOCKET_NODE(shader, "Shader", &Shader::node_type);
+ SOCKET_NODE(shader, "Shader", &Shader::node_type);
- return type;
+ return type;
}
-Light::Light()
-: Node(node_type)
+Light::Light() : Node(node_type)
{
}
void Light::tag_update(Scene *scene)
{
- scene->light_manager->need_update = true;
+ scene->light_manager->need_update = true;
}
bool Light::has_contribution(Scene *scene)
{
- if(is_portal) {
- return false;
- }
- if(type == LIGHT_BACKGROUND) {
- return true;
- }
- return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
+ if (is_portal) {
+ return false;
+ }
+ if (type == LIGHT_BACKGROUND) {
+ return true;
+ }
+ return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
}
/* Light Manager */
LightManager::LightManager()
{
- need_update = true;
- use_light_visibility = false;
+ need_update = true;
+ use_light_visibility = false;
}
LightManager::~LightManager()
{
- foreach(IESSlot *slot, ies_slots) {
- delete slot;
- }
+ foreach (IESSlot *slot, ies_slots) {
+ delete slot;
+ }
}
bool LightManager::has_background_light(Scene *scene)
{
- foreach(Light *light, scene->lights) {
- if(light->type == LIGHT_BACKGROUND && light->is_enabled) {
- return true;
- }
- }
- return false;
+ foreach (Light *light, scene->lights) {
+ if (light->type == LIGHT_BACKGROUND && light->is_enabled) {
+ return true;
+ }
+ }
+ return false;
}
void LightManager::disable_ineffective_light(Scene *scene)
{
- /* Make all lights enabled by default, and perform some preliminary checks
- * needed for finer-tuning of settings (for example, check whether we've
- * got portals or not).
- */
- bool has_portal = false, has_background = false;
- foreach(Light *light, scene->lights) {
- light->is_enabled = light->has_contribution(scene);
- has_portal |= light->is_portal;
- has_background |= light->type == LIGHT_BACKGROUND;
- }
-
- if(has_background) {
- /* Ignore background light if:
- * - If unsupported on a device
- * - If we don't need it (no HDRs etc.)
- */
- Shader *shader = (scene->background->shader) ? scene->background->shader : scene->default_background;
- bool disable_mis = !(has_portal || shader->has_surface_spatial_varying);
- if(disable_mis) {
- VLOG(1) << "Background MIS has been disabled.\n";
- foreach(Light *light, scene->lights) {
- if(light->type == LIGHT_BACKGROUND) {
- light->is_enabled = false;
- }
- }
- }
- }
+ /* Make all lights enabled by default, and perform some preliminary checks
+ * needed for finer-tuning of settings (for example, check whether we've
+ * got portals or not).
+ */
+ bool has_portal = false, has_background = false;
+ foreach (Light *light, scene->lights) {
+ light->is_enabled = light->has_contribution(scene);
+ has_portal |= light->is_portal;
+ has_background |= light->type == LIGHT_BACKGROUND;
+ }
+
+ if (has_background) {
+ /* Ignore background light if:
+ * - If unsupported on a device
+ * - If we don't need it (no HDRs etc.)
+ */
+ Shader *shader = (scene->background->shader) ? scene->background->shader :
+ scene->default_background;
+ bool disable_mis = !(has_portal || shader->has_surface_spatial_varying);
+ if (disable_mis) {
+ VLOG(1) << "Background MIS has been disabled.\n";
+ foreach (Light *light, scene->lights) {
+ if (light->type == LIGHT_BACKGROUND) {
+ light->is_enabled = false;
+ }
+ }
+ }
+ }
}
-bool LightManager::object_usable_as_light(Object *object) {
- Mesh *mesh = object->mesh;
- /* Skip objects with NaNs */
- if(!object->bounds.valid()) {
- return false;
- }
- /* Skip if we are not visible for BSDFs. */
- if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
- return false;
- }
- /* Skip if we have no emission shaders. */
- /* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll
- * iterate all mesh shaders twice (when counting and when calculating
- * triangle area.
- */
- foreach(const Shader *shader, mesh->used_shaders) {
- if(shader->use_mis && shader->has_surface_emission) {
- return true;
- }
- }
- return false;
+bool LightManager::object_usable_as_light(Object *object)
+{
+ Mesh *mesh = object->mesh;
+ /* Skip objects with NaNs */
+ if (!object->bounds.valid()) {
+ return false;
+ }
+ /* Skip if we are not visible for BSDFs. */
+ if (!(object->visibility & (PATH_RAY_DIFFUSE | PATH_RAY_GLOSSY | PATH_RAY_TRANSMIT))) {
+ return false;
+ }
+ /* Skip if we have no emission shaders. */
+ /* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll
+ * iterate all mesh shaders twice (when counting and when calculating
+ * triangle area.
+ */
+ foreach (const Shader *shader, mesh->used_shaders) {
+ if (shader->use_mis && shader->has_surface_emission) {
+ return true;
+ }
+ }
+ return false;
}
-void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
+void LightManager::device_update_distribution(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- progress.set_status("Updating Lights", "Computing distribution");
-
- /* count */
- size_t num_lights = 0;
- size_t num_portals = 0;
- size_t num_background_lights = 0;
- size_t num_triangles = 0;
-
- bool background_mis = false;
-
- foreach(Light *light, scene->lights) {
- if(light->is_enabled) {
- num_lights++;
- }
- if(light->is_portal) {
- num_portals++;
- }
- }
-
- foreach(Object *object, scene->objects) {
- if(progress.get_cancel()) return;
-
- if(!object_usable_as_light(object)) {
- continue;
- }
- /* Count triangles. */
- Mesh *mesh = object->mesh;
- size_t mesh_num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < mesh_num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size())
- ? mesh->used_shaders[shader_index]
- : scene->default_surface;
-
- if(shader->use_mis && shader->has_surface_emission) {
- num_triangles++;
- }
- }
- }
-
- size_t num_distribution = num_triangles + num_lights;
- VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
-
- /* emission area */
- KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
- float totarea = 0.0f;
-
- /* triangles */
- size_t offset = 0;
- int j = 0;
-
- foreach(Object *object, scene->objects) {
- if(progress.get_cancel()) return;
-
- if(!object_usable_as_light(object)) {
- j++;
- continue;
- }
- /* Sum area. */
- Mesh *mesh = object->mesh;
- bool transform_applied = mesh->transform_applied;
- Transform tfm = object->tfm;
- int object_id = j;
- int shader_flag = 0;
-
- if(!(object->visibility & PATH_RAY_DIFFUSE)) {
- shader_flag |= SHADER_EXCLUDE_DIFFUSE;
- use_light_visibility = true;
- }
- if(!(object->visibility & PATH_RAY_GLOSSY)) {
- shader_flag |= SHADER_EXCLUDE_GLOSSY;
- use_light_visibility = true;
- }
- if(!(object->visibility & PATH_RAY_TRANSMIT)) {
- shader_flag |= SHADER_EXCLUDE_TRANSMIT;
- use_light_visibility = true;
- }
- if(!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
- shader_flag |= SHADER_EXCLUDE_SCATTER;
- use_light_visibility = true;
- }
-
- size_t mesh_num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < mesh_num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size())
- ? mesh->used_shaders[shader_index]
- : scene->default_surface;
-
- if(shader->use_mis && shader->has_surface_emission) {
- distribution[offset].totarea = totarea;
- distribution[offset].prim = i + mesh->tri_offset;
- distribution[offset].mesh_light.shader_flag = shader_flag;
- distribution[offset].mesh_light.object_id = object_id;
- offset++;
-
- Mesh::Triangle t = mesh->get_triangle(i);
- if(!t.valid(&mesh->verts[0])) {
- continue;
- }
- float3 p1 = mesh->verts[t.v[0]];
- float3 p2 = mesh->verts[t.v[1]];
- float3 p3 = mesh->verts[t.v[2]];
-
- if(!transform_applied) {
- p1 = transform_point(&tfm, p1);
- p2 = transform_point(&tfm, p2);
- p3 = transform_point(&tfm, p3);
- }
-
- totarea += triangle_area(p1, p2, p3);
- }
- }
-
- j++;
- }
-
- float trianglearea = totarea;
-
- /* point lights */
- float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
- bool use_lamp_mis = false;
-
- int light_index = 0;
- foreach(Light *light, scene->lights) {
- if(!light->is_enabled)
- continue;
-
- distribution[offset].totarea = totarea;
- distribution[offset].prim = ~light_index;
- distribution[offset].lamp.pad = 1.0f;
- distribution[offset].lamp.size = light->size;
- totarea += lightarea;
-
- if(light->size > 0.0f && light->use_mis)
- use_lamp_mis = true;
- if(light->type == LIGHT_BACKGROUND) {
- num_background_lights++;
- background_mis = light->use_mis;
- }
-
- light_index++;
- offset++;
- }
-
- /* normalize cumulative distribution functions */
- distribution[num_distribution].totarea = totarea;
- distribution[num_distribution].prim = 0.0f;
- distribution[num_distribution].lamp.pad = 0.0f;
- distribution[num_distribution].lamp.size = 0.0f;
-
- if(totarea > 0.0f) {
- for(size_t i = 0; i < num_distribution; i++)
- distribution[i].totarea /= totarea;
- distribution[num_distribution].totarea = 1.0f;
- }
-
- if(progress.get_cancel()) return;
-
- /* update device */
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- KernelFilm *kfilm = &dscene->data.film;
- kintegrator->use_direct_light = (totarea > 0.0f);
-
- if(kintegrator->use_direct_light) {
- /* number of emissives */
- kintegrator->num_distribution = num_distribution;
-
- /* precompute pdfs */
- kintegrator->pdf_triangles = 0.0f;
- kintegrator->pdf_lights = 0.0f;
-
- /* sample one, with 0.5 probability of light or triangle */
- kintegrator->num_all_lights = num_lights;
-
- if(trianglearea > 0.0f) {
- kintegrator->pdf_triangles = 1.0f/trianglearea;
- if(num_lights)
- kintegrator->pdf_triangles *= 0.5f;
- }
-
- if(num_lights) {
- kintegrator->pdf_lights = 1.0f/num_lights;
- if(trianglearea > 0.0f)
- kintegrator->pdf_lights *= 0.5f;
- }
-
- kintegrator->use_lamp_mis = use_lamp_mis;
-
- /* bit of an ugly hack to compensate for emitting triangles influencing
- * amount of samples we get for this pass */
- kfilm->pass_shadow_scale = 1.0f;
-
- if(kintegrator->pdf_triangles != 0.0f)
- kfilm->pass_shadow_scale *= 0.5f;
-
- if(num_background_lights < num_lights)
- kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights;
-
- /* CDF */
- dscene->light_distribution.copy_to_device();
-
- /* Portals */
- if(num_portals > 0) {
- kintegrator->portal_offset = light_index;
- kintegrator->num_portals = num_portals;
- kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
- }
- else {
- kintegrator->num_portals = 0;
- kintegrator->portal_offset = 0;
- kintegrator->portal_pdf = 0.0f;
- }
- }
- else {
- dscene->light_distribution.free();
-
- kintegrator->num_distribution = 0;
- kintegrator->num_all_lights = 0;
- kintegrator->pdf_triangles = 0.0f;
- kintegrator->pdf_lights = 0.0f;
- kintegrator->use_lamp_mis = false;
- kintegrator->num_portals = 0;
- kintegrator->portal_offset = 0;
- kintegrator->portal_pdf = 0.0f;
-
- kfilm->pass_shadow_scale = 1.0f;
- }
+ progress.set_status("Updating Lights", "Computing distribution");
+
+ /* count */
+ size_t num_lights = 0;
+ size_t num_portals = 0;
+ size_t num_background_lights = 0;
+ size_t num_triangles = 0;
+
+ bool background_mis = false;
+
+ foreach (Light *light, scene->lights) {
+ if (light->is_enabled) {
+ num_lights++;
+ }
+ if (light->is_portal) {
+ num_portals++;
+ }
+ }
+
+ foreach (Object *object, scene->objects) {
+ if (progress.get_cancel())
+ return;
+
+ if (!object_usable_as_light(object)) {
+ continue;
+ }
+ /* Count triangles. */
+ Mesh *mesh = object->mesh;
+ size_t mesh_num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < mesh_num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (shader->use_mis && shader->has_surface_emission) {
+ num_triangles++;
+ }
+ }
+ }
+
+ size_t num_distribution = num_triangles + num_lights;
+ VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
+
+ /* emission area */
+ KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
+ float totarea = 0.0f;
+
+ /* triangles */
+ size_t offset = 0;
+ int j = 0;
+
+ foreach (Object *object, scene->objects) {
+ if (progress.get_cancel())
+ return;
+
+ if (!object_usable_as_light(object)) {
+ j++;
+ continue;
+ }
+ /* Sum area. */
+ Mesh *mesh = object->mesh;
+ bool transform_applied = mesh->transform_applied;
+ Transform tfm = object->tfm;
+ int object_id = j;
+ int shader_flag = 0;
+
+ if (!(object->visibility & PATH_RAY_DIFFUSE)) {
+ shader_flag |= SHADER_EXCLUDE_DIFFUSE;
+ use_light_visibility = true;
+ }
+ if (!(object->visibility & PATH_RAY_GLOSSY)) {
+ shader_flag |= SHADER_EXCLUDE_GLOSSY;
+ use_light_visibility = true;
+ }
+ if (!(object->visibility & PATH_RAY_TRANSMIT)) {
+ shader_flag |= SHADER_EXCLUDE_TRANSMIT;
+ use_light_visibility = true;
+ }
+ if (!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
+ shader_flag |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
+
+ size_t mesh_num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < mesh_num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (shader->use_mis && shader->has_surface_emission) {
+ distribution[offset].totarea = totarea;
+ distribution[offset].prim = i + mesh->tri_offset;
+ distribution[offset].mesh_light.shader_flag = shader_flag;
+ distribution[offset].mesh_light.object_id = object_id;
+ offset++;
+
+ Mesh::Triangle t = mesh->get_triangle(i);
+ if (!t.valid(&mesh->verts[0])) {
+ continue;
+ }
+ float3 p1 = mesh->verts[t.v[0]];
+ float3 p2 = mesh->verts[t.v[1]];
+ float3 p3 = mesh->verts[t.v[2]];
+
+ if (!transform_applied) {
+ p1 = transform_point(&tfm, p1);
+ p2 = transform_point(&tfm, p2);
+ p3 = transform_point(&tfm, p3);
+ }
+
+ totarea += triangle_area(p1, p2, p3);
+ }
+ }
+
+ j++;
+ }
+
+ float trianglearea = totarea;
+
+ /* point lights */
+ float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
+ bool use_lamp_mis = false;
+
+ int light_index = 0;
+ foreach (Light *light, scene->lights) {
+ if (!light->is_enabled)
+ continue;
+
+ distribution[offset].totarea = totarea;
+ distribution[offset].prim = ~light_index;
+ distribution[offset].lamp.pad = 1.0f;
+ distribution[offset].lamp.size = light->size;
+ totarea += lightarea;
+
+ if (light->size > 0.0f && light->use_mis)
+ use_lamp_mis = true;
+ if (light->type == LIGHT_BACKGROUND) {
+ num_background_lights++;
+ background_mis = light->use_mis;
+ }
+
+ light_index++;
+ offset++;
+ }
+
+ /* normalize cumulative distribution functions */
+ distribution[num_distribution].totarea = totarea;
+ distribution[num_distribution].prim = 0.0f;
+ distribution[num_distribution].lamp.pad = 0.0f;
+ distribution[num_distribution].lamp.size = 0.0f;
+
+ if (totarea > 0.0f) {
+ for (size_t i = 0; i < num_distribution; i++)
+ distribution[i].totarea /= totarea;
+ distribution[num_distribution].totarea = 1.0f;
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ /* update device */
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ KernelFilm *kfilm = &dscene->data.film;
+ kintegrator->use_direct_light = (totarea > 0.0f);
+
+ if (kintegrator->use_direct_light) {
+ /* number of emissives */
+ kintegrator->num_distribution = num_distribution;
+
+ /* precompute pdfs */
+ kintegrator->pdf_triangles = 0.0f;
+ kintegrator->pdf_lights = 0.0f;
+
+ /* sample one, with 0.5 probability of light or triangle */
+ kintegrator->num_all_lights = num_lights;
+
+ if (trianglearea > 0.0f) {
+ kintegrator->pdf_triangles = 1.0f / trianglearea;
+ if (num_lights)
+ kintegrator->pdf_triangles *= 0.5f;
+ }
+
+ if (num_lights) {
+ kintegrator->pdf_lights = 1.0f / num_lights;
+ if (trianglearea > 0.0f)
+ kintegrator->pdf_lights *= 0.5f;
+ }
+
+ kintegrator->use_lamp_mis = use_lamp_mis;
+
+ /* bit of an ugly hack to compensate for emitting triangles influencing
+ * amount of samples we get for this pass */
+ kfilm->pass_shadow_scale = 1.0f;
+
+ if (kintegrator->pdf_triangles != 0.0f)
+ kfilm->pass_shadow_scale *= 0.5f;
+
+ if (num_background_lights < num_lights)
+ kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights) / (float)num_lights;
+
+ /* CDF */
+ dscene->light_distribution.copy_to_device();
+
+ /* Portals */
+ if (num_portals > 0) {
+ kintegrator->portal_offset = light_index;
+ kintegrator->num_portals = num_portals;
+ kintegrator->portal_pdf = background_mis ? 0.5f : 1.0f;
+ }
+ else {
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+ }
+ }
+ else {
+ dscene->light_distribution.free();
+
+ kintegrator->num_distribution = 0;
+ kintegrator->num_all_lights = 0;
+ kintegrator->pdf_triangles = 0.0f;
+ kintegrator->pdf_lights = 0.0f;
+ kintegrator->use_lamp_mis = false;
+ kintegrator->num_portals = 0;
+ kintegrator->portal_offset = 0;
+ kintegrator->portal_pdf = 0.0f;
+
+ kfilm->pass_shadow_scale = 1.0f;
+ }
}
-static void background_cdf(int start,
- int end,
- int res_x,
- int res_y,
- const vector<float3> *pixels,
- float2 *cond_cdf)
+static void background_cdf(
+ int start, int end, int res_x, int res_y, const vector<float3> *pixels, float2 *cond_cdf)
{
- int cdf_width = res_x+1;
- /* Conditional CDFs (rows, U direction). */
- for(int i = start; i < end; i++) {
- float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
- float3 env_color = (*pixels)[i * res_x];
- float ave_luminance = average(env_color);
-
- cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
- cond_cdf[i * cdf_width].y = 0.0f;
-
- for(int j = 1; j < res_x; j++) {
- env_color = (*pixels)[i * res_x + j];
- ave_luminance = average(env_color);
-
- cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
- cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y + cond_cdf[i * cdf_width + j - 1].x / res_x;
- }
-
- float cdf_total = cond_cdf[i * cdf_width + res_x - 1].y + cond_cdf[i * cdf_width + res_x - 1].x / res_x;
- float cdf_total_inv = 1.0f / cdf_total;
-
- /* stuff the total into the brightness value for the last entry, because
- * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
- cond_cdf[i * cdf_width + res_x].x = cdf_total;
-
- if(cdf_total > 0.0f)
- for(int j = 1; j < res_x; j++)
- cond_cdf[i * cdf_width + j].y *= cdf_total_inv;
-
- cond_cdf[i * cdf_width + res_x].y = 1.0f;
- }
+ int cdf_width = res_x + 1;
+ /* Conditional CDFs (rows, U direction). */
+ for (int i = start; i < end; i++) {
+ float sin_theta = sinf(M_PI_F * (i + 0.5f) / res_y);
+ float3 env_color = (*pixels)[i * res_x];
+ float ave_luminance = average(env_color);
+
+ cond_cdf[i * cdf_width].x = ave_luminance * sin_theta;
+ cond_cdf[i * cdf_width].y = 0.0f;
+
+ for (int j = 1; j < res_x; j++) {
+ env_color = (*pixels)[i * res_x + j];
+ ave_luminance = average(env_color);
+
+ cond_cdf[i * cdf_width + j].x = ave_luminance * sin_theta;
+ cond_cdf[i * cdf_width + j].y = cond_cdf[i * cdf_width + j - 1].y +
+ cond_cdf[i * cdf_width + j - 1].x / res_x;
+ }
+
+ float cdf_total = cond_cdf[i * cdf_width + res_x - 1].y +
+ cond_cdf[i * cdf_width + res_x - 1].x / res_x;
+ float cdf_total_inv = 1.0f / cdf_total;
+
+ /* stuff the total into the brightness value for the last entry, because
+ * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
+ cond_cdf[i * cdf_width + res_x].x = cdf_total;
+
+ if (cdf_total > 0.0f)
+ for (int j = 1; j < res_x; j++)
+ cond_cdf[i * cdf_width + j].y *= cdf_total_inv;
+
+ cond_cdf[i * cdf_width + res_x].y = 1.0f;
+ }
}
void LightManager::device_update_background(Device *device,
DeviceScene *dscene,
Scene *scene,
- Progress& progress)
+ Progress &progress)
{
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- Light *background_light = NULL;
-
- /* find background light */
- foreach(Light *light, scene->lights) {
- if(light->type == LIGHT_BACKGROUND) {
- background_light = light;
- break;
- }
- }
-
- /* no background light found, signal renderer to skip sampling */
- if(!background_light || !background_light->is_enabled) {
- kintegrator->pdf_background_res_x = 0;
- kintegrator->pdf_background_res_y = 0;
- return;
- }
-
- progress.set_status("Updating Lights", "Importance map");
-
- assert(kintegrator->use_direct_light);
-
- /* get the resolution from the light's size (we stuff it in there) */
- int2 res = make_int2(background_light->map_resolution, background_light->map_resolution/2);
- /* If the resolution isn't set manually, try to find an environment texture. */
- if(res.x == 0) {
- Shader *shader = (scene->background->shader) ? scene->background->shader : scene->default_background;
- foreach(ShaderNode *node, shader->graph->nodes) {
- if(node->type == EnvironmentTextureNode::node_type) {
- EnvironmentTextureNode *env = (EnvironmentTextureNode*) node;
- ImageMetaData metadata;
- if(env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) {
- res.x = max(res.x, metadata.width);
- res.y = max(res.y, metadata.height);
- }
- }
- }
- if(res.x > 0 && res.y > 0) {
- VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n";
- }
- }
- /* If it's still unknown, just use the default. */
- if(res.x == 0 || res.y == 0) {
- res = make_int2(1024, 512);
- VLOG(2) << "Setting World MIS resolution to default\n";
- }
- kintegrator->pdf_background_res_x = res.x;
- kintegrator->pdf_background_res_y = res.y;
-
- vector<float3> pixels;
- shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
-
- if(progress.get_cancel())
- return;
-
- /* build row distributions and column distribution for the infinite area environment light */
- int cdf_width = res.x+1;
- float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(res.y + 1);
- float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y);
-
- double time_start = time_dt();
- if(max(res.x, res.y) < 512) {
- /* Small enough resolution, faster to do single-threaded. */
- background_cdf(0, res.y, res.x, res.y, &pixels, cond_cdf);
- }
- else {
- /* Threaded evaluation for large resolution. */
- const int num_blocks = TaskScheduler::num_threads();
- const int chunk_size = res.y / num_blocks;
- int start_row = 0;
- TaskPool pool;
- for(int i = 0; i < num_blocks; ++i) {
- const int current_chunk_size =
- (i != num_blocks - 1) ? chunk_size
- : (res.y - i * chunk_size);
- pool.push(function_bind(&background_cdf,
- start_row, start_row + current_chunk_size,
- res.x,
- res.y,
- &pixels,
- cond_cdf));
- start_row += current_chunk_size;
- }
- pool.wait_work();
- }
-
- /* marginal CDFs (column, V direction, sum of rows) */
- marg_cdf[0].x = cond_cdf[res.x].x;
- marg_cdf[0].y = 0.0f;
-
- for(int i = 1; i < res.y; i++) {
- marg_cdf[i].x = cond_cdf[i * cdf_width + res.x].x;
- marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res.y;
- }
-
- float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
- marg_cdf[res.y].x = cdf_total;
-
- if(cdf_total > 0.0f)
- for(int i = 1; i < res.y; i++)
- marg_cdf[i].y /= cdf_total;
-
- marg_cdf[res.y].y = 1.0f;
-
- VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
-
- /* update device */
- dscene->light_background_marginal_cdf.copy_to_device();
- dscene->light_background_conditional_cdf.copy_to_device();
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ Light *background_light = NULL;
+
+ /* find background light */
+ foreach (Light *light, scene->lights) {
+ if (light->type == LIGHT_BACKGROUND) {
+ background_light = light;
+ break;
+ }
+ }
+
+ /* no background light found, signal renderer to skip sampling */
+ if (!background_light || !background_light->is_enabled) {
+ kintegrator->pdf_background_res_x = 0;
+ kintegrator->pdf_background_res_y = 0;
+ return;
+ }
+
+ progress.set_status("Updating Lights", "Importance map");
+
+ assert(kintegrator->use_direct_light);
+
+ /* get the resolution from the light's size (we stuff it in there) */
+ int2 res = make_int2(background_light->map_resolution, background_light->map_resolution / 2);
+ /* If the resolution isn't set manually, try to find an environment texture. */
+ if (res.x == 0) {
+ Shader *shader = (scene->background->shader) ? scene->background->shader :
+ scene->default_background;
+ foreach (ShaderNode *node, shader->graph->nodes) {
+ if (node->type == EnvironmentTextureNode::node_type) {
+ EnvironmentTextureNode *env = (EnvironmentTextureNode *)node;
+ ImageMetaData metadata;
+ if (env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) {
+ res.x = max(res.x, metadata.width);
+ res.y = max(res.y, metadata.height);
+ }
+ }
+ }
+ if (res.x > 0 && res.y > 0) {
+ VLOG(2) << "Automatically set World MIS resolution to " << res.x << " by " << res.y << "\n";
+ }
+ }
+ /* If it's still unknown, just use the default. */
+ if (res.x == 0 || res.y == 0) {
+ res = make_int2(1024, 512);
+ VLOG(2) << "Setting World MIS resolution to default\n";
+ }
+ kintegrator->pdf_background_res_x = res.x;
+ kintegrator->pdf_background_res_y = res.y;
+
+ vector<float3> pixels;
+ shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
+
+ if (progress.get_cancel())
+ return;
+
+ /* build row distributions and column distribution for the infinite area environment light */
+ int cdf_width = res.x + 1;
+ float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(res.y + 1);
+ float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_width * res.y);
+
+ double time_start = time_dt();
+ if (max(res.x, res.y) < 512) {
+ /* Small enough resolution, faster to do single-threaded. */
+ background_cdf(0, res.y, res.x, res.y, &pixels, cond_cdf);
+ }
+ else {
+ /* Threaded evaluation for large resolution. */
+ const int num_blocks = TaskScheduler::num_threads();
+ const int chunk_size = res.y / num_blocks;
+ int start_row = 0;
+ TaskPool pool;
+ for (int i = 0; i < num_blocks; ++i) {
+ const int current_chunk_size = (i != num_blocks - 1) ? chunk_size : (res.y - i * chunk_size);
+ pool.push(function_bind(&background_cdf,
+ start_row,
+ start_row + current_chunk_size,
+ res.x,
+ res.y,
+ &pixels,
+ cond_cdf));
+ start_row += current_chunk_size;
+ }
+ pool.wait_work();
+ }
+
+ /* marginal CDFs (column, V direction, sum of rows) */
+ marg_cdf[0].x = cond_cdf[res.x].x;
+ marg_cdf[0].y = 0.0f;
+
+ for (int i = 1; i < res.y; i++) {
+ marg_cdf[i].x = cond_cdf[i * cdf_width + res.x].x;
+ marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res.y;
+ }
+
+ float cdf_total = marg_cdf[res.y - 1].y + marg_cdf[res.y - 1].x / res.y;
+ marg_cdf[res.y].x = cdf_total;
+
+ if (cdf_total > 0.0f)
+ for (int i = 1; i < res.y; i++)
+ marg_cdf[i].y /= cdf_total;
+
+ marg_cdf[res.y].y = 1.0f;
+
+ VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
+
+ /* update device */
+ dscene->light_background_marginal_cdf.copy_to_device();
+ dscene->light_background_conditional_cdf.copy_to_device();
}
-void LightManager::device_update_points(Device *,
- DeviceScene *dscene,
- Scene *scene)
+void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *scene)
{
- int num_scene_lights = scene->lights.size();
-
- int num_lights = 0;
- foreach(Light *light, scene->lights) {
- if(light->is_enabled || light->is_portal) {
- num_lights++;
- }
- }
-
- KernelLight *klights = dscene->lights.alloc(num_lights);
-
- if(num_lights == 0) {
- VLOG(1) << "No effective light, ignoring points update.";
- return;
- }
-
- int light_index = 0;
-
- foreach(Light *light, scene->lights) {
- if(!light->is_enabled) {
- continue;
- }
-
- float3 co = light->co;
- Shader *shader = (light->shader) ? light->shader : scene->default_light;
- int shader_id = scene->shader_manager->get_shader_id(shader);
- int samples = light->samples;
- int max_bounces = light->max_bounces;
- float random = (float)light->random_id * (1.0f/(float)0xFFFFFFFF);
-
- if(!light->cast_shadow)
- shader_id &= ~SHADER_CAST_SHADOW;
-
- if(!light->use_diffuse) {
- shader_id |= SHADER_EXCLUDE_DIFFUSE;
- use_light_visibility = true;
- }
- if(!light->use_glossy) {
- shader_id |= SHADER_EXCLUDE_GLOSSY;
- use_light_visibility = true;
- }
- if(!light->use_transmission) {
- shader_id |= SHADER_EXCLUDE_TRANSMIT;
- use_light_visibility = true;
- }
- if(!light->use_scatter) {
- shader_id |= SHADER_EXCLUDE_SCATTER;
- use_light_visibility = true;
- }
-
- klights[light_index].type = light->type;
- klights[light_index].samples = samples;
-
- if(light->type == LIGHT_POINT) {
- shader_id &= ~SHADER_AREA_LIGHT;
-
- float radius = light->size;
- float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
-
- if(light->use_mis && radius > 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].spot.radius = radius;
- klights[light_index].spot.invarea = invarea;
- }
- else if(light->type == LIGHT_DISTANT) {
- shader_id &= ~SHADER_AREA_LIGHT;
-
- float radius = light->size;
- float angle = atanf(radius);
- float cosangle = cosf(angle);
- float area = M_PI_F*radius*radius;
- float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- if(light->use_mis && area > 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = dir.x;
- klights[light_index].co[1] = dir.y;
- klights[light_index].co[2] = dir.z;
-
- klights[light_index].distant.invarea = invarea;
- klights[light_index].distant.radius = radius;
- klights[light_index].distant.cosangle = cosangle;
- }
- else if(light->type == LIGHT_BACKGROUND) {
- uint visibility = scene->background->visibility;
-
- shader_id &= ~SHADER_AREA_LIGHT;
- shader_id |= SHADER_USE_MIS;
-
- if(!(visibility & PATH_RAY_DIFFUSE)) {
- shader_id |= SHADER_EXCLUDE_DIFFUSE;
- use_light_visibility = true;
- }
- if(!(visibility & PATH_RAY_GLOSSY)) {
- shader_id |= SHADER_EXCLUDE_GLOSSY;
- use_light_visibility = true;
- }
- if(!(visibility & PATH_RAY_TRANSMIT)) {
- shader_id |= SHADER_EXCLUDE_TRANSMIT;
- use_light_visibility = true;
- }
- if(!(visibility & PATH_RAY_VOLUME_SCATTER)) {
- shader_id |= SHADER_EXCLUDE_SCATTER;
- use_light_visibility = true;
- }
- }
- else if(light->type == LIGHT_AREA) {
- float3 axisu = light->axisu*(light->sizeu*light->size);
- float3 axisv = light->axisv*(light->sizev*light->size);
- float area = len(axisu)*len(axisv);
- if(light->round) {
- area *= -M_PI_4_F;
- }
- float invarea = (area != 0.0f)? 1.0f/area: 1.0f;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- if(light->use_mis && area != 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].area.axisu[0] = axisu.x;
- klights[light_index].area.axisu[1] = axisu.y;
- klights[light_index].area.axisu[2] = axisu.z;
- klights[light_index].area.axisv[0] = axisv.x;
- klights[light_index].area.axisv[1] = axisv.y;
- klights[light_index].area.axisv[2] = axisv.z;
- klights[light_index].area.invarea = invarea;
- klights[light_index].area.dir[0] = dir.x;
- klights[light_index].area.dir[1] = dir.y;
- klights[light_index].area.dir[2] = dir.z;
- }
- else if(light->type == LIGHT_SPOT) {
- shader_id &= ~SHADER_AREA_LIGHT;
-
- float radius = light->size;
- float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
- float spot_angle = cosf(light->spot_angle*0.5f);
- float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- if(light->use_mis && radius > 0.0f)
- shader_id |= SHADER_USE_MIS;
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].spot.radius = radius;
- klights[light_index].spot.invarea = invarea;
- klights[light_index].spot.spot_angle = spot_angle;
- klights[light_index].spot.spot_smooth = spot_smooth;
- klights[light_index].spot.dir[0] = dir.x;
- klights[light_index].spot.dir[1] = dir.y;
- klights[light_index].spot.dir[2] = dir.z;
- }
-
- klights[light_index].shader_id = shader_id;
-
- klights[light_index].max_bounces = max_bounces;
- klights[light_index].random = random;
-
- klights[light_index].tfm = light->tfm;
- klights[light_index].itfm = transform_inverse(light->tfm);
-
- light_index++;
- }
-
- /* TODO(sergey): Consider moving portals update to their own function
- * keeping this one more manageable.
- */
- foreach(Light *light, scene->lights) {
- if(!light->is_portal)
- continue;
- assert(light->type == LIGHT_AREA);
-
- float3 co = light->co;
- float3 axisu = light->axisu*(light->sizeu*light->size);
- float3 axisv = light->axisv*(light->sizev*light->size);
- float area = len(axisu)*len(axisv);
- if(light->round) {
- area *= -M_PI_4_F;
- }
- float invarea = (area != 0.0f)? 1.0f/area: 1.0f;
- float3 dir = light->dir;
-
- dir = safe_normalize(dir);
-
- klights[light_index].co[0] = co.x;
- klights[light_index].co[1] = co.y;
- klights[light_index].co[2] = co.z;
-
- klights[light_index].area.axisu[0] = axisu.x;
- klights[light_index].area.axisu[1] = axisu.y;
- klights[light_index].area.axisu[2] = axisu.z;
- klights[light_index].area.axisv[0] = axisv.x;
- klights[light_index].area.axisv[1] = axisv.y;
- klights[light_index].area.axisv[2] = axisv.z;
- klights[light_index].area.invarea = invarea;
- klights[light_index].area.dir[0] = dir.x;
- klights[light_index].area.dir[1] = dir.y;
- klights[light_index].area.dir[2] = dir.z;
- klights[light_index].tfm = light->tfm;
- klights[light_index].itfm = transform_inverse(light->tfm);
-
- light_index++;
- }
-
- VLOG(1) << "Number of lights sent to the device: " << light_index;
-
- VLOG(1) << "Number of lights without contribution: "
- << num_scene_lights - light_index;
-
- dscene->lights.copy_to_device();
+ int num_scene_lights = scene->lights.size();
+
+ int num_lights = 0;
+ foreach (Light *light, scene->lights) {
+ if (light->is_enabled || light->is_portal) {
+ num_lights++;
+ }
+ }
+
+ KernelLight *klights = dscene->lights.alloc(num_lights);
+
+ if (num_lights == 0) {
+ VLOG(1) << "No effective light, ignoring points update.";
+ return;
+ }
+
+ int light_index = 0;
+
+ foreach (Light *light, scene->lights) {
+ if (!light->is_enabled) {
+ continue;
+ }
+
+ float3 co = light->co;
+ Shader *shader = (light->shader) ? light->shader : scene->default_light;
+ int shader_id = scene->shader_manager->get_shader_id(shader);
+ int samples = light->samples;
+ int max_bounces = light->max_bounces;
+ float random = (float)light->random_id * (1.0f / (float)0xFFFFFFFF);
+
+ if (!light->cast_shadow)
+ shader_id &= ~SHADER_CAST_SHADOW;
+
+ if (!light->use_diffuse) {
+ shader_id |= SHADER_EXCLUDE_DIFFUSE;
+ use_light_visibility = true;
+ }
+ if (!light->use_glossy) {
+ shader_id |= SHADER_EXCLUDE_GLOSSY;
+ use_light_visibility = true;
+ }
+ if (!light->use_transmission) {
+ shader_id |= SHADER_EXCLUDE_TRANSMIT;
+ use_light_visibility = true;
+ }
+ if (!light->use_scatter) {
+ shader_id |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
+
+ klights[light_index].type = light->type;
+ klights[light_index].samples = samples;
+
+ if (light->type == LIGHT_POINT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float radius = light->size;
+ float invarea = (radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) : 1.0f;
+
+ if (light->use_mis && radius > 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].spot.radius = radius;
+ klights[light_index].spot.invarea = invarea;
+ }
+ else if (light->type == LIGHT_DISTANT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float radius = light->size;
+ float angle = atanf(radius);
+ float cosangle = cosf(angle);
+ float area = M_PI_F * radius * radius;
+ float invarea = (area > 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ if (light->use_mis && area > 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = dir.x;
+ klights[light_index].co[1] = dir.y;
+ klights[light_index].co[2] = dir.z;
+
+ klights[light_index].distant.invarea = invarea;
+ klights[light_index].distant.radius = radius;
+ klights[light_index].distant.cosangle = cosangle;
+ }
+ else if (light->type == LIGHT_BACKGROUND) {
+ uint visibility = scene->background->visibility;
+
+ shader_id &= ~SHADER_AREA_LIGHT;
+ shader_id |= SHADER_USE_MIS;
+
+ if (!(visibility & PATH_RAY_DIFFUSE)) {
+ shader_id |= SHADER_EXCLUDE_DIFFUSE;
+ use_light_visibility = true;
+ }
+ if (!(visibility & PATH_RAY_GLOSSY)) {
+ shader_id |= SHADER_EXCLUDE_GLOSSY;
+ use_light_visibility = true;
+ }
+ if (!(visibility & PATH_RAY_TRANSMIT)) {
+ shader_id |= SHADER_EXCLUDE_TRANSMIT;
+ use_light_visibility = true;
+ }
+ if (!(visibility & PATH_RAY_VOLUME_SCATTER)) {
+ shader_id |= SHADER_EXCLUDE_SCATTER;
+ use_light_visibility = true;
+ }
+ }
+ else if (light->type == LIGHT_AREA) {
+ float3 axisu = light->axisu * (light->sizeu * light->size);
+ float3 axisv = light->axisv * (light->sizev * light->size);
+ float area = len(axisu) * len(axisv);
+ if (light->round) {
+ area *= -M_PI_4_F;
+ }
+ float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ if (light->use_mis && area != 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].area.axisu[0] = axisu.x;
+ klights[light_index].area.axisu[1] = axisu.y;
+ klights[light_index].area.axisu[2] = axisu.z;
+ klights[light_index].area.axisv[0] = axisv.x;
+ klights[light_index].area.axisv[1] = axisv.y;
+ klights[light_index].area.axisv[2] = axisv.z;
+ klights[light_index].area.invarea = invarea;
+ klights[light_index].area.dir[0] = dir.x;
+ klights[light_index].area.dir[1] = dir.y;
+ klights[light_index].area.dir[2] = dir.z;
+ }
+ else if (light->type == LIGHT_SPOT) {
+ shader_id &= ~SHADER_AREA_LIGHT;
+
+ float radius = light->size;
+ float invarea = (radius > 0.0f) ? 1.0f / (M_PI_F * radius * radius) : 1.0f;
+ float spot_angle = cosf(light->spot_angle * 0.5f);
+ float spot_smooth = (1.0f - spot_angle) * light->spot_smooth;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ if (light->use_mis && radius > 0.0f)
+ shader_id |= SHADER_USE_MIS;
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].spot.radius = radius;
+ klights[light_index].spot.invarea = invarea;
+ klights[light_index].spot.spot_angle = spot_angle;
+ klights[light_index].spot.spot_smooth = spot_smooth;
+ klights[light_index].spot.dir[0] = dir.x;
+ klights[light_index].spot.dir[1] = dir.y;
+ klights[light_index].spot.dir[2] = dir.z;
+ }
+
+ klights[light_index].shader_id = shader_id;
+
+ klights[light_index].max_bounces = max_bounces;
+ klights[light_index].random = random;
+
+ klights[light_index].tfm = light->tfm;
+ klights[light_index].itfm = transform_inverse(light->tfm);
+
+ light_index++;
+ }
+
+ /* TODO(sergey): Consider moving portals update to their own function
+ * keeping this one more manageable.
+ */
+ foreach (Light *light, scene->lights) {
+ if (!light->is_portal)
+ continue;
+ assert(light->type == LIGHT_AREA);
+
+ float3 co = light->co;
+ float3 axisu = light->axisu * (light->sizeu * light->size);
+ float3 axisv = light->axisv * (light->sizev * light->size);
+ float area = len(axisu) * len(axisv);
+ if (light->round) {
+ area *= -M_PI_4_F;
+ }
+ float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
+ float3 dir = light->dir;
+
+ dir = safe_normalize(dir);
+
+ klights[light_index].co[0] = co.x;
+ klights[light_index].co[1] = co.y;
+ klights[light_index].co[2] = co.z;
+
+ klights[light_index].area.axisu[0] = axisu.x;
+ klights[light_index].area.axisu[1] = axisu.y;
+ klights[light_index].area.axisu[2] = axisu.z;
+ klights[light_index].area.axisv[0] = axisv.x;
+ klights[light_index].area.axisv[1] = axisv.y;
+ klights[light_index].area.axisv[2] = axisv.z;
+ klights[light_index].area.invarea = invarea;
+ klights[light_index].area.dir[0] = dir.x;
+ klights[light_index].area.dir[1] = dir.y;
+ klights[light_index].area.dir[2] = dir.z;
+ klights[light_index].tfm = light->tfm;
+ klights[light_index].itfm = transform_inverse(light->tfm);
+
+ light_index++;
+ }
+
+ VLOG(1) << "Number of lights sent to the device: " << light_index;
+
+ VLOG(1) << "Number of lights without contribution: " << num_scene_lights - light_index;
+
+ dscene->lights.copy_to_device();
}
-void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void LightManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->lights.size() << " lights.";
+ VLOG(1) << "Total " << scene->lights.size() << " lights.";
- device_free(device, dscene);
+ device_free(device, dscene);
- use_light_visibility = false;
+ use_light_visibility = false;
- disable_ineffective_light(scene);
+ disable_ineffective_light(scene);
- device_update_points(device, dscene, scene);
- if(progress.get_cancel()) return;
+ device_update_points(device, dscene, scene);
+ if (progress.get_cancel())
+ return;
- device_update_distribution(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
+ device_update_distribution(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
- device_update_background(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
+ device_update_background(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
- device_update_ies(dscene);
- if(progress.get_cancel()) return;
+ device_update_ies(dscene);
+ if (progress.get_cancel())
+ return;
- if(use_light_visibility != scene->film->use_light_visibility) {
- scene->film->use_light_visibility = use_light_visibility;
- scene->film->tag_update(scene);
- }
+ if (use_light_visibility != scene->film->use_light_visibility) {
+ scene->film->use_light_visibility = use_light_visibility;
+ scene->film->tag_update(scene);
+ }
- need_update = false;
+ need_update = false;
}
void LightManager::device_free(Device *, DeviceScene *dscene)
{
- dscene->light_distribution.free();
- dscene->lights.free();
- dscene->light_background_marginal_cdf.free();
- dscene->light_background_conditional_cdf.free();
- dscene->ies_lights.free();
+ dscene->light_distribution.free();
+ dscene->lights.free();
+ dscene->light_background_marginal_cdf.free();
+ dscene->light_background_conditional_cdf.free();
+ dscene->ies_lights.free();
}
void LightManager::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
int LightManager::add_ies_from_file(ustring filename)
{
- string content;
+ string content;
- /* If the file can't be opened, call with an empty line */
- if(filename.empty() || !path_read_text(filename.c_str(), content)) {
- content = "\n";
- }
+ /* If the file can't be opened, call with an empty line */
+ if (filename.empty() || !path_read_text(filename.c_str(), content)) {
+ content = "\n";
+ }
- return add_ies(ustring(content));
+ return add_ies(ustring(content));
}
int LightManager::add_ies(ustring content)
{
- uint hash = hash_string(content.c_str());
-
- thread_scoped_lock ies_lock(ies_mutex);
-
- /* Check whether this IES already has a slot. */
- size_t slot;
- for(slot = 0; slot < ies_slots.size(); slot++) {
- if(ies_slots[slot]->hash == hash) {
- ies_slots[slot]->users++;
- return slot;
- }
- }
-
- /* Try to find an empty slot for the new IES. */
- for(slot = 0; slot < ies_slots.size(); slot++) {
- if(ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
- break;
- }
- }
-
- /* If there's no free slot, add one. */
- if(slot == ies_slots.size()) {
- ies_slots.push_back(new IESSlot());
- }
-
- ies_slots[slot]->ies.load(content);
- ies_slots[slot]->users = 1;
- ies_slots[slot]->hash = hash;
-
- need_update = true;
-
- return slot;
+ uint hash = hash_string(content.c_str());
+
+ thread_scoped_lock ies_lock(ies_mutex);
+
+ /* Check whether this IES already has a slot. */
+ size_t slot;
+ for (slot = 0; slot < ies_slots.size(); slot++) {
+ if (ies_slots[slot]->hash == hash) {
+ ies_slots[slot]->users++;
+ return slot;
+ }
+ }
+
+ /* Try to find an empty slot for the new IES. */
+ for (slot = 0; slot < ies_slots.size(); slot++) {
+ if (ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
+ break;
+ }
+ }
+
+ /* If there's no free slot, add one. */
+ if (slot == ies_slots.size()) {
+ ies_slots.push_back(new IESSlot());
+ }
+
+ ies_slots[slot]->ies.load(content);
+ ies_slots[slot]->users = 1;
+ ies_slots[slot]->hash = hash;
+
+ need_update = true;
+
+ return slot;
}
void LightManager::remove_ies(int slot)
{
- thread_scoped_lock ies_lock(ies_mutex);
+ thread_scoped_lock ies_lock(ies_mutex);
- if(slot < 0 || slot >= ies_slots.size()) {
- assert(false);
- return;
- }
+ if (slot < 0 || slot >= ies_slots.size()) {
+ assert(false);
+ return;
+ }
- assert(ies_slots[slot]->users > 0);
- ies_slots[slot]->users--;
+ assert(ies_slots[slot]->users > 0);
+ ies_slots[slot]->users--;
- /* If the slot has no more users, update the device to remove it. */
- need_update |= (ies_slots[slot]->users == 0);
+ /* If the slot has no more users, update the device to remove it. */
+ need_update |= (ies_slots[slot]->users == 0);
}
void LightManager::device_update_ies(DeviceScene *dscene)
{
- /* Clear empty slots. */
- foreach(IESSlot *slot, ies_slots) {
- if(slot->users == 0) {
- slot->hash = 0;
- slot->ies.clear();
- }
- }
-
- /* Shrink the slot table by removing empty slots at the end. */
- int slot_end;
- for(slot_end = ies_slots.size(); slot_end; slot_end--) {
- if(ies_slots[slot_end-1]->users > 0) {
- /* If the preceding slot has users, we found the new end of the table. */
- break;
- }
- else {
- /* The slot will be past the new end of the table, so free it. */
- delete ies_slots[slot_end-1];
- }
- }
- ies_slots.resize(slot_end);
-
- if(ies_slots.size() > 0) {
- int packed_size = 0;
- foreach(IESSlot *slot, ies_slots) {
- packed_size += slot->ies.packed_size();
- }
-
- /* ies_lights starts with an offset table that contains the offset of every slot,
- * or -1 if the slot is invalid.
- * Following that table, the packed valid IES lights are stored. */
- float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
-
- int offset = ies_slots.size();
- for(int i = 0; i < ies_slots.size(); i++) {
- int size = ies_slots[i]->ies.packed_size();
- if(size > 0) {
- data[i] = __int_as_float(offset);
- ies_slots[i]->ies.pack(data + offset);
- offset += size;
- }
- else {
- data[i] = __int_as_float(-1);
- }
- }
-
- dscene->ies_lights.copy_to_device();
- }
+ /* Clear empty slots. */
+ foreach (IESSlot *slot, ies_slots) {
+ if (slot->users == 0) {
+ slot->hash = 0;
+ slot->ies.clear();
+ }
+ }
+
+ /* Shrink the slot table by removing empty slots at the end. */
+ int slot_end;
+ for (slot_end = ies_slots.size(); slot_end; slot_end--) {
+ if (ies_slots[slot_end - 1]->users > 0) {
+ /* If the preceding slot has users, we found the new end of the table. */
+ break;
+ }
+ else {
+ /* The slot will be past the new end of the table, so free it. */
+ delete ies_slots[slot_end - 1];
+ }
+ }
+ ies_slots.resize(slot_end);
+
+ if (ies_slots.size() > 0) {
+ int packed_size = 0;
+ foreach (IESSlot *slot, ies_slots) {
+ packed_size += slot->ies.packed_size();
+ }
+
+ /* ies_lights starts with an offset table that contains the offset of every slot,
+ * or -1 if the slot is invalid.
+ * Following that table, the packed valid IES lights are stored. */
+ float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
+
+ int offset = ies_slots.size();
+ for (int i = 0; i < ies_slots.size(); i++) {
+ int size = ies_slots[i]->ies.packed_size();
+ if (size > 0) {
+ data[i] = __int_as_float(offset);
+ ies_slots[i]->ies.pack(data + offset);
+ offset += size;
+ }
+ else {
+ data[i] = __int_as_float(-1);
+ }
+ }
+
+ dscene->ies_lights.copy_to_device();
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index a627ec9bdc3..66732000f3b 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -36,108 +36,103 @@ class Scene;
class Shader;
class Light : public Node {
-public:
- NODE_DECLARE;
+ public:
+ NODE_DECLARE;
- Light();
+ Light();
- LightType type;
- float3 co;
+ LightType type;
+ float3 co;
- float3 dir;
- float size;
+ float3 dir;
+ float size;
- float3 axisu;
- float sizeu;
- float3 axisv;
- float sizev;
- bool round;
+ float3 axisu;
+ float sizeu;
+ float3 axisv;
+ float sizev;
+ bool round;
- Transform tfm;
+ Transform tfm;
- int map_resolution;
+ int map_resolution;
- float spot_angle;
- float spot_smooth;
+ float spot_angle;
+ float spot_smooth;
- bool cast_shadow;
- bool use_mis;
- bool use_diffuse;
- bool use_glossy;
- bool use_transmission;
- bool use_scatter;
+ bool cast_shadow;
+ bool use_mis;
+ bool use_diffuse;
+ bool use_glossy;
+ bool use_transmission;
+ bool use_scatter;
- bool is_portal;
- bool is_enabled;
+ bool is_portal;
+ bool is_enabled;
- Shader *shader;
- int samples;
- int max_bounces;
- uint random_id;
+ Shader *shader;
+ int samples;
+ int max_bounces;
+ uint random_id;
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
- /* Check whether the light has contribution the the scene. */
- bool has_contribution(Scene *scene);
+ /* Check whether the light has contribution the the scene. */
+ bool has_contribution(Scene *scene);
};
class LightManager {
-public:
- bool use_light_visibility;
- bool need_update;
-
- LightManager();
- ~LightManager();
-
- /* IES texture management */
- int add_ies(ustring ies);
- int add_ies_from_file(ustring filename);
- void remove_ies(int slot);
-
- void device_update(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
-
- void tag_update(Scene *scene);
-
- /* Check whether there is a background light. */
- bool has_background_light(Scene *scene);
-
-protected:
- /* Optimization: disable light which is either unsupported or
- * which doesn't contribute to the scene or which is only used for MIS
- * and scene doesn't need MIS.
- */
- void disable_ineffective_light(Scene *scene);
-
- void device_update_points(Device *device,
- DeviceScene *dscene,
- Scene *scene);
- void device_update_distribution(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
- void device_update_background(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
- void device_update_ies(DeviceScene *dscene);
-
- /* Check whether light manager can use the object as a light-emissive. */
- bool object_usable_as_light(Object *object);
-
- struct IESSlot {
- IESFile ies;
- uint hash;
- int users;
- };
-
- vector<IESSlot*> ies_slots;
- thread_mutex ies_mutex;
+ public:
+ bool use_light_visibility;
+ bool need_update;
+
+ LightManager();
+ ~LightManager();
+
+ /* IES texture management */
+ int add_ies(ustring ies);
+ int add_ies_from_file(ustring filename);
+ void remove_ies(int slot);
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
+
+ void tag_update(Scene *scene);
+
+ /* Check whether there is a background light. */
+ bool has_background_light(Scene *scene);
+
+ protected:
+ /* Optimization: disable light which is either unsupported or
+ * which doesn't contribute to the scene or which is only used for MIS
+ * and scene doesn't need MIS.
+ */
+ void disable_ineffective_light(Scene *scene);
+
+ void device_update_points(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_distribution(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+ void device_update_background(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+ void device_update_ies(DeviceScene *dscene);
+
+ /* Check whether light manager can use the object as a light-emissive. */
+ bool object_usable_as_light(Object *object);
+
+ struct IESSlot {
+ IESFile ies;
+ uint hash;
+ int users;
+ };
+
+ vector<IESSlot *> ies_slots;
+ thread_mutex ies_mutex;
};
CCL_NAMESPACE_END
-#endif /* __LIGHT_H__ */
+#endif /* __LIGHT_H__ */
diff --git a/intern/cycles/render/merge.cpp b/intern/cycles/render/merge.cpp
index 289bb023d72..cac07e59fe3 100644
--- a/intern/cycles/render/merge.cpp
+++ b/intern/cycles/render/merge.cpp
@@ -32,453 +32,443 @@ CCL_NAMESPACE_BEGIN
/* Merge Image Layer */
enum MergeChannelOp {
- MERGE_CHANNEL_NOP,
- MERGE_CHANNEL_COPY,
- MERGE_CHANNEL_SUM,
- MERGE_CHANNEL_AVERAGE
+ MERGE_CHANNEL_NOP,
+ MERGE_CHANNEL_COPY,
+ MERGE_CHANNEL_SUM,
+ MERGE_CHANNEL_AVERAGE
};
struct MergeImagePass {
- /* Full channel name. */
- string channel_name;
- /* Channel format in the file. */
- TypeDesc format;
- /* Type of operation to perform when merging. */
- MergeChannelOp op;
- /* Offset of layer channels in input image. */
- int offset;
- /* Offset of layer channels in merged image. */
- int merge_offset;
+ /* Full channel name. */
+ string channel_name;
+ /* Channel format in the file. */
+ TypeDesc format;
+ /* Type of operation to perform when merging. */
+ MergeChannelOp op;
+ /* Offset of layer channels in input image. */
+ int offset;
+ /* Offset of layer channels in merged image. */
+ int merge_offset;
};
struct MergeImageLayer {
- /* Layer name. */
- string name;
- /* Passes. */
- vector<MergeImagePass> passes;
- /* Sample amount that was used for rendering this layer. */
- int samples;
+ /* Layer name. */
+ string name;
+ /* Passes. */
+ vector<MergeImagePass> passes;
+ /* Sample amount that was used for rendering this layer. */
+ int samples;
};
/* Merge Image */
struct MergeImage {
- /* OIIO file handle. */
- unique_ptr<ImageInput> in;
- /* Image file path. */
- string filepath;
- /* Render layers. */
- vector<MergeImageLayer> layers;
+ /* OIIO file handle. */
+ unique_ptr<ImageInput> in;
+ /* Image file path. */
+ string filepath;
+ /* Render layers. */
+ vector<MergeImageLayer> layers;
};
/* Channel Parsing */
-static MergeChannelOp parse_channel_operation(const string& pass_name)
+static MergeChannelOp parse_channel_operation(const string &pass_name)
{
- if(pass_name == "Depth" ||
- pass_name == "IndexMA" ||
- pass_name == "IndexOB" ||
- string_startswith(pass_name, "Crypto"))
- {
- return MERGE_CHANNEL_COPY;
- }
- else if(string_startswith(pass_name, "Debug BVH") ||
- string_startswith(pass_name, "Debug Ray") ||
- string_startswith(pass_name, "Debug Render Time"))
- {
- return MERGE_CHANNEL_SUM;
- }
- else {
- return MERGE_CHANNEL_AVERAGE;
- }
+ if (pass_name == "Depth" || pass_name == "IndexMA" || pass_name == "IndexOB" ||
+ string_startswith(pass_name, "Crypto")) {
+ return MERGE_CHANNEL_COPY;
+ }
+ else if (string_startswith(pass_name, "Debug BVH") ||
+ string_startswith(pass_name, "Debug Ray") ||
+ string_startswith(pass_name, "Debug Render Time")) {
+ return MERGE_CHANNEL_SUM;
+ }
+ else {
+ return MERGE_CHANNEL_AVERAGE;
+ }
}
/* Splits in at its last dot, setting suffix to the part after the dot and
* into the part before it. Returns whether a dot was found. */
static bool split_last_dot(string &in, string &suffix)
{
- size_t pos = in.rfind(".");
- if(pos == string::npos) {
- return false;
- }
- suffix = in.substr(pos+1);
- in = in.substr(0, pos);
- return true;
+ size_t pos = in.rfind(".");
+ if (pos == string::npos) {
+ return false;
+ }
+ suffix = in.substr(pos + 1);
+ in = in.substr(0, pos);
+ return true;
}
/* Separate channel names as generated by Blender.
* Multiview format: RenderLayer.Pass.View.Channel
* Otherwise: RenderLayer.Pass.Channel */
-static bool parse_channel_name(string name,
- string &renderlayer,
- string &pass,
- string &channel,
- bool multiview_channels)
+static bool parse_channel_name(
+ string name, string &renderlayer, string &pass, string &channel, bool multiview_channels)
{
- if(!split_last_dot(name, channel)) {
- return false;
- }
- string view;
- if(multiview_channels && !split_last_dot(name, view)) {
- return false;
- }
- if(!split_last_dot(name, pass)) {
- return false;
- }
- renderlayer = name;
-
- if(multiview_channels) {
- renderlayer += "." + view;
- }
-
- return true;
+ if (!split_last_dot(name, channel)) {
+ return false;
+ }
+ string view;
+ if (multiview_channels && !split_last_dot(name, view)) {
+ return false;
+ }
+ if (!split_last_dot(name, pass)) {
+ return false;
+ }
+ renderlayer = name;
+
+ if (multiview_channels) {
+ renderlayer += "." + view;
+ }
+
+ return true;
}
static bool parse_channels(const ImageSpec &in_spec,
- vector<MergeImageLayer>& layers,
- string& error)
+ vector<MergeImageLayer> &layers,
+ string &error)
{
- const ParamValue *multiview = in_spec.find_attribute("multiView");
- const bool multiview_channels = (multiview &&
- multiview->type().basetype == TypeDesc::STRING &&
- multiview->type().arraylen >= 2);
-
- layers.clear();
-
- /* Loop over all the channels in the file, parse their name and sort them
- * by RenderLayer.
- * Channels that can't be parsed are directly passed through to the output. */
- map<string, MergeImageLayer> file_layers;
- for(int i = 0; i < in_spec.nchannels; i++) {
- MergeImagePass pass;
- pass.channel_name = in_spec.channelnames[i];
- pass.format = (in_spec.channelformats.size() > 0) ? in_spec.channelformats[i] : in_spec.format;
- pass.offset = i;
- pass.merge_offset = i;
-
- string layername, passname, channelname;
- if(parse_channel_name(pass.channel_name, layername, passname, channelname, multiview_channels)) {
- /* Channer part of a render layer. */
- pass.op = parse_channel_operation(passname);
- }
- else {
- /* Other channels are added in unnamed layer. */
- layername = "";
- pass.op = parse_channel_operation(pass.channel_name);
- }
-
- file_layers[layername].passes.push_back(pass);
- }
-
- /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
- * Any channels that won't be processed internally are also passed through. */
- for(auto& i: file_layers) {
- const string& name = i.first;
- MergeImageLayer& layer = i.second;
-
- layer.name = name;
- layer.samples = 0;
-
- /* Determine number of samples from metadata. */
- if(layer.name == "") {
- layer.samples = 1;
- }
- else if(layer.samples < 1) {
- string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
- if(sample_string != "") {
- if(!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
- error = "Failed to parse samples metadata: " + sample_string;
- return false;
- }
- }
- }
-
- if(layer.samples < 1) {
- error = string_printf("No sample number specified in the file for layer %s or on the command line", name.c_str());
- return false;
- }
-
- layers.push_back(layer);
- }
-
- return true;
+ const ParamValue *multiview = in_spec.find_attribute("multiView");
+ const bool multiview_channels = (multiview && multiview->type().basetype == TypeDesc::STRING &&
+ multiview->type().arraylen >= 2);
+
+ layers.clear();
+
+ /* Loop over all the channels in the file, parse their name and sort them
+ * by RenderLayer.
+ * Channels that can't be parsed are directly passed through to the output. */
+ map<string, MergeImageLayer> file_layers;
+ for (int i = 0; i < in_spec.nchannels; i++) {
+ MergeImagePass pass;
+ pass.channel_name = in_spec.channelnames[i];
+ pass.format = (in_spec.channelformats.size() > 0) ? in_spec.channelformats[i] : in_spec.format;
+ pass.offset = i;
+ pass.merge_offset = i;
+
+ string layername, passname, channelname;
+ if (parse_channel_name(
+ pass.channel_name, layername, passname, channelname, multiview_channels)) {
+ /* Channer part of a render layer. */
+ pass.op = parse_channel_operation(passname);
+ }
+ else {
+ /* Other channels are added in unnamed layer. */
+ layername = "";
+ pass.op = parse_channel_operation(pass.channel_name);
+ }
+
+ file_layers[layername].passes.push_back(pass);
+ }
+
+ /* Loop over all detected RenderLayers, check whether they contain a full set of input channels.
+ * Any channels that won't be processed internally are also passed through. */
+ for (auto &i : file_layers) {
+ const string &name = i.first;
+ MergeImageLayer &layer = i.second;
+
+ layer.name = name;
+ layer.samples = 0;
+
+ /* Determine number of samples from metadata. */
+ if (layer.name == "") {
+ layer.samples = 1;
+ }
+ else if (layer.samples < 1) {
+ string sample_string = in_spec.get_string_attribute("cycles." + name + ".samples", "");
+ if (sample_string != "") {
+ if (!sscanf(sample_string.c_str(), "%d", &layer.samples)) {
+ error = "Failed to parse samples metadata: " + sample_string;
+ return false;
+ }
+ }
+ }
+
+ if (layer.samples < 1) {
+ error = string_printf(
+ "No sample number specified in the file for layer %s or on the command line",
+ name.c_str());
+ return false;
+ }
+
+ layers.push_back(layer);
+ }
+
+ return true;
}
-static bool open_images(const vector<string>& filepaths,
- vector<MergeImage>& images,
- string& error)
+static bool open_images(const vector<string> &filepaths, vector<MergeImage> &images, string &error)
{
- for(const string& filepath: filepaths) {
- unique_ptr<ImageInput> in(ImageInput::open(filepath));
- if(!in) {
- error = "Couldn't open file: " + filepath;
- return false;
- }
-
- MergeImage image;
- image.in = std::move(in);
- image.filepath = filepath;
- if(!parse_channels(image.in->spec(), image.layers, error)) {
- return false;
- }
-
- if(image.layers.size() == 0) {
- error = "Could not find a render layer for merging";
- return false;
- }
-
- if(image.in->spec().deep) {
- error = "Merging deep images not supported.";
- return false;
- }
-
- if(images.size() > 0) {
- const ImageSpec& base_spec = images[0].in->spec();
- const ImageSpec& spec = image.in->spec();
-
- if(base_spec.width != spec.width ||
- base_spec.height != spec.height ||
- base_spec.depth != spec.depth ||
- base_spec.format != spec.format ||
- base_spec.deep != spec.deep)
- {
- error = "Images do not have matching size and data layout.";
- return false;
- }
- }
-
- images.push_back(std::move(image));
- }
-
- return true;
+ for (const string &filepath : filepaths) {
+ unique_ptr<ImageInput> in(ImageInput::open(filepath));
+ if (!in) {
+ error = "Couldn't open file: " + filepath;
+ return false;
+ }
+
+ MergeImage image;
+ image.in = std::move(in);
+ image.filepath = filepath;
+ if (!parse_channels(image.in->spec(), image.layers, error)) {
+ return false;
+ }
+
+ if (image.layers.size() == 0) {
+ error = "Could not find a render layer for merging";
+ return false;
+ }
+
+ if (image.in->spec().deep) {
+ error = "Merging deep images not supported.";
+ return false;
+ }
+
+ if (images.size() > 0) {
+ const ImageSpec &base_spec = images[0].in->spec();
+ const ImageSpec &spec = image.in->spec();
+
+ if (base_spec.width != spec.width || base_spec.height != spec.height ||
+ base_spec.depth != spec.depth || base_spec.format != spec.format ||
+ base_spec.deep != spec.deep) {
+ error = "Images do not have matching size and data layout.";
+ return false;
+ }
+ }
+
+ images.push_back(std::move(image));
+ }
+
+ return true;
}
-static void merge_render_time(ImageSpec& spec,
- const vector<MergeImage>& images,
- const string& name,
+static void merge_render_time(ImageSpec &spec,
+ const vector<MergeImage> &images,
+ const string &name,
const bool average)
{
- double time = 0.0;
+ double time = 0.0;
- for(const MergeImage& image: images) {
- string time_str = image.in->spec().get_string_attribute(name, "");
- time += time_human_readable_to_seconds(time_str);
- }
+ for (const MergeImage &image : images) {
+ string time_str = image.in->spec().get_string_attribute(name, "");
+ time += time_human_readable_to_seconds(time_str);
+ }
- if(average) {
- time /= images.size();
- }
+ if (average) {
+ time /= images.size();
+ }
- spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
+ spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
}
-static void merge_layer_render_time(ImageSpec& spec,
- const vector<MergeImage>& images,
- const string& layer_name,
- const string& time_name,
+static void merge_layer_render_time(ImageSpec &spec,
+ const vector<MergeImage> &images,
+ const string &layer_name,
+ const string &time_name,
const bool average)
{
- string name = "cycles." + layer_name + "." + time_name;
- double time = 0.0;
+ string name = "cycles." + layer_name + "." + time_name;
+ double time = 0.0;
- for(const MergeImage& image: images) {
- string time_str = image.in->spec().get_string_attribute(name, "");
- time += time_human_readable_to_seconds(time_str);
- }
+ for (const MergeImage &image : images) {
+ string time_str = image.in->spec().get_string_attribute(name, "");
+ time += time_human_readable_to_seconds(time_str);
+ }
- if(average) {
- time /= images.size();
- }
+ if (average) {
+ time /= images.size();
+ }
- spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
+ spec.attribute(name, TypeDesc::STRING, time_human_readable_from_seconds(time));
}
-static void merge_channels_metadata(vector<MergeImage>& images,
- ImageSpec& out_spec,
- vector<int>& channel_total_samples)
+static void merge_channels_metadata(vector<MergeImage> &images,
+ ImageSpec &out_spec,
+ vector<int> &channel_total_samples)
{
- /* Based on first image. */
- out_spec = images[0].in->spec();
-
- /* Merge channels and compute offsets. */
- out_spec.nchannels = 0;
- out_spec.channelformats.clear();
- out_spec.channelnames.clear();
-
- for(MergeImage& image: images) {
- for(MergeImageLayer& layer: image.layers) {
- for(MergeImagePass& pass: layer.passes) {
- /* Test if matching channel already exists in merged image. */
- bool found = false;
-
- for(size_t i = 0; i < out_spec.nchannels; i++) {
- if(pass.channel_name == out_spec.channelnames[i]) {
- pass.merge_offset = i;
- channel_total_samples[i] += layer.samples;
- /* First image wins for channels that can't be averaged or summed. */
- if (pass.op == MERGE_CHANNEL_COPY) {
- pass.op = MERGE_CHANNEL_NOP;
- }
- found = true;
- break;
- }
- }
-
- if(!found) {
- /* Add new channel. */
- pass.merge_offset = out_spec.nchannels;
- channel_total_samples.push_back(layer.samples);
-
- out_spec.channelnames.push_back(pass.channel_name);
- out_spec.channelformats.push_back(pass.format);
- out_spec.nchannels++;
- }
- }
- }
- }
-
- /* Merge metadata. */
- merge_render_time(out_spec, images, "RenderTime", false);
-
- map<string, int> layer_num_samples;
- for(MergeImage& image: images) {
- for(MergeImageLayer& layer: image.layers) {
- if(layer.name != "") {
- layer_num_samples[layer.name] += layer.samples;
- }
- }
- }
-
- for(const auto& i: layer_num_samples) {
- string name = "cycles." + i.first + ".samples";
- out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", i.second));
-
- merge_layer_render_time(out_spec, images, i.first, "total_time", false);
- merge_layer_render_time(out_spec, images, i.first, "render_time", false);
- merge_layer_render_time(out_spec, images, i.first, "synchronization_time", true);
- }
+ /* Based on first image. */
+ out_spec = images[0].in->spec();
+
+ /* Merge channels and compute offsets. */
+ out_spec.nchannels = 0;
+ out_spec.channelformats.clear();
+ out_spec.channelnames.clear();
+
+ for (MergeImage &image : images) {
+ for (MergeImageLayer &layer : image.layers) {
+ for (MergeImagePass &pass : layer.passes) {
+ /* Test if matching channel already exists in merged image. */
+ bool found = false;
+
+ for (size_t i = 0; i < out_spec.nchannels; i++) {
+ if (pass.channel_name == out_spec.channelnames[i]) {
+ pass.merge_offset = i;
+ channel_total_samples[i] += layer.samples;
+ /* First image wins for channels that can't be averaged or summed. */
+ if (pass.op == MERGE_CHANNEL_COPY) {
+ pass.op = MERGE_CHANNEL_NOP;
+ }
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Add new channel. */
+ pass.merge_offset = out_spec.nchannels;
+ channel_total_samples.push_back(layer.samples);
+
+ out_spec.channelnames.push_back(pass.channel_name);
+ out_spec.channelformats.push_back(pass.format);
+ out_spec.nchannels++;
+ }
+ }
+ }
+ }
+
+ /* Merge metadata. */
+ merge_render_time(out_spec, images, "RenderTime", false);
+
+ map<string, int> layer_num_samples;
+ for (MergeImage &image : images) {
+ for (MergeImageLayer &layer : image.layers) {
+ if (layer.name != "") {
+ layer_num_samples[layer.name] += layer.samples;
+ }
+ }
+ }
+
+ for (const auto &i : layer_num_samples) {
+ string name = "cycles." + i.first + ".samples";
+ out_spec.attribute(name, TypeDesc::STRING, string_printf("%d", i.second));
+
+ merge_layer_render_time(out_spec, images, i.first, "total_time", false);
+ merge_layer_render_time(out_spec, images, i.first, "render_time", false);
+ merge_layer_render_time(out_spec, images, i.first, "synchronization_time", true);
+ }
}
-static void alloc_pixels(const ImageSpec& spec, array<float>& pixels)
+static void alloc_pixels(const ImageSpec &spec, array<float> &pixels)
{
- const size_t width = spec.width;
- const size_t height = spec.height;
- const size_t num_channels = spec.nchannels;
+ const size_t width = spec.width;
+ const size_t height = spec.height;
+ const size_t num_channels = spec.nchannels;
- const size_t num_pixels = (size_t)width * (size_t)height;
- pixels.resize(num_pixels * num_channels);
+ const size_t num_pixels = (size_t)width * (size_t)height;
+ pixels.resize(num_pixels * num_channels);
}
-static bool merge_pixels(const vector<MergeImage>& images,
- const ImageSpec& out_spec,
- const vector<int>& channel_total_samples,
- array<float>& out_pixels,
- string& error)
+static bool merge_pixels(const vector<MergeImage> &images,
+ const ImageSpec &out_spec,
+ const vector<int> &channel_total_samples,
+ array<float> &out_pixels,
+ string &error)
{
- alloc_pixels(out_spec, out_pixels);
- memset(out_pixels.data(), 0, out_pixels.size() * sizeof(float));
-
- for(const MergeImage& image: images) {
- /* Read all channels into buffer. Reading all channels at once is
- * faster than individually due to interleaved EXR channel storage. */
- array<float> pixels;
- alloc_pixels(image.in->spec(), pixels);
-
- if(!image.in->read_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to read image: " + image.filepath;
- return false;
- }
-
- for(size_t li = 0; li < image.layers.size(); li++) {
- const MergeImageLayer& layer = image.layers[li];
-
- const size_t stride = image.in->spec().nchannels;
- const size_t out_stride = out_spec.nchannels;
- const size_t num_pixels = pixels.size();
-
- for(const MergeImagePass& pass: layer.passes) {
- size_t offset = pass.offset;
- size_t out_offset = pass.merge_offset;
-
- switch(pass.op) {
- case MERGE_CHANNEL_NOP:
- break;
- case MERGE_CHANNEL_COPY:
- for(; offset < num_pixels; offset += stride, out_offset += out_stride) {
- out_pixels[out_offset] = pixels[offset];
- }
- break;
- case MERGE_CHANNEL_SUM:
- for(; offset < num_pixels; offset += stride, out_offset += out_stride) {
- out_pixels[out_offset] += pixels[offset];
- }
- break;
- case MERGE_CHANNEL_AVERAGE:
- /* Weights based on sample metadata. Per channel since not
- * all files are guaranteed to have the same channels. */
- const int total_samples = channel_total_samples[out_offset];
- const float t = (float)layer.samples / (float)total_samples;
-
- for(; offset < num_pixels; offset += stride, out_offset += out_stride) {
- out_pixels[out_offset] += t * pixels[offset];
- }
- break;
- }
- }
- }
- }
-
- return true;
+ alloc_pixels(out_spec, out_pixels);
+ memset(out_pixels.data(), 0, out_pixels.size() * sizeof(float));
+
+ for (const MergeImage &image : images) {
+ /* Read all channels into buffer. Reading all channels at once is
+ * faster than individually due to interleaved EXR channel storage. */
+ array<float> pixels;
+ alloc_pixels(image.in->spec(), pixels);
+
+ if (!image.in->read_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to read image: " + image.filepath;
+ return false;
+ }
+
+ for (size_t li = 0; li < image.layers.size(); li++) {
+ const MergeImageLayer &layer = image.layers[li];
+
+ const size_t stride = image.in->spec().nchannels;
+ const size_t out_stride = out_spec.nchannels;
+ const size_t num_pixels = pixels.size();
+
+ for (const MergeImagePass &pass : layer.passes) {
+ size_t offset = pass.offset;
+ size_t out_offset = pass.merge_offset;
+
+ switch (pass.op) {
+ case MERGE_CHANNEL_NOP:
+ break;
+ case MERGE_CHANNEL_COPY:
+ for (; offset < num_pixels; offset += stride, out_offset += out_stride) {
+ out_pixels[out_offset] = pixels[offset];
+ }
+ break;
+ case MERGE_CHANNEL_SUM:
+ for (; offset < num_pixels; offset += stride, out_offset += out_stride) {
+ out_pixels[out_offset] += pixels[offset];
+ }
+ break;
+ case MERGE_CHANNEL_AVERAGE:
+ /* Weights based on sample metadata. Per channel since not
+ * all files are guaranteed to have the same channels. */
+ const int total_samples = channel_total_samples[out_offset];
+ const float t = (float)layer.samples / (float)total_samples;
+
+ for (; offset < num_pixels; offset += stride, out_offset += out_stride) {
+ out_pixels[out_offset] += t * pixels[offset];
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
}
-static bool save_output(const string& filepath,
- const ImageSpec& spec,
- const array<float>& pixels,
- string& error)
+static bool save_output(const string &filepath,
+ const ImageSpec &spec,
+ const array<float> &pixels,
+ string &error)
{
- /* Write to temporary file path, so we merge images in place and don't
- * risk destroying files when something goes wrong in file saving. */
- string extension = OIIO::Filesystem::extension(filepath);
- string unique_name = ".merge-tmp-" + OIIO::Filesystem::unique_path();
- string tmp_filepath = filepath + unique_name + extension;
- unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
-
- if(!out) {
- error = "Failed to open temporary file " + tmp_filepath + " for writing";
- return false;
- }
-
- /* Open temporary file and write image buffers. */
- if(!out->open(tmp_filepath, spec)) {
- error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
- return false;
- }
-
- bool ok = true;
- if(!out->write_image(TypeDesc::FLOAT, pixels.data())) {
- error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- if(!out->close()) {
- error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
- ok = false;
- }
-
- out.reset();
-
- /* Copy temporary file to outputput filepath. */
- string rename_error;
- if(ok && !OIIO::Filesystem::rename(tmp_filepath, filepath, rename_error)) {
- error = "Failed to move merged image to " + filepath + ": " + rename_error;
- ok = false;
- }
-
- if(!ok) {
- OIIO::Filesystem::remove(tmp_filepath);
- }
-
- return ok;
+ /* Write to temporary file path, so we merge images in place and don't
+ * risk destroying files when something goes wrong in file saving. */
+ string extension = OIIO::Filesystem::extension(filepath);
+ string unique_name = ".merge-tmp-" + OIIO::Filesystem::unique_path();
+ string tmp_filepath = filepath + unique_name + extension;
+ unique_ptr<ImageOutput> out(ImageOutput::create(tmp_filepath));
+
+ if (!out) {
+ error = "Failed to open temporary file " + tmp_filepath + " for writing";
+ return false;
+ }
+
+ /* Open temporary file and write image buffers. */
+ if (!out->open(tmp_filepath, spec)) {
+ error = "Failed to open file " + tmp_filepath + " for writing: " + out->geterror();
+ return false;
+ }
+
+ bool ok = true;
+ if (!out->write_image(TypeDesc::FLOAT, pixels.data())) {
+ error = "Failed to write to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ if (!out->close()) {
+ error = "Failed to save to file " + tmp_filepath + ": " + out->geterror();
+ ok = false;
+ }
+
+ out.reset();
+
+ /* Copy temporary file to outputput filepath. */
+ string rename_error;
+ if (ok && !OIIO::Filesystem::rename(tmp_filepath, filepath, rename_error)) {
+ error = "Failed to move merged image to " + filepath + ": " + rename_error;
+ ok = false;
+ }
+
+ if (!ok) {
+ OIIO::Filesystem::remove(tmp_filepath);
+ }
+
+ return ok;
}
/* Image Merger */
@@ -489,38 +479,38 @@ ImageMerger::ImageMerger()
bool ImageMerger::run()
{
- if(input.empty()) {
- error = "No input file paths specified.";
- return false;
- }
- if(output.empty()) {
- error = "No output file path specified.";
- return false;
- }
-
- /* Open images and verify they have matching layout. */
- vector<MergeImage> images;
- if(!open_images(input, images, error)) {
- return false;
- }
-
- /* Merge metadata and setup channels and offsets. */
- ImageSpec out_spec;
- vector<int> channel_total_samples;
- merge_channels_metadata(images, out_spec, channel_total_samples);
-
- /* Merge pixels. */
- array<float> out_pixels;
- if(!merge_pixels(images, out_spec, channel_total_samples, out_pixels, error)) {
- return false;
- }
-
- /* We don't need input anymore at this point, and will possibly
- * overwrite the same file. */
- images.clear();
-
- /* Save output file. */
- return save_output(output, out_spec, out_pixels, error);
+ if (input.empty()) {
+ error = "No input file paths specified.";
+ return false;
+ }
+ if (output.empty()) {
+ error = "No output file path specified.";
+ return false;
+ }
+
+ /* Open images and verify they have matching layout. */
+ vector<MergeImage> images;
+ if (!open_images(input, images, error)) {
+ return false;
+ }
+
+ /* Merge metadata and setup channels and offsets. */
+ ImageSpec out_spec;
+ vector<int> channel_total_samples;
+ merge_channels_metadata(images, out_spec, channel_total_samples);
+
+ /* Merge pixels. */
+ array<float> out_pixels;
+ if (!merge_pixels(images, out_spec, channel_total_samples, out_pixels, error)) {
+ return false;
+ }
+
+ /* We don't need input anymore at this point, and will possibly
+ * overwrite the same file. */
+ images.clear();
+
+ /* Save output file. */
+ return save_output(output, out_spec, out_pixels, error);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/merge.h b/intern/cycles/render/merge.h
index 48900a13c27..87e5d2d4723 100644
--- a/intern/cycles/render/merge.h
+++ b/intern/cycles/render/merge.h
@@ -25,17 +25,17 @@ CCL_NAMESPACE_BEGIN
/* Merge OpenEXR multilayer renders. */
class ImageMerger {
-public:
- ImageMerger();
- bool run();
+ public:
+ ImageMerger();
+ bool run();
- /* Error message after running, in case of failure. */
- string error;
+ /* Error message after running, in case of failure. */
+ string error;
- /* List of image filepaths to merge. */
- vector<string> input;
- /* Output filepath. */
- string output;
+ /* List of image filepaths to merge. */
+ vector<string> input;
+ /* Output filepath. */
+ string output;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index eadbe3eda89..54dacf5d1f4 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -47,11 +47,11 @@ CCL_NAMESPACE_BEGIN
/* Triangle */
-void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox& bounds) const
+void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox &bounds) const
{
- bounds.grow(verts[v[0]]);
- bounds.grow(verts[v[1]]);
- bounds.grow(verts[v[2]]);
+ bounds.grow(verts[v[0]]);
+ bounds.grow(verts[v[1]]);
+ bounds.grow(verts[v[2]]);
}
void Mesh::Triangle::motion_verts(const float3 *verts,
@@ -61,29 +61,19 @@ void Mesh::Triangle::motion_verts(const float3 *verts,
float time,
float3 r_verts[3]) const
{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time*max_step - step;
- /* Fetch vertex coordinates. */
- float3 curr_verts[3];
- float3 next_verts[3];
- verts_for_step(verts,
- vert_steps,
- num_verts,
- num_steps,
- step,
- curr_verts);
- verts_for_step(verts,
- vert_steps,
- num_verts,
- num_steps,
- step + 1,
- next_verts);
- /* Interpolate between steps. */
- r_verts[0] = (1.0f - t)*curr_verts[0] + t*next_verts[0];
- r_verts[1] = (1.0f - t)*curr_verts[1] + t*next_verts[1];
- r_verts[2] = (1.0f - t)*curr_verts[2] + t*next_verts[2];
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float3 curr_verts[3];
+ float3 next_verts[3];
+ verts_for_step(verts, vert_steps, num_verts, num_steps, step, curr_verts);
+ verts_for_step(verts, vert_steps, num_verts, num_steps, step + 1, next_verts);
+ /* Interpolate between steps. */
+ r_verts[0] = (1.0f - t) * curr_verts[0] + t * next_verts[0];
+ r_verts[1] = (1.0f - t) * curr_verts[1] + t * next_verts[1];
+ r_verts[2] = (1.0f - t) * curr_verts[2] + t * next_verts[2];
}
void Mesh::Triangle::verts_for_step(const float3 *verts,
@@ -93,120 +83,121 @@ void Mesh::Triangle::verts_for_step(const float3 *verts,
size_t step,
float3 r_verts[3]) const
{
- const size_t center_step = ((num_steps - 1) / 2);
- if(step == center_step) {
- /* Center step: regular vertex location. */
- r_verts[0] = verts[v[0]];
- r_verts[1] = verts[v[1]];
- r_verts[2] = verts[v[2]];
- }
- else {
- /* Center step not stored in the attribute array array. */
- if(step > center_step) {
- step--;
- }
- size_t offset = step * num_verts;
- r_verts[0] = vert_steps[offset + v[0]];
- r_verts[1] = vert_steps[offset + v[1]];
- r_verts[2] = vert_steps[offset + v[2]];
- }
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular vertex location. */
+ r_verts[0] = verts[v[0]];
+ r_verts[1] = verts[v[1]];
+ r_verts[2] = verts[v[2]];
+ }
+ else {
+ /* Center step not stored in the attribute array array. */
+ if (step > center_step) {
+ step--;
+ }
+ size_t offset = step * num_verts;
+ r_verts[0] = vert_steps[offset + v[0]];
+ r_verts[1] = vert_steps[offset + v[1]];
+ r_verts[2] = vert_steps[offset + v[2]];
+ }
}
float3 Mesh::Triangle::compute_normal(const float3 *verts) const
{
- const float3& v0 = verts[v[0]];
- const float3& v1 = verts[v[1]];
- const float3& v2 = verts[v[2]];
- const float3 norm = cross(v1 - v0, v2 - v0);
- const float normlen = len(norm);
- if(normlen == 0.0f) {
- return make_float3(1.0f, 0.0f, 0.0f);
- }
- return norm / normlen;
+ const float3 &v0 = verts[v[0]];
+ const float3 &v1 = verts[v[1]];
+ const float3 &v2 = verts[v[2]];
+ const float3 norm = cross(v1 - v0, v2 - v0);
+ const float normlen = len(norm);
+ if (normlen == 0.0f) {
+ return make_float3(1.0f, 0.0f, 0.0f);
+ }
+ return norm / normlen;
}
bool Mesh::Triangle::valid(const float3 *verts) const
{
- return isfinite3_safe(verts[v[0]]) &&
- isfinite3_safe(verts[v[1]]) &&
- isfinite3_safe(verts[v[2]]);
+ return isfinite3_safe(verts[v[0]]) && isfinite3_safe(verts[v[1]]) && isfinite3_safe(verts[v[2]]);
}
/* Curve */
-void Mesh::Curve::bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox& bounds) const
+void Mesh::Curve::bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox &bounds) const
{
- float3 P[4];
+ float3 P[4];
- P[0] = curve_keys[max(first_key + k - 1,first_key)];
- P[1] = curve_keys[first_key + k];
- P[2] = curve_keys[first_key + k + 1];
- P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
+ P[0] = curve_keys[max(first_key + k - 1, first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
- float3 lower;
- float3 upper;
+ float3 lower;
+ float3 upper;
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
}
void Mesh::Curve::bounds_grow(const int k,
const float3 *curve_keys,
const float *curve_radius,
- const Transform& aligned_space,
- BoundBox& bounds) const
+ const Transform &aligned_space,
+ BoundBox &bounds) const
{
- float3 P[4];
+ float3 P[4];
- P[0] = curve_keys[max(first_key + k - 1,first_key)];
- P[1] = curve_keys[first_key + k];
- P[2] = curve_keys[first_key + k + 1];
- P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
+ P[0] = curve_keys[max(first_key + k - 1, first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
- P[0] = transform_point(&aligned_space, P[0]);
- P[1] = transform_point(&aligned_space, P[1]);
- P[2] = transform_point(&aligned_space, P[2]);
- P[3] = transform_point(&aligned_space, P[3]);
+ P[0] = transform_point(&aligned_space, P[0]);
+ P[1] = transform_point(&aligned_space, P[1]);
+ P[2] = transform_point(&aligned_space, P[2]);
+ P[3] = transform_point(&aligned_space, P[3]);
- float3 lower;
- float3 upper;
+ float3 lower;
+ float3 upper;
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
}
-void Mesh::Curve::bounds_grow(float4 keys[4], BoundBox& bounds) const
+void Mesh::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const
{
- float3 P[4] = {
- float4_to_float3(keys[0]),
- float4_to_float3(keys[1]),
- float4_to_float3(keys[2]),
- float4_to_float3(keys[3]),
- };
+ float3 P[4] = {
+ float4_to_float3(keys[0]),
+ float4_to_float3(keys[1]),
+ float4_to_float3(keys[2]),
+ float4_to_float3(keys[3]),
+ };
- float3 lower;
- float3 upper;
+ float3 lower;
+ float3 upper;
- curvebounds(&lower.x, &upper.x, P, 0);
- curvebounds(&lower.y, &upper.y, P, 1);
- curvebounds(&lower.z, &upper.z, P, 2);
+ curvebounds(&lower.x, &upper.x, P, 0);
+ curvebounds(&lower.y, &upper.y, P, 1);
+ curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(keys[1].w, keys[2].w);
+ float mr = max(keys[1].w, keys[2].w);
- bounds.grow(lower, mr);
- bounds.grow(upper, mr);
+ bounds.grow(lower, mr);
+ bounds.grow(upper, mr);
}
void Mesh::Curve::motion_keys(const float3 *curve_keys,
@@ -215,35 +206,24 @@ void Mesh::Curve::motion_keys(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
float time,
- size_t k0, size_t k1,
+ size_t k0,
+ size_t k1,
float4 r_keys[2]) const
{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time*max_step - step;
- /* Fetch vertex coordinates. */
- float4 curr_keys[2];
- float4 next_keys[2];
- keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step,
- k0, k1,
- curr_keys);
- keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step + 1,
- k0, k1,
- next_keys);
- /* Interpolate between steps. */
- r_keys[0] = (1.0f - t)*curr_keys[0] + t*next_keys[0];
- r_keys[1] = (1.0f - t)*curr_keys[1] + t*next_keys[1];
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float4 curr_keys[2];
+ float4 next_keys[2];
+ keys_for_step(
+ curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys);
+ keys_for_step(
+ curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys);
+ /* Interpolate between steps. */
+ r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
+ r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
}
void Mesh::Curve::cardinal_motion_keys(const float3 *curve_keys,
@@ -252,38 +232,46 @@ void Mesh::Curve::cardinal_motion_keys(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
float time,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
float4 r_keys[4]) const
{
- /* Figure out which steps we need to fetch and their interpolation factor. */
- const size_t max_step = num_steps - 1;
- const size_t step = min((int)(time * max_step), max_step - 1);
- const float t = time*max_step - step;
- /* Fetch vertex coordinates. */
- float4 curr_keys[4];
- float4 next_keys[4];
- cardinal_keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step,
- k0, k1, k2, k3,
- curr_keys);
- cardinal_keys_for_step(curve_keys,
- curve_radius,
- key_steps,
- num_curve_keys,
- num_steps,
- step + 1,
- k0, k1, k2, k3,
- next_keys);
- /* Interpolate between steps. */
- r_keys[0] = (1.0f - t)*curr_keys[0] + t*next_keys[0];
- r_keys[1] = (1.0f - t)*curr_keys[1] + t*next_keys[1];
- r_keys[2] = (1.0f - t)*curr_keys[2] + t*next_keys[2];
- r_keys[3] = (1.0f - t)*curr_keys[3] + t*next_keys[3];
+ /* Figure out which steps we need to fetch and their interpolation factor. */
+ const size_t max_step = num_steps - 1;
+ const size_t step = min((int)(time * max_step), max_step - 1);
+ const float t = time * max_step - step;
+ /* Fetch vertex coordinates. */
+ float4 curr_keys[4];
+ float4 next_keys[4];
+ cardinal_keys_for_step(curve_keys,
+ curve_radius,
+ key_steps,
+ num_curve_keys,
+ num_steps,
+ step,
+ k0,
+ k1,
+ k2,
+ k3,
+ curr_keys);
+ cardinal_keys_for_step(curve_keys,
+ curve_radius,
+ key_steps,
+ num_curve_keys,
+ num_steps,
+ step + 1,
+ k0,
+ k1,
+ k2,
+ k3,
+ next_keys);
+ /* Interpolate between steps. */
+ r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
+ r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
+ r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2];
+ r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3];
}
void Mesh::Curve::keys_for_step(const float3 *curve_keys,
@@ -292,41 +280,42 @@ void Mesh::Curve::keys_for_step(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
size_t step,
- size_t k0, size_t k1,
+ size_t k0,
+ size_t k1,
float4 r_keys[2]) const
{
- k0 = max(k0, 0);
- k1 = min(k1, num_keys - 1);
- const size_t center_step = ((num_steps - 1) / 2);
- if(step == center_step) {
- /* Center step: regular key location. */
- /* TODO(sergey): Consider adding make_float4(float3, float)
- * function.
- */
- r_keys[0] = make_float4(curve_keys[first_key + k0].x,
- curve_keys[first_key + k0].y,
- curve_keys[first_key + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(curve_keys[first_key + k1].x,
- curve_keys[first_key + k1].y,
- curve_keys[first_key + k1].z,
- curve_radius[first_key + k1]);
- }
- else {
- /* Center step is not stored in this array. */
- if(step > center_step) {
- step--;
- }
- const size_t offset = first_key + step * num_curve_keys;
- r_keys[0] = make_float4(key_steps[offset + k0].x,
- key_steps[offset + k0].y,
- key_steps[offset + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(key_steps[offset + k1].x,
- key_steps[offset + k1].y,
- key_steps[offset + k1].z,
- curve_radius[first_key + k1]);
- }
+ k0 = max(k0, 0);
+ k1 = min(k1, num_keys - 1);
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular key location. */
+ /* TODO(sergey): Consider adding make_float4(float3, float)
+ * function.
+ */
+ r_keys[0] = make_float4(curve_keys[first_key + k0].x,
+ curve_keys[first_key + k0].y,
+ curve_keys[first_key + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(curve_keys[first_key + k1].x,
+ curve_keys[first_key + k1].y,
+ curve_keys[first_key + k1].z,
+ curve_radius[first_key + k1]);
+ }
+ else {
+ /* Center step is not stored in this array. */
+ if (step > center_step) {
+ step--;
+ }
+ const size_t offset = first_key + step * num_curve_keys;
+ r_keys[0] = make_float4(key_steps[offset + k0].x,
+ key_steps[offset + k0].y,
+ key_steps[offset + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(key_steps[offset + k1].x,
+ key_steps[offset + k1].y,
+ key_steps[offset + k1].z,
+ curve_radius[first_key + k1]);
+ }
}
void Mesh::Curve::cardinal_keys_for_step(const float3 *curve_keys,
@@ -335,2033 +324,2044 @@ void Mesh::Curve::cardinal_keys_for_step(const float3 *curve_keys,
size_t num_curve_keys,
size_t num_steps,
size_t step,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
float4 r_keys[4]) const
{
- k0 = max(k0, 0);
- k3 = min(k3, num_keys - 1);
- const size_t center_step = ((num_steps - 1) / 2);
- if(step == center_step) {
- /* Center step: regular key location. */
- r_keys[0] = make_float4(curve_keys[first_key + k0].x,
- curve_keys[first_key + k0].y,
- curve_keys[first_key + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(curve_keys[first_key + k1].x,
- curve_keys[first_key + k1].y,
- curve_keys[first_key + k1].z,
- curve_radius[first_key + k1]);
- r_keys[2] = make_float4(curve_keys[first_key + k2].x,
- curve_keys[first_key + k2].y,
- curve_keys[first_key + k2].z,
- curve_radius[first_key + k2]);
- r_keys[3] = make_float4(curve_keys[first_key + k3].x,
- curve_keys[first_key + k3].y,
- curve_keys[first_key + k3].z,
- curve_radius[first_key + k3]);
- }
- else {
- /* Center step is not stored in this array. */
- if(step > center_step) {
- step--;
- }
- const size_t offset = first_key + step * num_curve_keys;
- r_keys[0] = make_float4(key_steps[offset + k0].x,
- key_steps[offset + k0].y,
- key_steps[offset + k0].z,
- curve_radius[first_key + k0]);
- r_keys[1] = make_float4(key_steps[offset + k1].x,
- key_steps[offset + k1].y,
- key_steps[offset + k1].z,
- curve_radius[first_key + k1]);
- r_keys[2] = make_float4(key_steps[offset + k2].x,
- key_steps[offset + k2].y,
- key_steps[offset + k2].z,
- curve_radius[first_key + k2]);
- r_keys[3] = make_float4(key_steps[offset + k3].x,
- key_steps[offset + k3].y,
- key_steps[offset + k3].z,
- curve_radius[first_key + k3]);
- }
+ k0 = max(k0, 0);
+ k3 = min(k3, num_keys - 1);
+ const size_t center_step = ((num_steps - 1) / 2);
+ if (step == center_step) {
+ /* Center step: regular key location. */
+ r_keys[0] = make_float4(curve_keys[first_key + k0].x,
+ curve_keys[first_key + k0].y,
+ curve_keys[first_key + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(curve_keys[first_key + k1].x,
+ curve_keys[first_key + k1].y,
+ curve_keys[first_key + k1].z,
+ curve_radius[first_key + k1]);
+ r_keys[2] = make_float4(curve_keys[first_key + k2].x,
+ curve_keys[first_key + k2].y,
+ curve_keys[first_key + k2].z,
+ curve_radius[first_key + k2]);
+ r_keys[3] = make_float4(curve_keys[first_key + k3].x,
+ curve_keys[first_key + k3].y,
+ curve_keys[first_key + k3].z,
+ curve_radius[first_key + k3]);
+ }
+ else {
+ /* Center step is not stored in this array. */
+ if (step > center_step) {
+ step--;
+ }
+ const size_t offset = first_key + step * num_curve_keys;
+ r_keys[0] = make_float4(key_steps[offset + k0].x,
+ key_steps[offset + k0].y,
+ key_steps[offset + k0].z,
+ curve_radius[first_key + k0]);
+ r_keys[1] = make_float4(key_steps[offset + k1].x,
+ key_steps[offset + k1].y,
+ key_steps[offset + k1].z,
+ curve_radius[first_key + k1]);
+ r_keys[2] = make_float4(key_steps[offset + k2].x,
+ key_steps[offset + k2].y,
+ key_steps[offset + k2].z,
+ curve_radius[first_key + k2]);
+ r_keys[3] = make_float4(key_steps[offset + k3].x,
+ key_steps[offset + k3].y,
+ key_steps[offset + k3].z,
+ curve_radius[first_key + k3]);
+ }
}
/* SubdFace */
float3 Mesh::SubdFace::normal(const Mesh *mesh) const
{
- float3 v0 = mesh->verts[mesh->subd_face_corners[start_corner+0]];
- float3 v1 = mesh->verts[mesh->subd_face_corners[start_corner+1]];
- float3 v2 = mesh->verts[mesh->subd_face_corners[start_corner+2]];
+ float3 v0 = mesh->verts[mesh->subd_face_corners[start_corner + 0]];
+ float3 v1 = mesh->verts[mesh->subd_face_corners[start_corner + 1]];
+ float3 v2 = mesh->verts[mesh->subd_face_corners[start_corner + 2]];
- return safe_normalize(cross(v1 - v0, v2 - v0));
+ return safe_normalize(cross(v1 - v0, v2 - v0));
}
/* Mesh */
NODE_DEFINE(Mesh)
{
- NodeType* type = NodeType::add("mesh", create);
+ NodeType *type = NodeType::add("mesh", create);
- SOCKET_UINT(motion_steps, "Motion Steps", 3);
- SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
+ SOCKET_UINT(motion_steps, "Motion Steps", 3);
+ SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
- SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
- SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
- SOCKET_INT_ARRAY(shader, "Shader", array<int>());
- SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
+ SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
+ SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
+ SOCKET_INT_ARRAY(shader, "Shader", array<int>());
+ SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
- SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
- SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
- SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
- SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
+ SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
+ SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
+ SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
+ SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
- return type;
+ return type;
}
-Mesh::Mesh()
-: Node(node_type)
+Mesh::Mesh() : Node(node_type)
{
- need_update = true;
- need_update_rebuild = false;
- transform_applied = false;
- transform_negative_scaled = false;
- transform_normal = transform_identity();
- bounds = BoundBox::empty;
+ need_update = true;
+ need_update_rebuild = false;
+ transform_applied = false;
+ transform_negative_scaled = false;
+ transform_normal = transform_identity();
+ bounds = BoundBox::empty;
- bvh = NULL;
+ bvh = NULL;
- tri_offset = 0;
- vert_offset = 0;
+ tri_offset = 0;
+ vert_offset = 0;
- curve_offset = 0;
- curvekey_offset = 0;
+ curve_offset = 0;
+ curvekey_offset = 0;
- patch_offset = 0;
- face_offset = 0;
- corner_offset = 0;
+ patch_offset = 0;
+ face_offset = 0;
+ corner_offset = 0;
- attr_map_offset = 0;
+ attr_map_offset = 0;
- num_subd_verts = 0;
+ num_subd_verts = 0;
- attributes.triangle_mesh = this;
- curve_attributes.curve_mesh = this;
- subd_attributes.subd_mesh = this;
+ attributes.triangle_mesh = this;
+ curve_attributes.curve_mesh = this;
+ subd_attributes.subd_mesh = this;
- geometry_flags = GEOMETRY_NONE;
+ geometry_flags = GEOMETRY_NONE;
- volume_isovalue = 0.001f;
- has_volume = false;
- has_surface_bssrdf = false;
+ volume_isovalue = 0.001f;
+ has_volume = false;
+ has_surface_bssrdf = false;
- num_ngons = 0;
+ num_ngons = 0;
- subdivision_type = SUBDIVISION_NONE;
- subd_params = NULL;
+ subdivision_type = SUBDIVISION_NONE;
+ subd_params = NULL;
- patch_table = NULL;
+ patch_table = NULL;
}
Mesh::~Mesh()
{
- delete bvh;
- delete patch_table;
- delete subd_params;
+ delete bvh;
+ delete patch_table;
+ delete subd_params;
}
void Mesh::resize_mesh(int numverts, int numtris)
{
- verts.resize(numverts);
- triangles.resize(numtris * 3);
- shader.resize(numtris);
- smooth.resize(numtris);
+ verts.resize(numverts);
+ triangles.resize(numtris * 3);
+ shader.resize(numtris);
+ smooth.resize(numtris);
- if(subd_faces.size()) {
- triangle_patch.resize(numtris);
- vert_patch_uv.resize(numverts);
- }
+ if (subd_faces.size()) {
+ triangle_patch.resize(numtris);
+ vert_patch_uv.resize(numverts);
+ }
- attributes.resize();
+ attributes.resize();
}
void Mesh::reserve_mesh(int numverts, int numtris)
{
- /* reserve space to add verts and triangles later */
- verts.reserve(numverts);
- triangles.reserve(numtris * 3);
- shader.reserve(numtris);
- smooth.reserve(numtris);
+ /* reserve space to add verts and triangles later */
+ verts.reserve(numverts);
+ triangles.reserve(numtris * 3);
+ shader.reserve(numtris);
+ smooth.reserve(numtris);
- if(subd_faces.size()) {
- triangle_patch.reserve(numtris);
- vert_patch_uv.reserve(numverts);
- }
+ if (subd_faces.size()) {
+ triangle_patch.reserve(numtris);
+ vert_patch_uv.reserve(numverts);
+ }
- attributes.resize(true);
+ attributes.resize(true);
}
void Mesh::resize_curves(int numcurves, int numkeys)
{
- curve_keys.resize(numkeys);
- curve_radius.resize(numkeys);
- curve_first_key.resize(numcurves);
- curve_shader.resize(numcurves);
+ curve_keys.resize(numkeys);
+ curve_radius.resize(numkeys);
+ curve_first_key.resize(numcurves);
+ curve_shader.resize(numcurves);
- curve_attributes.resize();
+ curve_attributes.resize();
}
void Mesh::reserve_curves(int numcurves, int numkeys)
{
- curve_keys.reserve(numkeys);
- curve_radius.reserve(numkeys);
- curve_first_key.reserve(numcurves);
- curve_shader.reserve(numcurves);
+ curve_keys.reserve(numkeys);
+ curve_radius.reserve(numkeys);
+ curve_first_key.reserve(numcurves);
+ curve_shader.reserve(numcurves);
- curve_attributes.resize(true);
+ curve_attributes.resize(true);
}
void Mesh::resize_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
- subd_faces.resize(numfaces);
- subd_face_corners.resize(numcorners);
- num_ngons = num_ngons_;
+ subd_faces.resize(numfaces);
+ subd_face_corners.resize(numcorners);
+ num_ngons = num_ngons_;
- subd_attributes.resize();
+ subd_attributes.resize();
}
void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners)
{
- subd_faces.reserve(numfaces);
- subd_face_corners.reserve(numcorners);
- num_ngons = num_ngons_;
+ subd_faces.reserve(numfaces);
+ subd_face_corners.reserve(numcorners);
+ num_ngons = num_ngons_;
- subd_attributes.resize(true);
+ subd_attributes.resize(true);
}
void Mesh::clear(bool preserve_voxel_data)
{
- /* clear all verts and triangles */
- verts.clear();
- triangles.clear();
- shader.clear();
- smooth.clear();
+ /* clear all verts and triangles */
+ verts.clear();
+ triangles.clear();
+ shader.clear();
+ smooth.clear();
- triangle_patch.clear();
- vert_patch_uv.clear();
+ triangle_patch.clear();
+ vert_patch_uv.clear();
- curve_keys.clear();
- curve_radius.clear();
- curve_first_key.clear();
- curve_shader.clear();
+ curve_keys.clear();
+ curve_radius.clear();
+ curve_first_key.clear();
+ curve_shader.clear();
- subd_faces.clear();
- subd_face_corners.clear();
+ subd_faces.clear();
+ subd_face_corners.clear();
- num_subd_verts = 0;
+ num_subd_verts = 0;
- subd_creases.clear();
+ subd_creases.clear();
- curve_attributes.clear();
- subd_attributes.clear();
- attributes.clear(preserve_voxel_data);
+ curve_attributes.clear();
+ subd_attributes.clear();
+ attributes.clear(preserve_voxel_data);
- used_shaders.clear();
+ used_shaders.clear();
- if(!preserve_voxel_data) {
- geometry_flags = GEOMETRY_NONE;
- }
+ if (!preserve_voxel_data) {
+ geometry_flags = GEOMETRY_NONE;
+ }
- transform_applied = false;
- transform_negative_scaled = false;
- transform_normal = transform_identity();
+ transform_applied = false;
+ transform_negative_scaled = false;
+ transform_normal = transform_identity();
- delete patch_table;
- patch_table = NULL;
+ delete patch_table;
+ patch_table = NULL;
}
void Mesh::add_vertex(float3 P)
{
- verts.push_back_reserved(P);
+ verts.push_back_reserved(P);
- if(subd_faces.size()) {
- vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f));
- }
+ if (subd_faces.size()) {
+ vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f));
+ }
}
void Mesh::add_vertex_slow(float3 P)
{
- verts.push_back_slow(P);
+ verts.push_back_slow(P);
- if(subd_faces.size()) {
- vert_patch_uv.push_back_slow(make_float2(0.0f, 0.0f));
- }
+ if (subd_faces.size()) {
+ vert_patch_uv.push_back_slow(make_float2(0.0f, 0.0f));
+ }
}
void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
{
- triangles.push_back_reserved(v0);
- triangles.push_back_reserved(v1);
- triangles.push_back_reserved(v2);
- shader.push_back_reserved(shader_);
- smooth.push_back_reserved(smooth_);
+ triangles.push_back_reserved(v0);
+ triangles.push_back_reserved(v1);
+ triangles.push_back_reserved(v2);
+ shader.push_back_reserved(shader_);
+ smooth.push_back_reserved(smooth_);
- if(subd_faces.size()) {
- triangle_patch.push_back_reserved(-1);
- }
+ if (subd_faces.size()) {
+ triangle_patch.push_back_reserved(-1);
+ }
}
void Mesh::add_curve_key(float3 co, float radius)
{
- curve_keys.push_back_reserved(co);
- curve_radius.push_back_reserved(radius);
+ curve_keys.push_back_reserved(co);
+ curve_radius.push_back_reserved(radius);
}
void Mesh::add_curve(int first_key, int shader)
{
- curve_first_key.push_back_reserved(first_key);
- curve_shader.push_back_reserved(shader);
+ curve_first_key.push_back_reserved(first_key);
+ curve_shader.push_back_reserved(shader);
}
-void Mesh::add_subd_face(int* corners, int num_corners, int shader_, bool smooth_)
+void Mesh::add_subd_face(int *corners, int num_corners, int shader_, bool smooth_)
{
- int start_corner = subd_face_corners.size();
+ int start_corner = subd_face_corners.size();
- for(int i = 0; i < num_corners; i++) {
- subd_face_corners.push_back_reserved(corners[i]);
- }
+ for (int i = 0; i < num_corners; i++) {
+ subd_face_corners.push_back_reserved(corners[i]);
+ }
- int ptex_offset = 0;
+ int ptex_offset = 0;
- if(subd_faces.size()) {
- SubdFace& s = subd_faces[subd_faces.size()-1];
- ptex_offset = s.ptex_offset + s.num_ptex_faces();
- }
+ if (subd_faces.size()) {
+ SubdFace &s = subd_faces[subd_faces.size() - 1];
+ ptex_offset = s.ptex_offset + s.num_ptex_faces();
+ }
- SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset};
- subd_faces.push_back_reserved(face);
+ SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset};
+ subd_faces.push_back_reserved(face);
}
void Mesh::compute_bounds()
{
- BoundBox bnds = BoundBox::empty;
- size_t verts_size = verts.size();
- size_t curve_keys_size = curve_keys.size();
+ BoundBox bnds = BoundBox::empty;
+ size_t verts_size = verts.size();
+ size_t curve_keys_size = curve_keys.size();
- if(verts_size + curve_keys_size > 0) {
- for(size_t i = 0; i < verts_size; i++)
- bnds.grow(verts[i]);
+ if (verts_size + curve_keys_size > 0) {
+ for (size_t i = 0; i < verts_size; i++)
+ bnds.grow(verts[i]);
- for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow(curve_keys[i], curve_radius[i]);
+ for (size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow(curve_keys[i], curve_radius[i]);
- Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(use_motion_blur && attr) {
- size_t steps_size = verts.size() * (motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
+ Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (use_motion_blur && attr) {
+ size_t steps_size = verts.size() * (motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow(vert_steps[i]);
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow(vert_steps[i]);
+ }
- Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- if(use_motion_blur && curve_attr) {
- size_t steps_size = curve_keys.size() * (motion_steps - 1);
- float3 *key_steps = curve_attr->data_float3();
+ Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if (use_motion_blur && curve_attr) {
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float3 *key_steps = curve_attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow(key_steps[i]);
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow(key_steps[i]);
+ }
- if(!bnds.valid()) {
- bnds = BoundBox::empty;
+ if (!bnds.valid()) {
+ bnds = BoundBox::empty;
- /* skip nan or inf coordinates */
- for(size_t i = 0; i < verts_size; i++)
- bnds.grow_safe(verts[i]);
+ /* skip nan or inf coordinates */
+ for (size_t i = 0; i < verts_size; i++)
+ bnds.grow_safe(verts[i]);
- for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow_safe(curve_keys[i], curve_radius[i]);
+ for (size_t i = 0; i < curve_keys_size; i++)
+ bnds.grow_safe(curve_keys[i], curve_radius[i]);
- if(use_motion_blur && attr) {
- size_t steps_size = verts.size() * (motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
+ if (use_motion_blur && attr) {
+ size_t steps_size = verts.size() * (motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow_safe(vert_steps[i]);
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow_safe(vert_steps[i]);
+ }
- if(use_motion_blur && curve_attr) {
- size_t steps_size = curve_keys.size() * (motion_steps - 1);
- float3 *key_steps = curve_attr->data_float3();
+ if (use_motion_blur && curve_attr) {
+ size_t steps_size = curve_keys.size() * (motion_steps - 1);
+ float3 *key_steps = curve_attr->data_float3();
- for(size_t i = 0; i < steps_size; i++)
- bnds.grow_safe(key_steps[i]);
- }
- }
- }
+ for (size_t i = 0; i < steps_size; i++)
+ bnds.grow_safe(key_steps[i]);
+ }
+ }
+ }
- if(!bnds.valid()) {
- /* empty mesh */
- bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
- }
+ if (!bnds.valid()) {
+ /* empty mesh */
+ bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
+ }
- bounds = bnds;
+ bounds = bnds;
}
void Mesh::add_face_normals()
{
- /* don't compute if already there */
- if(attributes.find(ATTR_STD_FACE_NORMAL))
- return;
+ /* don't compute if already there */
+ if (attributes.find(ATTR_STD_FACE_NORMAL))
+ return;
- /* get attributes */
- Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
- float3 *fN = attr_fN->data_float3();
+ /* get attributes */
+ Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
+ float3 *fN = attr_fN->data_float3();
- /* compute face normals */
- size_t triangles_size = num_triangles();
+ /* compute face normals */
+ size_t triangles_size = num_triangles();
- if(triangles_size) {
- float3 *verts_ptr = verts.data();
+ if (triangles_size) {
+ float3 *verts_ptr = verts.data();
- for(size_t i = 0; i < triangles_size; i++) {
- fN[i] = get_triangle(i).compute_normal(verts_ptr);
- }
- }
+ for (size_t i = 0; i < triangles_size; i++) {
+ fN[i] = get_triangle(i).compute_normal(verts_ptr);
+ }
+ }
- /* expected to be in local space */
- if(transform_applied) {
- Transform ntfm = transform_inverse(transform_normal);
+ /* expected to be in local space */
+ if (transform_applied) {
+ Transform ntfm = transform_inverse(transform_normal);
- for(size_t i = 0; i < triangles_size; i++)
- fN[i] = normalize(transform_direction(&ntfm, fN[i]));
- }
+ for (size_t i = 0; i < triangles_size; i++)
+ fN[i] = normalize(transform_direction(&ntfm, fN[i]));
+ }
}
void Mesh::add_vertex_normals()
{
- bool flip = transform_negative_scaled;
- size_t verts_size = verts.size();
- size_t triangles_size = num_triangles();
-
- /* static vertex normals */
- if(!attributes.find(ATTR_STD_VERTEX_NORMAL) && triangles_size) {
- /* get attributes */
- Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
- Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL);
-
- float3 *fN = attr_fN->data_float3();
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
- memset(vN, 0, verts.size()*sizeof(float3));
-
- for(size_t i = 0; i < triangles_size; i++) {
- for(size_t j = 0; j < 3; j++) {
- vN[get_triangle(i).v[j]] += fN[i];
- }
- }
-
- for(size_t i = 0; i < verts_size; i++) {
- vN[i] = normalize(vN[i]);
- if(flip) {
- vN[i] = -vN[i];
- }
- }
- }
-
- /* motion vertex normals */
- Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(has_motion_blur() && attr_mP && !attr_mN && triangles_size) {
- /* create attribute */
- attr_mN = attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- for(int step = 0; step < motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*verts.size();
- float3 *mN = attr_mN->data_float3() + step*verts.size();
-
- /* compute */
- memset(mN, 0, verts.size()*sizeof(float3));
-
- for(size_t i = 0; i < triangles_size; i++) {
- for(size_t j = 0; j < 3; j++) {
- float3 fN = get_triangle(i).compute_normal(mP);
- mN[get_triangle(i).v[j]] += fN;
- }
- }
-
- for(size_t i = 0; i < verts_size; i++) {
- mN[i] = normalize(mN[i]);
- if(flip) {
- mN[i] = -mN[i];
- }
- }
- }
- }
-
- /* subd vertex normals */
- if(!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) {
- /* get attributes */
- Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL);
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
- memset(vN, 0, verts.size()*sizeof(float3));
-
- for(size_t i = 0; i < subd_faces.size(); i++) {
- SubdFace& face = subd_faces[i];
- float3 fN = face.normal(this);
-
- for(size_t j = 0; j < face.num_corners; j++) {
- size_t corner = subd_face_corners[face.start_corner+j];
- vN[corner] += fN;
- }
- }
-
- for(size_t i = 0; i < verts_size; i++) {
- vN[i] = normalize(vN[i]);
- if(flip) {
- vN[i] = -vN[i];
- }
- }
- }
+ bool flip = transform_negative_scaled;
+ size_t verts_size = verts.size();
+ size_t triangles_size = num_triangles();
+
+ /* static vertex normals */
+ if (!attributes.find(ATTR_STD_VERTEX_NORMAL) && triangles_size) {
+ /* get attributes */
+ Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
+ Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL);
+
+ float3 *fN = attr_fN->data_float3();
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+ memset(vN, 0, verts.size() * sizeof(float3));
+
+ for (size_t i = 0; i < triangles_size; i++) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[get_triangle(i).v[j]] += fN[i];
+ }
+ }
+
+ for (size_t i = 0; i < verts_size; i++) {
+ vN[i] = normalize(vN[i]);
+ if (flip) {
+ vN[i] = -vN[i];
+ }
+ }
+ }
+
+ /* motion vertex normals */
+ Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mN = attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (has_motion_blur() && attr_mP && !attr_mN && triangles_size) {
+ /* create attribute */
+ attr_mN = attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ for (int step = 0; step < motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * verts.size();
+ float3 *mN = attr_mN->data_float3() + step * verts.size();
+
+ /* compute */
+ memset(mN, 0, verts.size() * sizeof(float3));
+
+ for (size_t i = 0; i < triangles_size; i++) {
+ for (size_t j = 0; j < 3; j++) {
+ float3 fN = get_triangle(i).compute_normal(mP);
+ mN[get_triangle(i).v[j]] += fN;
+ }
+ }
+
+ for (size_t i = 0; i < verts_size; i++) {
+ mN[i] = normalize(mN[i]);
+ if (flip) {
+ mN[i] = -mN[i];
+ }
+ }
+ }
+ }
+
+ /* subd vertex normals */
+ if (!subd_attributes.find(ATTR_STD_VERTEX_NORMAL) && subd_faces.size()) {
+ /* get attributes */
+ Attribute *attr_vN = subd_attributes.add(ATTR_STD_VERTEX_NORMAL);
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+ memset(vN, 0, verts.size() * sizeof(float3));
+
+ for (size_t i = 0; i < subd_faces.size(); i++) {
+ SubdFace &face = subd_faces[i];
+ float3 fN = face.normal(this);
+
+ for (size_t j = 0; j < face.num_corners; j++) {
+ size_t corner = subd_face_corners[face.start_corner + j];
+ vN[corner] += fN;
+ }
+ }
+
+ for (size_t i = 0; i < verts_size; i++) {
+ vN[i] = normalize(vN[i]);
+ if (flip) {
+ vN[i] = -vN[i];
+ }
+ }
+ }
}
void Mesh::add_undisplaced()
{
- AttributeSet& attrs = (subdivision_type == SUBDIVISION_NONE) ? attributes : subd_attributes;
+ AttributeSet &attrs = (subdivision_type == SUBDIVISION_NONE) ? attributes : subd_attributes;
- /* don't compute if already there */
- if(attrs.find(ATTR_STD_POSITION_UNDISPLACED)) {
- return;
- }
+ /* don't compute if already there */
+ if (attrs.find(ATTR_STD_POSITION_UNDISPLACED)) {
+ return;
+ }
- /* get attribute */
- Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED);
- attr->flags |= ATTR_SUBDIVIDED;
+ /* get attribute */
+ Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED);
+ attr->flags |= ATTR_SUBDIVIDED;
- float3 *data = attr->data_float3();
+ float3 *data = attr->data_float3();
- /* copy verts */
- size_t size = attr->buffer_size(this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD);
+ /* copy verts */
+ size_t size = attr->buffer_size(
+ this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD);
- /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will be
- * calculated later, we subtract them from size here so we don't have an overflow while copying.
- */
- size -= num_ngons * attr->data_sizeof();
+ /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will be
+ * calculated later, we subtract them from size here so we don't have an overflow while copying.
+ */
+ size -= num_ngons * attr->data_sizeof();
- if(size) {
- memcpy(data, verts.data(), size);
- }
+ if (size) {
+ memcpy(data, verts.data(), size);
+ }
}
void Mesh::pack_shaders(Scene *scene, uint *tri_shader)
{
- uint shader_id = 0;
- uint last_shader = -1;
- bool last_smooth = false;
+ uint shader_id = 0;
+ uint last_shader = -1;
+ bool last_smooth = false;
- size_t triangles_size = num_triangles();
- int *shader_ptr = shader.data();
+ size_t triangles_size = num_triangles();
+ int *shader_ptr = shader.data();
- for(size_t i = 0; i < triangles_size; i++) {
- if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
- last_shader = shader_ptr[i];
- last_smooth = smooth[i];
- Shader *shader = (last_shader < used_shaders.size()) ?
- used_shaders[last_shader] : scene->default_surface;
- shader_id = scene->shader_manager->get_shader_id(shader, last_smooth);
- }
+ for (size_t i = 0; i < triangles_size; i++) {
+ if (shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
+ last_shader = shader_ptr[i];
+ last_smooth = smooth[i];
+ Shader *shader = (last_shader < used_shaders.size()) ? used_shaders[last_shader] :
+ scene->default_surface;
+ shader_id = scene->shader_manager->get_shader_id(shader, last_smooth);
+ }
- tri_shader[i] = shader_id;
- }
+ tri_shader[i] = shader_id;
+ }
}
void Mesh::pack_normals(float4 *vnormal)
{
- Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
- if(attr_vN == NULL) {
- /* Happens on objects with just hair. */
- return;
- }
+ Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
+ if (attr_vN == NULL) {
+ /* Happens on objects with just hair. */
+ return;
+ }
- bool do_transform = transform_applied;
- Transform ntfm = transform_normal;
+ bool do_transform = transform_applied;
+ Transform ntfm = transform_normal;
- float3 *vN = attr_vN->data_float3();
- size_t verts_size = verts.size();
+ float3 *vN = attr_vN->data_float3();
+ size_t verts_size = verts.size();
- for(size_t i = 0; i < verts_size; i++) {
- float3 vNi = vN[i];
+ for (size_t i = 0; i < verts_size; i++) {
+ float3 vNi = vN[i];
- if(do_transform)
- vNi = safe_normalize(transform_direction(&ntfm, vNi));
+ if (do_transform)
+ vNi = safe_normalize(transform_direction(&ntfm, vNi));
- vnormal[i] = make_float4(vNi.x, vNi.y, vNi.z, 0.0f);
- }
+ vnormal[i] = make_float4(vNi.x, vNi.y, vNi.z, 0.0f);
+ }
}
-void Mesh::pack_verts(const vector<uint>& tri_prim_index,
+void Mesh::pack_verts(const vector<uint> &tri_prim_index,
uint4 *tri_vindex,
uint *tri_patch,
float2 *tri_patch_uv,
size_t vert_offset,
size_t tri_offset)
{
- size_t verts_size = verts.size();
+ size_t verts_size = verts.size();
- if(verts_size && subd_faces.size()) {
- float2 *vert_patch_uv_ptr = vert_patch_uv.data();
+ if (verts_size && subd_faces.size()) {
+ float2 *vert_patch_uv_ptr = vert_patch_uv.data();
- for(size_t i = 0; i < verts_size; i++) {
- tri_patch_uv[i] = vert_patch_uv_ptr[i];
- }
- }
+ for (size_t i = 0; i < verts_size; i++) {
+ tri_patch_uv[i] = vert_patch_uv_ptr[i];
+ }
+ }
- size_t triangles_size = num_triangles();
+ size_t triangles_size = num_triangles();
- for(size_t i = 0; i < triangles_size; i++) {
- Triangle t = get_triangle(i);
- tri_vindex[i] = make_uint4(t.v[0] + vert_offset,
- t.v[1] + vert_offset,
- t.v[2] + vert_offset,
- tri_prim_index[i + tri_offset]);
+ for (size_t i = 0; i < triangles_size; i++) {
+ Triangle t = get_triangle(i);
+ tri_vindex[i] = make_uint4(t.v[0] + vert_offset,
+ t.v[1] + vert_offset,
+ t.v[2] + vert_offset,
+ tri_prim_index[i + tri_offset]);
- tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i]*8 + patch_offset);
- }
+ tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i] * 8 + patch_offset);
+ }
}
-void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset)
+void Mesh::pack_curves(Scene *scene,
+ float4 *curve_key_co,
+ float4 *curve_data,
+ size_t curvekey_offset)
{
- size_t curve_keys_size = curve_keys.size();
+ size_t curve_keys_size = curve_keys.size();
- /* pack curve keys */
- if(curve_keys_size) {
- float3 *keys_ptr = curve_keys.data();
- float *radius_ptr = curve_radius.data();
+ /* pack curve keys */
+ if (curve_keys_size) {
+ float3 *keys_ptr = curve_keys.data();
+ float *radius_ptr = curve_radius.data();
- for(size_t i = 0; i < curve_keys_size; i++)
- curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
- }
+ for (size_t i = 0; i < curve_keys_size; i++)
+ curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
+ }
- /* pack curve segments */
- size_t curve_num = num_curves();
+ /* pack curve segments */
+ size_t curve_num = num_curves();
- for(size_t i = 0; i < curve_num; i++) {
- Curve curve = get_curve(i);
- int shader_id = curve_shader[i];
- Shader *shader = (shader_id < used_shaders.size()) ?
- used_shaders[shader_id] : scene->default_surface;
- shader_id = scene->shader_manager->get_shader_id(shader, false);
+ for (size_t i = 0; i < curve_num; i++) {
+ Curve curve = get_curve(i);
+ int shader_id = curve_shader[i];
+ Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] :
+ scene->default_surface;
+ shader_id = scene->shader_manager->get_shader_id(shader, false);
- curve_data[i] = make_float4(
- __int_as_float(curve.first_key + curvekey_offset),
- __int_as_float(curve.num_keys),
- __int_as_float(shader_id),
- 0.0f);
- }
+ curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset),
+ __int_as_float(curve.num_keys),
+ __int_as_float(shader_id),
+ 0.0f);
+ }
}
void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset)
{
- size_t num_faces = subd_faces.size();
- int ngons = 0;
-
- for(size_t f = 0; f < num_faces; f++) {
- SubdFace face = subd_faces[f];
-
- if(face.is_quad()) {
- int c[4];
- memcpy(c, &subd_face_corners[face.start_corner], sizeof(int)*4);
-
- *(patch_data++) = c[0] + vert_offset;
- *(patch_data++) = c[1] + vert_offset;
- *(patch_data++) = c[2] + vert_offset;
- *(patch_data++) = c[3] + vert_offset;
-
- *(patch_data++) = f+face_offset;
- *(patch_data++) = face.num_corners;
- *(patch_data++) = face.start_corner + corner_offset;
- *(patch_data++) = 0;
- }
- else {
- for(int i = 0; i < face.num_corners; i++) {
- int c[4];
- c[0] = subd_face_corners[face.start_corner + mod(i + 0, face.num_corners)];
- c[1] = subd_face_corners[face.start_corner + mod(i + 1, face.num_corners)];
- c[2] = verts.size() - num_subd_verts + ngons;
- c[3] = subd_face_corners[face.start_corner + mod(i - 1, face.num_corners)];
-
- *(patch_data++) = c[0] + vert_offset;
- *(patch_data++) = c[1] + vert_offset;
- *(patch_data++) = c[2] + vert_offset;
- *(patch_data++) = c[3] + vert_offset;
-
- *(patch_data++) = f+face_offset;
- *(patch_data++) = face.num_corners | (i << 16);
- *(patch_data++) = face.start_corner + corner_offset;
- *(patch_data++) = subd_face_corners.size() + ngons + corner_offset;
- }
-
- ngons++;
- }
- }
-}
-
-void Mesh::compute_bvh(Device *device,
- DeviceScene *dscene,
- SceneParams *params,
- Progress *progress,
- int n,
- int total)
-{
- if(progress->get_cancel())
- return;
-
- compute_bounds();
-
- if(need_build_bvh()) {
- string msg = "Updating Mesh BVH ";
- if(name == "")
- msg += string_printf("%u/%u", (uint)(n+1), (uint)total);
- else
- msg += string_printf("%s %u/%u", name.c_str(), (uint)(n+1), (uint)total);
-
- Object object;
- object.mesh = this;
-
- vector<Object*> objects;
- objects.push_back(&object);
-
- if(bvh && !need_update_rebuild) {
- progress->set_status(msg, "Refitting BVH");
- bvh->objects = objects;
- bvh->refit(*progress);
- }
- else {
- progress->set_status(msg, "Building BVH");
-
- BVHParams bparams;
- bparams.use_spatial_split = params->use_bvh_spatial_split;
- bparams.bvh_layout = BVHParams::best_bvh_layout(
- params->bvh_layout,
- device->get_bvh_layout_mask());
- bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
- params->use_bvh_unaligned_nodes;
- bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
- bparams.num_motion_curve_steps = params->num_bvh_time_steps;
- bparams.bvh_type = params->bvh_type;
- bparams.curve_flags = dscene->data.curve.curveflags;
- bparams.curve_subdivisions = dscene->data.curve.subdivisions;
-
- delete bvh;
- bvh = BVH::create(bparams, objects);
- MEM_GUARDED_CALL(progress, bvh->build, *progress);
- }
- }
-
- need_update = false;
- need_update_rebuild = false;
+ size_t num_faces = subd_faces.size();
+ int ngons = 0;
+
+ for (size_t f = 0; f < num_faces; f++) {
+ SubdFace face = subd_faces[f];
+
+ if (face.is_quad()) {
+ int c[4];
+ memcpy(c, &subd_face_corners[face.start_corner], sizeof(int) * 4);
+
+ *(patch_data++) = c[0] + vert_offset;
+ *(patch_data++) = c[1] + vert_offset;
+ *(patch_data++) = c[2] + vert_offset;
+ *(patch_data++) = c[3] + vert_offset;
+
+ *(patch_data++) = f + face_offset;
+ *(patch_data++) = face.num_corners;
+ *(patch_data++) = face.start_corner + corner_offset;
+ *(patch_data++) = 0;
+ }
+ else {
+ for (int i = 0; i < face.num_corners; i++) {
+ int c[4];
+ c[0] = subd_face_corners[face.start_corner + mod(i + 0, face.num_corners)];
+ c[1] = subd_face_corners[face.start_corner + mod(i + 1, face.num_corners)];
+ c[2] = verts.size() - num_subd_verts + ngons;
+ c[3] = subd_face_corners[face.start_corner + mod(i - 1, face.num_corners)];
+
+ *(patch_data++) = c[0] + vert_offset;
+ *(patch_data++) = c[1] + vert_offset;
+ *(patch_data++) = c[2] + vert_offset;
+ *(patch_data++) = c[3] + vert_offset;
+
+ *(patch_data++) = f + face_offset;
+ *(patch_data++) = face.num_corners | (i << 16);
+ *(patch_data++) = face.start_corner + corner_offset;
+ *(patch_data++) = subd_face_corners.size() + ngons + corner_offset;
+ }
+
+ ngons++;
+ }
+ }
+}
+
+void Mesh::compute_bvh(
+ Device *device, DeviceScene *dscene, SceneParams *params, Progress *progress, int n, int total)
+{
+ if (progress->get_cancel())
+ return;
+
+ compute_bounds();
+
+ if (need_build_bvh()) {
+ string msg = "Updating Mesh BVH ";
+ if (name == "")
+ msg += string_printf("%u/%u", (uint)(n + 1), (uint)total);
+ else
+ msg += string_printf("%s %u/%u", name.c_str(), (uint)(n + 1), (uint)total);
+
+ Object object;
+ object.mesh = this;
+
+ vector<Object *> objects;
+ objects.push_back(&object);
+
+ if (bvh && !need_update_rebuild) {
+ progress->set_status(msg, "Refitting BVH");
+ bvh->objects = objects;
+ bvh->refit(*progress);
+ }
+ else {
+ progress->set_status(msg, "Building BVH");
+
+ BVHParams bparams;
+ bparams.use_spatial_split = params->use_bvh_spatial_split;
+ bparams.bvh_layout = BVHParams::best_bvh_layout(params->bvh_layout,
+ device->get_bvh_layout_mask());
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ params->use_bvh_unaligned_nodes;
+ bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
+ bparams.num_motion_curve_steps = params->num_bvh_time_steps;
+ bparams.bvh_type = params->bvh_type;
+ bparams.curve_flags = dscene->data.curve.curveflags;
+ bparams.curve_subdivisions = dscene->data.curve.subdivisions;
+
+ delete bvh;
+ bvh = BVH::create(bparams, objects);
+ MEM_GUARDED_CALL(progress, bvh->build, *progress);
+ }
+ }
+
+ need_update = false;
+ need_update_rebuild = false;
}
void Mesh::tag_update(Scene *scene, bool rebuild)
{
- need_update = true;
+ need_update = true;
- if(rebuild) {
- need_update_rebuild = true;
- scene->light_manager->need_update = true;
- }
- else {
- foreach(Shader *shader, used_shaders)
- if(shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
+ if (rebuild) {
+ need_update_rebuild = true;
+ scene->light_manager->need_update = true;
+ }
+ else {
+ foreach (Shader *shader, used_shaders)
+ if (shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
- scene->mesh_manager->need_update = true;
- scene->object_manager->need_update = true;
+ scene->mesh_manager->need_update = true;
+ scene->object_manager->need_update = true;
}
bool Mesh::has_motion_blur() const
{
- return (use_motion_blur &&
- (attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) ||
- curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)));
+ return (use_motion_blur && (attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) ||
+ curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)));
}
bool Mesh::has_true_displacement() const
{
- foreach(Shader *shader, used_shaders) {
- if(shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
- return true;
- }
- }
+ foreach (Shader *shader, used_shaders) {
+ if (shader->has_displacement && shader->displacement_method != DISPLACE_BUMP) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
float Mesh::motion_time(int step) const
{
- return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
+ return (motion_steps > 1) ? 2.0f * step / (motion_steps - 1) - 1.0f : 0.0f;
}
int Mesh::motion_step(float time) const
{
- if(motion_steps > 1) {
- int attr_step = 0;
+ if (motion_steps > 1) {
+ int attr_step = 0;
- for(int step = 0; step < motion_steps; step++) {
- float step_time = motion_time(step);
- if(step_time == time) {
- return attr_step;
- }
+ for (int step = 0; step < motion_steps; step++) {
+ float step_time = motion_time(step);
+ if (step_time == time) {
+ return attr_step;
+ }
- /* Center step is stored in a separate attribute. */
- if(step != motion_steps / 2) {
- attr_step++;
- }
- }
- }
+ /* Center step is stored in a separate attribute. */
+ if (step != motion_steps / 2) {
+ attr_step++;
+ }
+ }
+ }
- return -1;
+ return -1;
}
bool Mesh::need_build_bvh() const
{
- return !transform_applied || has_surface_bssrdf;
+ return !transform_applied || has_surface_bssrdf;
}
bool Mesh::is_instanced() const
{
- /* Currently we treat subsurface objects as instanced.
- *
- * While it might be not very optimal for ray traversal, it avoids having
- * duplicated BVH in the memory, saving quite some space.
- */
- return !transform_applied || has_surface_bssrdf;
+ /* Currently we treat subsurface objects as instanced.
+ *
+ * While it might be not very optimal for ray traversal, it avoids having
+ * duplicated BVH in the memory, saving quite some space.
+ */
+ return !transform_applied || has_surface_bssrdf;
}
/* Mesh Manager */
MeshManager::MeshManager()
{
- need_update = true;
- need_flags_update = true;
+ need_update = true;
+ need_flags_update = true;
}
MeshManager::~MeshManager()
{
}
-void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes)
+void MeshManager::update_osl_attributes(Device *device,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes)
{
#ifdef WITH_OSL
- /* for OSL, a hash map is used to lookup the attribute by name. */
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
-
- og->object_name_map.clear();
- og->attribute_map.clear();
- og->object_names.clear();
-
- og->attribute_map.resize(scene->objects.size()*ATTR_PRIM_TYPES);
-
- for(size_t i = 0; i < scene->objects.size(); i++) {
- /* set object name to object index map */
- Object *object = scene->objects[i];
- og->object_name_map[object->name] = i;
- og->object_names.push_back(object->name);
-
- /* set object attributes */
- foreach(ParamValue& attr, object->attributes) {
- OSLGlobals::Attribute osl_attr;
-
- osl_attr.type = attr.type();
- osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
- osl_attr.value = attr;
- osl_attr.desc.offset = 0;
- osl_attr.desc.flags = 0;
-
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr;
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr;
- }
-
- /* find mesh attributes */
- size_t j;
-
- for(j = 0; j < scene->meshes.size(); j++)
- if(scene->meshes[j] == object->mesh)
- break;
-
- AttributeRequestSet& attributes = mesh_attributes[j];
-
- /* set object attributes */
- foreach(AttributeRequest& req, attributes.requests) {
- OSLGlobals::Attribute osl_attr;
-
- if(req.triangle_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.triangle_desc;
-
- if(req.triangle_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if(req.triangle_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else if(req.triangle_type == TypeFloat2)
- osl_attr.type = TypeFloat2;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][stdname] = osl_attr;
- }
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr;
- }
- }
-
- if(req.curve_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.curve_desc;
-
- if(req.curve_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if(req.curve_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
- }
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
- }
- }
-
- if(req.subd_desc.element != ATTR_ELEMENT_NONE) {
- osl_attr.desc = req.subd_desc;
-
- if(req.subd_type == TypeDesc::TypeFloat)
- osl_attr.type = TypeDesc::TypeFloat;
- else if(req.subd_type == TypeDesc::TypeMatrix)
- osl_attr.type = TypeDesc::TypeMatrix;
- else
- osl_attr.type = TypeDesc::TypeColor;
-
- if(req.std != ATTR_STD_NONE) {
- /* if standard attribute, add lookup by geom: name convention */
- ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr;
- }
- else if(req.name != ustring()) {
- /* add lookup by mesh attribute name */
- og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr;
- }
- }
- }
- }
+ /* for OSL, a hash map is used to lookup the attribute by name. */
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
+
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+
+ og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES);
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ /* set object name to object index map */
+ Object *object = scene->objects[i];
+ og->object_name_map[object->name] = i;
+ og->object_names.push_back(object->name);
+
+ /* set object attributes */
+ foreach (ParamValue &attr, object->attributes) {
+ OSLGlobals::Attribute osl_attr;
+
+ osl_attr.type = attr.type();
+ osl_attr.desc.element = ATTR_ELEMENT_OBJECT;
+ osl_attr.value = attr;
+ osl_attr.desc.offset = 0;
+ osl_attr.desc.flags = 0;
+
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][attr.name()] = osl_attr;
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][attr.name()] = osl_attr;
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr;
+ }
+
+ /* find mesh attributes */
+ size_t j;
+
+ for (j = 0; j < scene->meshes.size(); j++)
+ if (scene->meshes[j] == object->mesh)
+ break;
+
+ AttributeRequestSet &attributes = mesh_attributes[j];
+
+ /* set object attributes */
+ foreach (AttributeRequest &req, attributes.requests) {
+ OSLGlobals::Attribute osl_attr;
+
+ if (req.triangle_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.triangle_desc;
+
+ if (req.triangle_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.triangle_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else if (req.triangle_type == TypeFloat2)
+ osl_attr.type = TypeFloat2;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr;
+ }
+ }
+
+ if (req.curve_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.curve_desc;
+
+ if (req.curve_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.curve_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
+ }
+ }
+
+ if (req.subd_desc.element != ATTR_ELEMENT_NONE) {
+ osl_attr.desc = req.subd_desc;
+
+ if (req.subd_type == TypeDesc::TypeFloat)
+ osl_attr.type = TypeDesc::TypeFloat;
+ else if (req.subd_type == TypeDesc::TypeMatrix)
+ osl_attr.type = TypeDesc::TypeMatrix;
+ else
+ osl_attr.type = TypeDesc::TypeColor;
+
+ if (req.std != ATTR_STD_NONE) {
+ /* if standard attribute, add lookup by geom: name convention */
+ ustring stdname(string("geom:") + string(Attribute::standard_name(req.std)));
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr;
+ }
+ else if (req.name != ustring()) {
+ /* add lookup by mesh attribute name */
+ og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr;
+ }
+ }
+ }
+ }
#else
- (void) device;
- (void) scene;
- (void) mesh_attributes;
+ (void)device;
+ (void)scene;
+ (void)mesh_attributes;
#endif
}
-void MeshManager::update_svm_attributes(Device *, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes)
-{
- /* for SVM, the attributes_map table is used to lookup the offset of an
- * attribute, based on a unique shader attribute id. */
-
- /* compute array stride */
- int attr_map_size = 0;
+void MeshManager::update_svm_attributes(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes)
+{
+ /* for SVM, the attributes_map table is used to lookup the offset of an
+ * attribute, based on a unique shader attribute id. */
+
+ /* compute array stride */
+ int attr_map_size = 0;
+
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ mesh->attr_map_offset = attr_map_size;
+ attr_map_size += (mesh_attributes[i].size() + 1) * ATTR_PRIM_TYPES;
+ }
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- mesh->attr_map_offset = attr_map_size;
- attr_map_size += (mesh_attributes[i].size() + 1)*ATTR_PRIM_TYPES;
- }
+ if (attr_map_size == 0)
+ return;
- if(attr_map_size == 0)
- return;
+ /* create attribute map */
+ uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
+ memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint));
- /* create attribute map */
- uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size);
- memset(attr_map, 0, dscene->attributes_map.size()*sizeof(uint));
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet &attributes = mesh_attributes[i];
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet& attributes = mesh_attributes[i];
+ /* set object attributes */
+ int index = mesh->attr_map_offset;
- /* set object attributes */
- int index = mesh->attr_map_offset;
+ foreach (AttributeRequest &req, attributes.requests) {
+ uint id;
- foreach(AttributeRequest& req, attributes.requests) {
- uint id;
+ if (req.std == ATTR_STD_NONE)
+ id = scene->shader_manager->get_attribute_id(req.name);
+ else
+ id = scene->shader_manager->get_attribute_id(req.std);
- if(req.std == ATTR_STD_NONE)
- id = scene->shader_manager->get_attribute_id(req.name);
- else
- id = scene->shader_manager->get_attribute_id(req.std);
+ if (mesh->num_triangles()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.triangle_desc.element;
+ attr_map[index].z = as_uint(req.triangle_desc.offset);
- if(mesh->num_triangles()) {
- attr_map[index].x = id;
- attr_map[index].y = req.triangle_desc.element;
- attr_map[index].z = as_uint(req.triangle_desc.offset);
+ if (req.triangle_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.triangle_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.triangle_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
- if(req.triangle_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if(req.triangle_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if(req.triangle_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ attr_map[index].w |= req.triangle_desc.flags << 8;
+ }
- attr_map[index].w |= req.triangle_desc.flags << 8;
- }
+ index++;
- index++;
+ if (mesh->num_curves()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.curve_desc.element;
+ attr_map[index].z = as_uint(req.curve_desc.offset);
- if(mesh->num_curves()) {
- attr_map[index].x = id;
- attr_map[index].y = req.curve_desc.element;
- attr_map[index].z = as_uint(req.curve_desc.offset);
+ if (req.curve_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.curve_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.curve_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
- if(req.curve_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if(req.curve_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if(req.curve_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ attr_map[index].w |= req.curve_desc.flags << 8;
+ }
- attr_map[index].w |= req.curve_desc.flags << 8;
- }
+ index++;
- index++;
+ if (mesh->subd_faces.size()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.subd_desc.element;
+ attr_map[index].z = as_uint(req.subd_desc.offset);
- if(mesh->subd_faces.size()) {
- attr_map[index].x = id;
- attr_map[index].y = req.subd_desc.element;
- attr_map[index].z = as_uint(req.subd_desc.offset);
+ if (req.subd_type == TypeDesc::TypeFloat)
+ attr_map[index].w = NODE_ATTR_FLOAT;
+ else if (req.subd_type == TypeDesc::TypeMatrix)
+ attr_map[index].w = NODE_ATTR_MATRIX;
+ else if (req.subd_type == TypeFloat2)
+ attr_map[index].w = NODE_ATTR_FLOAT2;
+ else
+ attr_map[index].w = NODE_ATTR_FLOAT3;
- if(req.subd_type == TypeDesc::TypeFloat)
- attr_map[index].w = NODE_ATTR_FLOAT;
- else if(req.subd_type == TypeDesc::TypeMatrix)
- attr_map[index].w = NODE_ATTR_MATRIX;
- else if(req.subd_type == TypeFloat2)
- attr_map[index].w = NODE_ATTR_FLOAT2;
- else
- attr_map[index].w = NODE_ATTR_FLOAT3;
+ attr_map[index].w |= req.subd_desc.flags << 8;
+ }
- attr_map[index].w |= req.subd_desc.flags << 8;
- }
+ index++;
+ }
- index++;
- }
-
- /* terminator */
- for(int j = 0; j < ATTR_PRIM_TYPES; j++) {
- attr_map[index].x = ATTR_STD_NONE;
- attr_map[index].y = 0;
- attr_map[index].z = 0;
- attr_map[index].w = 0;
-
- index++;
- }
- }
-
- /* copy to device */
- dscene->attributes_map.copy_to_device();
+ /* terminator */
+ for (int j = 0; j < ATTR_PRIM_TYPES; j++) {
+ attr_map[index].x = ATTR_STD_NONE;
+ attr_map[index].y = 0;
+ attr_map[index].z = 0;
+ attr_map[index].w = 0;
+
+ index++;
+ }
+ }
+
+ /* copy to device */
+ dscene->attributes_map.copy_to_device();
}
static void update_attribute_element_size(Mesh *mesh,
Attribute *mattr,
AttributePrimitive prim,
size_t *attr_float_size,
- size_t *attr_float2_size,
+ size_t *attr_float2_size,
size_t *attr_float3_size,
size_t *attr_uchar4_size)
{
- if(mattr) {
- size_t size = mattr->element_size(mesh, prim);
-
- if(mattr->element == ATTR_ELEMENT_VOXEL) {
- /* pass */
- }
- else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
- *attr_uchar4_size += size;
- }
- else if(mattr->type == TypeDesc::TypeFloat) {
- *attr_float_size += size;
- }
- else if(mattr->type == TypeFloat2) {
- *attr_float2_size += size;
- }
- else if(mattr->type == TypeDesc::TypeMatrix) {
- *attr_float3_size += size * 4;
- }
- else {
- *attr_float3_size += size;
- }
- }
+ if (mattr) {
+ size_t size = mattr->element_size(mesh, prim);
+
+ if (mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* pass */
+ }
+ else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ *attr_uchar4_size += size;
+ }
+ else if (mattr->type == TypeDesc::TypeFloat) {
+ *attr_float_size += size;
+ }
+ else if (mattr->type == TypeFloat2) {
+ *attr_float2_size += size;
+ }
+ else if (mattr->type == TypeDesc::TypeMatrix) {
+ *attr_float3_size += size * 4;
+ }
+ else {
+ *attr_float3_size += size;
+ }
+ }
}
static void update_attribute_element_offset(Mesh *mesh,
- device_vector<float>& attr_float,
- size_t& attr_float_offset,
- device_vector<float2>& attr_float2,
- size_t& attr_float2_offset,
- device_vector<float4>& attr_float3,
- size_t& attr_float3_offset,
- device_vector<uchar4>& attr_uchar4,
- size_t& attr_uchar4_offset,
+ device_vector<float> &attr_float,
+ size_t &attr_float_offset,
+ device_vector<float2> &attr_float2,
+ size_t &attr_float2_offset,
+ device_vector<float4> &attr_float3,
+ size_t &attr_float3_offset,
+ device_vector<uchar4> &attr_uchar4,
+ size_t &attr_uchar4_offset,
Attribute *mattr,
AttributePrimitive prim,
- TypeDesc& type,
- AttributeDescriptor& desc)
-{
- if(mattr) {
- /* store element and type */
- desc.element = mattr->element;
- desc.flags = mattr->flags;
- type = mattr->type;
-
- /* store attribute data in arrays */
- size_t size = mattr->element_size(mesh, prim);
-
- AttributeElement& element = desc.element;
- int& offset = desc.offset;
-
- if(mattr->element == ATTR_ELEMENT_VOXEL) {
- /* store slot in offset value */
- VoxelAttribute *voxel_data = mattr->data_voxel();
- offset = voxel_data->slot;
- }
- else if(mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
- uchar4 *data = mattr->data_uchar4();
- offset = attr_uchar4_offset;
-
- assert(attr_uchar4.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_uchar4[offset+k] = data[k];
- }
- attr_uchar4_offset += size;
- }
- else if(mattr->type == TypeDesc::TypeFloat) {
- float *data = mattr->data_float();
- offset = attr_float_offset;
-
- assert(attr_float.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_float[offset+k] = data[k];
- }
- attr_float_offset += size;
- }
- else if(mattr->type == TypeFloat2) {
- float2 *data = mattr->data_float2();
- offset = attr_float2_offset;
-
- assert(attr_float2.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_float2[offset+k] = data[k];
- }
- attr_float2_offset += size;
- }
- else if(mattr->type == TypeDesc::TypeMatrix) {
- Transform *tfm = mattr->data_transform();
- offset = attr_float3_offset;
-
- assert(attr_float3.size() >= offset + size * 3);
- for(size_t k = 0; k < size*3; k++) {
- attr_float3[offset+k] = (&tfm->x)[k];
- }
- attr_float3_offset += size * 3;
- }
- else {
- float4 *data = mattr->data_float4();
- offset = attr_float3_offset;
-
- assert(attr_float3.size() >= offset + size);
- for(size_t k = 0; k < size; k++) {
- attr_float3[offset+k] = data[k];
- }
- attr_float3_offset += size;
- }
-
- /* mesh vertex/curve index is global, not per object, so we sneak
- * a correction for that in here */
- if(mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK && desc.flags & ATTR_SUBDIVIDED) {
- /* indices for subdivided attributes are retrieved
- * from patch table so no need for correction here*/
- }
- else if(element == ATTR_ELEMENT_VERTEX)
- offset -= mesh->vert_offset;
- else if(element == ATTR_ELEMENT_VERTEX_MOTION)
- offset -= mesh->vert_offset;
- else if(element == ATTR_ELEMENT_FACE) {
- if(prim == ATTR_PRIM_TRIANGLE)
- offset -= mesh->tri_offset;
- else
- offset -= mesh->face_offset;
- }
- else if(element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
- if(prim == ATTR_PRIM_TRIANGLE)
- offset -= 3*mesh->tri_offset;
- else
- offset -= mesh->corner_offset;
- }
- else if(element == ATTR_ELEMENT_CURVE)
- offset -= mesh->curve_offset;
- else if(element == ATTR_ELEMENT_CURVE_KEY)
- offset -= mesh->curvekey_offset;
- else if(element == ATTR_ELEMENT_CURVE_KEY_MOTION)
- offset -= mesh->curvekey_offset;
- }
- else {
- /* attribute not found */
- desc.element = ATTR_ELEMENT_NONE;
- desc.offset = 0;
- }
-}
-
-void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
- progress.set_status("Updating Mesh", "Computing attributes");
-
- /* gather per mesh requested attributes. as meshes may have multiple
- * shaders assigned, this merges the requested attributes that have
- * been set per shader by the shader manager */
- vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());
-
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
-
- scene->need_global_attributes(mesh_attributes[i]);
-
- foreach(Shader *shader, mesh->used_shaders) {
- mesh_attributes[i].add(shader->attributes);
- }
- }
-
- /* mesh attribute are stored in a single array per data type. here we fill
- * those arrays, and set the offset and element type to create attribute
- * maps next */
-
- /* Pre-allocate attributes to avoid arrays re-allocation which would
- * take 2x of overall attribute memory usage.
- */
- size_t attr_float_size = 0;
- size_t attr_float2_size = 0;
- size_t attr_float3_size = 0;
- size_t attr_uchar4_size = 0;
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet& attributes = mesh_attributes[i];
- foreach(AttributeRequest& req, attributes.requests) {
- Attribute *triangle_mattr = mesh->attributes.find(req);
- Attribute *curve_mattr = mesh->curve_attributes.find(req);
- Attribute *subd_mattr = mesh->subd_attributes.find(req);
-
- update_attribute_element_size(mesh,
- triangle_mattr,
- ATTR_PRIM_TRIANGLE,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- update_attribute_element_size(mesh,
- curve_mattr,
- ATTR_PRIM_CURVE,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- update_attribute_element_size(mesh,
- subd_mattr,
- ATTR_PRIM_SUBD,
- &attr_float_size,
- &attr_float2_size,
- &attr_float3_size,
- &attr_uchar4_size);
- }
- }
-
- dscene->attributes_float.alloc(attr_float_size);
- dscene->attributes_float2.alloc(attr_float2_size);
- dscene->attributes_float3.alloc(attr_float3_size);
- dscene->attributes_uchar4.alloc(attr_uchar4_size);
-
- size_t attr_float_offset = 0;
- size_t attr_float2_offset = 0;
- size_t attr_float3_offset = 0;
- size_t attr_uchar4_offset = 0;
-
- /* Fill in attributes. */
- for(size_t i = 0; i < scene->meshes.size(); i++) {
- Mesh *mesh = scene->meshes[i];
- AttributeRequestSet& attributes = mesh_attributes[i];
-
- /* todo: we now store std and name attributes from requests even if
- * they actually refer to the same mesh attributes, optimize */
- foreach(AttributeRequest& req, attributes.requests) {
- Attribute *triangle_mattr = mesh->attributes.find(req);
- Attribute *curve_mattr = mesh->curve_attributes.find(req);
- Attribute *subd_mattr = mesh->subd_attributes.find(req);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float, attr_float_offset,
- dscene->attributes_float2, attr_float2_offset,
- dscene->attributes_float3, attr_float3_offset,
- dscene->attributes_uchar4, attr_uchar4_offset,
- triangle_mattr,
- ATTR_PRIM_TRIANGLE,
- req.triangle_type,
- req.triangle_desc);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float, attr_float_offset,
- dscene->attributes_float2, attr_float2_offset,
- dscene->attributes_float3, attr_float3_offset,
- dscene->attributes_uchar4, attr_uchar4_offset,
- curve_mattr,
- ATTR_PRIM_CURVE,
- req.curve_type,
- req.curve_desc);
-
- update_attribute_element_offset(mesh,
- dscene->attributes_float, attr_float_offset,
- dscene->attributes_float2, attr_float2_offset,
- dscene->attributes_float3, attr_float3_offset,
- dscene->attributes_uchar4, attr_uchar4_offset,
- subd_mattr,
- ATTR_PRIM_SUBD,
- req.subd_type,
- req.subd_desc);
-
- if(progress.get_cancel()) return;
- }
- }
-
- /* create attribute lookup maps */
- if(scene->shader_manager->use_osl())
- update_osl_attributes(device, scene, mesh_attributes);
-
- update_svm_attributes(device, dscene, scene, mesh_attributes);
-
- if(progress.get_cancel()) return;
-
- /* copy to device */
- progress.set_status("Updating Mesh", "Copying Attributes to device");
-
- if(dscene->attributes_float.size()) {
- dscene->attributes_float.copy_to_device();
- }
- if(dscene->attributes_float2.size()) {
- dscene->attributes_float2.copy_to_device();
- }
- if(dscene->attributes_float3.size()) {
- dscene->attributes_float3.copy_to_device();
- }
- if(dscene->attributes_uchar4.size()) {
- dscene->attributes_uchar4.copy_to_device();
- }
-
- if(progress.get_cancel()) return;
-
- /* After mesh attributes and patch tables have been copied to device memory,
- * we need to update offsets in the objects. */
- scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
+ TypeDesc &type,
+ AttributeDescriptor &desc)
+{
+ if (mattr) {
+ /* store element and type */
+ desc.element = mattr->element;
+ desc.flags = mattr->flags;
+ type = mattr->type;
+
+ /* store attribute data in arrays */
+ size_t size = mattr->element_size(mesh, prim);
+
+ AttributeElement &element = desc.element;
+ int &offset = desc.offset;
+
+ if (mattr->element == ATTR_ELEMENT_VOXEL) {
+ /* store slot in offset value */
+ VoxelAttribute *voxel_data = mattr->data_voxel();
+ offset = voxel_data->slot;
+ }
+ else if (mattr->element == ATTR_ELEMENT_CORNER_BYTE) {
+ uchar4 *data = mattr->data_uchar4();
+ offset = attr_uchar4_offset;
+
+ assert(attr_uchar4.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_uchar4[offset + k] = data[k];
+ }
+ attr_uchar4_offset += size;
+ }
+ else if (mattr->type == TypeDesc::TypeFloat) {
+ float *data = mattr->data_float();
+ offset = attr_float_offset;
+
+ assert(attr_float.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float[offset + k] = data[k];
+ }
+ attr_float_offset += size;
+ }
+ else if (mattr->type == TypeFloat2) {
+ float2 *data = mattr->data_float2();
+ offset = attr_float2_offset;
+
+ assert(attr_float2.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float2[offset + k] = data[k];
+ }
+ attr_float2_offset += size;
+ }
+ else if (mattr->type == TypeDesc::TypeMatrix) {
+ Transform *tfm = mattr->data_transform();
+ offset = attr_float3_offset;
+
+ assert(attr_float3.size() >= offset + size * 3);
+ for (size_t k = 0; k < size * 3; k++) {
+ attr_float3[offset + k] = (&tfm->x)[k];
+ }
+ attr_float3_offset += size * 3;
+ }
+ else {
+ float4 *data = mattr->data_float4();
+ offset = attr_float3_offset;
+
+ assert(attr_float3.size() >= offset + size);
+ for (size_t k = 0; k < size; k++) {
+ attr_float3[offset + k] = data[k];
+ }
+ attr_float3_offset += size;
+ }
+
+ /* mesh vertex/curve index is global, not per object, so we sneak
+ * a correction for that in here */
+ if (mesh->subdivision_type == Mesh::SUBDIVISION_CATMULL_CLARK &&
+ desc.flags & ATTR_SUBDIVIDED) {
+ /* indices for subdivided attributes are retrieved
+ * from patch table so no need for correction here*/
+ }
+ else if (element == ATTR_ELEMENT_VERTEX)
+ offset -= mesh->vert_offset;
+ else if (element == ATTR_ELEMENT_VERTEX_MOTION)
+ offset -= mesh->vert_offset;
+ else if (element == ATTR_ELEMENT_FACE) {
+ if (prim == ATTR_PRIM_TRIANGLE)
+ offset -= mesh->tri_offset;
+ else
+ offset -= mesh->face_offset;
+ }
+ else if (element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE) {
+ if (prim == ATTR_PRIM_TRIANGLE)
+ offset -= 3 * mesh->tri_offset;
+ else
+ offset -= mesh->corner_offset;
+ }
+ else if (element == ATTR_ELEMENT_CURVE)
+ offset -= mesh->curve_offset;
+ else if (element == ATTR_ELEMENT_CURVE_KEY)
+ offset -= mesh->curvekey_offset;
+ else if (element == ATTR_ELEMENT_CURVE_KEY_MOTION)
+ offset -= mesh->curvekey_offset;
+ }
+ else {
+ /* attribute not found */
+ desc.element = ATTR_ELEMENT_NONE;
+ desc.offset = 0;
+ }
+}
+
+void MeshManager::device_update_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ progress.set_status("Updating Mesh", "Computing attributes");
+
+ /* gather per mesh requested attributes. as meshes may have multiple
+ * shaders assigned, this merges the requested attributes that have
+ * been set per shader by the shader manager */
+ vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());
+
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+
+ scene->need_global_attributes(mesh_attributes[i]);
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ mesh_attributes[i].add(shader->attributes);
+ }
+ }
+
+ /* mesh attribute are stored in a single array per data type. here we fill
+ * those arrays, and set the offset and element type to create attribute
+ * maps next */
+
+ /* Pre-allocate attributes to avoid arrays re-allocation which would
+ * take 2x of overall attribute memory usage.
+ */
+ size_t attr_float_size = 0;
+ size_t attr_float2_size = 0;
+ size_t attr_float3_size = 0;
+ size_t attr_uchar4_size = 0;
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet &attributes = mesh_attributes[i];
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+ Attribute *subd_mattr = mesh->subd_attributes.find(req);
+
+ update_attribute_element_size(mesh,
+ triangle_mattr,
+ ATTR_PRIM_TRIANGLE,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ curve_mattr,
+ ATTR_PRIM_CURVE,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ subd_mattr,
+ ATTR_PRIM_SUBD,
+ &attr_float_size,
+ &attr_float2_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ }
+ }
+
+ dscene->attributes_float.alloc(attr_float_size);
+ dscene->attributes_float2.alloc(attr_float2_size);
+ dscene->attributes_float3.alloc(attr_float3_size);
+ dscene->attributes_uchar4.alloc(attr_uchar4_size);
+
+ size_t attr_float_offset = 0;
+ size_t attr_float2_offset = 0;
+ size_t attr_float3_offset = 0;
+ size_t attr_uchar4_offset = 0;
+
+ /* Fill in attributes. */
+ for (size_t i = 0; i < scene->meshes.size(); i++) {
+ Mesh *mesh = scene->meshes[i];
+ AttributeRequestSet &attributes = mesh_attributes[i];
+
+ /* todo: we now store std and name attributes from requests even if
+ * they actually refer to the same mesh attributes, optimize */
+ foreach (AttributeRequest &req, attributes.requests) {
+ Attribute *triangle_mattr = mesh->attributes.find(req);
+ Attribute *curve_mattr = mesh->curve_attributes.find(req);
+ Attribute *subd_mattr = mesh->subd_attributes.find(req);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ triangle_mattr,
+ ATTR_PRIM_TRIANGLE,
+ req.triangle_type,
+ req.triangle_desc);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ curve_mattr,
+ ATTR_PRIM_CURVE,
+ req.curve_type,
+ req.curve_desc);
+
+ update_attribute_element_offset(mesh,
+ dscene->attributes_float,
+ attr_float_offset,
+ dscene->attributes_float2,
+ attr_float2_offset,
+ dscene->attributes_float3,
+ attr_float3_offset,
+ dscene->attributes_uchar4,
+ attr_uchar4_offset,
+ subd_mattr,
+ ATTR_PRIM_SUBD,
+ req.subd_type,
+ req.subd_desc);
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* create attribute lookup maps */
+ if (scene->shader_manager->use_osl())
+ update_osl_attributes(device, scene, mesh_attributes);
+
+ update_svm_attributes(device, dscene, scene, mesh_attributes);
+
+ if (progress.get_cancel())
+ return;
+
+ /* copy to device */
+ progress.set_status("Updating Mesh", "Copying Attributes to device");
+
+ if (dscene->attributes_float.size()) {
+ dscene->attributes_float.copy_to_device();
+ }
+ if (dscene->attributes_float2.size()) {
+ dscene->attributes_float2.copy_to_device();
+ }
+ if (dscene->attributes_float3.size()) {
+ dscene->attributes_float3.copy_to_device();
+ }
+ if (dscene->attributes_uchar4.size()) {
+ dscene->attributes_uchar4.copy_to_device();
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ /* After mesh attributes and patch tables have been copied to device memory,
+ * we need to update offsets in the objects. */
+ scene->object_manager->device_update_mesh_offsets(device, dscene, scene);
}
void MeshManager::mesh_calc_offset(Scene *scene)
{
- size_t vert_size = 0;
- size_t tri_size = 0;
-
- size_t curve_key_size = 0;
- size_t curve_size = 0;
-
- size_t patch_size = 0;
- size_t face_size = 0;
- size_t corner_size = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->vert_offset = vert_size;
- mesh->tri_offset = tri_size;
-
- mesh->curvekey_offset = curve_key_size;
- mesh->curve_offset = curve_size;
-
- mesh->patch_offset = patch_size;
- mesh->face_offset = face_size;
- mesh->corner_offset = corner_size;
-
- vert_size += mesh->verts.size();
- tri_size += mesh->num_triangles();
-
- curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->num_curves();
-
- if(mesh->subd_faces.size()) {
- Mesh::SubdFace& last = mesh->subd_faces[mesh->subd_faces.size()-1];
- patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
-
- /* patch tables are stored in same array so include them in patch_size */
- if(mesh->patch_table) {
- mesh->patch_table_offset = patch_size;
- patch_size += mesh->patch_table->total_size();
- }
- }
- face_size += mesh->subd_faces.size();
- corner_size += mesh->subd_face_corners.size();
- }
-}
-
-void MeshManager::device_update_mesh(Device *,
- DeviceScene *dscene,
- Scene *scene,
- bool for_displacement,
- Progress& progress)
-{
- /* Count. */
- size_t vert_size = 0;
- size_t tri_size = 0;
-
- size_t curve_key_size = 0;
- size_t curve_size = 0;
-
- size_t patch_size = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- vert_size += mesh->verts.size();
- tri_size += mesh->num_triangles();
-
- curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->num_curves();
-
- if(mesh->subd_faces.size()) {
- Mesh::SubdFace& last = mesh->subd_faces[mesh->subd_faces.size()-1];
- patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
-
- /* patch tables are stored in same array so include them in patch_size */
- if(mesh->patch_table) {
- mesh->patch_table_offset = patch_size;
- patch_size += mesh->patch_table->total_size();
- }
- }
- }
-
- /* Create mapping from triangle to primitive triangle array. */
- vector<uint> tri_prim_index(tri_size);
- if(for_displacement) {
- /* For displacement kernels we do some trickery to make them believe
- * we've got all required data ready. However, that data is different
- * from final render kernels since we don't have BVH yet, so can't
- * really use same semantic of arrays.
- */
- foreach(Mesh *mesh, scene->meshes) {
- for(size_t i = 0; i < mesh->num_triangles(); ++i) {
- tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset);
- }
- }
- }
- else {
- for(size_t i = 0; i < dscene->prim_index.size(); ++i) {
- if((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
- tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i];
- }
- }
- }
-
- /* Fill in all the arrays. */
- if(tri_size != 0) {
- /* normals */
- progress.set_status("Updating Mesh", "Computing normals");
-
- uint *tri_shader = dscene->tri_shader.alloc(tri_size);
- float4 *vnormal = dscene->tri_vnormal.alloc(vert_size);
- uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
- uint *tri_patch = dscene->tri_patch.alloc(tri_size);
- float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_shaders(scene,
- &tri_shader[mesh->tri_offset]);
- mesh->pack_normals(&vnormal[mesh->vert_offset]);
- mesh->pack_verts(tri_prim_index,
- &tri_vindex[mesh->tri_offset],
- &tri_patch[mesh->tri_offset],
- &tri_patch_uv[mesh->vert_offset],
- mesh->vert_offset,
- mesh->tri_offset);
- if(progress.get_cancel()) return;
- }
-
- /* vertex coordinates */
- progress.set_status("Updating Mesh", "Copying Mesh to device");
-
- dscene->tri_shader.copy_to_device();
- dscene->tri_vnormal.copy_to_device();
- dscene->tri_vindex.copy_to_device();
- dscene->tri_patch.copy_to_device();
- dscene->tri_patch_uv.copy_to_device();
- }
-
- if(curve_size != 0) {
- progress.set_status("Updating Mesh", "Copying Strands to device");
-
- float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
- float4 *curves = dscene->curves.alloc(curve_size);
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_curves(scene, &curve_keys[mesh->curvekey_offset], &curves[mesh->curve_offset], mesh->curvekey_offset);
- if(progress.get_cancel()) return;
- }
-
- dscene->curve_keys.copy_to_device();
- dscene->curves.copy_to_device();
- }
-
- if(patch_size != 0) {
- progress.set_status("Updating Mesh", "Copying Patches to device");
-
- uint *patch_data = dscene->patches.alloc(patch_size);
-
- foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_patches(&patch_data[mesh->patch_offset], mesh->vert_offset, mesh->face_offset, mesh->corner_offset);
-
- if(mesh->patch_table) {
- mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], mesh->patch_table_offset);
- }
-
- if(progress.get_cancel()) return;
- }
-
- dscene->patches.copy_to_device();
- }
-
- if(for_displacement) {
- float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
- foreach(Mesh *mesh, scene->meshes) {
- for(size_t i = 0; i < mesh->num_triangles(); ++i) {
- Mesh::Triangle t = mesh->get_triangle(i);
- size_t offset = 3 * (i + mesh->tri_offset);
- prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
- prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
- prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
- }
- }
- dscene->prim_tri_verts.copy_to_device();
- }
-}
-
-void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
- /* bvh build */
- progress.set_status("Updating Scene BVH", "Building");
-
- BVHParams bparams;
- bparams.top_level = true;
- bparams.bvh_layout = BVHParams::best_bvh_layout(
- scene->params.bvh_layout,
- device->get_bvh_layout_mask());
- bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
- bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
- scene->params.use_bvh_unaligned_nodes;
- bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
- bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
- bparams.bvh_type = scene->params.bvh_type;
- bparams.curve_flags = dscene->data.curve.curveflags;
- bparams.curve_subdivisions = dscene->data.curve.subdivisions;
-
- VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout)
- << " layout.";
+ size_t vert_size = 0;
+ size_t tri_size = 0;
+
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
+ size_t patch_size = 0;
+ size_t face_size = 0;
+ size_t corner_size = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->vert_offset = vert_size;
+ mesh->tri_offset = tri_size;
+
+ mesh->curvekey_offset = curve_key_size;
+ mesh->curve_offset = curve_size;
+
+ mesh->patch_offset = patch_size;
+ mesh->face_offset = face_size;
+ mesh->corner_offset = corner_size;
+
+ vert_size += mesh->verts.size();
+ tri_size += mesh->num_triangles();
+
+ curve_key_size += mesh->curve_keys.size();
+ curve_size += mesh->num_curves();
+
+ if (mesh->subd_faces.size()) {
+ Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
+
+ /* patch tables are stored in same array so include them in patch_size */
+ if (mesh->patch_table) {
+ mesh->patch_table_offset = patch_size;
+ patch_size += mesh->patch_table->total_size();
+ }
+ }
+ face_size += mesh->subd_faces.size();
+ corner_size += mesh->subd_face_corners.size();
+ }
+}
+
+void MeshManager::device_update_mesh(
+ Device *, DeviceScene *dscene, Scene *scene, bool for_displacement, Progress &progress)
+{
+ /* Count. */
+ size_t vert_size = 0;
+ size_t tri_size = 0;
+
+ size_t curve_key_size = 0;
+ size_t curve_size = 0;
+
+ size_t patch_size = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ vert_size += mesh->verts.size();
+ tri_size += mesh->num_triangles();
+
+ curve_key_size += mesh->curve_keys.size();
+ curve_size += mesh->num_curves();
+
+ if (mesh->subd_faces.size()) {
+ Mesh::SubdFace &last = mesh->subd_faces[mesh->subd_faces.size() - 1];
+ patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8;
+
+ /* patch tables are stored in same array so include them in patch_size */
+ if (mesh->patch_table) {
+ mesh->patch_table_offset = patch_size;
+ patch_size += mesh->patch_table->total_size();
+ }
+ }
+ }
+
+ /* Create mapping from triangle to primitive triangle array. */
+ vector<uint> tri_prim_index(tri_size);
+ if (for_displacement) {
+ /* For displacement kernels we do some trickery to make them believe
+ * we've got all required data ready. However, that data is different
+ * from final render kernels since we don't have BVH yet, so can't
+ * really use same semantic of arrays.
+ */
+ foreach (Mesh *mesh, scene->meshes) {
+ for (size_t i = 0; i < mesh->num_triangles(); ++i) {
+ tri_prim_index[i + mesh->tri_offset] = 3 * (i + mesh->tri_offset);
+ }
+ }
+ }
+ else {
+ for (size_t i = 0; i < dscene->prim_index.size(); ++i) {
+ if ((dscene->prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ tri_prim_index[dscene->prim_index[i]] = dscene->prim_tri_index[i];
+ }
+ }
+ }
+
+ /* Fill in all the arrays. */
+ if (tri_size != 0) {
+ /* normals */
+ progress.set_status("Updating Mesh", "Computing normals");
+
+ uint *tri_shader = dscene->tri_shader.alloc(tri_size);
+ float4 *vnormal = dscene->tri_vnormal.alloc(vert_size);
+ uint4 *tri_vindex = dscene->tri_vindex.alloc(tri_size);
+ uint *tri_patch = dscene->tri_patch.alloc(tri_size);
+ float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size);
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->pack_shaders(scene, &tri_shader[mesh->tri_offset]);
+ mesh->pack_normals(&vnormal[mesh->vert_offset]);
+ mesh->pack_verts(tri_prim_index,
+ &tri_vindex[mesh->tri_offset],
+ &tri_patch[mesh->tri_offset],
+ &tri_patch_uv[mesh->vert_offset],
+ mesh->vert_offset,
+ mesh->tri_offset);
+ if (progress.get_cancel())
+ return;
+ }
+
+ /* vertex coordinates */
+ progress.set_status("Updating Mesh", "Copying Mesh to device");
+
+ dscene->tri_shader.copy_to_device();
+ dscene->tri_vnormal.copy_to_device();
+ dscene->tri_vindex.copy_to_device();
+ dscene->tri_patch.copy_to_device();
+ dscene->tri_patch_uv.copy_to_device();
+ }
+
+ if (curve_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Strands to device");
+
+ float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size);
+ float4 *curves = dscene->curves.alloc(curve_size);
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->pack_curves(scene,
+ &curve_keys[mesh->curvekey_offset],
+ &curves[mesh->curve_offset],
+ mesh->curvekey_offset);
+ if (progress.get_cancel())
+ return;
+ }
+
+ dscene->curve_keys.copy_to_device();
+ dscene->curves.copy_to_device();
+ }
+
+ if (patch_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Patches to device");
+
+ uint *patch_data = dscene->patches.alloc(patch_size);
+
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->pack_patches(&patch_data[mesh->patch_offset],
+ mesh->vert_offset,
+ mesh->face_offset,
+ mesh->corner_offset);
+
+ if (mesh->patch_table) {
+ mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset],
+ mesh->patch_table_offset);
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ dscene->patches.copy_to_device();
+ }
+
+ if (for_displacement) {
+ float4 *prim_tri_verts = dscene->prim_tri_verts.alloc(tri_size * 3);
+ foreach (Mesh *mesh, scene->meshes) {
+ for (size_t i = 0; i < mesh->num_triangles(); ++i) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ size_t offset = 3 * (i + mesh->tri_offset);
+ prim_tri_verts[offset + 0] = float3_to_float4(mesh->verts[t.v[0]]);
+ prim_tri_verts[offset + 1] = float3_to_float4(mesh->verts[t.v[1]]);
+ prim_tri_verts[offset + 2] = float3_to_float4(mesh->verts[t.v[2]]);
+ }
+ }
+ dscene->prim_tri_verts.copy_to_device();
+ }
+}
+
+void MeshManager::device_update_bvh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ /* bvh build */
+ progress.set_status("Updating Scene BVH", "Building");
+
+ BVHParams bparams;
+ bparams.top_level = true;
+ bparams.bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout,
+ device->get_bvh_layout_mask());
+ bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ scene->params.use_bvh_unaligned_nodes;
+ bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
+ bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
+ bparams.bvh_type = scene->params.bvh_type;
+ bparams.curve_flags = dscene->data.curve.curveflags;
+ bparams.curve_subdivisions = dscene->data.curve.subdivisions;
+
+ VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
#ifdef WITH_EMBREE
- if(bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- if(dscene->data.bvh.scene) {
- BVHEmbree::destroy(dscene->data.bvh.scene);
- }
- }
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ if (dscene->data.bvh.scene) {
+ BVHEmbree::destroy(dscene->data.bvh.scene);
+ }
+ }
#endif
- BVH *bvh = BVH::create(bparams, scene->objects);
- bvh->build(progress, &device->stats);
+ BVH *bvh = BVH::create(bparams, scene->objects);
+ bvh->build(progress, &device->stats);
- if(progress.get_cancel()) {
+ if (progress.get_cancel()) {
#ifdef WITH_EMBREE
- if(bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- if(dscene->data.bvh.scene) {
- BVHEmbree::destroy(dscene->data.bvh.scene);
- }
- }
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ if (dscene->data.bvh.scene) {
+ BVHEmbree::destroy(dscene->data.bvh.scene);
+ }
+ }
#endif
- delete bvh;
- return;
- }
-
- /* copy to device */
- progress.set_status("Updating Scene BVH", "Copying BVH to device");
-
- PackedBVH& pack = bvh->pack;
-
- if(pack.nodes.size()) {
- dscene->bvh_nodes.steal_data(pack.nodes);
- dscene->bvh_nodes.copy_to_device();
- }
- if(pack.leaf_nodes.size()) {
- dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
- dscene->bvh_leaf_nodes.copy_to_device();
- }
- if(pack.object_node.size()) {
- dscene->object_node.steal_data(pack.object_node);
- dscene->object_node.copy_to_device();
- }
- if(pack.prim_tri_index.size()) {
- dscene->prim_tri_index.steal_data(pack.prim_tri_index);
- dscene->prim_tri_index.copy_to_device();
- }
- if(pack.prim_tri_verts.size()) {
- dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
- dscene->prim_tri_verts.copy_to_device();
- }
- if(pack.prim_type.size()) {
- dscene->prim_type.steal_data(pack.prim_type);
- dscene->prim_type.copy_to_device();
- }
- if(pack.prim_visibility.size()) {
- dscene->prim_visibility.steal_data(pack.prim_visibility);
- dscene->prim_visibility.copy_to_device();
- }
- if(pack.prim_index.size()) {
- dscene->prim_index.steal_data(pack.prim_index);
- dscene->prim_index.copy_to_device();
- }
- if(pack.prim_object.size()) {
- dscene->prim_object.steal_data(pack.prim_object);
- dscene->prim_object.copy_to_device();
- }
- if(pack.prim_time.size()) {
- dscene->prim_time.steal_data(pack.prim_time);
- dscene->prim_time.copy_to_device();
- }
-
- dscene->data.bvh.root = pack.root_index;
- dscene->data.bvh.bvh_layout = bparams.bvh_layout;
- dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
-
+ delete bvh;
+ return;
+ }
+
+ /* copy to device */
+ progress.set_status("Updating Scene BVH", "Copying BVH to device");
+
+ PackedBVH &pack = bvh->pack;
+
+ if (pack.nodes.size()) {
+ dscene->bvh_nodes.steal_data(pack.nodes);
+ dscene->bvh_nodes.copy_to_device();
+ }
+ if (pack.leaf_nodes.size()) {
+ dscene->bvh_leaf_nodes.steal_data(pack.leaf_nodes);
+ dscene->bvh_leaf_nodes.copy_to_device();
+ }
+ if (pack.object_node.size()) {
+ dscene->object_node.steal_data(pack.object_node);
+ dscene->object_node.copy_to_device();
+ }
+ if (pack.prim_tri_index.size()) {
+ dscene->prim_tri_index.steal_data(pack.prim_tri_index);
+ dscene->prim_tri_index.copy_to_device();
+ }
+ if (pack.prim_tri_verts.size()) {
+ dscene->prim_tri_verts.steal_data(pack.prim_tri_verts);
+ dscene->prim_tri_verts.copy_to_device();
+ }
+ if (pack.prim_type.size()) {
+ dscene->prim_type.steal_data(pack.prim_type);
+ dscene->prim_type.copy_to_device();
+ }
+ if (pack.prim_visibility.size()) {
+ dscene->prim_visibility.steal_data(pack.prim_visibility);
+ dscene->prim_visibility.copy_to_device();
+ }
+ if (pack.prim_index.size()) {
+ dscene->prim_index.steal_data(pack.prim_index);
+ dscene->prim_index.copy_to_device();
+ }
+ if (pack.prim_object.size()) {
+ dscene->prim_object.steal_data(pack.prim_object);
+ dscene->prim_object.copy_to_device();
+ }
+ if (pack.prim_time.size()) {
+ dscene->prim_time.steal_data(pack.prim_time);
+ dscene->prim_time.copy_to_device();
+ }
+
+ dscene->data.bvh.root = pack.root_index;
+ dscene->data.bvh.bvh_layout = bparams.bvh_layout;
+ dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
#ifdef WITH_EMBREE
- if(bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
- dscene->data.bvh.scene = ((BVHEmbree*)bvh)->scene;
- }
- else {
- dscene->data.bvh.scene = NULL;
- }
+ if (bparams.bvh_layout == BVH_LAYOUT_EMBREE) {
+ dscene->data.bvh.scene = ((BVHEmbree *)bvh)->scene;
+ }
+ else {
+ dscene->data.bvh.scene = NULL;
+ }
#endif
- delete bvh;
+ delete bvh;
}
-void MeshManager::device_update_preprocess(Device *device,
- Scene *scene,
- Progress& progress)
+void MeshManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress)
{
- if(!need_update && !need_flags_update) {
- return;
- }
+ if (!need_update && !need_flags_update) {
+ return;
+ }
- progress.set_status("Updating Meshes Flags");
+ progress.set_status("Updating Meshes Flags");
- /* Update flags. */
- bool volume_images_updated = false;
+ /* Update flags. */
+ bool volume_images_updated = false;
- foreach(Mesh *mesh, scene->meshes) {
- mesh->has_volume = false;
+ foreach (Mesh *mesh, scene->meshes) {
+ mesh->has_volume = false;
- foreach(const Shader *shader, mesh->used_shaders) {
- if(shader->has_volume) {
- mesh->has_volume = true;
- }
- if(shader->has_surface_bssrdf) {
- mesh->has_surface_bssrdf = true;
- }
- }
+ foreach (const Shader *shader, mesh->used_shaders) {
+ if (shader->has_volume) {
+ mesh->has_volume = true;
+ }
+ if (shader->has_surface_bssrdf) {
+ mesh->has_surface_bssrdf = true;
+ }
+ }
- if(need_update && mesh->has_volume) {
- /* Create volume meshes if there is voxel data. */
- bool has_voxel_attributes = false;
+ if (need_update && mesh->has_volume) {
+ /* Create volume meshes if there is voxel data. */
+ bool has_voxel_attributes = false;
- foreach(Attribute& attr, mesh->attributes.attributes) {
- if(attr.element == ATTR_ELEMENT_VOXEL) {
- has_voxel_attributes = true;
- }
- }
+ foreach (Attribute &attr, mesh->attributes.attributes) {
+ if (attr.element == ATTR_ELEMENT_VOXEL) {
+ has_voxel_attributes = true;
+ }
+ }
- if(has_voxel_attributes) {
- if(!volume_images_updated) {
- progress.set_status("Updating Meshes Volume Bounds");
- device_update_volume_images(device, scene, progress);
- volume_images_updated = true;
- }
+ if (has_voxel_attributes) {
+ if (!volume_images_updated) {
+ progress.set_status("Updating Meshes Volume Bounds");
+ device_update_volume_images(device, scene, progress);
+ volume_images_updated = true;
+ }
- create_volume_mesh(scene, mesh, progress);
- }
- }
- }
+ create_volume_mesh(scene, mesh, progress);
+ }
+ }
+ }
- need_flags_update = false;
+ need_flags_update = false;
}
void MeshManager::device_update_displacement_images(Device *device,
Scene *scene,
- Progress& progress)
-{
- progress.set_status("Updating Displacement Images");
- TaskPool pool;
- ImageManager *image_manager = scene->image_manager;
- set<int> bump_images;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update) {
- foreach(Shader *shader, mesh->used_shaders) {
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
- foreach(ShaderNode* node, shader->graph->nodes) {
- if(node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
- continue;
- }
-
- ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode*>(node);
- int slot = image_node->slot;
- if(slot != -1) {
- bump_images.insert(slot);
- }
- }
- }
- }
- }
- foreach(int slot, bump_images) {
- pool.push(function_bind(&ImageManager::device_update_slot,
- image_manager,
- device,
- scene,
- slot,
- &progress));
- }
- pool.wait_work();
-}
-
-void MeshManager::device_update_volume_images(Device *device,
- Scene *scene,
- Progress& progress)
-{
- progress.set_status("Updating Volume Images");
- TaskPool pool;
- ImageManager *image_manager = scene->image_manager;
- set<int> volume_images;
-
- foreach(Mesh *mesh, scene->meshes) {
- if(!mesh->need_update) {
- continue;
- }
-
- foreach(Attribute& attr, mesh->attributes.attributes) {
- if(attr.element != ATTR_ELEMENT_VOXEL) {
- continue;
- }
-
- VoxelAttribute *voxel = attr.data_voxel();
-
- if(voxel->slot != -1) {
- volume_images.insert(voxel->slot);
- }
- }
- }
-
- foreach(int slot, volume_images) {
- pool.push(function_bind(&ImageManager::device_update_slot,
- image_manager,
- device,
- scene,
- slot,
- &progress));
- }
- pool.wait_work();
-}
-
-void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
-{
- if(!need_update)
- return;
-
- VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
-
- bool true_displacement_used = false;
- size_t total_tess_needed = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->need_update_mesh)
- mesh->need_update = true;
- }
-
- if(mesh->need_update) {
- /* Update normals. */
- mesh->add_face_normals();
- mesh->add_vertex_normals();
-
- if(mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
- mesh->add_undisplaced();
- }
-
- /* Test if we need tessellation. */
- if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 &&
- mesh->subd_params)
- {
- total_tess_needed++;
- }
-
- /* Test if we need displacement. */
- if(mesh->has_true_displacement()) {
- true_displacement_used = true;
- }
-
- if(progress.get_cancel()) return;
- }
- }
-
- /* Tessellate meshes that are using subdivision */
- if(total_tess_needed) {
- Camera *dicing_camera = scene->dicing_camera;
- dicing_camera->update(scene);
-
- size_t i = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update &&
- mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
- mesh->num_subd_verts == 0 &&
- mesh->subd_params)
- {
- string msg = "Tessellating ";
- if(mesh->name == "")
- msg += string_printf("%u/%u", (uint)(i+1), (uint)total_tess_needed);
- else
- msg += string_printf("%s %u/%u", mesh->name.c_str(), (uint)(i+1), (uint)total_tess_needed);
-
- progress.set_status("Updating Mesh", msg);
-
- mesh->subd_params->camera = dicing_camera;
- DiagSplit dsplit(*mesh->subd_params);
- mesh->tessellate(&dsplit);
-
- i++;
-
- if(progress.get_cancel()) return;
- }
-
- }
- }
-
- /* Update images needed for true displacement. */
- bool old_need_object_flags_update = false;
- if(true_displacement_used) {
- VLOG(1) << "Updating images used for true displacement.";
- device_update_displacement_images(device, scene, progress);
- old_need_object_flags_update = scene->object_manager->need_flags_update;
- scene->object_manager->device_update_flags(device,
- dscene,
- scene,
- progress,
- false);
- }
-
- /* Device update. */
- device_free(device, dscene);
-
- mesh_calc_offset(scene);
- if(true_displacement_used) {
- device_update_mesh(device, dscene, scene, true, progress);
- }
- if(progress.get_cancel()) return;
-
- device_update_attributes(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
-
- /* Update displacement. */
- bool displacement_done = false;
- size_t num_bvh = 0;
-
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update) {
- if(displace(device, dscene, scene, mesh, progress)) {
- displacement_done = true;
- }
-
- if(mesh->need_build_bvh()) {
- num_bvh++;
- }
- }
-
- if(progress.get_cancel()) return;
- }
-
- /* Device re-update after displacement. */
- if(displacement_done) {
- device_free(device, dscene);
-
- device_update_attributes(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
- }
-
- TaskPool pool;
-
- size_t i = 0;
- foreach(Mesh *mesh, scene->meshes) {
- if(mesh->need_update) {
- pool.push(function_bind(&Mesh::compute_bvh,
- mesh,
- device,
- dscene,
- &scene->params,
- &progress,
- i,
- num_bvh));
- if(mesh->need_build_bvh()) {
- i++;
- }
- }
- }
-
- TaskPool::Summary summary;
- pool.wait_work(&summary);
- VLOG(2) << "Objects BVH build pool statistics:\n"
- << summary.full_report();
-
- foreach(Shader *shader, scene->shaders) {
- shader->need_update_mesh = false;
- }
-
- Scene::MotionType need_motion = scene->need_motion();
- bool motion_blur = need_motion == Scene::MOTION_BLUR;
-
- /* Update objects. */
- vector<Object *> volume_objects;
- foreach(Object *object, scene->objects) {
- object->compute_bounds(motion_blur);
- }
-
- if(progress.get_cancel()) return;
-
- device_update_bvh(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
-
- device_update_mesh(device, dscene, scene, false, progress);
- if(progress.get_cancel()) return;
-
- need_update = false;
-
- if(true_displacement_used) {
- /* Re-tag flags for update, so they're re-evaluated
- * for meshes with correct bounding boxes.
- *
- * This wouldn't cause wrong results, just true
- * displacement might be less optimal ot calculate.
- */
- scene->object_manager->need_flags_update = old_need_object_flags_update;
- }
+ Progress &progress)
+{
+ progress.set_status("Updating Displacement Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> bump_images;
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update) {
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+ foreach (ShaderNode *node, shader->graph->nodes) {
+ if (node->special_type != SHADER_SPECIAL_TYPE_IMAGE_SLOT) {
+ continue;
+ }
+
+ ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode *>(node);
+ int slot = image_node->slot;
+ if (slot != -1) {
+ bump_images.insert(slot);
+ }
+ }
+ }
+ }
+ }
+ foreach (int slot, bump_images) {
+ pool.push(function_bind(
+ &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
+ }
+ pool.wait_work();
+}
+
+void MeshManager::device_update_volume_images(Device *device, Scene *scene, Progress &progress)
+{
+ progress.set_status("Updating Volume Images");
+ TaskPool pool;
+ ImageManager *image_manager = scene->image_manager;
+ set<int> volume_images;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ if (!mesh->need_update) {
+ continue;
+ }
+
+ foreach (Attribute &attr, mesh->attributes.attributes) {
+ if (attr.element != ATTR_ELEMENT_VOXEL) {
+ continue;
+ }
+
+ VoxelAttribute *voxel = attr.data_voxel();
+
+ if (voxel->slot != -1) {
+ volume_images.insert(voxel->slot);
+ }
+ }
+ }
+
+ foreach (int slot, volume_images) {
+ pool.push(function_bind(
+ &ImageManager::device_update_slot, image_manager, device, scene, slot, &progress));
+ }
+ pool.wait_work();
+}
+
+void MeshManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
+{
+ if (!need_update)
+ return;
+
+ VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
+
+ bool true_displacement_used = false;
+ size_t total_tess_needed = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->need_update_mesh)
+ mesh->need_update = true;
+ }
+
+ if (mesh->need_update) {
+ /* Update normals. */
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+
+ if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
+ mesh->add_undisplaced();
+ }
+
+ /* Test if we need tessellation. */
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE && mesh->num_subd_verts == 0 &&
+ mesh->subd_params) {
+ total_tess_needed++;
+ }
+
+ /* Test if we need displacement. */
+ if (mesh->has_true_displacement()) {
+ true_displacement_used = true;
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ /* Tessellate meshes that are using subdivision */
+ if (total_tess_needed) {
+ Camera *dicing_camera = scene->dicing_camera;
+ dicing_camera->update(scene);
+
+ size_t i = 0;
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update && mesh->subdivision_type != Mesh::SUBDIVISION_NONE &&
+ mesh->num_subd_verts == 0 && mesh->subd_params) {
+ string msg = "Tessellating ";
+ if (mesh->name == "")
+ msg += string_printf("%u/%u", (uint)(i + 1), (uint)total_tess_needed);
+ else
+ msg += string_printf(
+ "%s %u/%u", mesh->name.c_str(), (uint)(i + 1), (uint)total_tess_needed);
+
+ progress.set_status("Updating Mesh", msg);
+
+ mesh->subd_params->camera = dicing_camera;
+ DiagSplit dsplit(*mesh->subd_params);
+ mesh->tessellate(&dsplit);
+
+ i++;
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+ }
+
+ /* Update images needed for true displacement. */
+ bool old_need_object_flags_update = false;
+ if (true_displacement_used) {
+ VLOG(1) << "Updating images used for true displacement.";
+ device_update_displacement_images(device, scene, progress);
+ old_need_object_flags_update = scene->object_manager->need_flags_update;
+ scene->object_manager->device_update_flags(device, dscene, scene, progress, false);
+ }
+
+ /* Device update. */
+ device_free(device, dscene);
+
+ mesh_calc_offset(scene);
+ if (true_displacement_used) {
+ device_update_mesh(device, dscene, scene, true, progress);
+ }
+ if (progress.get_cancel())
+ return;
+
+ device_update_attributes(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
+ /* Update displacement. */
+ bool displacement_done = false;
+ size_t num_bvh = 0;
+
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update) {
+ if (displace(device, dscene, scene, mesh, progress)) {
+ displacement_done = true;
+ }
+
+ if (mesh->need_build_bvh()) {
+ num_bvh++;
+ }
+ }
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ /* Device re-update after displacement. */
+ if (displacement_done) {
+ device_free(device, dscene);
+
+ device_update_attributes(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+ }
+
+ TaskPool pool;
+
+ size_t i = 0;
+ foreach (Mesh *mesh, scene->meshes) {
+ if (mesh->need_update) {
+ pool.push(function_bind(
+ &Mesh::compute_bvh, mesh, device, dscene, &scene->params, &progress, i, num_bvh));
+ if (mesh->need_build_bvh()) {
+ i++;
+ }
+ }
+ }
+
+ TaskPool::Summary summary;
+ pool.wait_work(&summary);
+ VLOG(2) << "Objects BVH build pool statistics:\n" << summary.full_report();
+
+ foreach (Shader *shader, scene->shaders) {
+ shader->need_update_mesh = false;
+ }
+
+ Scene::MotionType need_motion = scene->need_motion();
+ bool motion_blur = need_motion == Scene::MOTION_BLUR;
+
+ /* Update objects. */
+ vector<Object *> volume_objects;
+ foreach (Object *object, scene->objects) {
+ object->compute_bounds(motion_blur);
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ device_update_bvh(device, dscene, scene, progress);
+ if (progress.get_cancel())
+ return;
+
+ device_update_mesh(device, dscene, scene, false, progress);
+ if (progress.get_cancel())
+ return;
+
+ need_update = false;
+
+ if (true_displacement_used) {
+ /* Re-tag flags for update, so they're re-evaluated
+ * for meshes with correct bounding boxes.
+ *
+ * This wouldn't cause wrong results, just true
+ * displacement might be less optimal ot calculate.
+ */
+ scene->object_manager->need_flags_update = old_need_object_flags_update;
+ }
}
void MeshManager::device_free(Device *device, DeviceScene *dscene)
{
- dscene->bvh_nodes.free();
- dscene->bvh_leaf_nodes.free();
- dscene->object_node.free();
- dscene->prim_tri_verts.free();
- dscene->prim_tri_index.free();
- dscene->prim_type.free();
- dscene->prim_visibility.free();
- dscene->prim_index.free();
- dscene->prim_object.free();
- dscene->prim_time.free();
- dscene->tri_shader.free();
- dscene->tri_vnormal.free();
- dscene->tri_vindex.free();
- dscene->tri_patch.free();
- dscene->tri_patch_uv.free();
- dscene->curves.free();
- dscene->curve_keys.free();
- dscene->patches.free();
- dscene->attributes_map.free();
- dscene->attributes_float.free();
- dscene->attributes_float2.free();
- dscene->attributes_float3.free();
- dscene->attributes_uchar4.free();
+ dscene->bvh_nodes.free();
+ dscene->bvh_leaf_nodes.free();
+ dscene->object_node.free();
+ dscene->prim_tri_verts.free();
+ dscene->prim_tri_index.free();
+ dscene->prim_type.free();
+ dscene->prim_visibility.free();
+ dscene->prim_index.free();
+ dscene->prim_object.free();
+ dscene->prim_time.free();
+ dscene->tri_shader.free();
+ dscene->tri_vnormal.free();
+ dscene->tri_vindex.free();
+ dscene->tri_patch.free();
+ dscene->tri_patch_uv.free();
+ dscene->curves.free();
+ dscene->curve_keys.free();
+ dscene->patches.free();
+ dscene->attributes_map.free();
+ dscene->attributes_float.free();
+ dscene->attributes_float2.free();
+ dscene->attributes_float3.free();
+ dscene->attributes_uchar4.free();
#ifdef WITH_OSL
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
- if(og) {
- og->object_name_map.clear();
- og->attribute_map.clear();
- og->object_names.clear();
- }
+ if (og) {
+ og->object_name_map.clear();
+ og->attribute_map.clear();
+ og->object_names.clear();
+ }
#else
- (void) device;
+ (void)device;
#endif
}
void MeshManager::tag_update(Scene *scene)
{
- need_update = true;
- scene->object_manager->need_update = true;
+ need_update = true;
+ scene->object_manager->need_update = true;
}
void MeshManager::collect_statistics(const Scene *scene, RenderStats *stats)
{
- foreach(Mesh *mesh, scene->meshes) {
- stats->mesh.geometry.add_entry(
- NamedSizeEntry(string(mesh->name.c_str()),
- mesh->get_total_size_in_bytes()));
- }
+ foreach (Mesh *mesh, scene->meshes) {
+ stats->mesh.geometry.add_entry(
+ NamedSizeEntry(string(mesh->name.c_str()), mesh->get_total_size_in_bytes()));
+ }
}
bool Mesh::need_attribute(Scene *scene, AttributeStandard std)
{
- if(std == ATTR_STD_NONE)
- return false;
+ if (std == ATTR_STD_NONE)
+ return false;
- if(scene->need_global_attribute(std))
- return true;
+ if (scene->need_global_attribute(std))
+ return true;
- foreach(Shader *shader, used_shaders)
- if(shader->attributes.find(std))
- return true;
+ foreach (Shader *shader, used_shaders)
+ if (shader->attributes.find(std))
+ return true;
- return false;
+ return false;
}
bool Mesh::need_attribute(Scene * /*scene*/, ustring name)
{
- if(name == ustring())
- return false;
+ if (name == ustring())
+ return false;
- foreach(Shader *shader, used_shaders)
- if(shader->attributes.find(name))
- return true;
+ foreach (Shader *shader, used_shaders)
+ if (shader->attributes.find(name))
+ return true;
- return false;
+ return false;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 789d1cc2b54..05c67ccb3b7 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -50,344 +50,352 @@ struct PackedPatchTable;
/* Mesh */
class Mesh : public Node {
-public:
- NODE_DECLARE
-
- /* Mesh Triangle */
- struct Triangle {
- int v[3];
-
- void bounds_grow(const float3 *verts, BoundBox& bounds) const;
-
- void motion_verts(const float3 *verts,
- const float3 *vert_steps,
- size_t num_verts,
- size_t num_steps,
- float time,
- float3 r_verts[3]) const;
-
- void verts_for_step(const float3 *verts,
- const float3 *vert_steps,
- size_t num_verts,
- size_t num_steps,
- size_t step,
- float3 r_verts[3]) const;
-
- float3 compute_normal(const float3 *verts) const;
-
- bool valid(const float3 *verts) const;
- };
-
- Triangle get_triangle(size_t i) const
- {
- Triangle tri = {{triangles[i*3 + 0],
- triangles[i*3 + 1],
- triangles[i*3 + 2]}};
- return tri;
- }
-
- size_t num_triangles() const
- {
- return triangles.size() / 3;
- }
-
- /* Mesh Curve */
- struct Curve {
- int first_key;
- int num_keys;
-
- int num_segments() { return num_keys - 1; }
-
- void bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- BoundBox& bounds) const;
- void bounds_grow(float4 keys[4], BoundBox& bounds) const;
- void bounds_grow(const int k,
- const float3 *curve_keys,
- const float *curve_radius,
- const Transform& aligned_space,
- BoundBox& bounds) const;
-
- void motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0, size_t k1,
- float4 r_keys[2]) const;
- void cardinal_motion_keys(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- float time,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
- float4 r_keys[4]) const;
-
- void keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0, size_t k1,
- float4 r_keys[2]) const;
- void cardinal_keys_for_step(const float3 *curve_keys,
- const float *curve_radius,
- const float3 *key_steps,
- size_t num_curve_keys,
- size_t num_steps,
- size_t step,
- size_t k0, size_t k1,
- size_t k2, size_t k3,
- float4 r_keys[4]) const;
- };
-
- Curve get_curve(size_t i) const
- {
- int first = curve_first_key[i];
- int next_first = (i+1 < curve_first_key.size()) ? curve_first_key[i+1] : curve_keys.size();
-
- Curve curve = {first, next_first - first};
- return curve;
- }
-
- size_t num_curves() const
- {
- return curve_first_key.size();
- }
-
- /* Mesh SubdFace */
- struct SubdFace {
- int start_corner;
- int num_corners;
- int shader;
- bool smooth;
- int ptex_offset;
-
- bool is_quad() { return num_corners == 4; }
- float3 normal(const Mesh *mesh) const;
- int num_ptex_faces() const { return num_corners == 4 ? 1 : num_corners; }
- };
-
- struct SubdEdgeCrease {
- int v[2];
- float crease;
- };
-
- enum SubdivisionType {
- SUBDIVISION_NONE,
- SUBDIVISION_LINEAR,
- SUBDIVISION_CATMULL_CLARK,
- };
-
- SubdivisionType subdivision_type;
-
- /* Mesh Data */
- enum GeometryFlags {
- GEOMETRY_NONE = 0,
- GEOMETRY_TRIANGLES = (1 << 0),
- GEOMETRY_CURVES = (1 << 1),
- };
- int geometry_flags; /* used to distinguish meshes with no verts
- and meshed for which geometry is not created */
-
- array<int> triangles;
- array<float3> verts;
- array<int> shader;
- array<bool> smooth;
-
- /* used for storing patch info for subd triangles, only allocated if there are patches */
- array<int> triangle_patch; /* must be < 0 for non subd triangles */
- array<float2> vert_patch_uv;
-
- float volume_isovalue;
- bool has_volume; /* Set in the device_update_flags(). */
- bool has_surface_bssrdf; /* Set in the device_update_flags(). */
-
- array<float3> curve_keys;
- array<float> curve_radius;
- array<int> curve_first_key;
- array<int> curve_shader;
-
- array<SubdFace> subd_faces;
- array<int> subd_face_corners;
- int num_ngons;
-
- array<SubdEdgeCrease> subd_creases;
-
- SubdParams *subd_params;
-
- vector<Shader*> used_shaders;
- AttributeSet attributes;
- AttributeSet curve_attributes;
- AttributeSet subd_attributes;
-
- BoundBox bounds;
- bool transform_applied;
- bool transform_negative_scaled;
- Transform transform_normal;
-
- PackedPatchTable *patch_table;
-
- uint motion_steps;
- bool use_motion_blur;
-
- /* Update Flags */
- bool need_update;
- bool need_update_rebuild;
-
- /* BVH */
- BVH *bvh;
- size_t tri_offset;
- size_t vert_offset;
-
- size_t curve_offset;
- size_t curvekey_offset;
-
- size_t patch_offset;
- size_t patch_table_offset;
- size_t face_offset;
- size_t corner_offset;
-
- size_t attr_map_offset;
-
- size_t num_subd_verts;
-
- /* Functions */
- Mesh();
- ~Mesh();
-
- void resize_mesh(int numverts, int numfaces);
- void reserve_mesh(int numverts, int numfaces);
- void resize_curves(int numcurves, int numkeys);
- void reserve_curves(int numcurves, int numkeys);
- void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
- void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
- void clear(bool preserve_voxel_data = false);
- void add_vertex(float3 P);
- void add_vertex_slow(float3 P);
- void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
- void add_curve_key(float3 loc, float radius);
- void add_curve(int first_key, int shader);
- void add_subd_face(int* corners, int num_corners, int shader_, bool smooth_);
-
- void compute_bounds();
- void add_face_normals();
- void add_vertex_normals();
- void add_undisplaced();
-
- void pack_shaders(Scene *scene, uint *shader);
- void pack_normals(float4 *vnormal);
- void pack_verts(const vector<uint>& tri_prim_index,
- uint4 *tri_vindex,
- uint *tri_patch,
- float2 *tri_patch_uv,
- size_t vert_offset,
- size_t tri_offset);
- void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
- void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
-
- void compute_bvh(Device *device,
- DeviceScene *dscene,
- SceneParams *params,
- Progress *progress,
- int n,
- int total);
-
- bool need_attribute(Scene *scene, AttributeStandard std);
- bool need_attribute(Scene *scene, ustring name);
-
- void tag_update(Scene *scene, bool rebuild);
-
- bool has_motion_blur() const;
- bool has_true_displacement() const;
-
- /* Convert between normalized -1..1 motion time and index
- * in the VERTEX_MOTION attribute. */
- float motion_time(int step) const;
- int motion_step(float time) const;
-
- /* Check whether the mesh should have own BVH built separately. Briefly,
- * own BVH is needed for mesh, if:
- *
- * - It is instanced multiple times, so each instance object should share the
- * same BVH tree.
- * - Special ray intersection is needed, for example to limit subsurface rays
- * to only the mesh itself.
- */
- bool need_build_bvh() const;
-
- /* Check if the mesh should be treated as instanced. */
- bool is_instanced() const;
-
- void tessellate(DiagSplit *split);
+ public:
+ NODE_DECLARE
+
+ /* Mesh Triangle */
+ struct Triangle {
+ int v[3];
+
+ void bounds_grow(const float3 *verts, BoundBox &bounds) const;
+
+ void motion_verts(const float3 *verts,
+ const float3 *vert_steps,
+ size_t num_verts,
+ size_t num_steps,
+ float time,
+ float3 r_verts[3]) const;
+
+ void verts_for_step(const float3 *verts,
+ const float3 *vert_steps,
+ size_t num_verts,
+ size_t num_steps,
+ size_t step,
+ float3 r_verts[3]) const;
+
+ float3 compute_normal(const float3 *verts) const;
+
+ bool valid(const float3 *verts) const;
+ };
+
+ Triangle get_triangle(size_t i) const
+ {
+ Triangle tri = {{triangles[i * 3 + 0], triangles[i * 3 + 1], triangles[i * 3 + 2]}};
+ return tri;
+ }
+
+ size_t num_triangles() const
+ {
+ return triangles.size() / 3;
+ }
+
+ /* Mesh Curve */
+ struct Curve {
+ int first_key;
+ int num_keys;
+
+ int num_segments()
+ {
+ return num_keys - 1;
+ }
+
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox &bounds) const;
+ void bounds_grow(float4 keys[4], BoundBox &bounds) const;
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ const Transform &aligned_space,
+ BoundBox &bounds) const;
+
+ void motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const;
+ void cardinal_motion_keys(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ float time,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const;
+
+ void keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ float4 r_keys[2]) const;
+ void cardinal_keys_for_step(const float3 *curve_keys,
+ const float *curve_radius,
+ const float3 *key_steps,
+ size_t num_curve_keys,
+ size_t num_steps,
+ size_t step,
+ size_t k0,
+ size_t k1,
+ size_t k2,
+ size_t k3,
+ float4 r_keys[4]) const;
+ };
+
+ Curve get_curve(size_t i) const
+ {
+ int first = curve_first_key[i];
+ int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] : curve_keys.size();
+
+ Curve curve = {first, next_first - first};
+ return curve;
+ }
+
+ size_t num_curves() const
+ {
+ return curve_first_key.size();
+ }
+
+ /* Mesh SubdFace */
+ struct SubdFace {
+ int start_corner;
+ int num_corners;
+ int shader;
+ bool smooth;
+ int ptex_offset;
+
+ bool is_quad()
+ {
+ return num_corners == 4;
+ }
+ float3 normal(const Mesh *mesh) const;
+ int num_ptex_faces() const
+ {
+ return num_corners == 4 ? 1 : num_corners;
+ }
+ };
+
+ struct SubdEdgeCrease {
+ int v[2];
+ float crease;
+ };
+
+ enum SubdivisionType {
+ SUBDIVISION_NONE,
+ SUBDIVISION_LINEAR,
+ SUBDIVISION_CATMULL_CLARK,
+ };
+
+ SubdivisionType subdivision_type;
+
+ /* Mesh Data */
+ enum GeometryFlags {
+ GEOMETRY_NONE = 0,
+ GEOMETRY_TRIANGLES = (1 << 0),
+ GEOMETRY_CURVES = (1 << 1),
+ };
+ int geometry_flags; /* used to distinguish meshes with no verts
+ and meshed for which geometry is not created */
+
+ array<int> triangles;
+ array<float3> verts;
+ array<int> shader;
+ array<bool> smooth;
+
+ /* used for storing patch info for subd triangles, only allocated if there are patches */
+ array<int> triangle_patch; /* must be < 0 for non subd triangles */
+ array<float2> vert_patch_uv;
+
+ float volume_isovalue;
+ bool has_volume; /* Set in the device_update_flags(). */
+ bool has_surface_bssrdf; /* Set in the device_update_flags(). */
+
+ array<float3> curve_keys;
+ array<float> curve_radius;
+ array<int> curve_first_key;
+ array<int> curve_shader;
+
+ array<SubdFace> subd_faces;
+ array<int> subd_face_corners;
+ int num_ngons;
+
+ array<SubdEdgeCrease> subd_creases;
+
+ SubdParams *subd_params;
+
+ vector<Shader *> used_shaders;
+ AttributeSet attributes;
+ AttributeSet curve_attributes;
+ AttributeSet subd_attributes;
+
+ BoundBox bounds;
+ bool transform_applied;
+ bool transform_negative_scaled;
+ Transform transform_normal;
+
+ PackedPatchTable *patch_table;
+
+ uint motion_steps;
+ bool use_motion_blur;
+
+ /* Update Flags */
+ bool need_update;
+ bool need_update_rebuild;
+
+ /* BVH */
+ BVH *bvh;
+ size_t tri_offset;
+ size_t vert_offset;
+
+ size_t curve_offset;
+ size_t curvekey_offset;
+
+ size_t patch_offset;
+ size_t patch_table_offset;
+ size_t face_offset;
+ size_t corner_offset;
+
+ size_t attr_map_offset;
+
+ size_t num_subd_verts;
+
+ /* Functions */
+ Mesh();
+ ~Mesh();
+
+ void resize_mesh(int numverts, int numfaces);
+ void reserve_mesh(int numverts, int numfaces);
+ void resize_curves(int numcurves, int numkeys);
+ void reserve_curves(int numcurves, int numkeys);
+ void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
+ void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
+ void clear(bool preserve_voxel_data = false);
+ void add_vertex(float3 P);
+ void add_vertex_slow(float3 P);
+ void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
+ void add_curve_key(float3 loc, float radius);
+ void add_curve(int first_key, int shader);
+ void add_subd_face(int *corners, int num_corners, int shader_, bool smooth_);
+
+ void compute_bounds();
+ void add_face_normals();
+ void add_vertex_normals();
+ void add_undisplaced();
+
+ void pack_shaders(Scene *scene, uint *shader);
+ void pack_normals(float4 *vnormal);
+ void pack_verts(const vector<uint> &tri_prim_index,
+ uint4 *tri_vindex,
+ uint *tri_patch,
+ float2 *tri_patch_uv,
+ size_t vert_offset,
+ size_t tri_offset);
+ void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
+ void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
+
+ void compute_bvh(Device *device,
+ DeviceScene *dscene,
+ SceneParams *params,
+ Progress *progress,
+ int n,
+ int total);
+
+ bool need_attribute(Scene *scene, AttributeStandard std);
+ bool need_attribute(Scene *scene, ustring name);
+
+ void tag_update(Scene *scene, bool rebuild);
+
+ bool has_motion_blur() const;
+ bool has_true_displacement() const;
+
+ /* Convert between normalized -1..1 motion time and index
+ * in the VERTEX_MOTION attribute. */
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+
+ /* Check whether the mesh should have own BVH built separately. Briefly,
+ * own BVH is needed for mesh, if:
+ *
+ * - It is instanced multiple times, so each instance object should share the
+ * same BVH tree.
+ * - Special ray intersection is needed, for example to limit subsurface rays
+ * to only the mesh itself.
+ */
+ bool need_build_bvh() const;
+
+ /* Check if the mesh should be treated as instanced. */
+ bool is_instanced() const;
+
+ void tessellate(DiagSplit *split);
};
/* Mesh Manager */
class MeshManager {
-public:
- bool need_update;
- bool need_flags_update;
+ public:
+ bool need_update;
+ bool need_flags_update;
- MeshManager();
- ~MeshManager();
+ MeshManager();
+ ~MeshManager();
- bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress);
+ bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress);
- /* attributes */
- void update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
- void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
+ /* attributes */
+ void update_osl_attributes(Device *device,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes);
+ void update_svm_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ vector<AttributeRequestSet> &mesh_attributes);
- void device_update_preprocess(Device *device, Scene *scene, Progress& progress);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+ void device_update_preprocess(Device *device, Scene *scene, Progress &progress);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_free(Device *device, DeviceScene *dscene);
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
- void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
+ void create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress);
- void collect_statistics(const Scene *scene, RenderStats *stats);
+ void collect_statistics(const Scene *scene, RenderStats *stats);
-protected:
- /* Calculate verts/triangles/curves offsets in global arrays. */
- void mesh_calc_offset(Scene *scene);
+ protected:
+ /* Calculate verts/triangles/curves offsets in global arrays. */
+ void mesh_calc_offset(Scene *scene);
- void device_update_object(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
+ void device_update_object(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
- void device_update_mesh(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- bool for_displacement,
- Progress& progress);
+ void device_update_mesh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ bool for_displacement,
+ Progress &progress);
- void device_update_attributes(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
+ void device_update_attributes(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
- void device_update_bvh(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
+ void device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
- void device_update_displacement_images(Device *device,
- Scene *scene,
- Progress& progress);
+ void device_update_displacement_images(Device *device, Scene *scene, Progress &progress);
- void device_update_volume_images(Device *device,
- Scene *scene,
- Progress& progress);
+ void device_update_volume_images(Device *device, Scene *scene, Progress &progress);
};
CCL_NAMESPACE_END
-#endif /* __MESH_H__ */
+#endif /* __MESH_H__ */
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index 53b9bfa3451..5ae9348d83e 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -26,296 +26,301 @@
CCL_NAMESPACE_BEGIN
-static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts)
+static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
{
- float3 v0 = verts[t.v[0]];
- float3 v1 = verts[t.v[1]];
- float3 v2 = verts[t.v[2]];
+ float3 v0 = verts[t.v[0]];
+ float3 v1 = verts[t.v[1]];
+ float3 v2 = verts[t.v[2]];
- float3 norm = cross(v1 - v0, v2 - v0);
- float normlen = len(norm);
+ float3 norm = cross(v1 - v0, v2 - v0);
+ float normlen = len(norm);
- if(normlen == 0.0f)
- return make_float3(1.0f, 0.0f, 0.0f);
+ if (normlen == 0.0f)
+ return make_float3(1.0f, 0.0f, 0.0f);
- return norm / normlen;
+ return norm / normlen;
}
-bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress)
+bool MeshManager::displace(
+ Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress &progress)
{
- /* verify if we have a displacement shader */
- if(!mesh->has_true_displacement()) {
- return false;
- }
-
- string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
- progress.set_status("Updating Mesh", msg);
-
- /* find object index. todo: is arbitrary */
- size_t object_index = OBJECT_NONE;
-
- for(size_t i = 0; i < scene->objects.size(); i++) {
- if(scene->objects[i]->mesh == mesh) {
- object_index = i;
- break;
- }
- }
-
- /* setup input for device task */
- const size_t num_verts = mesh->verts.size();
- vector<bool> done(num_verts, false);
- device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
- uint4 *d_input_data = d_input.alloc(num_verts);
- size_t d_input_size = 0;
-
- size_t num_triangles = mesh->num_triangles();
- for(size_t i = 0; i < num_triangles; i++) {
- Mesh::Triangle t = mesh->get_triangle(i);
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
-
- for(int j = 0; j < 3; j++) {
- if(done[t.v[j]])
- continue;
-
- done[t.v[j]] = true;
-
- /* set up object, primitive and barycentric coordinates */
- int object = object_index;
- int prim = mesh->tri_offset + i;
- float u, v;
-
- switch(j) {
- case 0:
- u = 1.0f;
- v = 0.0f;
- break;
- case 1:
- u = 0.0f;
- v = 1.0f;
- break;
- default:
- u = 0.0f;
- v = 0.0f;
- break;
- }
-
- /* back */
- uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
- d_input_data[d_input_size++] = in;
- }
- }
-
- if(d_input_size == 0)
- return false;
-
- /* run device task */
- device_vector<float4> d_output(device, "displace_output", MEM_READ_WRITE);
- d_output.alloc(d_input_size);
- d_output.zero_to_device();
- d_input.copy_to_device();
-
- /* needs to be up to data for attribute access */
- device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
-
- DeviceTask task(DeviceTask::SHADER);
- task.shader_input = d_input.device_pointer;
- task.shader_output = d_output.device_pointer;
- task.shader_eval_type = SHADER_EVAL_DISPLACE;
- task.shader_x = 0;
- task.shader_w = d_output.size();
- task.num_samples = 1;
- task.get_cancel = function_bind(&Progress::get_cancel, &progress);
-
- device->task_add(task);
- device->task_wait();
-
- if(progress.get_cancel()) {
- d_input.free();
- d_output.free();
- return false;
- }
-
- d_output.copy_from_device(0, 1, d_output.size());
- d_input.free();
-
- /* read result */
- done.clear();
- done.resize(num_verts, false);
- int k = 0;
-
- float4 *offset = d_output.data();
-
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(size_t i = 0; i < num_triangles; i++) {
- Mesh::Triangle t = mesh->get_triangle(i);
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
- continue;
- }
-
- for(int j = 0; j < 3; j++) {
- if(!done[t.v[j]]) {
- done[t.v[j]] = true;
- float3 off = float4_to_float3(offset[k++]);
- /* Avoid illegal vertex coordinates. */
- off = ensure_finite3(off);
- mesh->verts[t.v[j]] += off;
- if(attr_mP != NULL) {
- for(int step = 0; step < mesh->motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*num_verts;
- mP[t.v[j]] += off;
- }
- }
- }
- }
- }
-
- d_output.free();
-
- /* for displacement method both, we only need to recompute the face
- * normals, as bump mapping in the shader will already alter the
- * vertex normal, so we start from the non-displaced vertex normals
- * to avoid applying the perturbation twice. */
- mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
- mesh->add_face_normals();
-
- bool need_recompute_vertex_normals = false;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
- need_recompute_vertex_normals = true;
- break;
- }
- }
-
- if(need_recompute_vertex_normals) {
- bool flip = mesh->transform_negative_scaled;
- vector<bool> tri_has_true_disp(num_triangles, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- int shader_index = mesh->shader[i];
- Shader *shader = (shader_index < mesh->used_shaders.size()) ?
- mesh->used_shaders[shader_index] : scene->default_surface;
-
- tri_has_true_disp[i] = shader->has_displacement && shader->displacement_method == DISPLACE_TRUE;
- }
-
- /* static vertex normals */
-
- /* get attributes */
- Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
- Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
-
- float3 *fN = attr_fN->data_float3();
- float3 *vN = attr_vN->data_float3();
-
- /* compute vertex normals */
-
- /* zero vertex normals on triangles with true displacement */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- /* add face normals to vertex normals */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- vN[mesh->get_triangle(i).v[j]] += fN[i];
- }
- }
- }
-
- /* normalize vertex normals */
- done.clear();
- done.resize(num_verts, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- int vert = mesh->get_triangle(i).v[j];
-
- if(done[vert]) {
- continue;
- }
-
- vN[vert] = normalize(vN[vert]);
- if(flip)
- vN[vert] = -vN[vert];
-
- done[vert] = true;
- }
- }
- }
-
- /* motion vertex normals */
- Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(mesh->has_motion_blur() && attr_mP && attr_mN) {
- for(int step = 0; step < mesh->motion_steps - 1; step++) {
- float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
- float3 *mN = attr_mN->data_float3() + step*mesh->verts.size();
-
- /* compute */
-
- /* zero vertex normals on triangles with true displacement */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
- }
- }
- }
-
- /* add face normals to vertex normals */
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
- mN[mesh->get_triangle(i).v[j]] += fN;
- }
- }
- }
-
- /* normalize vertex normals */
- done.clear();
- done.resize(num_verts, false);
-
- for(size_t i = 0; i < num_triangles; i++) {
- if(tri_has_true_disp[i]) {
- for(size_t j = 0; j < 3; j++) {
- int vert = mesh->get_triangle(i).v[j];
-
- if(done[vert]) {
- continue;
- }
-
- mN[vert] = normalize(mN[vert]);
- if(flip)
- mN[vert] = -mN[vert];
-
- done[vert] = true;
- }
- }
- }
- }
- }
- }
-
- return true;
+ /* verify if we have a displacement shader */
+ if (!mesh->has_true_displacement()) {
+ return false;
+ }
+
+ string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
+ progress.set_status("Updating Mesh", msg);
+
+ /* find object index. todo: is arbitrary */
+ size_t object_index = OBJECT_NONE;
+
+ for (size_t i = 0; i < scene->objects.size(); i++) {
+ if (scene->objects[i]->mesh == mesh) {
+ object_index = i;
+ break;
+ }
+ }
+
+ /* setup input for device task */
+ const size_t num_verts = mesh->verts.size();
+ vector<bool> done(num_verts, false);
+ device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
+ uint4 *d_input_data = d_input.alloc(num_verts);
+ size_t d_input_size = 0;
+
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (done[t.v[j]])
+ continue;
+
+ done[t.v[j]] = true;
+
+ /* set up object, primitive and barycentric coordinates */
+ int object = object_index;
+ int prim = mesh->tri_offset + i;
+ float u, v;
+
+ switch (j) {
+ case 0:
+ u = 1.0f;
+ v = 0.0f;
+ break;
+ case 1:
+ u = 0.0f;
+ v = 1.0f;
+ break;
+ default:
+ u = 0.0f;
+ v = 0.0f;
+ break;
+ }
+
+ /* back */
+ uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
+ d_input_data[d_input_size++] = in;
+ }
+ }
+
+ if (d_input_size == 0)
+ return false;
+
+ /* run device task */
+ device_vector<float4> d_output(device, "displace_output", MEM_READ_WRITE);
+ d_output.alloc(d_input_size);
+ d_output.zero_to_device();
+ d_input.copy_to_device();
+
+ /* needs to be up to data for attribute access */
+ device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
+
+ DeviceTask task(DeviceTask::SHADER);
+ task.shader_input = d_input.device_pointer;
+ task.shader_output = d_output.device_pointer;
+ task.shader_eval_type = SHADER_EVAL_DISPLACE;
+ task.shader_x = 0;
+ task.shader_w = d_output.size();
+ task.num_samples = 1;
+ task.get_cancel = function_bind(&Progress::get_cancel, &progress);
+
+ device->task_add(task);
+ device->task_wait();
+
+ if (progress.get_cancel()) {
+ d_input.free();
+ d_output.free();
+ return false;
+ }
+
+ d_output.copy_from_device(0, 1, d_output.size());
+ d_input.free();
+
+ /* read result */
+ done.clear();
+ done.resize(num_verts, false);
+ int k = 0;
+
+ float4 *offset = d_output.data();
+
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ for (size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ if (!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
+ continue;
+ }
+
+ for (int j = 0; j < 3; j++) {
+ if (!done[t.v[j]]) {
+ done[t.v[j]] = true;
+ float3 off = float4_to_float3(offset[k++]);
+ /* Avoid illegal vertex coordinates. */
+ off = ensure_finite3(off);
+ mesh->verts[t.v[j]] += off;
+ if (attr_mP != NULL) {
+ for (int step = 0; step < mesh->motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * num_verts;
+ mP[t.v[j]] += off;
+ }
+ }
+ }
+ }
+ }
+
+ d_output.free();
+
+ /* for displacement method both, we only need to recompute the face
+ * normals, as bump mapping in the shader will already alter the
+ * vertex normal, so we start from the non-displaced vertex normals
+ * to avoid applying the perturbation twice. */
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+
+ bool need_recompute_vertex_normals = false;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
+ need_recompute_vertex_normals = true;
+ break;
+ }
+ }
+
+ if (need_recompute_vertex_normals) {
+ bool flip = mesh->transform_negative_scaled;
+ vector<bool> tri_has_true_disp(num_triangles, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ int shader_index = mesh->shader[i];
+ Shader *shader = (shader_index < mesh->used_shaders.size()) ?
+ mesh->used_shaders[shader_index] :
+ scene->default_surface;
+
+ tri_has_true_disp[i] = shader->has_displacement &&
+ shader->displacement_method == DISPLACE_TRUE;
+ }
+
+ /* static vertex normals */
+
+ /* get attributes */
+ Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
+ Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
+
+ float3 *fN = attr_fN->data_float3();
+ float3 *vN = attr_vN->data_float3();
+
+ /* compute vertex normals */
+
+ /* zero vertex normals on triangles with true displacement */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ /* add face normals to vertex normals */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ vN[mesh->get_triangle(i).v[j]] += fN[i];
+ }
+ }
+ }
+
+ /* normalize vertex normals */
+ done.clear();
+ done.resize(num_verts, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ int vert = mesh->get_triangle(i).v[j];
+
+ if (done[vert]) {
+ continue;
+ }
+
+ vN[vert] = normalize(vN[vert]);
+ if (flip)
+ vN[vert] = -vN[vert];
+
+ done[vert] = true;
+ }
+ }
+ }
+
+ /* motion vertex normals */
+ Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (mesh->has_motion_blur() && attr_mP && attr_mN) {
+ for (int step = 0; step < mesh->motion_steps - 1; step++) {
+ float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();
+ float3 *mN = attr_mN->data_float3() + step * mesh->verts.size();
+
+ /* compute */
+
+ /* zero vertex normals on triangles with true displacement */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ /* add face normals to vertex normals */
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
+ mN[mesh->get_triangle(i).v[j]] += fN;
+ }
+ }
+ }
+
+ /* normalize vertex normals */
+ done.clear();
+ done.resize(num_verts, false);
+
+ for (size_t i = 0; i < num_triangles; i++) {
+ if (tri_has_true_disp[i]) {
+ for (size_t j = 0; j < 3; j++) {
+ int vert = mesh->get_triangle(i).v[j];
+
+ if (done[vert]) {
+ continue;
+ }
+
+ mN[vert] = normalize(mN[vert]);
+ if (flip)
+ mN[vert] = -mN[vert];
+
+ done[vert] = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
index 95cc6f1fca1..46c8240fb71 100644
--- a/intern/cycles/render/mesh_subdivision.cpp
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -31,87 +31,92 @@ CCL_NAMESPACE_BEGIN
CCL_NAMESPACE_END
-#include <opensubdiv/far/topologyRefinerFactory.h>
-#include <opensubdiv/far/primvarRefiner.h>
-#include <opensubdiv/far/patchTableFactory.h>
-#include <opensubdiv/far/patchMap.h>
+# include <opensubdiv/far/topologyRefinerFactory.h>
+# include <opensubdiv/far/primvarRefiner.h>
+# include <opensubdiv/far/patchTableFactory.h>
+# include <opensubdiv/far/patchMap.h>
/* specializations of TopologyRefinerFactory for ccl::Mesh */
namespace OpenSubdiv {
namespace OPENSUBDIV_VERSION {
namespace Far {
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh)
- {
- setNumBaseVertices(refiner, mesh.verts.size());
- setNumBaseFaces(refiner, mesh.subd_faces.size());
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::resizeComponentTopology(TopologyRefiner &refiner,
+ ccl::Mesh const &mesh)
+{
+ setNumBaseVertices(refiner, mesh.verts.size());
+ setNumBaseFaces(refiner, mesh.subd_faces.size());
- const ccl::Mesh::SubdFace* face = mesh.subd_faces.data();
+ const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
- for(int i = 0; i < mesh.subd_faces.size(); i++, face++) {
- setNumBaseFaceVertices(refiner, i, face->num_corners);
- }
+ for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
+ setNumBaseFaceVertices(refiner, i, face->num_corners);
+ }
- return true;
- }
+ return true;
+}
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner& refiner, ccl::Mesh const& mesh)
- {
- const ccl::Mesh::SubdFace* face = mesh.subd_faces.data();
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTopology(TopologyRefiner &refiner,
+ ccl::Mesh const &mesh)
+{
+ const ccl::Mesh::SubdFace *face = mesh.subd_faces.data();
- for(int i = 0; i < mesh.subd_faces.size(); i++, face++) {
- IndexArray face_verts = getBaseFaceVertices(refiner, i);
+ for (int i = 0; i < mesh.subd_faces.size(); i++, face++) {
+ IndexArray face_verts = getBaseFaceVertices(refiner, i);
- int* corner = &mesh.subd_face_corners[face->start_corner];
+ int *corner = &mesh.subd_face_corners[face->start_corner];
- for(int j = 0; j < face->num_corners; j++, corner++) {
- face_verts[j] = *corner;
- }
- }
+ for (int j = 0; j < face->num_corners; j++, corner++) {
+ face_verts[j] = *corner;
+ }
+ }
- return true;
- }
+ return true;
+}
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner& refiner, ccl::Mesh const& mesh)
- {
- const ccl::Mesh::SubdEdgeCrease* crease = mesh.subd_creases.data();
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::assignComponentTags(TopologyRefiner &refiner,
+ ccl::Mesh const &mesh)
+{
+ const ccl::Mesh::SubdEdgeCrease *crease = mesh.subd_creases.data();
- for(int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
- Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
+ for (int i = 0; i < mesh.subd_creases.size(); i++, crease++) {
+ Index edge = findBaseEdge(refiner, crease->v[0], crease->v[1]);
- if(edge != INDEX_INVALID) {
- setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
- }
- }
+ if (edge != INDEX_INVALID) {
+ setBaseEdgeSharpness(refiner, edge, crease->crease * 10.0f);
+ }
+ }
- for(int i = 0; i < mesh.verts.size(); i++) {
- ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
+ for (int i = 0; i < mesh.verts.size(); i++) {
+ ConstIndexArray vert_edges = getBaseVertexEdges(refiner, i);
- if(vert_edges.size() == 2) {
- float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
- sharpness = ccl::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
+ if (vert_edges.size() == 2) {
+ float sharpness = refiner.getLevel(0).getEdgeSharpness(vert_edges[0]);
+ sharpness = ccl::min(sharpness, refiner.getLevel(0).getEdgeSharpness(vert_edges[1]));
- setBaseVertexSharpness(refiner, i, sharpness);
- }
- }
+ setBaseVertexSharpness(refiner, i, sharpness);
+ }
+ }
- return true;
- }
+ return true;
+}
- template<>
- bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner& /*refiner*/, ccl::Mesh const& /*mesh*/)
- {
- return true;
- }
+template<>
+bool TopologyRefinerFactory<ccl::Mesh>::assignFaceVaryingTopology(TopologyRefiner & /*refiner*/,
+ ccl::Mesh const & /*mesh*/)
+{
+ return true;
+}
- template<>
- void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/,
- char const * /*msg*/, ccl::Mesh const& /*mesh*/)
- {
- }
+template<>
+void TopologyRefinerFactory<ccl::Mesh>::reportInvalidTopology(TopologyError /*err_code*/,
+ char const * /*msg*/,
+ ccl::Mesh const & /*mesh*/)
+{
+}
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@@ -122,226 +127,242 @@ using namespace OpenSubdiv;
/* struct that implements OpenSubdiv's vertex interface */
-template<typename T>
-struct OsdValue {
- T value;
+template<typename T> struct OsdValue {
+ T value;
- OsdValue() {}
+ OsdValue()
+ {
+ }
- void Clear(void* = 0) {
- memset(&value, 0, sizeof(T));
- }
+ void Clear(void * = 0)
+ {
+ memset(&value, 0, sizeof(T));
+ }
- void AddWithWeight(OsdValue<T> const& src, float weight) {
- value += src.value * weight;
- }
+ void AddWithWeight(OsdValue<T> const &src, float weight)
+ {
+ value += src.value * weight;
+ }
};
-template<>
-void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const& src, float weight)
+template<> void OsdValue<uchar4>::AddWithWeight(OsdValue<uchar4> const &src, float weight)
{
- for(int i = 0; i < 4; i++) {
- value[i] += (uchar)(src.value[i] * weight);
- }
+ for (int i = 0; i < 4; i++) {
+ value[i] += (uchar)(src.value[i] * weight);
+ }
}
/* class for holding OpenSubdiv data used during tessellation */
class OsdData {
- Mesh* mesh;
- vector<OsdValue<float3> > verts;
- Far::TopologyRefiner* refiner;
- Far::PatchTable* patch_table;
- Far::PatchMap* patch_map;
-
-public:
- OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL) {}
-
- ~OsdData()
- {
- delete refiner;
- delete patch_table;
- delete patch_map;
- }
-
- void build_from_mesh(Mesh* mesh_)
- {
- mesh = mesh_;
-
- /* type and options */
- Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
-
- Sdc::Options options;
- options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
-
- /* create refiner */
- refiner = Far::TopologyRefinerFactory<Mesh>::Create(*mesh,
- Far::TopologyRefinerFactory<Mesh>::Options(type, options));
-
- /* adaptive refinement */
- int max_isolation = calculate_max_isolation();
- refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
-
- /* create patch table */
- Far::PatchTableFactory::Options patch_options;
- patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
-
- patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
-
- /* interpolate verts */
- int num_refiner_verts = refiner->GetNumVerticesTotal();
- int num_local_points = patch_table->GetNumLocalPoints();
-
- verts.resize(num_refiner_verts + num_local_points);
- for(int i = 0; i < mesh->verts.size(); i++) {
- verts[i].value = mesh->verts[i];
- }
-
- OsdValue<float3>* src = verts.data();
- for(int i = 0; i < refiner->GetMaxLevel(); i++) {
- OsdValue<float3>* dest = src + refiner->GetLevel(i).GetNumVertices();
- Far::PrimvarRefiner(*refiner).Interpolate(i+1, src, dest);
- src = dest;
- }
-
- if(num_local_points) {
- patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]);
- }
-
- /* create patch map */
- patch_map = new Far::PatchMap(*patch_table);
- }
-
- void subdivide_attribute(Attribute& attr)
- {
- Far::PrimvarRefiner primvar_refiner(*refiner);
-
- if(attr.element == ATTR_ELEMENT_VERTEX) {
- int num_refiner_verts = refiner->GetNumVerticesTotal();
- int num_local_points = patch_table->GetNumLocalPoints();
-
- attr.resize(num_refiner_verts + num_local_points);
- attr.flags |= ATTR_FINAL_SIZE;
-
- char* src = attr.buffer.data();
-
- for(int i = 0; i < refiner->GetMaxLevel(); i++) {
- char* dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof();
-
- if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
- primvar_refiner.Interpolate(i+1, (OsdValue<float>*)src, (OsdValue<float>*&)dest);
- }
- else if(attr.same_storage(attr.type, TypeFloat2)) {
- primvar_refiner.Interpolate(i+1, (OsdValue<float2>*)src, (OsdValue<float2>*&)dest);
- }
- else {
- primvar_refiner.Interpolate(i+1, (OsdValue<float4>*)src, (OsdValue<float4>*&)dest);
- }
-
- src = dest;
- }
-
- if(num_local_points) {
- if(attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
- patch_table->ComputeLocalPointValues((OsdValue<float>*)&attr.buffer[0],
- (OsdValue<float>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
- }
- else if(attr.same_storage(attr.type, TypeFloat2)) {
- patch_table->ComputeLocalPointValues((OsdValue<float2>*)&attr.buffer[0],
- (OsdValue<float2>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
- }
- else {
- patch_table->ComputeLocalPointValues((OsdValue<float4>*)&attr.buffer[0],
- (OsdValue<float4>*)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
- }
- }
- }
- else if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
- // TODO(mai): fvar interpolation
- }
- }
-
- int calculate_max_isolation()
- {
- /* loop over all edges to find longest in screen space */
- const Far::TopologyLevel& level = refiner->GetLevel(0);
- Transform objecttoworld = mesh->subd_params->objecttoworld;
- Camera* cam = mesh->subd_params->camera;
-
- float longest_edge = 0.0f;
-
- for(size_t i = 0; i < level.GetNumEdges(); i++) {
- Far::ConstIndexArray verts = level.GetEdgeVertices(i);
-
- float3 a = mesh->verts[verts[0]];
- float3 b = mesh->verts[verts[1]];
-
- float edge_len;
-
- if(cam) {
- a = transform_point(&objecttoworld, a);
- b = transform_point(&objecttoworld, b);
-
- edge_len = len(a - b) / cam->world_to_raster_size((a + b) * 0.5f);
- }
- else {
- edge_len = len(a - b);
- }
-
- longest_edge = max(longest_edge, edge_len);
- }
-
- /* calculate isolation level */
- int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
-
- return min(isolation, 10);
- }
-
- friend struct OsdPatch;
- friend class Mesh;
+ Mesh *mesh;
+ vector<OsdValue<float3>> verts;
+ Far::TopologyRefiner *refiner;
+ Far::PatchTable *patch_table;
+ Far::PatchMap *patch_map;
+
+ public:
+ OsdData() : mesh(NULL), refiner(NULL), patch_table(NULL), patch_map(NULL)
+ {
+ }
+
+ ~OsdData()
+ {
+ delete refiner;
+ delete patch_table;
+ delete patch_map;
+ }
+
+ void build_from_mesh(Mesh *mesh_)
+ {
+ mesh = mesh_;
+
+ /* type and options */
+ Sdc::SchemeType type = Sdc::SCHEME_CATMARK;
+
+ Sdc::Options options;
+ options.SetVtxBoundaryInterpolation(Sdc::Options::VTX_BOUNDARY_EDGE_ONLY);
+
+ /* create refiner */
+ refiner = Far::TopologyRefinerFactory<Mesh>::Create(
+ *mesh, Far::TopologyRefinerFactory<Mesh>::Options(type, options));
+
+ /* adaptive refinement */
+ int max_isolation = calculate_max_isolation();
+ refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
+
+ /* create patch table */
+ Far::PatchTableFactory::Options patch_options;
+ patch_options.endCapType = Far::PatchTableFactory::Options::ENDCAP_GREGORY_BASIS;
+
+ patch_table = Far::PatchTableFactory::Create(*refiner, patch_options);
+
+ /* interpolate verts */
+ int num_refiner_verts = refiner->GetNumVerticesTotal();
+ int num_local_points = patch_table->GetNumLocalPoints();
+
+ verts.resize(num_refiner_verts + num_local_points);
+ for (int i = 0; i < mesh->verts.size(); i++) {
+ verts[i].value = mesh->verts[i];
+ }
+
+ OsdValue<float3> *src = verts.data();
+ for (int i = 0; i < refiner->GetMaxLevel(); i++) {
+ OsdValue<float3> *dest = src + refiner->GetLevel(i).GetNumVertices();
+ Far::PrimvarRefiner(*refiner).Interpolate(i + 1, src, dest);
+ src = dest;
+ }
+
+ if (num_local_points) {
+ patch_table->ComputeLocalPointValues(&verts[0], &verts[num_refiner_verts]);
+ }
+
+ /* create patch map */
+ patch_map = new Far::PatchMap(*patch_table);
+ }
+
+ void subdivide_attribute(Attribute &attr)
+ {
+ Far::PrimvarRefiner primvar_refiner(*refiner);
+
+ if (attr.element == ATTR_ELEMENT_VERTEX) {
+ int num_refiner_verts = refiner->GetNumVerticesTotal();
+ int num_local_points = patch_table->GetNumLocalPoints();
+
+ attr.resize(num_refiner_verts + num_local_points);
+ attr.flags |= ATTR_FINAL_SIZE;
+
+ char *src = attr.buffer.data();
+
+ for (int i = 0; i < refiner->GetMaxLevel(); i++) {
+ char *dest = src + refiner->GetLevel(i).GetNumVertices() * attr.data_sizeof();
+
+ if (attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
+ primvar_refiner.Interpolate(i + 1, (OsdValue<float> *)src, (OsdValue<float> *&)dest);
+ }
+ else if (attr.same_storage(attr.type, TypeFloat2)) {
+ primvar_refiner.Interpolate(i + 1, (OsdValue<float2> *)src, (OsdValue<float2> *&)dest);
+ }
+ else {
+ primvar_refiner.Interpolate(i + 1, (OsdValue<float4> *)src, (OsdValue<float4> *&)dest);
+ }
+
+ src = dest;
+ }
+
+ if (num_local_points) {
+ if (attr.same_storage(attr.type, TypeDesc::TypeFloat)) {
+ patch_table->ComputeLocalPointValues(
+ (OsdValue<float> *)&attr.buffer[0],
+ (OsdValue<float> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+ }
+ else if (attr.same_storage(attr.type, TypeFloat2)) {
+ patch_table->ComputeLocalPointValues(
+ (OsdValue<float2> *)&attr.buffer[0],
+ (OsdValue<float2> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+ }
+ else {
+ patch_table->ComputeLocalPointValues(
+ (OsdValue<float4> *)&attr.buffer[0],
+ (OsdValue<float4> *)&attr.buffer[num_refiner_verts * attr.data_sizeof()]);
+ }
+ }
+ }
+ else if (attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
+ // TODO(mai): fvar interpolation
+ }
+ }
+
+ int calculate_max_isolation()
+ {
+ /* loop over all edges to find longest in screen space */
+ const Far::TopologyLevel &level = refiner->GetLevel(0);
+ Transform objecttoworld = mesh->subd_params->objecttoworld;
+ Camera *cam = mesh->subd_params->camera;
+
+ float longest_edge = 0.0f;
+
+ for (size_t i = 0; i < level.GetNumEdges(); i++) {
+ Far::ConstIndexArray verts = level.GetEdgeVertices(i);
+
+ float3 a = mesh->verts[verts[0]];
+ float3 b = mesh->verts[verts[1]];
+
+ float edge_len;
+
+ if (cam) {
+ a = transform_point(&objecttoworld, a);
+ b = transform_point(&objecttoworld, b);
+
+ edge_len = len(a - b) / cam->world_to_raster_size((a + b) * 0.5f);
+ }
+ else {
+ edge_len = len(a - b);
+ }
+
+ longest_edge = max(longest_edge, edge_len);
+ }
+
+ /* calculate isolation level */
+ int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
+
+ return min(isolation, 10);
+ }
+
+ friend struct OsdPatch;
+ friend class Mesh;
};
/* ccl::Patch implementation that uses OpenSubdiv for eval */
struct OsdPatch : Patch {
- OsdData* osd_data;
-
- OsdPatch(OsdData* data) : osd_data(data) {}
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
- {
- const Far::PatchTable::PatchHandle* handle = osd_data->patch_map->FindPatch(patch_index, u, v);
- assert(handle);
-
- float p_weights[20], du_weights[20], dv_weights[20];
- osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
-
- Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
-
- float3 du, dv;
- if(P) *P = make_float3(0.0f, 0.0f, 0.0f);
- du = make_float3(0.0f, 0.0f, 0.0f);
- dv = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < cv.size(); i++) {
- float3 p = osd_data->verts[cv[i]].value;
-
- if(P) *P += p * p_weights[i];
- du += p * du_weights[i];
- dv += p * dv_weights[i];
- }
-
- if(dPdu) *dPdu = du;
- if(dPdv) *dPdv = dv;
- if(N) {
- *N = cross(du, dv);
-
- float t = len(*N);
- *N = (t != 0.0f) ? *N/t : make_float3(0.0f, 0.0f, 1.0f);
- }
- }
-
- BoundBox bound() { return BoundBox::empty; }
+ OsdData *osd_data;
+
+ OsdPatch(OsdData *data) : osd_data(data)
+ {
+ }
+
+ void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
+ {
+ const Far::PatchTable::PatchHandle *handle = osd_data->patch_map->FindPatch(patch_index, u, v);
+ assert(handle);
+
+ float p_weights[20], du_weights[20], dv_weights[20];
+ osd_data->patch_table->EvaluateBasis(*handle, u, v, p_weights, du_weights, dv_weights);
+
+ Far::ConstIndexArray cv = osd_data->patch_table->GetPatchVertices(*handle);
+
+ float3 du, dv;
+ if (P)
+ *P = make_float3(0.0f, 0.0f, 0.0f);
+ du = make_float3(0.0f, 0.0f, 0.0f);
+ dv = make_float3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 0; i < cv.size(); i++) {
+ float3 p = osd_data->verts[cv[i]].value;
+
+ if (P)
+ *P += p * p_weights[i];
+ du += p * du_weights[i];
+ dv += p * dv_weights[i];
+ }
+
+ if (dPdu)
+ *dPdu = du;
+ if (dPdv)
+ *dPdv = dv;
+ if (N) {
+ *N = cross(du, dv);
+
+ float t = len(*N);
+ *N = (t != 0.0f) ? *N / t : make_float3(0.0f, 0.0f, 1.0f);
+ }
+ }
+
+ BoundBox bound()
+ {
+ return BoundBox::empty;
+ }
};
#endif
@@ -349,273 +370,280 @@ struct OsdPatch : Patch {
void Mesh::tessellate(DiagSplit *split)
{
#ifdef WITH_OPENSUBDIV
- OsdData osd_data;
- bool need_packed_patch_table = false;
-
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- if(subd_faces.size()) {
- osd_data.build_from_mesh(this);
- }
- }
- else
+ OsdData osd_data;
+ bool need_packed_patch_table = false;
+
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
+ if (subd_faces.size()) {
+ osd_data.build_from_mesh(this);
+ }
+ }
+ else
#endif
- {
- /* force linear subdivision if OpenSubdiv is unavailable to avoid
- * falling into catmull-clark code paths by accident
- */
- subdivision_type = SUBDIVISION_LINEAR;
+ {
+ /* force linear subdivision if OpenSubdiv is unavailable to avoid
+ * falling into catmull-clark code paths by accident
+ */
+ subdivision_type = SUBDIVISION_LINEAR;
- /* force disable attribute subdivision for same reason as above */
- foreach(Attribute& attr, subd_attributes.attributes) {
- attr.flags &= ~ATTR_SUBDIVIDED;
- }
- }
+ /* force disable attribute subdivision for same reason as above */
+ foreach (Attribute &attr, subd_attributes.attributes) {
+ attr.flags &= ~ATTR_SUBDIVIDED;
+ }
+ }
- int num_faces = subd_faces.size();
+ int num_faces = subd_faces.size();
- Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
- float3* vN = attr_vN->data_float3();
+ Attribute *attr_vN = subd_attributes.find(ATTR_STD_VERTEX_NORMAL);
+ float3 *vN = attr_vN->data_float3();
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
- if(face.is_quad()) {
- /* quad */
- QuadDice::SubPatch subpatch;
+ if (face.is_quad()) {
+ /* quad */
+ QuadDice::SubPatch subpatch;
- LinearQuadPatch quad_patch;
+ LinearQuadPatch quad_patch;
#ifdef WITH_OPENSUBDIV
- OsdPatch osd_patch(&osd_data);
+ OsdPatch osd_patch(&osd_data);
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- osd_patch.patch_index = face.ptex_offset;
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
+ osd_patch.patch_index = face.ptex_offset;
- subpatch.patch = &osd_patch;
- }
- else
+ subpatch.patch = &osd_patch;
+ }
+ else
#endif
- {
- float3 *hull = quad_patch.hull;
- float3 *normals = quad_patch.normals;
-
- quad_patch.patch_index = face.ptex_offset;
-
- for(int i = 0; i < 4; i++) {
- hull[i] = verts[subd_face_corners[face.start_corner+i]];
- }
-
- if(face.smooth) {
- for(int i = 0; i < 4; i++) {
- normals[i] = vN[subd_face_corners[face.start_corner+i]];
- }
- }
- else {
- float3 N = face.normal(this);
- for(int i = 0; i < 4; i++) {
- normals[i] = N;
- }
- }
-
- swap(hull[2], hull[3]);
- swap(normals[2], normals[3]);
-
- subpatch.patch = &quad_patch;
- }
-
- subpatch.patch->shader = face.shader;
-
- /* Quad faces need to be split at least once to line up with split ngons, we do this
- * here in this manner because if we do it later edge factors may end up slightly off.
- */
- subpatch.P00 = make_float2(0.0f, 0.0f);
- subpatch.P10 = make_float2(0.5f, 0.0f);
- subpatch.P01 = make_float2(0.0f, 0.5f);
- subpatch.P11 = make_float2(0.5f, 0.5f);
- split->split_quad(subpatch.patch, &subpatch);
-
- subpatch.P00 = make_float2(0.5f, 0.0f);
- subpatch.P10 = make_float2(1.0f, 0.0f);
- subpatch.P01 = make_float2(0.5f, 0.5f);
- subpatch.P11 = make_float2(1.0f, 0.5f);
- split->split_quad(subpatch.patch, &subpatch);
-
- subpatch.P00 = make_float2(0.0f, 0.5f);
- subpatch.P10 = make_float2(0.5f, 0.5f);
- subpatch.P01 = make_float2(0.0f, 1.0f);
- subpatch.P11 = make_float2(0.5f, 1.0f);
- split->split_quad(subpatch.patch, &subpatch);
-
- subpatch.P00 = make_float2(0.5f, 0.5f);
- subpatch.P10 = make_float2(1.0f, 0.5f);
- subpatch.P01 = make_float2(0.5f, 1.0f);
- subpatch.P11 = make_float2(1.0f, 1.0f);
- split->split_quad(subpatch.patch, &subpatch);
- }
- else {
- /* ngon */
+ {
+ float3 *hull = quad_patch.hull;
+ float3 *normals = quad_patch.normals;
+
+ quad_patch.patch_index = face.ptex_offset;
+
+ for (int i = 0; i < 4; i++) {
+ hull[i] = verts[subd_face_corners[face.start_corner + i]];
+ }
+
+ if (face.smooth) {
+ for (int i = 0; i < 4; i++) {
+ normals[i] = vN[subd_face_corners[face.start_corner + i]];
+ }
+ }
+ else {
+ float3 N = face.normal(this);
+ for (int i = 0; i < 4; i++) {
+ normals[i] = N;
+ }
+ }
+
+ swap(hull[2], hull[3]);
+ swap(normals[2], normals[3]);
+
+ subpatch.patch = &quad_patch;
+ }
+
+ subpatch.patch->shader = face.shader;
+
+ /* Quad faces need to be split at least once to line up with split ngons, we do this
+ * here in this manner because if we do it later edge factors may end up slightly off.
+ */
+ subpatch.P00 = make_float2(0.0f, 0.0f);
+ subpatch.P10 = make_float2(0.5f, 0.0f);
+ subpatch.P01 = make_float2(0.0f, 0.5f);
+ subpatch.P11 = make_float2(0.5f, 0.5f);
+ split->split_quad(subpatch.patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.5f, 0.0f);
+ subpatch.P10 = make_float2(1.0f, 0.0f);
+ subpatch.P01 = make_float2(0.5f, 0.5f);
+ subpatch.P11 = make_float2(1.0f, 0.5f);
+ split->split_quad(subpatch.patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.0f, 0.5f);
+ subpatch.P10 = make_float2(0.5f, 0.5f);
+ subpatch.P01 = make_float2(0.0f, 1.0f);
+ subpatch.P11 = make_float2(0.5f, 1.0f);
+ split->split_quad(subpatch.patch, &subpatch);
+
+ subpatch.P00 = make_float2(0.5f, 0.5f);
+ subpatch.P10 = make_float2(1.0f, 0.5f);
+ subpatch.P01 = make_float2(0.5f, 1.0f);
+ subpatch.P11 = make_float2(1.0f, 1.0f);
+ split->split_quad(subpatch.patch, &subpatch);
+ }
+ else {
+ /* ngon */
#ifdef WITH_OPENSUBDIV
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK) {
- OsdPatch patch(&osd_data);
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK) {
+ OsdPatch patch(&osd_data);
- patch.shader = face.shader;
+ patch.shader = face.shader;
- for(int corner = 0; corner < face.num_corners; corner++) {
- patch.patch_index = face.ptex_offset + corner;
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ patch.patch_index = face.ptex_offset + corner;
- split->split_quad(&patch);
- }
- }
- else
+ split->split_quad(&patch);
+ }
+ }
+ else
#endif
- {
- float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
- float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
-
- float inv_num_corners = 1.0f/float(face.num_corners);
- for(int corner = 0; corner < face.num_corners; corner++) {
- center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
- center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
- }
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- LinearQuadPatch patch;
- float3 *hull = patch.hull;
- float3 *normals = patch.normals;
-
- patch.patch_index = face.ptex_offset + corner;
-
- patch.shader = face.shader;
-
- hull[0] = verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
- hull[1] = verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
- hull[2] = verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
- hull[3] = center_vert;
-
- hull[1] = (hull[1] + hull[0]) * 0.5;
- hull[2] = (hull[2] + hull[0]) * 0.5;
-
- if(face.smooth) {
- normals[0] = vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
- normals[1] = vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
- normals[2] = vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
- normals[3] = center_normal;
-
- normals[1] = (normals[1] + normals[0]) * 0.5;
- normals[2] = (normals[2] + normals[0]) * 0.5;
- }
- else {
- float3 N = face.normal(this);
- for(int i = 0; i < 4; i++) {
- normals[i] = N;
- }
- }
-
- split->split_quad(&patch);
- }
- }
- }
- }
-
- /* interpolate center points for attributes */
- foreach(Attribute& attr, subd_attributes.attributes) {
+ {
+ float3 center_vert = make_float3(0.0f, 0.0f, 0.0f);
+ float3 center_normal = make_float3(0.0f, 0.0f, 0.0f);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ center_vert += verts[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
+ center_normal += vN[subd_face_corners[face.start_corner + corner]] * inv_num_corners;
+ }
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ LinearQuadPatch patch;
+ float3 *hull = patch.hull;
+ float3 *normals = patch.normals;
+
+ patch.patch_index = face.ptex_offset + corner;
+
+ patch.shader = face.shader;
+
+ hull[0] =
+ verts[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
+ hull[1] =
+ verts[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
+ hull[2] =
+ verts[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
+ hull[3] = center_vert;
+
+ hull[1] = (hull[1] + hull[0]) * 0.5;
+ hull[2] = (hull[2] + hull[0]) * 0.5;
+
+ if (face.smooth) {
+ normals[0] =
+ vN[subd_face_corners[face.start_corner + mod(corner + 0, face.num_corners)]];
+ normals[1] =
+ vN[subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)]];
+ normals[2] =
+ vN[subd_face_corners[face.start_corner + mod(corner - 1, face.num_corners)]];
+ normals[3] = center_normal;
+
+ normals[1] = (normals[1] + normals[0]) * 0.5;
+ normals[2] = (normals[2] + normals[0]) * 0.5;
+ }
+ else {
+ float3 N = face.normal(this);
+ for (int i = 0; i < 4; i++) {
+ normals[i] = N;
+ }
+ }
+
+ split->split_quad(&patch);
+ }
+ }
+ }
+ }
+
+ /* interpolate center points for attributes */
+ foreach (Attribute &attr, subd_attributes.attributes) {
#ifdef WITH_OPENSUBDIV
- if(subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) {
- if(attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
- /* keep subdivision for corner attributes disabled for now */
- attr.flags &= ~ATTR_SUBDIVIDED;
- }
- else if(subd_faces.size()) {
- osd_data.subdivide_attribute(attr);
-
- need_packed_patch_table = true;
- continue;
- }
- }
+ if (subdivision_type == SUBDIVISION_CATMULL_CLARK && attr.flags & ATTR_SUBDIVIDED) {
+ if (attr.element == ATTR_ELEMENT_CORNER || attr.element == ATTR_ELEMENT_CORNER_BYTE) {
+ /* keep subdivision for corner attributes disabled for now */
+ attr.flags &= ~ATTR_SUBDIVIDED;
+ }
+ else if (subd_faces.size()) {
+ osd_data.subdivide_attribute(attr);
+
+ need_packed_patch_table = true;
+ continue;
+ }
+ }
#endif
- char* data = attr.data();
- size_t stride = attr.data_sizeof();
- int ngons = 0;
-
- switch(attr.element) {
- case ATTR_ELEMENT_VERTEX: {
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
-
- if(!face.is_quad()) {
- char* center = data + (verts.size() - num_subd_verts + ngons) * stride;
- attr.zero_data(center);
-
- float inv_num_corners = 1.0f / float(face.num_corners);
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- attr.add_with_weight(center,
- data + subd_face_corners[face.start_corner + corner] * stride,
- inv_num_corners);
- }
-
- ngons++;
- }
- }
- } break;
- case ATTR_ELEMENT_VERTEX_MOTION: {
- // TODO(mai): implement
- } break;
- case ATTR_ELEMENT_CORNER: {
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
-
- if(!face.is_quad()) {
- char* center = data + (subd_face_corners.size() + ngons) * stride;
- attr.zero_data(center);
-
- float inv_num_corners = 1.0f / float(face.num_corners);
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- attr.add_with_weight(center,
- data + (face.start_corner + corner) * stride,
- inv_num_corners);
- }
-
- ngons++;
- }
- }
- } break;
- case ATTR_ELEMENT_CORNER_BYTE: {
- for(int f = 0; f < num_faces; f++) {
- SubdFace& face = subd_faces[f];
-
- if(!face.is_quad()) {
- uchar* center = (uchar*)data + (subd_face_corners.size() + ngons) * stride;
-
- float inv_num_corners = 1.0f / float(face.num_corners);
- float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-
- for(int corner = 0; corner < face.num_corners; corner++) {
- for(int i = 0; i < 4; i++) {
- val[i] += float(*(data + (face.start_corner + corner) * stride + i)) * inv_num_corners;
- }
- }
-
- for(int i = 0; i < 4; i++) {
- center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
- }
-
- ngons++;
- }
- }
- } break;
- default: break;
- }
- }
+ char *data = attr.data();
+ size_t stride = attr.data_sizeof();
+ int ngons = 0;
+
+ switch (attr.element) {
+ case ATTR_ELEMENT_VERTEX: {
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
+
+ if (!face.is_quad()) {
+ char *center = data + (verts.size() - num_subd_verts + ngons) * stride;
+ attr.zero_data(center);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ attr.add_with_weight(center,
+ data + subd_face_corners[face.start_corner + corner] * stride,
+ inv_num_corners);
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ case ATTR_ELEMENT_VERTEX_MOTION: {
+ // TODO(mai): implement
+ } break;
+ case ATTR_ELEMENT_CORNER: {
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
+
+ if (!face.is_quad()) {
+ char *center = data + (subd_face_corners.size() + ngons) * stride;
+ attr.zero_data(center);
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ attr.add_with_weight(
+ center, data + (face.start_corner + corner) * stride, inv_num_corners);
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ case ATTR_ELEMENT_CORNER_BYTE: {
+ for (int f = 0; f < num_faces; f++) {
+ SubdFace &face = subd_faces[f];
+
+ if (!face.is_quad()) {
+ uchar *center = (uchar *)data + (subd_face_corners.size() + ngons) * stride;
+
+ float inv_num_corners = 1.0f / float(face.num_corners);
+ float4 val = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+
+ for (int corner = 0; corner < face.num_corners; corner++) {
+ for (int i = 0; i < 4; i++) {
+ val[i] += float(*(data + (face.start_corner + corner) * stride + i)) *
+ inv_num_corners;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ center[i] = uchar(min(max(val[i], 0.0f), 255.0f));
+ }
+
+ ngons++;
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ }
#ifdef WITH_OPENSUBDIV
- /* pack patch tables */
- if(need_packed_patch_table) {
- delete patch_table;
- patch_table = new PackedPatchTable;
- patch_table->pack(osd_data.patch_table);
- }
+ /* pack patch tables */
+ if (need_packed_patch_table) {
+ delete patch_table;
+ patch_table = new PackedPatchTable;
+ patch_table->pack(osd_data.patch_table);
+ }
#endif
}
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index 3ee4124ba0f..a1d61fd4db7 100644
--- a/intern/cycles/render/mesh_volume.cpp
+++ b/intern/cycles/render/mesh_volume.cpp
@@ -27,98 +27,106 @@ CCL_NAMESPACE_BEGIN
static size_t compute_voxel_index(const int3 &resolution, size_t x, size_t y, size_t z)
{
- if(x == -1 || x >= resolution.x) {
- return -1;
- }
+ if (x == -1 || x >= resolution.x) {
+ return -1;
+ }
- if(y == -1 || y >= resolution.y) {
- return -1;
- }
+ if (y == -1 || y >= resolution.y) {
+ return -1;
+ }
- if(z == -1 || z >= resolution.z) {
- return -1;
- }
+ if (z == -1 || z >= resolution.z) {
+ return -1;
+ }
- return x + y*resolution.x + z*resolution.x*resolution.y;
+ return x + y * resolution.x + z * resolution.x * resolution.y;
}
struct QuadData {
- int v0, v1, v2, v3;
+ int v0, v1, v2, v3;
- float3 normal;
+ float3 normal;
};
enum {
- QUAD_X_MIN = 0,
- QUAD_X_MAX = 1,
- QUAD_Y_MIN = 2,
- QUAD_Y_MAX = 3,
- QUAD_Z_MIN = 4,
- QUAD_Z_MAX = 5,
+ QUAD_X_MIN = 0,
+ QUAD_X_MAX = 1,
+ QUAD_Y_MIN = 2,
+ QUAD_Y_MAX = 3,
+ QUAD_Z_MIN = 4,
+ QUAD_Z_MAX = 5,
};
const int quads_indices[6][4] = {
- /* QUAD_X_MIN */
- { 4, 0, 3, 7 },
- /* QUAD_X_MAX */
- { 1, 5, 6, 2 },
- /* QUAD_Y_MIN */
- { 4, 5, 1, 0 },
- /* QUAD_Y_MAX */
- { 3, 2, 6, 7 },
- /* QUAD_Z_MIN */
- { 0, 1, 2, 3 },
- /* QUAD_Z_MAX */
- { 5, 4, 7, 6 },
+ /* QUAD_X_MIN */
+ {4, 0, 3, 7},
+ /* QUAD_X_MAX */
+ {1, 5, 6, 2},
+ /* QUAD_Y_MIN */
+ {4, 5, 1, 0},
+ /* QUAD_Y_MAX */
+ {3, 2, 6, 7},
+ /* QUAD_Z_MIN */
+ {0, 1, 2, 3},
+ /* QUAD_Z_MAX */
+ {5, 4, 7, 6},
};
const float3 quads_normals[6] = {
- /* QUAD_X_MIN */
- make_float3(-1.0f, 0.0f, 0.0f),
- /* QUAD_X_MAX */
- make_float3(1.0f, 0.0f, 0.0f),
- /* QUAD_Y_MIN */
- make_float3(0.0f, -1.0f, 0.0f),
- /* QUAD_Y_MAX */
- make_float3(0.0f, 1.0f, 0.0f),
- /* QUAD_Z_MIN */
- make_float3(0.0f, 0.0f, -1.0f),
- /* QUAD_Z_MAX */
- make_float3(0.0f, 0.0f, 1.0f),
+ /* QUAD_X_MIN */
+ make_float3(-1.0f, 0.0f, 0.0f),
+ /* QUAD_X_MAX */
+ make_float3(1.0f, 0.0f, 0.0f),
+ /* QUAD_Y_MIN */
+ make_float3(0.0f, -1.0f, 0.0f),
+ /* QUAD_Y_MAX */
+ make_float3(0.0f, 1.0f, 0.0f),
+ /* QUAD_Z_MIN */
+ make_float3(0.0f, 0.0f, -1.0f),
+ /* QUAD_Z_MAX */
+ make_float3(0.0f, 0.0f, 1.0f),
};
-static int add_vertex(int3 v, vector<int3> &vertices, int3 res, unordered_map<size_t, int> &used_verts)
+static int add_vertex(int3 v,
+ vector<int3> &vertices,
+ int3 res,
+ unordered_map<size_t, int> &used_verts)
{
- size_t vert_key = v.x + v.y * (res.x+1) + v.z * (res.x+1)*(res.y+1);
- unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
+ size_t vert_key = v.x + v.y * (res.x + 1) + v.z * (res.x + 1) * (res.y + 1);
+ unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
- if(it != used_verts.end()) {
- return it->second;
- }
+ if (it != used_verts.end()) {
+ return it->second;
+ }
- int vertex_offset = vertices.size();
- used_verts[vert_key] = vertex_offset;
- vertices.push_back(v);
- return vertex_offset;
+ int vertex_offset = vertices.size();
+ used_verts[vert_key] = vertex_offset;
+ vertices.push_back(v);
+ return vertex_offset;
}
-static void create_quad(int3 corners[8], vector<int3> &vertices, vector<QuadData> &quads, int3 res, unordered_map<size_t, int> &used_verts, int face_index)
+static void create_quad(int3 corners[8],
+ vector<int3> &vertices,
+ vector<QuadData> &quads,
+ int3 res,
+ unordered_map<size_t, int> &used_verts,
+ int face_index)
{
- QuadData quad;
- quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
- quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
- quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
- quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
- quad.normal = quads_normals[face_index];
-
- quads.push_back(quad);
+ QuadData quad;
+ quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
+ quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
+ quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
+ quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
+ quad.normal = quads_normals[face_index];
+
+ quads.push_back(quad);
}
struct VolumeParams {
- int3 resolution;
- float3 cell_size;
- float3 start_point;
- int pad_size;
+ int3 resolution;
+ float3 cell_size;
+ float3 start_point;
+ int pad_size;
};
static const int CUBE_SIZE = 8;
@@ -135,373 +143,365 @@ static const int CUBE_SIZE = 8;
* volume to generate a tight mesh around the volume.
*/
class VolumeMeshBuilder {
- /* Auxilliary volume that is used to check if a node already added. */
- vector<char> grid;
+ /* Auxilliary volume that is used to check if a node already added. */
+ vector<char> grid;
- /* The resolution of the auxilliary volume, set to be equal to 1/CUBE_SIZE
- * of the original volume on each axis. */
- int3 res;
+ /* The resolution of the auxilliary volume, set to be equal to 1/CUBE_SIZE
+ * of the original volume on each axis. */
+ int3 res;
- size_t number_of_nodes;
+ size_t number_of_nodes;
- /* Offset due to padding in the original grid. Padding will transform the
- * coordinates of the original grid from 0...res to -padding...res+padding,
- * so some coordinates are negative, and we need to properly account for
- * them. */
- int3 pad_offset;
+ /* Offset due to padding in the original grid. Padding will transform the
+ * coordinates of the original grid from 0...res to -padding...res+padding,
+ * so some coordinates are negative, and we need to properly account for
+ * them. */
+ int3 pad_offset;
- VolumeParams *params;
+ VolumeParams *params;
-public:
- VolumeMeshBuilder(VolumeParams *volume_params);
+ public:
+ VolumeMeshBuilder(VolumeParams *volume_params);
- void add_node(int x, int y, int z);
+ void add_node(int x, int y, int z);
- void add_node_with_padding(int x, int y, int z);
+ void add_node_with_padding(int x, int y, int z);
- void create_mesh(vector<float3> &vertices,
- vector<int> &indices,
- vector<float3> &face_normals);
+ void create_mesh(vector<float3> &vertices, vector<int> &indices, vector<float3> &face_normals);
-private:
- void generate_vertices_and_quads(vector<int3> &vertices_is,
- vector<QuadData> &quads);
+ private:
+ void generate_vertices_and_quads(vector<int3> &vertices_is, vector<QuadData> &quads);
- void convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices);
+ void convert_object_space(const vector<int3> &vertices, vector<float3> &out_vertices);
- void convert_quads_to_tris(const vector<QuadData> &quads,
- vector<int> &tris,
- vector<float3> &face_normals);
+ void convert_quads_to_tris(const vector<QuadData> &quads,
+ vector<int> &tris,
+ vector<float3> &face_normals);
};
VolumeMeshBuilder::VolumeMeshBuilder(VolumeParams *volume_params)
{
- params = volume_params;
- number_of_nodes = 0;
+ params = volume_params;
+ number_of_nodes = 0;
- const size_t x = divide_up(params->resolution.x, CUBE_SIZE);
- const size_t y = divide_up(params->resolution.y, CUBE_SIZE);
- const size_t z = divide_up(params->resolution.z, CUBE_SIZE);
+ const size_t x = divide_up(params->resolution.x, CUBE_SIZE);
+ const size_t y = divide_up(params->resolution.y, CUBE_SIZE);
+ const size_t z = divide_up(params->resolution.z, CUBE_SIZE);
- /* Adding 2*pad_size since we pad in both positive and negative directions
- * along the axis. */
- const size_t px = divide_up(params->resolution.x + 2*params->pad_size, CUBE_SIZE);
- const size_t py = divide_up(params->resolution.y + 2*params->pad_size, CUBE_SIZE);
- const size_t pz = divide_up(params->resolution.z + 2*params->pad_size, CUBE_SIZE);
+ /* Adding 2*pad_size since we pad in both positive and negative directions
+ * along the axis. */
+ const size_t px = divide_up(params->resolution.x + 2 * params->pad_size, CUBE_SIZE);
+ const size_t py = divide_up(params->resolution.y + 2 * params->pad_size, CUBE_SIZE);
+ const size_t pz = divide_up(params->resolution.z + 2 * params->pad_size, CUBE_SIZE);
- res = make_int3(px, py, pz);
- pad_offset = make_int3(px - x, py - y, pz - z);
+ res = make_int3(px, py, pz);
+ pad_offset = make_int3(px - x, py - y, pz - z);
- grid.resize(px*py*pz, 0);
+ grid.resize(px * py * pz, 0);
}
void VolumeMeshBuilder::add_node(int x, int y, int z)
{
- /* Map coordinates to index space. */
- const int index_x = (x/CUBE_SIZE) + pad_offset.x;
- const int index_y = (y/CUBE_SIZE) + pad_offset.y;
- const int index_z = (z/CUBE_SIZE) + pad_offset.z;
+ /* Map coordinates to index space. */
+ const int index_x = (x / CUBE_SIZE) + pad_offset.x;
+ const int index_y = (y / CUBE_SIZE) + pad_offset.y;
+ const int index_z = (z / CUBE_SIZE) + pad_offset.z;
- assert((index_x >= 0) && (index_y >= 0) && (index_z >= 0));
+ assert((index_x >= 0) && (index_y >= 0) && (index_z >= 0));
- const size_t index = compute_voxel_index(res, index_x, index_y, index_z);
+ const size_t index = compute_voxel_index(res, index_x, index_y, index_z);
- /* We already have a node here. */
- if(grid[index] == 1) {
- return;
- }
+ /* We already have a node here. */
+ if (grid[index] == 1) {
+ return;
+ }
- ++number_of_nodes;
+ ++number_of_nodes;
- grid[index] = 1;
+ grid[index] = 1;
}
void VolumeMeshBuilder::add_node_with_padding(int x, int y, int z)
{
- for(int px = x - params->pad_size; px < x + params->pad_size; ++px) {
- for(int py = y - params->pad_size; py < y + params->pad_size; ++py) {
- for(int pz = z - params->pad_size; pz < z + params->pad_size; ++pz) {
- add_node(px, py, pz);
- }
- }
- }
+ for (int px = x - params->pad_size; px < x + params->pad_size; ++px) {
+ for (int py = y - params->pad_size; py < y + params->pad_size; ++py) {
+ for (int pz = z - params->pad_size; pz < z + params->pad_size; ++pz) {
+ add_node(px, py, pz);
+ }
+ }
+ }
}
void VolumeMeshBuilder::create_mesh(vector<float3> &vertices,
vector<int> &indices,
vector<float3> &face_normals)
{
- /* We create vertices in index space (is), and only convert them to object
- * space when done. */
- vector<int3> vertices_is;
- vector<QuadData> quads;
+ /* We create vertices in index space (is), and only convert them to object
+ * space when done. */
+ vector<int3> vertices_is;
+ vector<QuadData> quads;
- generate_vertices_and_quads(vertices_is, quads);
+ generate_vertices_and_quads(vertices_is, quads);
- convert_object_space(vertices_is, vertices);
+ convert_object_space(vertices_is, vertices);
- convert_quads_to_tris(quads, indices, face_normals);
+ convert_quads_to_tris(quads, indices, face_normals);
}
-void VolumeMeshBuilder::generate_vertices_and_quads(
- vector<ccl::int3> &vertices_is,
- vector<QuadData> &quads)
+void VolumeMeshBuilder::generate_vertices_and_quads(vector<ccl::int3> &vertices_is,
+ vector<QuadData> &quads)
{
- unordered_map<size_t, int> used_verts;
-
- for(int z = 0; z < res.z; ++z) {
- for(int y = 0; y < res.y; ++y) {
- for(int x = 0; x < res.x; ++x) {
- size_t voxel_index = compute_voxel_index(res, x, y, z);
- if(grid[voxel_index] == 0) {
- continue;
- }
-
- /* Compute min and max coords of the node in index space. */
- int3 min = make_int3((x - pad_offset.x)*CUBE_SIZE,
- (y - pad_offset.y)*CUBE_SIZE,
- (z - pad_offset.z)*CUBE_SIZE);
-
- /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */
- int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE);
-
- int3 corners[8] = {
- make_int3(min[0], min[1], min[2]),
- make_int3(max[0], min[1], min[2]),
- make_int3(max[0], max[1], min[2]),
- make_int3(min[0], max[1], min[2]),
- make_int3(min[0], min[1], max[2]),
- make_int3(max[0], min[1], max[2]),
- make_int3(max[0], max[1], max[2]),
- make_int3(min[0], max[1], max[2]),
- };
-
- /* Only create a quad if on the border between an active and
- * an inactive node.
- */
-
- voxel_index = compute_voxel_index(res, x - 1, y, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
- }
-
- voxel_index = compute_voxel_index(res, x + 1, y, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
- }
-
- voxel_index = compute_voxel_index(res, x, y - 1, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
- }
-
- voxel_index = compute_voxel_index(res, x, y + 1, z);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
- }
-
- voxel_index = compute_voxel_index(res, x, y, z - 1);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
- }
-
- voxel_index = compute_voxel_index(res, x, y, z + 1);
- if(voxel_index == -1 || grid[voxel_index] == 0) {
- create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
- }
- }
- }
- }
+ unordered_map<size_t, int> used_verts;
+
+ for (int z = 0; z < res.z; ++z) {
+ for (int y = 0; y < res.y; ++y) {
+ for (int x = 0; x < res.x; ++x) {
+ size_t voxel_index = compute_voxel_index(res, x, y, z);
+ if (grid[voxel_index] == 0) {
+ continue;
+ }
+
+ /* Compute min and max coords of the node in index space. */
+ int3 min = make_int3((x - pad_offset.x) * CUBE_SIZE,
+ (y - pad_offset.y) * CUBE_SIZE,
+ (z - pad_offset.z) * CUBE_SIZE);
+
+ /* Maximum is just CUBE_SIZE voxels away from minimum on each axis. */
+ int3 max = make_int3(min.x + CUBE_SIZE, min.y + CUBE_SIZE, min.z + CUBE_SIZE);
+
+ int3 corners[8] = {
+ make_int3(min[0], min[1], min[2]),
+ make_int3(max[0], min[1], min[2]),
+ make_int3(max[0], max[1], min[2]),
+ make_int3(min[0], max[1], min[2]),
+ make_int3(min[0], min[1], max[2]),
+ make_int3(max[0], min[1], max[2]),
+ make_int3(max[0], max[1], max[2]),
+ make_int3(min[0], max[1], max[2]),
+ };
+
+ /* Only create a quad if on the border between an active and
+ * an inactive node.
+ */
+
+ voxel_index = compute_voxel_index(res, x - 1, y, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MIN);
+ }
+
+ voxel_index = compute_voxel_index(res, x + 1, y, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_X_MAX);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y - 1, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MIN);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y + 1, z);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Y_MAX);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y, z - 1);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MIN);
+ }
+
+ voxel_index = compute_voxel_index(res, x, y, z + 1);
+ if (voxel_index == -1 || grid[voxel_index] == 0) {
+ create_quad(corners, vertices_is, quads, res, used_verts, QUAD_Z_MAX);
+ }
+ }
+ }
+ }
}
void VolumeMeshBuilder::convert_object_space(const vector<int3> &vertices,
- vector<float3> &out_vertices)
+ vector<float3> &out_vertices)
{
- out_vertices.reserve(vertices.size());
+ out_vertices.reserve(vertices.size());
- for(size_t i = 0; i < vertices.size(); ++i) {
- float3 vertex = make_float3(vertices[i].x, vertices[i].y, vertices[i].z);
- vertex *= params->cell_size;
- vertex += params->start_point;
+ for (size_t i = 0; i < vertices.size(); ++i) {
+ float3 vertex = make_float3(vertices[i].x, vertices[i].y, vertices[i].z);
+ vertex *= params->cell_size;
+ vertex += params->start_point;
- out_vertices.push_back(vertex);
- }
+ out_vertices.push_back(vertex);
+ }
}
void VolumeMeshBuilder::convert_quads_to_tris(const vector<QuadData> &quads,
vector<int> &tris,
vector<float3> &face_normals)
{
- int index_offset = 0;
- tris.resize(quads.size()*6);
- face_normals.reserve(quads.size()*2);
+ int index_offset = 0;
+ tris.resize(quads.size() * 6);
+ face_normals.reserve(quads.size() * 2);
- for(size_t i = 0; i < quads.size(); ++i) {
- tris[index_offset++] = quads[i].v0;
- tris[index_offset++] = quads[i].v2;
- tris[index_offset++] = quads[i].v1;
+ for (size_t i = 0; i < quads.size(); ++i) {
+ tris[index_offset++] = quads[i].v0;
+ tris[index_offset++] = quads[i].v2;
+ tris[index_offset++] = quads[i].v1;
- face_normals.push_back(quads[i].normal);
+ face_normals.push_back(quads[i].normal);
- tris[index_offset++] = quads[i].v0;
- tris[index_offset++] = quads[i].v3;
- tris[index_offset++] = quads[i].v2;
+ tris[index_offset++] = quads[i].v0;
+ tris[index_offset++] = quads[i].v3;
+ tris[index_offset++] = quads[i].v2;
- face_normals.push_back(quads[i].normal);
- }
+ face_normals.push_back(quads[i].normal);
+ }
}
/* ************************************************************************** */
struct VoxelAttributeGrid {
- float *data;
- int channels;
+ float *data;
+ int channels;
};
-void MeshManager::create_volume_mesh(Scene *scene,
- Mesh *mesh,
- Progress& progress)
+void MeshManager::create_volume_mesh(Scene *scene, Mesh *mesh, Progress &progress)
{
- string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
- progress.set_status("Updating Mesh", msg);
-
- vector<VoxelAttributeGrid> voxel_grids;
-
- /* Compute volume parameters. */
- VolumeParams volume_params;
- volume_params.resolution = make_int3(0, 0, 0);
-
- foreach(Attribute& attr, mesh->attributes.attributes) {
- if(attr.element != ATTR_ELEMENT_VOXEL) {
- continue;
- }
-
- VoxelAttribute *voxel = attr.data_voxel();
- device_memory *image_memory = scene->image_manager->image_memory(voxel->slot);
- int3 resolution = make_int3(image_memory->data_width,
- image_memory->data_height,
- image_memory->data_depth);
-
- if(volume_params.resolution == make_int3(0, 0, 0)) {
- volume_params.resolution = resolution;
- }
- else if(volume_params.resolution != resolution) {
- VLOG(1) << "Can't create volume mesh, all voxel grid resolutions must be equal\n";
- return;
- }
-
- VoxelAttributeGrid voxel_grid;
- voxel_grid.data = static_cast<float*>(image_memory->host_pointer);
- voxel_grid.channels = image_memory->data_elements;
- voxel_grids.push_back(voxel_grid);
- }
-
- if(voxel_grids.empty()) {
- return;
- }
-
- /* Compute padding. */
- Shader *volume_shader = NULL;
- int pad_size = 0;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(!shader->has_volume) {
- continue;
- }
-
- volume_shader = shader;
-
- if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
- pad_size = max(1, pad_size);
- }
- else if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
- pad_size = max(2, pad_size);
- }
-
- break;
- }
-
- if(!volume_shader) {
- return;
- }
-
- /* Compute start point and cell size from transform. */
- Attribute *attr = mesh->attributes.find(ATTR_STD_GENERATED_TRANSFORM);
- const int3 resolution = volume_params.resolution;
- float3 start_point = make_float3(0.0f, 0.0f, 0.0f);
- float3 cell_size = make_float3(1.0f/resolution.x,
- 1.0f/resolution.y,
- 1.0f/resolution.z);
-
- if(attr) {
- const Transform *tfm = attr->data_transform();
- const Transform itfm = transform_inverse(*tfm);
- start_point = transform_point(&itfm, start_point);
- cell_size = transform_direction(&itfm, cell_size);
- }
-
- volume_params.start_point = start_point;
- volume_params.cell_size = cell_size;
- volume_params.pad_size = pad_size;
-
- /* Build bounding mesh around non-empty volume cells. */
- VolumeMeshBuilder builder(&volume_params);
- const float isovalue = mesh->volume_isovalue;
-
- for(int z = 0; z < resolution.z; ++z) {
- for(int y = 0; y < resolution.y; ++y) {
- for(int x = 0; x < resolution.x; ++x) {
- size_t voxel_index = compute_voxel_index(resolution, x, y, z);
-
- for(size_t i = 0; i < voxel_grids.size(); ++i) {
- const VoxelAttributeGrid &voxel_grid = voxel_grids[i];
- const int channels = voxel_grid.channels;
-
- for(int c = 0; c < channels; c++) {
- if(voxel_grid.data[voxel_index * channels + c] >= isovalue) {
- builder.add_node_with_padding(x, y, z);
- break;
- }
- }
- }
- }
- }
- }
-
- /* Create mesh. */
- vector<float3> vertices;
- vector<int> indices;
- vector<float3> face_normals;
- builder.create_mesh(vertices, indices, face_normals);
-
- mesh->clear(true);
- mesh->reserve_mesh(vertices.size(), indices.size()/3);
- mesh->used_shaders.push_back(volume_shader);
-
- for(size_t i = 0; i < vertices.size(); ++i) {
- mesh->add_vertex(vertices[i]);
- }
-
- for(size_t i = 0; i < indices.size(); i += 3) {
- mesh->add_triangle(indices[i], indices[i + 1], indices[i + 2], 0, false);
- }
-
- Attribute *attr_fN = mesh->attributes.add(ATTR_STD_FACE_NORMAL);
- float3 *fN = attr_fN->data_float3();
-
- for(size_t i = 0; i < face_normals.size(); ++i) {
- fN[i] = face_normals[i];
- }
-
- /* Print stats. */
- VLOG(1) << "Memory usage volume mesh: "
- << ((vertices.size() + face_normals.size())*sizeof(float3) + indices.size()*sizeof(int))/(1024.0*1024.0)
- << "Mb.";
-
- VLOG(1) << "Memory usage volume grid: "
- << (resolution.x*resolution.y*resolution.z*sizeof(float))/(1024.0*1024.0)
- << "Mb.";
+ string msg = string_printf("Computing Volume Mesh %s", mesh->name.c_str());
+ progress.set_status("Updating Mesh", msg);
+
+ vector<VoxelAttributeGrid> voxel_grids;
+
+ /* Compute volume parameters. */
+ VolumeParams volume_params;
+ volume_params.resolution = make_int3(0, 0, 0);
+
+ foreach (Attribute &attr, mesh->attributes.attributes) {
+ if (attr.element != ATTR_ELEMENT_VOXEL) {
+ continue;
+ }
+
+ VoxelAttribute *voxel = attr.data_voxel();
+ device_memory *image_memory = scene->image_manager->image_memory(voxel->slot);
+ int3 resolution = make_int3(
+ image_memory->data_width, image_memory->data_height, image_memory->data_depth);
+
+ if (volume_params.resolution == make_int3(0, 0, 0)) {
+ volume_params.resolution = resolution;
+ }
+ else if (volume_params.resolution != resolution) {
+ VLOG(1) << "Can't create volume mesh, all voxel grid resolutions must be equal\n";
+ return;
+ }
+
+ VoxelAttributeGrid voxel_grid;
+ voxel_grid.data = static_cast<float *>(image_memory->host_pointer);
+ voxel_grid.channels = image_memory->data_elements;
+ voxel_grids.push_back(voxel_grid);
+ }
+
+ if (voxel_grids.empty()) {
+ return;
+ }
+
+ /* Compute padding. */
+ Shader *volume_shader = NULL;
+ int pad_size = 0;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (!shader->has_volume) {
+ continue;
+ }
+
+ volume_shader = shader;
+
+ if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
+ pad_size = max(1, pad_size);
+ }
+ else if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
+ pad_size = max(2, pad_size);
+ }
+
+ break;
+ }
+
+ if (!volume_shader) {
+ return;
+ }
+
+ /* Compute start point and cell size from transform. */
+ Attribute *attr = mesh->attributes.find(ATTR_STD_GENERATED_TRANSFORM);
+ const int3 resolution = volume_params.resolution;
+ float3 start_point = make_float3(0.0f, 0.0f, 0.0f);
+ float3 cell_size = make_float3(1.0f / resolution.x, 1.0f / resolution.y, 1.0f / resolution.z);
+
+ if (attr) {
+ const Transform *tfm = attr->data_transform();
+ const Transform itfm = transform_inverse(*tfm);
+ start_point = transform_point(&itfm, start_point);
+ cell_size = transform_direction(&itfm, cell_size);
+ }
+
+ volume_params.start_point = start_point;
+ volume_params.cell_size = cell_size;
+ volume_params.pad_size = pad_size;
+
+ /* Build bounding mesh around non-empty volume cells. */
+ VolumeMeshBuilder builder(&volume_params);
+ const float isovalue = mesh->volume_isovalue;
+
+ for (int z = 0; z < resolution.z; ++z) {
+ for (int y = 0; y < resolution.y; ++y) {
+ for (int x = 0; x < resolution.x; ++x) {
+ size_t voxel_index = compute_voxel_index(resolution, x, y, z);
+
+ for (size_t i = 0; i < voxel_grids.size(); ++i) {
+ const VoxelAttributeGrid &voxel_grid = voxel_grids[i];
+ const int channels = voxel_grid.channels;
+
+ for (int c = 0; c < channels; c++) {
+ if (voxel_grid.data[voxel_index * channels + c] >= isovalue) {
+ builder.add_node_with_padding(x, y, z);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Create mesh. */
+ vector<float3> vertices;
+ vector<int> indices;
+ vector<float3> face_normals;
+ builder.create_mesh(vertices, indices, face_normals);
+
+ mesh->clear(true);
+ mesh->reserve_mesh(vertices.size(), indices.size() / 3);
+ mesh->used_shaders.push_back(volume_shader);
+
+ for (size_t i = 0; i < vertices.size(); ++i) {
+ mesh->add_vertex(vertices[i]);
+ }
+
+ for (size_t i = 0; i < indices.size(); i += 3) {
+ mesh->add_triangle(indices[i], indices[i + 1], indices[i + 2], 0, false);
+ }
+
+ Attribute *attr_fN = mesh->attributes.add(ATTR_STD_FACE_NORMAL);
+ float3 *fN = attr_fN->data_float3();
+
+ for (size_t i = 0; i < face_normals.size(); ++i) {
+ fN[i] = face_normals[i];
+ }
+
+ /* Print stats. */
+ VLOG(1) << "Memory usage volume mesh: "
+ << ((vertices.size() + face_normals.size()) * sizeof(float3) +
+ indices.size() * sizeof(int)) /
+ (1024.0 * 1024.0)
+ << "Mb.";
+
+ VLOG(1) << "Memory usage volume grid: "
+ << (resolution.x * resolution.y * resolution.z * sizeof(float)) / (1024.0 * 1024.0)
+ << "Mb.";
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index cc9dd8f2679..f3572ee1585 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -37,36 +37,36 @@ CCL_NAMESPACE_BEGIN
/* Texture Mapping */
#define TEXTURE_MAPPING_DEFINE(TextureNode) \
- SOCKET_POINT(tex_mapping.translation, "Translation", make_float3(0.0f, 0.0f, 0.0f)); \
- SOCKET_VECTOR(tex_mapping.rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); \
- SOCKET_VECTOR(tex_mapping.scale, "Scale", make_float3(1.0f, 1.0f, 1.0f)); \
- \
- SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \
- SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \
- SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \
- \
- static NodeEnum mapping_axis_enum; \
- mapping_axis_enum.insert("none", TextureMapping::NONE); \
- mapping_axis_enum.insert("x", TextureMapping::X); \
- mapping_axis_enum.insert("y", TextureMapping::Y); \
- mapping_axis_enum.insert("z", TextureMapping::Z); \
- SOCKET_ENUM(tex_mapping.x_mapping, "x_mapping", mapping_axis_enum, TextureMapping::X); \
- SOCKET_ENUM(tex_mapping.y_mapping, "y_mapping", mapping_axis_enum, TextureMapping::Y); \
- SOCKET_ENUM(tex_mapping.z_mapping, "z_mapping", mapping_axis_enum, TextureMapping::Z); \
- \
- static NodeEnum mapping_type_enum; \
- mapping_type_enum.insert("point", TextureMapping::POINT); \
- mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \
- mapping_type_enum.insert("vector", TextureMapping::VECTOR); \
- mapping_type_enum.insert("normal", TextureMapping::NORMAL); \
- SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \
- \
- static NodeEnum mapping_projection_enum; \
- mapping_projection_enum.insert("flat", TextureMapping::FLAT); \
- mapping_projection_enum.insert("cube", TextureMapping::CUBE); \
- mapping_projection_enum.insert("tube", TextureMapping::TUBE); \
- mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \
- SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT);
+ SOCKET_POINT(tex_mapping.translation, "Translation", make_float3(0.0f, 0.0f, 0.0f)); \
+ SOCKET_VECTOR(tex_mapping.rotation, "Rotation", make_float3(0.0f, 0.0f, 0.0f)); \
+ SOCKET_VECTOR(tex_mapping.scale, "Scale", make_float3(1.0f, 1.0f, 1.0f)); \
+\
+ SOCKET_VECTOR(tex_mapping.min, "Min", make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX)); \
+ SOCKET_VECTOR(tex_mapping.max, "Max", make_float3(FLT_MAX, FLT_MAX, FLT_MAX)); \
+ SOCKET_BOOLEAN(tex_mapping.use_minmax, "Use Min Max", false); \
+\
+ static NodeEnum mapping_axis_enum; \
+ mapping_axis_enum.insert("none", TextureMapping::NONE); \
+ mapping_axis_enum.insert("x", TextureMapping::X); \
+ mapping_axis_enum.insert("y", TextureMapping::Y); \
+ mapping_axis_enum.insert("z", TextureMapping::Z); \
+ SOCKET_ENUM(tex_mapping.x_mapping, "x_mapping", mapping_axis_enum, TextureMapping::X); \
+ SOCKET_ENUM(tex_mapping.y_mapping, "y_mapping", mapping_axis_enum, TextureMapping::Y); \
+ SOCKET_ENUM(tex_mapping.z_mapping, "z_mapping", mapping_axis_enum, TextureMapping::Z); \
+\
+ static NodeEnum mapping_type_enum; \
+ mapping_type_enum.insert("point", TextureMapping::POINT); \
+ mapping_type_enum.insert("texture", TextureMapping::TEXTURE); \
+ mapping_type_enum.insert("vector", TextureMapping::VECTOR); \
+ mapping_type_enum.insert("normal", TextureMapping::NORMAL); \
+ SOCKET_ENUM(tex_mapping.type, "Type", mapping_type_enum, TextureMapping::TEXTURE); \
+\
+ static NodeEnum mapping_projection_enum; \
+ mapping_projection_enum.insert("flat", TextureMapping::FLAT); \
+ mapping_projection_enum.insert("cube", TextureMapping::CUBE); \
+ mapping_projection_enum.insert("tube", TextureMapping::TUBE); \
+ mapping_projection_enum.insert("sphere", TextureMapping::SPHERE); \
+ SOCKET_ENUM(tex_mapping.projection, "Projection", mapping_projection_enum, TextureMapping::FLAT);
TextureMapping::TextureMapping()
{
@@ -74,6146 +74,6096 @@ TextureMapping::TextureMapping()
Transform TextureMapping::compute_transform()
{
- Transform mmat = transform_scale(make_float3(0.0f, 0.0f, 0.0f));
-
- if(x_mapping != NONE)
- mmat[0][x_mapping-1] = 1.0f;
- if(y_mapping != NONE)
- mmat[1][y_mapping-1] = 1.0f;
- if(z_mapping != NONE)
- mmat[2][z_mapping-1] = 1.0f;
-
- float3 scale_clamped = scale;
-
- if(type == TEXTURE || type == NORMAL) {
- /* keep matrix invertible */
- if(fabsf(scale.x) < 1e-5f)
- scale_clamped.x = signf(scale.x)*1e-5f;
- if(fabsf(scale.y) < 1e-5f)
- scale_clamped.y = signf(scale.y)*1e-5f;
- if(fabsf(scale.z) < 1e-5f)
- scale_clamped.z = signf(scale.z)*1e-5f;
- }
-
- Transform smat = transform_scale(scale_clamped);
- Transform rmat = transform_euler(rotation);
- Transform tmat = transform_translate(translation);
-
- Transform mat;
-
- switch(type) {
- case TEXTURE:
- /* inverse transform on texture coordinate gives
- * forward transform on texture */
- mat = tmat*rmat*smat;
- mat = transform_inverse(mat);
- break;
- case POINT:
- /* full transform */
- mat = tmat*rmat*smat;
- break;
- case VECTOR:
- /* no translation for vectors */
- mat = rmat*smat;
- break;
- case NORMAL:
- /* no translation for normals, and inverse transpose */
- mat = rmat*smat;
- mat = transform_transposed_inverse(mat);
- break;
- }
-
- /* projection last */
- mat = mat*mmat;
-
- return mat;
+ Transform mmat = transform_scale(make_float3(0.0f, 0.0f, 0.0f));
+
+ if (x_mapping != NONE)
+ mmat[0][x_mapping - 1] = 1.0f;
+ if (y_mapping != NONE)
+ mmat[1][y_mapping - 1] = 1.0f;
+ if (z_mapping != NONE)
+ mmat[2][z_mapping - 1] = 1.0f;
+
+ float3 scale_clamped = scale;
+
+ if (type == TEXTURE || type == NORMAL) {
+ /* keep matrix invertible */
+ if (fabsf(scale.x) < 1e-5f)
+ scale_clamped.x = signf(scale.x) * 1e-5f;
+ if (fabsf(scale.y) < 1e-5f)
+ scale_clamped.y = signf(scale.y) * 1e-5f;
+ if (fabsf(scale.z) < 1e-5f)
+ scale_clamped.z = signf(scale.z) * 1e-5f;
+ }
+
+ Transform smat = transform_scale(scale_clamped);
+ Transform rmat = transform_euler(rotation);
+ Transform tmat = transform_translate(translation);
+
+ Transform mat;
+
+ switch (type) {
+ case TEXTURE:
+ /* inverse transform on texture coordinate gives
+ * forward transform on texture */
+ mat = tmat * rmat * smat;
+ mat = transform_inverse(mat);
+ break;
+ case POINT:
+ /* full transform */
+ mat = tmat * rmat * smat;
+ break;
+ case VECTOR:
+ /* no translation for vectors */
+ mat = rmat * smat;
+ break;
+ case NORMAL:
+ /* no translation for normals, and inverse transpose */
+ mat = rmat * smat;
+ mat = transform_transposed_inverse(mat);
+ break;
+ }
+
+ /* projection last */
+ mat = mat * mmat;
+
+ return mat;
}
bool TextureMapping::skip()
{
- if(translation != make_float3(0.0f, 0.0f, 0.0f))
- return false;
- if(rotation != make_float3(0.0f, 0.0f, 0.0f))
- return false;
- if(scale != make_float3(1.0f, 1.0f, 1.0f))
- return false;
+ if (translation != make_float3(0.0f, 0.0f, 0.0f))
+ return false;
+ if (rotation != make_float3(0.0f, 0.0f, 0.0f))
+ return false;
+ if (scale != make_float3(1.0f, 1.0f, 1.0f))
+ return false;
- if(x_mapping != X || y_mapping != Y || z_mapping != Z)
- return false;
- if(use_minmax)
- return false;
+ if (x_mapping != X || y_mapping != Y || z_mapping != Z)
+ return false;
+ if (use_minmax)
+ return false;
- return true;
+ return true;
}
-void TextureMapping::compile(SVMCompiler& compiler, int offset_in, int offset_out)
+void TextureMapping::compile(SVMCompiler &compiler, int offset_in, int offset_out)
{
- compiler.add_node(NODE_MAPPING, offset_in, offset_out);
+ compiler.add_node(NODE_MAPPING, offset_in, offset_out);
- Transform tfm = compute_transform();
- compiler.add_node(tfm.x);
- compiler.add_node(tfm.y);
- compiler.add_node(tfm.z);
+ Transform tfm = compute_transform();
+ compiler.add_node(tfm.x);
+ compiler.add_node(tfm.y);
+ compiler.add_node(tfm.z);
- if(use_minmax) {
- compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
- compiler.add_node(float3_to_float4(min));
- compiler.add_node(float3_to_float4(max));
- }
+ if (use_minmax) {
+ compiler.add_node(NODE_MIN_MAX, offset_out, offset_out);
+ compiler.add_node(float3_to_float4(min));
+ compiler.add_node(float3_to_float4(max));
+ }
- if(type == NORMAL) {
- compiler.add_node(NODE_VECTOR_MATH, NODE_VECTOR_MATH_NORMALIZE, offset_out, offset_out);
- compiler.add_node(NODE_VECTOR_MATH, SVM_STACK_INVALID, offset_out);
- }
+ if (type == NORMAL) {
+ compiler.add_node(NODE_VECTOR_MATH, NODE_VECTOR_MATH_NORMALIZE, offset_out, offset_out);
+ compiler.add_node(NODE_VECTOR_MATH, SVM_STACK_INVALID, offset_out);
+ }
}
/* Convenience function for texture nodes, allocating stack space to output
* a modified vector and returning its offset */
-int TextureMapping::compile_begin(SVMCompiler& compiler, ShaderInput *vector_in)
+int TextureMapping::compile_begin(SVMCompiler &compiler, ShaderInput *vector_in)
{
- if(!skip()) {
- int offset_in = compiler.stack_assign(vector_in);
- int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
+ if (!skip()) {
+ int offset_in = compiler.stack_assign(vector_in);
+ int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
- compile(compiler, offset_in, offset_out);
+ compile(compiler, offset_in, offset_out);
- return offset_out;
- }
+ return offset_out;
+ }
- return compiler.stack_assign(vector_in);
+ return compiler.stack_assign(vector_in);
}
-void TextureMapping::compile_end(SVMCompiler& compiler, ShaderInput *vector_in, int vector_offset)
+void TextureMapping::compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset)
{
- if(!skip()) {
- compiler.stack_clear_offset(vector_in->type(), vector_offset);
- }
+ if (!skip()) {
+ compiler.stack_clear_offset(vector_in->type(), vector_offset);
+ }
}
void TextureMapping::compile(OSLCompiler &compiler)
{
- if(!skip()) {
- compiler.parameter("mapping", compute_transform());
- compiler.parameter("use_mapping", 1);
- }
+ if (!skip()) {
+ compiler.parameter("mapping", compute_transform());
+ compiler.parameter("use_mapping", 1);
+ }
}
/* Image Texture */
NODE_DEFINE(ImageTextureNode)
{
- NodeType* type = NodeType::add("image_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("image_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(ImageTextureNode);
+ TEXTURE_MAPPING_DEFINE(ImageTextureNode);
- SOCKET_STRING(filename, "Filename", ustring());
+ SOCKET_STRING(filename, "Filename", ustring());
- static NodeEnum color_space_enum;
- color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
- color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
- SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
+ static NodeEnum color_space_enum;
+ color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
+ color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
+ SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
- SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
+ SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
- static NodeEnum interpolation_enum;
- interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
- interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
- interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
- interpolation_enum.insert("smart", INTERPOLATION_SMART);
- SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
+ static NodeEnum interpolation_enum;
+ interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
+ interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
+ interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
+ interpolation_enum.insert("smart", INTERPOLATION_SMART);
+ SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
- static NodeEnum extension_enum;
- extension_enum.insert("periodic", EXTENSION_REPEAT);
- extension_enum.insert("clamp", EXTENSION_EXTEND);
- extension_enum.insert("black", EXTENSION_CLIP);
- SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
+ static NodeEnum extension_enum;
+ extension_enum.insert("periodic", EXTENSION_REPEAT);
+ extension_enum.insert("clamp", EXTENSION_EXTEND);
+ extension_enum.insert("black", EXTENSION_CLIP);
+ SOCKET_ENUM(extension, "Extension", extension_enum, EXTENSION_REPEAT);
- static NodeEnum projection_enum;
- projection_enum.insert("flat", NODE_IMAGE_PROJ_FLAT);
- projection_enum.insert("box", NODE_IMAGE_PROJ_BOX);
- projection_enum.insert("sphere", NODE_IMAGE_PROJ_SPHERE);
- projection_enum.insert("tube", NODE_IMAGE_PROJ_TUBE);
- SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT);
+ static NodeEnum projection_enum;
+ projection_enum.insert("flat", NODE_IMAGE_PROJ_FLAT);
+ projection_enum.insert("box", NODE_IMAGE_PROJ_BOX);
+ projection_enum.insert("sphere", NODE_IMAGE_PROJ_SPHERE);
+ projection_enum.insert("tube", NODE_IMAGE_PROJ_TUBE);
+ SOCKET_ENUM(projection, "Projection", projection_enum, NODE_IMAGE_PROJ_FLAT);
- SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
+ SOCKET_FLOAT(projection_blend, "Projection Blend", 0.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(alpha, "Alpha");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
- return type;
+ return type;
}
-ImageTextureNode::ImageTextureNode()
-: ImageSlotTextureNode(node_type)
+ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type)
{
- image_manager = NULL;
- slot = -1;
- is_float = -1;
- is_linear = false;
- builtin_data = NULL;
- animated = false;
+ image_manager = NULL;
+ slot = -1;
+ is_float = -1;
+ is_linear = false;
+ builtin_data = NULL;
+ animated = false;
}
ImageTextureNode::~ImageTextureNode()
{
- if(image_manager) {
- image_manager->remove_image(filename.string(),
- builtin_data,
- interpolation,
- extension,
- use_alpha);
- }
+ if (image_manager) {
+ image_manager->remove_image(
+ filename.string(), builtin_data, interpolation, extension, use_alpha);
+ }
}
ShaderNode *ImageTextureNode::clone() const
{
- ImageTextureNode *node = new ImageTextureNode(*this);
- node->image_manager = NULL;
- node->slot = -1;
- node->is_float = -1;
- node->is_linear = false;
- return node;
+ ImageTextureNode *node = new ImageTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ node->is_float = -1;
+ node->is_linear = false;
+ return node;
}
void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
#ifdef WITH_PTEX
- /* todo: avoid loading other texture coordinates when using ptex,
- * and hide texture coordinate socket in the UI */
- if(shader->has_surface && string_endswith(filename, ".ptx")) {
- /* ptex */
- attributes->add(ATTR_STD_PTEX_FACE_ID);
- attributes->add(ATTR_STD_PTEX_UV);
- }
+ /* todo: avoid loading other texture coordinates when using ptex,
+ * and hide texture coordinate socket in the UI */
+ if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
#endif
- ShaderNode::attributes(shader, attributes);
-}
-
-void ImageTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *alpha_out = output("Alpha");
-
- image_manager = compiler.image_manager;
- if(is_float == -1) {
- ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- extension,
- use_alpha,
- metadata);
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot != -1) {
- int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
-
- if(projection != NODE_IMAGE_PROJ_BOX) {
- compiler.add_node(NODE_TEX_IMAGE,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out),
- srgb),
- projection);
- }
- else {
- compiler.add_node(NODE_TEX_IMAGE_BOX,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out),
- srgb),
- __float_as_int(projection_blend));
- }
-
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
- }
- else {
- /* image not found */
- if(!color_out->links.empty()) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
- TEX_IMAGE_MISSING_G,
- TEX_IMAGE_MISSING_B));
- }
- if(!alpha_out->links.empty())
- compiler.add_node(NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
- }
-}
-
-void ImageTextureNode::compile(OSLCompiler& compiler)
-{
- ShaderOutput *alpha_out = output("Alpha");
-
- tex_mapping.compile(compiler);
-
- image_manager = compiler.image_manager;
- if(is_float == -1) {
- ImageMetaData metadata;
- if(builtin_data == NULL) {
- image_manager->get_image_metadata(filename.string(), NULL, metadata);
- }
- else {
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- extension,
- use_alpha,
- metadata);
- }
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot == -1) {
- compiler.parameter(this, "filename");
- }
- else {
- /* TODO(sergey): It's not so simple to pass custom attribute
- * to the texture() function in order to make builtin images
- * support more clear. So we use special file name which is
- * "@i<slot_number>" and check whether file name matches this
- * mask in the OSLRenderServices::texture().
- */
- compiler.parameter("filename", string_printf("@i%d", slot).c_str());
- }
- if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
- compiler.parameter("color_space", "linear");
- else
- compiler.parameter("color_space", "sRGB");
- compiler.parameter(this, "projection");
- compiler.parameter(this, "projection_blend");
- compiler.parameter("is_float", is_float);
- compiler.parameter("use_alpha", !alpha_out->links.empty());
- compiler.parameter(this, "interpolation");
- compiler.parameter(this, "extension");
-
- compiler.add(this, "node_image_texture");
+ ShaderNode::attributes(shader, attributes);
+}
+
+void ImageTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *alpha_out = output("Alpha");
+
+ image_manager = compiler.image_manager;
+ if (is_float == -1) {
+ ImageMetaData metadata;
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ extension,
+ use_alpha,
+ metadata);
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot != -1) {
+ int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR) ? 0 : 1;
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ if (projection != NODE_IMAGE_PROJ_BOX) {
+ compiler.add_node(NODE_TEX_IMAGE,
+ slot,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out),
+ srgb),
+ projection);
+ }
+ else {
+ compiler.add_node(NODE_TEX_IMAGE_BOX,
+ slot,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out),
+ srgb),
+ __float_as_int(projection_blend));
+ }
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ }
+ else {
+ /* image not found */
+ if (!color_out->links.empty()) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_VALUE_V,
+ make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
+ }
+ if (!alpha_out->links.empty())
+ compiler.add_node(
+ NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
+ }
+}
+
+void ImageTextureNode::compile(OSLCompiler &compiler)
+{
+ ShaderOutput *alpha_out = output("Alpha");
+
+ tex_mapping.compile(compiler);
+
+ image_manager = compiler.image_manager;
+ if (is_float == -1) {
+ ImageMetaData metadata;
+ if (builtin_data == NULL) {
+ image_manager->get_image_metadata(filename.string(), NULL, metadata);
+ }
+ else {
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ extension,
+ use_alpha,
+ metadata);
+ }
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot == -1) {
+ compiler.parameter(this, "filename");
+ }
+ else {
+ /* TODO(sergey): It's not so simple to pass custom attribute
+ * to the texture() function in order to make builtin images
+ * support more clear. So we use special file name which is
+ * "@i<slot_number>" and check whether file name matches this
+ * mask in the OSLRenderServices::texture().
+ */
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
+ }
+ if (is_linear || color_space != NODE_COLOR_SPACE_COLOR)
+ compiler.parameter("color_space", "linear");
+ else
+ compiler.parameter("color_space", "sRGB");
+ compiler.parameter(this, "projection");
+ compiler.parameter(this, "projection_blend");
+ compiler.parameter("is_float", is_float);
+ compiler.parameter("use_alpha", !alpha_out->links.empty());
+ compiler.parameter(this, "interpolation");
+ compiler.parameter(this, "extension");
+
+ compiler.add(this, "node_image_texture");
}
/* Environment Texture */
NODE_DEFINE(EnvironmentTextureNode)
{
- NodeType* type = NodeType::add("environment_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("environment_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
+ TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
- SOCKET_STRING(filename, "Filename", ustring());
+ SOCKET_STRING(filename, "Filename", ustring());
- static NodeEnum color_space_enum;
- color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
- color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
- SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
+ static NodeEnum color_space_enum;
+ color_space_enum.insert("none", NODE_COLOR_SPACE_NONE);
+ color_space_enum.insert("color", NODE_COLOR_SPACE_COLOR);
+ SOCKET_ENUM(color_space, "Color Space", color_space_enum, NODE_COLOR_SPACE_COLOR);
- SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
+ SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
- static NodeEnum interpolation_enum;
- interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
- interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
- interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
- interpolation_enum.insert("smart", INTERPOLATION_SMART);
- SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
+ static NodeEnum interpolation_enum;
+ interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
+ interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
+ interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
+ interpolation_enum.insert("smart", INTERPOLATION_SMART);
+ SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
- static NodeEnum projection_enum;
- projection_enum.insert("equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR);
- projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
- SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
+ static NodeEnum projection_enum;
+ projection_enum.insert("equirectangular", NODE_ENVIRONMENT_EQUIRECTANGULAR);
+ projection_enum.insert("mirror_ball", NODE_ENVIRONMENT_MIRROR_BALL);
+ SOCKET_ENUM(projection, "Projection", projection_enum, NODE_ENVIRONMENT_EQUIRECTANGULAR);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(alpha, "Alpha");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
- return type;
+ return type;
}
-EnvironmentTextureNode::EnvironmentTextureNode()
-: ImageSlotTextureNode(node_type)
+EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_type)
{
- image_manager = NULL;
- slot = -1;
- is_float = -1;
- is_linear = false;
- builtin_data = NULL;
- animated = false;
+ image_manager = NULL;
+ slot = -1;
+ is_float = -1;
+ is_linear = false;
+ builtin_data = NULL;
+ animated = false;
}
EnvironmentTextureNode::~EnvironmentTextureNode()
{
- if(image_manager) {
- image_manager->remove_image(filename.string(),
- builtin_data,
- interpolation,
- EXTENSION_REPEAT,
- use_alpha);
- }
+ if (image_manager) {
+ image_manager->remove_image(
+ filename.string(), builtin_data, interpolation, EXTENSION_REPEAT, use_alpha);
+ }
}
ShaderNode *EnvironmentTextureNode::clone() const
{
- EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
- node->image_manager = NULL;
- node->slot = -1;
- node->is_float = -1;
- node->is_linear = false;
- return node;
+ EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ node->is_float = -1;
+ node->is_linear = false;
+ return node;
}
void EnvironmentTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
#ifdef WITH_PTEX
- if(shader->has_surface && string_endswith(filename, ".ptx")) {
- /* ptex */
- attributes->add(ATTR_STD_PTEX_FACE_ID);
- attributes->add(ATTR_STD_PTEX_UV);
- }
+ if (shader->has_surface && string_endswith(filename, ".ptx")) {
+ /* ptex */
+ attributes->add(ATTR_STD_PTEX_FACE_ID);
+ attributes->add(ATTR_STD_PTEX_UV);
+ }
#endif
- ShaderNode::attributes(shader, attributes);
-}
-
-void EnvironmentTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *alpha_out = output("Alpha");
-
- image_manager = compiler.image_manager;
- if(slot == -1) {
- ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- EXTENSION_REPEAT,
- use_alpha,
- metadata);
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot != -1) {
- int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
-
- compiler.add_node(NODE_TEX_ENVIRONMENT,
- slot,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out),
- srgb),
- projection);
-
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
- }
- else {
- /* image not found */
- if(!color_out->links.empty()) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
- TEX_IMAGE_MISSING_G,
- TEX_IMAGE_MISSING_B));
- }
- if(!alpha_out->links.empty())
- compiler.add_node(NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
- }
-}
-
-void EnvironmentTextureNode::compile(OSLCompiler& compiler)
-{
- ShaderOutput *alpha_out = output("Alpha");
-
- tex_mapping.compile(compiler);
-
- /* See comments in ImageTextureNode::compile about support
- * of builtin images.
- */
- image_manager = compiler.image_manager;
- if(is_float == -1) {
- ImageMetaData metadata;
- if(builtin_data == NULL) {
- image_manager->get_image_metadata(filename.string(), NULL, metadata);
- }
- else {
- slot = image_manager->add_image(filename.string(),
- builtin_data,
- animated,
- 0,
- interpolation,
- EXTENSION_REPEAT,
- use_alpha,
- metadata);
- }
- is_float = metadata.is_float;
- is_linear = metadata.is_linear;
- }
-
- if(slot == -1) {
- compiler.parameter(this, "filename");
- }
- else {
- compiler.parameter("filename", string_printf("@i%d", slot).c_str());
- }
- compiler.parameter(this, "projection");
- if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
- compiler.parameter("color_space", "linear");
- else
- compiler.parameter("color_space", "sRGB");
-
- compiler.parameter(this, "interpolation");
- compiler.parameter("is_float", is_float);
- compiler.parameter("use_alpha", !alpha_out->links.empty());
- compiler.add(this, "node_environment_texture");
+ ShaderNode::attributes(shader, attributes);
+}
+
+void EnvironmentTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *alpha_out = output("Alpha");
+
+ image_manager = compiler.image_manager;
+ if (slot == -1) {
+ ImageMetaData metadata;
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ EXTENSION_REPEAT,
+ use_alpha,
+ metadata);
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot != -1) {
+ int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR) ? 0 : 1;
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ compiler.add_node(NODE_TEX_ENVIRONMENT,
+ slot,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out),
+ srgb),
+ projection);
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ }
+ else {
+ /* image not found */
+ if (!color_out->links.empty()) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_VALUE_V,
+ make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
+ }
+ if (!alpha_out->links.empty())
+ compiler.add_node(
+ NODE_VALUE_F, __float_as_int(TEX_IMAGE_MISSING_A), compiler.stack_assign(alpha_out));
+ }
+}
+
+void EnvironmentTextureNode::compile(OSLCompiler &compiler)
+{
+ ShaderOutput *alpha_out = output("Alpha");
+
+ tex_mapping.compile(compiler);
+
+ /* See comments in ImageTextureNode::compile about support
+ * of builtin images.
+ */
+ image_manager = compiler.image_manager;
+ if (is_float == -1) {
+ ImageMetaData metadata;
+ if (builtin_data == NULL) {
+ image_manager->get_image_metadata(filename.string(), NULL, metadata);
+ }
+ else {
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ animated,
+ 0,
+ interpolation,
+ EXTENSION_REPEAT,
+ use_alpha,
+ metadata);
+ }
+ is_float = metadata.is_float;
+ is_linear = metadata.is_linear;
+ }
+
+ if (slot == -1) {
+ compiler.parameter(this, "filename");
+ }
+ else {
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
+ }
+ compiler.parameter(this, "projection");
+ if (is_linear || color_space != NODE_COLOR_SPACE_COLOR)
+ compiler.parameter("color_space", "linear");
+ else
+ compiler.parameter("color_space", "sRGB");
+
+ compiler.parameter(this, "interpolation");
+ compiler.parameter("is_float", is_float);
+ compiler.parameter("use_alpha", !alpha_out->links.empty());
+ compiler.add(this, "node_environment_texture");
}
/* Sky Texture */
static float2 sky_spherical_coordinates(float3 dir)
{
- return make_float2(acosf(dir.z), atan2f(dir.x, dir.y));
+ return make_float2(acosf(dir.z), atan2f(dir.x, dir.y));
}
typedef struct SunSky {
- /* sun direction in spherical and cartesian */
- float theta, phi;
+ /* sun direction in spherical and cartesian */
+ float theta, phi;
- /* Parameter */
- float radiance_x, radiance_y, radiance_z;
- float config_x[9], config_y[9], config_z[9];
+ /* Parameter */
+ float radiance_x, radiance_y, radiance_z;
+ float config_x[9], config_y[9], config_z[9];
} SunSky;
/* Preetham model */
static float sky_perez_function(float lam[6], float theta, float gamma)
{
- return (1.0f + lam[0]*expf(lam[1]/cosf(theta))) * (1.0f + lam[2]*expf(lam[3]*gamma) + lam[4]*cosf(gamma)*cosf(gamma));
+ return (1.0f + lam[0] * expf(lam[1] / cosf(theta))) *
+ (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cosf(gamma) * cosf(gamma));
}
static void sky_texture_precompute_old(SunSky *sunsky, float3 dir, float turbidity)
{
- /*
- * We re-use the SunSky struct of the new model, to avoid extra variables
- * zenith_Y/x/y is now radiance_x/y/z
- * perez_Y/x/y is now config_x/y/z
- */
-
- float2 spherical = sky_spherical_coordinates(dir);
- float theta = spherical.x;
- float phi = spherical.y;
-
- sunsky->theta = theta;
- sunsky->phi = phi;
-
- float theta2 = theta*theta;
- float theta3 = theta2*theta;
- float T = turbidity;
- float T2 = T * T;
-
- float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
- sunsky->radiance_x = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
- sunsky->radiance_x *= 0.06f;
-
- sunsky->radiance_y =
- (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
- (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * T +
- (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
-
- sunsky->radiance_z =
- (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
- (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * T +
- (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
-
- sunsky->config_x[0] = (0.1787f * T - 1.4630f);
- sunsky->config_x[1] = (-0.3554f * T + 0.4275f);
- sunsky->config_x[2] = (-0.0227f * T + 5.3251f);
- sunsky->config_x[3] = (0.1206f * T - 2.5771f);
- sunsky->config_x[4] = (-0.0670f * T + 0.3703f);
-
- sunsky->config_y[0] = (-0.0193f * T - 0.2592f);
- sunsky->config_y[1] = (-0.0665f * T + 0.0008f);
- sunsky->config_y[2] = (-0.0004f * T + 0.2125f);
- sunsky->config_y[3] = (-0.0641f * T - 0.8989f);
- sunsky->config_y[4] = (-0.0033f * T + 0.0452f);
-
- sunsky->config_z[0] = (-0.0167f * T - 0.2608f);
- sunsky->config_z[1] = (-0.0950f * T + 0.0092f);
- sunsky->config_z[2] = (-0.0079f * T + 0.2102f);
- sunsky->config_z[3] = (-0.0441f * T - 1.6537f);
- sunsky->config_z[4] = (-0.0109f * T + 0.0529f);
-
- /* unused for old sky model */
- for(int i = 5; i < 9; i++) {
- sunsky->config_x[i] = 0.0f;
- sunsky->config_y[i] = 0.0f;
- sunsky->config_z[i] = 0.0f;
- }
-
- sunsky->radiance_x /= sky_perez_function(sunsky->config_x, 0, theta);
- sunsky->radiance_y /= sky_perez_function(sunsky->config_y, 0, theta);
- sunsky->radiance_z /= sky_perez_function(sunsky->config_z, 0, theta);
+ /*
+ * We re-use the SunSky struct of the new model, to avoid extra variables
+ * zenith_Y/x/y is now radiance_x/y/z
+ * perez_Y/x/y is now config_x/y/z
+ */
+
+ float2 spherical = sky_spherical_coordinates(dir);
+ float theta = spherical.x;
+ float phi = spherical.y;
+
+ sunsky->theta = theta;
+ sunsky->phi = phi;
+
+ float theta2 = theta * theta;
+ float theta3 = theta2 * theta;
+ float T = turbidity;
+ float T2 = T * T;
+
+ float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI_F - 2.0f * theta);
+ sunsky->radiance_x = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
+ sunsky->radiance_x *= 0.06f;
+
+ sunsky->radiance_y = (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
+ (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) * T +
+ (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
+
+ sunsky->radiance_z = (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
+ (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) * T +
+ (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
+
+ sunsky->config_x[0] = (0.1787f * T - 1.4630f);
+ sunsky->config_x[1] = (-0.3554f * T + 0.4275f);
+ sunsky->config_x[2] = (-0.0227f * T + 5.3251f);
+ sunsky->config_x[3] = (0.1206f * T - 2.5771f);
+ sunsky->config_x[4] = (-0.0670f * T + 0.3703f);
+
+ sunsky->config_y[0] = (-0.0193f * T - 0.2592f);
+ sunsky->config_y[1] = (-0.0665f * T + 0.0008f);
+ sunsky->config_y[2] = (-0.0004f * T + 0.2125f);
+ sunsky->config_y[3] = (-0.0641f * T - 0.8989f);
+ sunsky->config_y[4] = (-0.0033f * T + 0.0452f);
+
+ sunsky->config_z[0] = (-0.0167f * T - 0.2608f);
+ sunsky->config_z[1] = (-0.0950f * T + 0.0092f);
+ sunsky->config_z[2] = (-0.0079f * T + 0.2102f);
+ sunsky->config_z[3] = (-0.0441f * T - 1.6537f);
+ sunsky->config_z[4] = (-0.0109f * T + 0.0529f);
+
+ /* unused for old sky model */
+ for (int i = 5; i < 9; i++) {
+ sunsky->config_x[i] = 0.0f;
+ sunsky->config_y[i] = 0.0f;
+ sunsky->config_z[i] = 0.0f;
+ }
+
+ sunsky->radiance_x /= sky_perez_function(sunsky->config_x, 0, theta);
+ sunsky->radiance_y /= sky_perez_function(sunsky->config_y, 0, theta);
+ sunsky->radiance_z /= sky_perez_function(sunsky->config_z, 0, theta);
}
/* Hosek / Wilkie */
-static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidity, float ground_albedo)
+static void sky_texture_precompute_new(SunSky *sunsky,
+ float3 dir,
+ float turbidity,
+ float ground_albedo)
{
- /* Calculate Sun Direction and save coordinates */
- float2 spherical = sky_spherical_coordinates(dir);
- float theta = spherical.x;
- float phi = spherical.y;
+ /* Calculate Sun Direction and save coordinates */
+ float2 spherical = sky_spherical_coordinates(dir);
+ float theta = spherical.x;
+ float phi = spherical.y;
- /* Clamp Turbidity */
- turbidity = clamp(turbidity, 0.0f, 10.0f);
+ /* Clamp Turbidity */
+ turbidity = clamp(turbidity, 0.0f, 10.0f);
- /* Clamp to Horizon */
- theta = clamp(theta, 0.0f, M_PI_2_F);
+ /* Clamp to Horizon */
+ theta = clamp(theta, 0.0f, M_PI_2_F);
- sunsky->theta = theta;
- sunsky->phi = phi;
+ sunsky->theta = theta;
+ sunsky->phi = phi;
- float solarElevation = M_PI_2_F - theta;
+ float solarElevation = M_PI_2_F - theta;
- /* Initialize Sky Model */
- ArHosekSkyModelState *sky_state;
- sky_state = arhosek_xyz_skymodelstate_alloc_init((double)turbidity, (double)ground_albedo, (double)solarElevation);
+ /* Initialize Sky Model */
+ ArHosekSkyModelState *sky_state;
+ sky_state = arhosek_xyz_skymodelstate_alloc_init(
+ (double)turbidity, (double)ground_albedo, (double)solarElevation);
- /* Copy values from sky_state to SunSky */
- for(int i = 0; i < 9; ++i) {
- sunsky->config_x[i] = (float)sky_state->configs[0][i];
- sunsky->config_y[i] = (float)sky_state->configs[1][i];
- sunsky->config_z[i] = (float)sky_state->configs[2][i];
- }
- sunsky->radiance_x = (float)sky_state->radiances[0];
- sunsky->radiance_y = (float)sky_state->radiances[1];
- sunsky->radiance_z = (float)sky_state->radiances[2];
+ /* Copy values from sky_state to SunSky */
+ for (int i = 0; i < 9; ++i) {
+ sunsky->config_x[i] = (float)sky_state->configs[0][i];
+ sunsky->config_y[i] = (float)sky_state->configs[1][i];
+ sunsky->config_z[i] = (float)sky_state->configs[2][i];
+ }
+ sunsky->radiance_x = (float)sky_state->radiances[0];
+ sunsky->radiance_y = (float)sky_state->radiances[1];
+ sunsky->radiance_z = (float)sky_state->radiances[2];
- /* Free sky_state */
- arhosekskymodelstate_free(sky_state);
+ /* Free sky_state */
+ arhosekskymodelstate_free(sky_state);
}
NODE_DEFINE(SkyTextureNode)
{
- NodeType* type = NodeType::add("sky_texture", create, NodeType::SHADER);
-
- TEXTURE_MAPPING_DEFINE(SkyTextureNode);
-
- static NodeEnum type_enum;
- type_enum.insert("preetham", NODE_SKY_OLD);
- type_enum.insert("hosek_wilkie", NODE_SKY_NEW);
- SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NEW);
-
- SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
- SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
- SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
-
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
-
- SOCKET_OUT_COLOR(color, "Color");
-
- return type;
-}
-
-SkyTextureNode::SkyTextureNode()
-: TextureNode(node_type)
-{
-}
-
-void SkyTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
-
- SunSky sunsky;
- if(type == NODE_SKY_OLD)
- sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type == NODE_SKY_NEW)
- sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
- else
- assert(false);
-
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
-
- compiler.stack_assign(color_out);
- compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type);
- compiler.add_node(__float_as_uint(sunsky.phi), __float_as_uint(sunsky.theta), __float_as_uint(sunsky.radiance_x), __float_as_uint(sunsky.radiance_y));
- compiler.add_node(__float_as_uint(sunsky.radiance_z), __float_as_uint(sunsky.config_x[0]), __float_as_uint(sunsky.config_x[1]), __float_as_uint(sunsky.config_x[2]));
- compiler.add_node(__float_as_uint(sunsky.config_x[3]), __float_as_uint(sunsky.config_x[4]), __float_as_uint(sunsky.config_x[5]), __float_as_uint(sunsky.config_x[6]));
- compiler.add_node(__float_as_uint(sunsky.config_x[7]), __float_as_uint(sunsky.config_x[8]), __float_as_uint(sunsky.config_y[0]), __float_as_uint(sunsky.config_y[1]));
- compiler.add_node(__float_as_uint(sunsky.config_y[2]), __float_as_uint(sunsky.config_y[3]), __float_as_uint(sunsky.config_y[4]), __float_as_uint(sunsky.config_y[5]));
- compiler.add_node(__float_as_uint(sunsky.config_y[6]), __float_as_uint(sunsky.config_y[7]), __float_as_uint(sunsky.config_y[8]), __float_as_uint(sunsky.config_z[0]));
- compiler.add_node(__float_as_uint(sunsky.config_z[1]), __float_as_uint(sunsky.config_z[2]), __float_as_uint(sunsky.config_z[3]), __float_as_uint(sunsky.config_z[4]));
- compiler.add_node(__float_as_uint(sunsky.config_z[5]), __float_as_uint(sunsky.config_z[6]), __float_as_uint(sunsky.config_z[7]), __float_as_uint(sunsky.config_z[8]));
-
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
-}
-
-void SkyTextureNode::compile(OSLCompiler& compiler)
-{
- tex_mapping.compile(compiler);
-
- SunSky sunsky;
- if(type == NODE_SKY_OLD)
- sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type == NODE_SKY_NEW)
- sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
- else
- assert(false);
-
- compiler.parameter(this, "type");
- compiler.parameter("theta", sunsky.theta);
- compiler.parameter("phi", sunsky.phi);
- compiler.parameter_color("radiance", make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
- compiler.parameter_array("config_x", sunsky.config_x, 9);
- compiler.parameter_array("config_y", sunsky.config_y, 9);
- compiler.parameter_array("config_z", sunsky.config_z, 9);
- compiler.add(this, "node_sky_texture");
+ NodeType *type = NodeType::add("sky_texture", create, NodeType::SHADER);
+
+ TEXTURE_MAPPING_DEFINE(SkyTextureNode);
+
+ static NodeEnum type_enum;
+ type_enum.insert("preetham", NODE_SKY_OLD);
+ type_enum.insert("hosek_wilkie", NODE_SKY_NEW);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_SKY_NEW);
+
+ SOCKET_VECTOR(sun_direction, "Sun Direction", make_float3(0.0f, 0.0f, 1.0f));
+ SOCKET_FLOAT(turbidity, "Turbidity", 2.2f);
+ SOCKET_FLOAT(ground_albedo, "Ground Albedo", 0.3f);
+
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+
+ SOCKET_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
+SkyTextureNode::SkyTextureNode() : TextureNode(node_type)
+{
+}
+
+void SkyTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+
+ SunSky sunsky;
+ if (type == NODE_SKY_OLD)
+ sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
+ else if (type == NODE_SKY_NEW)
+ sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
+ else
+ assert(false);
+
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ compiler.stack_assign(color_out);
+ compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), type);
+ compiler.add_node(__float_as_uint(sunsky.phi),
+ __float_as_uint(sunsky.theta),
+ __float_as_uint(sunsky.radiance_x),
+ __float_as_uint(sunsky.radiance_y));
+ compiler.add_node(__float_as_uint(sunsky.radiance_z),
+ __float_as_uint(sunsky.config_x[0]),
+ __float_as_uint(sunsky.config_x[1]),
+ __float_as_uint(sunsky.config_x[2]));
+ compiler.add_node(__float_as_uint(sunsky.config_x[3]),
+ __float_as_uint(sunsky.config_x[4]),
+ __float_as_uint(sunsky.config_x[5]),
+ __float_as_uint(sunsky.config_x[6]));
+ compiler.add_node(__float_as_uint(sunsky.config_x[7]),
+ __float_as_uint(sunsky.config_x[8]),
+ __float_as_uint(sunsky.config_y[0]),
+ __float_as_uint(sunsky.config_y[1]));
+ compiler.add_node(__float_as_uint(sunsky.config_y[2]),
+ __float_as_uint(sunsky.config_y[3]),
+ __float_as_uint(sunsky.config_y[4]),
+ __float_as_uint(sunsky.config_y[5]));
+ compiler.add_node(__float_as_uint(sunsky.config_y[6]),
+ __float_as_uint(sunsky.config_y[7]),
+ __float_as_uint(sunsky.config_y[8]),
+ __float_as_uint(sunsky.config_z[0]));
+ compiler.add_node(__float_as_uint(sunsky.config_z[1]),
+ __float_as_uint(sunsky.config_z[2]),
+ __float_as_uint(sunsky.config_z[3]),
+ __float_as_uint(sunsky.config_z[4]));
+ compiler.add_node(__float_as_uint(sunsky.config_z[5]),
+ __float_as_uint(sunsky.config_z[6]),
+ __float_as_uint(sunsky.config_z[7]),
+ __float_as_uint(sunsky.config_z[8]));
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+}
+
+void SkyTextureNode::compile(OSLCompiler &compiler)
+{
+ tex_mapping.compile(compiler);
+
+ SunSky sunsky;
+ if (type == NODE_SKY_OLD)
+ sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
+ else if (type == NODE_SKY_NEW)
+ sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
+ else
+ assert(false);
+
+ compiler.parameter(this, "type");
+ compiler.parameter("theta", sunsky.theta);
+ compiler.parameter("phi", sunsky.phi);
+ compiler.parameter_color("radiance",
+ make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
+ compiler.parameter_array("config_x", sunsky.config_x, 9);
+ compiler.parameter_array("config_y", sunsky.config_y, 9);
+ compiler.parameter_array("config_z", sunsky.config_z, 9);
+ compiler.add(this, "node_sky_texture");
}
/* Gradient Texture */
NODE_DEFINE(GradientTextureNode)
{
- NodeType* type = NodeType::add("gradient_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("gradient_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(GradientTextureNode);
+ TEXTURE_MAPPING_DEFINE(GradientTextureNode);
- static NodeEnum type_enum;
- type_enum.insert("linear", NODE_BLEND_LINEAR);
- type_enum.insert("quadratic", NODE_BLEND_QUADRATIC);
- type_enum.insert("easing", NODE_BLEND_EASING);
- type_enum.insert("diagonal", NODE_BLEND_DIAGONAL);
- type_enum.insert("radial", NODE_BLEND_RADIAL);
- type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
- type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR);
+ static NodeEnum type_enum;
+ type_enum.insert("linear", NODE_BLEND_LINEAR);
+ type_enum.insert("quadratic", NODE_BLEND_QUADRATIC);
+ type_enum.insert("easing", NODE_BLEND_EASING);
+ type_enum.insert("diagonal", NODE_BLEND_DIAGONAL);
+ type_enum.insert("radial", NODE_BLEND_RADIAL);
+ type_enum.insert("quadratic_sphere", NODE_BLEND_QUADRATIC_SPHERE);
+ type_enum.insert("spherical", NODE_BLEND_SPHERICAL);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_BLEND_LINEAR);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-GradientTextureNode::GradientTextureNode()
-: TextureNode(node_type)
+GradientTextureNode::GradientTextureNode() : TextureNode(node_type)
{
}
-void GradientTextureNode::compile(SVMCompiler& compiler)
+void GradientTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_GRADIENT,
- compiler.encode_uchar4(
- type,
- vector_offset,
- compiler.stack_assign_if_linked(fac_out),
- compiler.stack_assign_if_linked(color_out)));
+ compiler.add_node(NODE_TEX_GRADIENT,
+ compiler.encode_uchar4(type,
+ vector_offset,
+ compiler.stack_assign_if_linked(fac_out),
+ compiler.stack_assign_if_linked(color_out)));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void GradientTextureNode::compile(OSLCompiler& compiler)
+void GradientTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "type");
- compiler.add(this, "node_gradient_texture");
+ compiler.parameter(this, "type");
+ compiler.add(this, "node_gradient_texture");
}
/* Noise Texture */
NODE_DEFINE(NoiseTextureNode)
{
- NodeType* type = NodeType::add("noise_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("noise_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(NoiseTextureNode);
+ TEXTURE_MAPPING_DEFINE(NoiseTextureNode);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
- SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
+ SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-NoiseTextureNode::NoiseTextureNode()
-: TextureNode(node_type)
+NoiseTextureNode::NoiseTextureNode() : TextureNode(node_type)
{
}
-void NoiseTextureNode::compile(SVMCompiler& compiler)
+void NoiseTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *distortion_in = input("Distortion");
- ShaderInput *detail_in = input("Detail");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *distortion_in = input("Distortion");
+ ShaderInput *detail_in = input("Detail");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_NOISE,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(detail_in),
- compiler.stack_assign_if_linked(distortion_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)));
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(detail),
- __float_as_int(distortion));
+ compiler.add_node(NODE_TEX_NOISE,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(detail_in),
+ compiler.stack_assign_if_linked(distortion_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)));
+ compiler.add_node(__float_as_int(scale), __float_as_int(detail), __float_as_int(distortion));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void NoiseTextureNode::compile(OSLCompiler& compiler)
+void NoiseTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.add(this, "node_noise_texture");
+ compiler.add(this, "node_noise_texture");
}
/* Voronoi Texture */
NODE_DEFINE(VoronoiTextureNode)
{
- NodeType* type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(VoronoiTextureNode);
+ TEXTURE_MAPPING_DEFINE(VoronoiTextureNode);
- static NodeEnum coloring_enum;
- coloring_enum.insert("intensity", NODE_VORONOI_INTENSITY);
- coloring_enum.insert("cells", NODE_VORONOI_CELLS);
- SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY);
+ static NodeEnum coloring_enum;
+ coloring_enum.insert("intensity", NODE_VORONOI_INTENSITY);
+ coloring_enum.insert("cells", NODE_VORONOI_CELLS);
+ SOCKET_ENUM(coloring, "Coloring", coloring_enum, NODE_VORONOI_INTENSITY);
- static NodeEnum metric;
- metric.insert("distance", NODE_VORONOI_DISTANCE);
- metric.insert("manhattan", NODE_VORONOI_MANHATTAN);
- metric.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
- metric.insert("minkowski", NODE_VORONOI_MINKOWSKI);
- SOCKET_ENUM(metric, "Distance Metric", metric, NODE_VORONOI_INTENSITY);
+ static NodeEnum metric;
+ metric.insert("distance", NODE_VORONOI_DISTANCE);
+ metric.insert("manhattan", NODE_VORONOI_MANHATTAN);
+ metric.insert("chebychev", NODE_VORONOI_CHEBYCHEV);
+ metric.insert("minkowski", NODE_VORONOI_MINKOWSKI);
+ SOCKET_ENUM(metric, "Distance Metric", metric, NODE_VORONOI_INTENSITY);
- static NodeEnum feature_enum;
- feature_enum.insert("F1", NODE_VORONOI_F1);
- feature_enum.insert("F2", NODE_VORONOI_F2);
- feature_enum.insert("F3", NODE_VORONOI_F3);
- feature_enum.insert("F4", NODE_VORONOI_F4);
- feature_enum.insert("F2F1", NODE_VORONOI_F2F1);
- SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_INTENSITY);
+ static NodeEnum feature_enum;
+ feature_enum.insert("F1", NODE_VORONOI_F1);
+ feature_enum.insert("F2", NODE_VORONOI_F2);
+ feature_enum.insert("F3", NODE_VORONOI_F3);
+ feature_enum.insert("F4", NODE_VORONOI_F4);
+ feature_enum.insert("F2F1", NODE_VORONOI_F2F1);
+ SOCKET_ENUM(feature, "Feature", feature_enum, NODE_VORONOI_INTENSITY);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(exponent, "Exponent", 0.5f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-VoronoiTextureNode::VoronoiTextureNode()
-: TextureNode(node_type)
+VoronoiTextureNode::VoronoiTextureNode() : TextureNode(node_type)
{
}
-void VoronoiTextureNode::compile(SVMCompiler& compiler)
+void VoronoiTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *scale_in = input("Scale");
- ShaderInput *vector_in = input("Vector");
- ShaderInput *exponent_in = input("Exponent");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *exponent_in = input("Exponent");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- if(vector_in->link) compiler.stack_assign(vector_in);
- if(scale_in->link) compiler.stack_assign(scale_in);
- if(exponent_in->link) compiler.stack_assign(exponent_in);
+ if (vector_in->link)
+ compiler.stack_assign(vector_in);
+ if (scale_in->link)
+ compiler.stack_assign(scale_in);
+ if (exponent_in->link)
+ compiler.stack_assign(exponent_in);
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_VORONOI,
- compiler.encode_uchar4(
- vector_offset,
- coloring,
- metric,
- feature
- ),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(exponent_in),
- compiler.stack_assign(fac_out),
- compiler.stack_assign(color_out)
- ));
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(exponent));
+ compiler.add_node(NODE_TEX_VORONOI,
+ compiler.encode_uchar4(vector_offset, coloring, metric, feature),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(exponent_in),
+ compiler.stack_assign(fac_out),
+ compiler.stack_assign(color_out)));
+ compiler.add_node(__float_as_int(scale), __float_as_int(exponent));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void VoronoiTextureNode::compile(OSLCompiler& compiler)
+void VoronoiTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "coloring");
- compiler.parameter(this, "metric");
- compiler.parameter(this, "feature");
- compiler.add(this, "node_voronoi_texture");
+ compiler.parameter(this, "coloring");
+ compiler.parameter(this, "metric");
+ compiler.parameter(this, "feature");
+ compiler.add(this, "node_voronoi_texture");
}
/* IES Light */
NODE_DEFINE(IESLightNode)
{
- NodeType* type = NodeType::add("ies_light", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("ies_light", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(IESLightNode);
+ TEXTURE_MAPPING_DEFINE(IESLightNode);
- SOCKET_STRING(ies, "IES", ustring());
- SOCKET_STRING(filename, "File Name", ustring());
+ SOCKET_STRING(ies, "IES", ustring());
+ SOCKET_STRING(filename, "File Name", ustring());
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_NORMAL);
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_NORMAL);
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-IESLightNode::IESLightNode()
-: TextureNode(node_type)
+IESLightNode::IESLightNode() : TextureNode(node_type)
{
- light_manager = NULL;
- slot = -1;
+ light_manager = NULL;
+ slot = -1;
}
ShaderNode *IESLightNode::clone() const
{
- IESLightNode *node = new IESLightNode(*this);
+ IESLightNode *node = new IESLightNode(*this);
- node->light_manager = NULL;
- node->slot = -1;
+ node->light_manager = NULL;
+ node->slot = -1;
- return node;
+ return node;
}
IESLightNode::~IESLightNode()
{
- if(light_manager) {
- light_manager->remove_ies(slot);
- }
+ if (light_manager) {
+ light_manager->remove_ies(slot);
+ }
}
void IESLightNode::get_slot()
{
- assert(light_manager);
+ assert(light_manager);
- if(slot == -1) {
- if(ies.empty()) {
- slot = light_manager->add_ies_from_file(filename);
- }
- else {
- slot = light_manager->add_ies(ies);
- }
- }
+ if (slot == -1) {
+ if (ies.empty()) {
+ slot = light_manager->add_ies_from_file(filename);
+ }
+ else {
+ slot = light_manager->add_ies(ies);
+ }
+ }
}
-void IESLightNode::compile(SVMCompiler& compiler)
+void IESLightNode::compile(SVMCompiler &compiler)
{
- light_manager = compiler.light_manager;
- get_slot();
+ light_manager = compiler.light_manager;
+ get_slot();
- ShaderInput *strength_in = input("Strength");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_IES,
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(strength_in),
- vector_offset,
- compiler.stack_assign(fac_out),
- 0),
- slot,
- __float_as_int(strength));
+ compiler.add_node(NODE_IES,
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(strength_in),
+ vector_offset,
+ compiler.stack_assign(fac_out),
+ 0),
+ slot,
+ __float_as_int(strength));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void IESLightNode::compile(OSLCompiler& compiler)
+void IESLightNode::compile(OSLCompiler &compiler)
{
- light_manager = compiler.light_manager;
- get_slot();
+ light_manager = compiler.light_manager;
+ get_slot();
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter("slot", slot);
- compiler.add(this, "node_ies_light");
+ compiler.parameter("slot", slot);
+ compiler.add(this, "node_ies_light");
}
/* Musgrave Texture */
NODE_DEFINE(MusgraveTextureNode)
{
- NodeType* type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
+ TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
- static NodeEnum type_enum;
- type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
- type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
- type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
- type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
- type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
+ static NodeEnum type_enum;
+ type_enum.insert("multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
+ type_enum.insert("fBM", NODE_MUSGRAVE_FBM);
+ type_enum.insert("hybrid_multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
+ type_enum.insert("ridged_multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
+ type_enum.insert("hetero_terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MUSGRAVE_FBM);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
- SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
- SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 1.0f);
- SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
- SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
+ SOCKET_IN_FLOAT(dimension, "Dimension", 2.0f);
+ SOCKET_IN_FLOAT(lacunarity, "Lacunarity", 1.0f);
+ SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
+ SOCKET_IN_FLOAT(gain, "Gain", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-MusgraveTextureNode::MusgraveTextureNode()
-: TextureNode(node_type)
+MusgraveTextureNode::MusgraveTextureNode() : TextureNode(node_type)
{
}
-void MusgraveTextureNode::compile(SVMCompiler& compiler)
+void MusgraveTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *dimension_in = input("Dimension");
- ShaderInput *lacunarity_in = input("Lacunarity");
- ShaderInput *detail_in = input("Detail");
- ShaderInput *offset_in = input("Offset");
- ShaderInput *gain_in = input("Gain");
- ShaderOutput *fac_out = output("Fac");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *dimension_in = input("Dimension");
+ ShaderInput *lacunarity_in = input("Lacunarity");
+ ShaderInput *detail_in = input("Detail");
+ ShaderInput *offset_in = input("Offset");
+ ShaderInput *gain_in = input("Gain");
+ ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_MUSGRAVE,
- compiler.encode_uchar4(
- type,
- vector_offset,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(dimension_in),
- compiler.stack_assign_if_linked(lacunarity_in),
- compiler.stack_assign_if_linked(detail_in),
- compiler.stack_assign_if_linked(offset_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(gain_in),
- compiler.stack_assign_if_linked(scale_in)));
- compiler.add_node(__float_as_int(dimension),
- __float_as_int(lacunarity),
- __float_as_int(detail),
- __float_as_int(offset));
- compiler.add_node(__float_as_int(gain),
- __float_as_int(scale));
+ compiler.add_node(NODE_TEX_MUSGRAVE,
+ compiler.encode_uchar4(type,
+ vector_offset,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(dimension_in),
+ compiler.stack_assign_if_linked(lacunarity_in),
+ compiler.stack_assign_if_linked(detail_in),
+ compiler.stack_assign_if_linked(offset_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(gain_in),
+ compiler.stack_assign_if_linked(scale_in)));
+ compiler.add_node(__float_as_int(dimension),
+ __float_as_int(lacunarity),
+ __float_as_int(detail),
+ __float_as_int(offset));
+ compiler.add_node(__float_as_int(gain), __float_as_int(scale));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void MusgraveTextureNode::compile(OSLCompiler& compiler)
+void MusgraveTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "type");
- compiler.add(this, "node_musgrave_texture");
+ compiler.parameter(this, "type");
+ compiler.add(this, "node_musgrave_texture");
}
/* Wave Texture */
NODE_DEFINE(WaveTextureNode)
{
- NodeType* type = NodeType::add("wave_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("wave_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(WaveTextureNode);
+ TEXTURE_MAPPING_DEFINE(WaveTextureNode);
- static NodeEnum type_enum;
- type_enum.insert("bands", NODE_WAVE_BANDS);
- type_enum.insert("rings", NODE_WAVE_RINGS);
- SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS);
+ static NodeEnum type_enum;
+ type_enum.insert("bands", NODE_WAVE_BANDS);
+ type_enum.insert("rings", NODE_WAVE_RINGS);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_WAVE_BANDS);
- static NodeEnum profile_enum;
- profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN);
- profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW);
- SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
+ static NodeEnum profile_enum;
+ profile_enum.insert("sine", NODE_WAVE_PROFILE_SIN);
+ profile_enum.insert("saw", NODE_WAVE_PROFILE_SAW);
+ SOCKET_ENUM(profile, "Profile", profile_enum, NODE_WAVE_PROFILE_SIN);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
- SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
- SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_FLOAT(distortion, "Distortion", 0.0f);
+ SOCKET_IN_FLOAT(detail, "Detail", 2.0f);
+ SOCKET_IN_FLOAT(detail_scale, "Detail Scale", 0.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-WaveTextureNode::WaveTextureNode()
-: TextureNode(node_type)
+WaveTextureNode::WaveTextureNode() : TextureNode(node_type)
{
}
-void WaveTextureNode::compile(SVMCompiler& compiler)
+void WaveTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *scale_in = input("Scale");
- ShaderInput *distortion_in = input("Distortion");
- ShaderInput *dscale_in = input("Detail Scale");
- ShaderInput *detail_in = input("Detail");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *fac_out = output("Fac");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *distortion_in = input("Distortion");
+ ShaderInput *dscale_in = input("Detail Scale");
+ ShaderInput *detail_in = input("Detail");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_WAVE,
- compiler.encode_uchar4(
- type,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out),
- compiler.stack_assign_if_linked(dscale_in)),
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(detail_in),
- compiler.stack_assign_if_linked(distortion_in)),
- profile);
+ compiler.add_node(NODE_TEX_WAVE,
+ compiler.encode_uchar4(type,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out),
+ compiler.stack_assign_if_linked(dscale_in)),
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(detail_in),
+ compiler.stack_assign_if_linked(distortion_in)),
+ profile);
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(detail),
- __float_as_int(distortion),
- __float_as_int(detail_scale));
+ compiler.add_node(__float_as_int(scale),
+ __float_as_int(detail),
+ __float_as_int(distortion),
+ __float_as_int(detail_scale));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void WaveTextureNode::compile(OSLCompiler& compiler)
+void WaveTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "type");
- compiler.parameter(this, "profile");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "profile");
- compiler.add(this, "node_wave_texture");
+ compiler.add(this, "node_wave_texture");
}
/* Magic Texture */
NODE_DEFINE(MagicTextureNode)
{
- NodeType* type = NodeType::add("magic_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("magic_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(MagicTextureNode);
+ TEXTURE_MAPPING_DEFINE(MagicTextureNode);
- SOCKET_INT(depth, "Depth", 2);
+ SOCKET_INT(depth, "Depth", 2);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
- SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
+ SOCKET_IN_FLOAT(distortion, "Distortion", 1.0f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-MagicTextureNode::MagicTextureNode()
-: TextureNode(node_type)
+MagicTextureNode::MagicTextureNode() : TextureNode(node_type)
{
}
-void MagicTextureNode::compile(SVMCompiler& compiler)
+void MagicTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *distortion_in = input("Distortion");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *distortion_in = input("Distortion");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_MAGIC,
- compiler.encode_uchar4(
- depth,
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)),
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(distortion_in)));
- compiler.add_node(
- __float_as_int(scale),
- __float_as_int(distortion));
+ compiler.add_node(NODE_TEX_MAGIC,
+ compiler.encode_uchar4(depth,
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)),
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(distortion_in)));
+ compiler.add_node(__float_as_int(scale), __float_as_int(distortion));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void MagicTextureNode::compile(OSLCompiler& compiler)
+void MagicTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "depth");
- compiler.add(this, "node_magic_texture");
+ compiler.parameter(this, "depth");
+ compiler.add(this, "node_magic_texture");
}
/* Checker Texture */
NODE_DEFINE(CheckerTextureNode)
{
- NodeType* type = NodeType::add("checker_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("checker_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(CheckerTextureNode);
+ TEXTURE_MAPPING_DEFINE(CheckerTextureNode);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-CheckerTextureNode::CheckerTextureNode()
-: TextureNode(node_type)
+CheckerTextureNode::CheckerTextureNode() : TextureNode(node_type)
{
}
-void CheckerTextureNode::compile(SVMCompiler& compiler)
+void CheckerTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderInput *scale_in = input("Scale");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderInput *scale_in = input("Scale");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_CHECKER,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign(color1_in),
- compiler.stack_assign(color2_in),
- compiler.stack_assign_if_linked(scale_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out)),
- __float_as_int(scale));
+ compiler.add_node(NODE_TEX_CHECKER,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign(color1_in),
+ compiler.stack_assign(color2_in),
+ compiler.stack_assign_if_linked(scale_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out)),
+ __float_as_int(scale));
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void CheckerTextureNode::compile(OSLCompiler& compiler)
+void CheckerTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.add(this, "node_checker_texture");
+ compiler.add(this, "node_checker_texture");
}
/* Brick Texture */
NODE_DEFINE(BrickTextureNode)
{
- NodeType* type = NodeType::add("brick_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("brick_texture", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(BrickTextureNode);
+ TEXTURE_MAPPING_DEFINE(BrickTextureNode);
- SOCKET_FLOAT(offset, "Offset", 0.5f);
- SOCKET_INT(offset_frequency, "Offset Frequency", 2);
- SOCKET_FLOAT(squash, "Squash", 1.0f);
- SOCKET_INT(squash_frequency, "Squash Frequency", 2);
+ SOCKET_FLOAT(offset, "Offset", 0.5f);
+ SOCKET_INT(offset_frequency, "Offset Frequency", 2);
+ SOCKET_FLOAT(squash, "Squash", 1.0f);
+ SOCKET_INT(squash_frequency, "Squash Frequency", 2);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ SOCKET_IN_POINT(
+ vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(mortar, "Mortar", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
- SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f);
- SOCKET_IN_FLOAT(mortar_smooth, "Mortar Smooth", 0.0f);
- SOCKET_IN_FLOAT(bias, "Bias", 0.0f);
- SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
- SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
+ SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(mortar, "Mortar", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(scale, "Scale", 5.0f);
+ SOCKET_IN_FLOAT(mortar_size, "Mortar Size", 0.02f);
+ SOCKET_IN_FLOAT(mortar_smooth, "Mortar Smooth", 0.0f);
+ SOCKET_IN_FLOAT(bias, "Bias", 0.0f);
+ SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
+ SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-BrickTextureNode::BrickTextureNode()
-: TextureNode(node_type)
+BrickTextureNode::BrickTextureNode() : TextureNode(node_type)
{
}
-void BrickTextureNode::compile(SVMCompiler& compiler)
+void BrickTextureNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderInput *mortar_in = input("Mortar");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *mortar_size_in = input("Mortar Size");
- ShaderInput *mortar_smooth_in = input("Mortar Smooth");
- ShaderInput *bias_in = input("Bias");
- ShaderInput *brick_width_in = input("Brick Width");
- ShaderInput *row_height_in = input("Row Height");
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderInput *mortar_in = input("Mortar");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *mortar_size_in = input("Mortar Size");
+ ShaderInput *mortar_smooth_in = input("Mortar Smooth");
+ ShaderInput *bias_in = input("Bias");
+ ShaderInput *brick_width_in = input("Brick Width");
+ ShaderInput *row_height_in = input("Row Height");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *fac_out = output("Fac");
- int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- compiler.add_node(NODE_TEX_BRICK,
- compiler.encode_uchar4(
- vector_offset,
- compiler.stack_assign(color1_in),
- compiler.stack_assign(color2_in),
- compiler.stack_assign(mortar_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(scale_in),
- compiler.stack_assign_if_linked(mortar_size_in),
- compiler.stack_assign_if_linked(bias_in),
- compiler.stack_assign_if_linked(brick_width_in)),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(row_height_in),
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(fac_out),
- compiler.stack_assign_if_linked(mortar_smooth_in)));
+ compiler.add_node(NODE_TEX_BRICK,
+ compiler.encode_uchar4(vector_offset,
+ compiler.stack_assign(color1_in),
+ compiler.stack_assign(color2_in),
+ compiler.stack_assign(mortar_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(scale_in),
+ compiler.stack_assign_if_linked(mortar_size_in),
+ compiler.stack_assign_if_linked(bias_in),
+ compiler.stack_assign_if_linked(brick_width_in)),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(row_height_in),
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(fac_out),
+ compiler.stack_assign_if_linked(mortar_smooth_in)));
- compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
- __float_as_int(scale),
- __float_as_int(mortar_size),
- __float_as_int(bias));
+ compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
+ __float_as_int(scale),
+ __float_as_int(mortar_size),
+ __float_as_int(bias));
- compiler.add_node(__float_as_int(brick_width),
- __float_as_int(row_height),
- __float_as_int(offset),
- __float_as_int(squash));
+ compiler.add_node(__float_as_int(brick_width),
+ __float_as_int(row_height),
+ __float_as_int(offset),
+ __float_as_int(squash));
- compiler.add_node(__float_as_int(mortar_smooth),
- SVM_STACK_INVALID,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID);
+ compiler.add_node(
+ __float_as_int(mortar_smooth), SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID);
- tex_mapping.compile_end(compiler, vector_in, vector_offset);
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
-void BrickTextureNode::compile(OSLCompiler& compiler)
+void BrickTextureNode::compile(OSLCompiler &compiler)
{
- tex_mapping.compile(compiler);
+ tex_mapping.compile(compiler);
- compiler.parameter(this, "offset");
- compiler.parameter(this, "offset_frequency");
- compiler.parameter(this, "squash");
- compiler.parameter(this, "squash_frequency");
- compiler.add(this, "node_brick_texture");
+ compiler.parameter(this, "offset");
+ compiler.parameter(this, "offset_frequency");
+ compiler.parameter(this, "squash");
+ compiler.parameter(this, "squash_frequency");
+ compiler.add(this, "node_brick_texture");
}
/* Point Density Texture */
NODE_DEFINE(PointDensityTextureNode)
{
- NodeType* type = NodeType::add("point_density_texture", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("point_density_texture", create, NodeType::SHADER);
- SOCKET_STRING(filename, "Filename", ustring());
+ SOCKET_STRING(filename, "Filename", ustring());
- static NodeEnum space_enum;
- space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
- space_enum.insert("world", NODE_TEX_VOXEL_SPACE_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT);
+ static NodeEnum space_enum;
+ space_enum.insert("object", NODE_TEX_VOXEL_SPACE_OBJECT);
+ space_enum.insert("world", NODE_TEX_VOXEL_SPACE_WORLD);
+ SOCKET_ENUM(space, "Space", space_enum, NODE_TEX_VOXEL_SPACE_OBJECT);
- static NodeEnum interpolation_enum;
- interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
- interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
- interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
- interpolation_enum.insert("smart", INTERPOLATION_SMART);
- SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
+ static NodeEnum interpolation_enum;
+ interpolation_enum.insert("closest", INTERPOLATION_CLOSEST);
+ interpolation_enum.insert("linear", INTERPOLATION_LINEAR);
+ interpolation_enum.insert("cubic", INTERPOLATION_CUBIC);
+ interpolation_enum.insert("smart", INTERPOLATION_SMART);
+ SOCKET_ENUM(interpolation, "Interpolation", interpolation_enum, INTERPOLATION_LINEAR);
- SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
- SOCKET_OUT_FLOAT(density, "Density");
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(density, "Density");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-PointDensityTextureNode::PointDensityTextureNode()
-: ShaderNode(node_type)
+PointDensityTextureNode::PointDensityTextureNode() : ShaderNode(node_type)
{
- image_manager = NULL;
- slot = -1;
- builtin_data = NULL;
+ image_manager = NULL;
+ slot = -1;
+ builtin_data = NULL;
}
PointDensityTextureNode::~PointDensityTextureNode()
{
- if(image_manager) {
- image_manager->remove_image(filename.string(),
- builtin_data,
- interpolation,
- EXTENSION_CLIP,
- true);
- }
+ if (image_manager) {
+ image_manager->remove_image(
+ filename.string(), builtin_data, interpolation, EXTENSION_CLIP, true);
+ }
}
ShaderNode *PointDensityTextureNode::clone() const
{
- PointDensityTextureNode *node = new PointDensityTextureNode(*this);
- node->image_manager = NULL;
- node->slot = -1;
- return node;
+ PointDensityTextureNode *node = new PointDensityTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ return node;
}
-void PointDensityTextureNode::attributes(Shader *shader,
- AttributeRequestSet *attributes)
+void PointDensityTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_volume)
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ if (shader->has_volume)
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
void PointDensityTextureNode::add_image()
{
- if(slot == -1) {
- ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(), builtin_data,
- false, 0,
- interpolation,
- EXTENSION_CLIP,
- true,
- metadata);
- }
-}
-
-void PointDensityTextureNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *density_out = output("Density");
- ShaderOutput *color_out = output("Color");
-
- const bool use_density = !density_out->links.empty();
- const bool use_color = !color_out->links.empty();
-
- image_manager = compiler.image_manager;
-
- if(use_density || use_color) {
- add_image();
-
- if(slot != -1) {
- compiler.stack_assign(vector_in);
- compiler.add_node(NODE_TEX_VOXEL,
- slot,
- compiler.encode_uchar4(compiler.stack_assign(vector_in),
- compiler.stack_assign_if_linked(density_out),
- compiler.stack_assign_if_linked(color_out),
- space));
- if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
- compiler.add_node(tfm.x);
- compiler.add_node(tfm.y);
- compiler.add_node(tfm.z);
- }
- }
- else {
- if(use_density) {
- compiler.add_node(NODE_VALUE_F,
- __float_as_int(0.0f),
- compiler.stack_assign(density_out));
- }
- if(use_color) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
- TEX_IMAGE_MISSING_G,
- TEX_IMAGE_MISSING_B));
- }
- }
- }
-}
-
-void PointDensityTextureNode::compile(OSLCompiler& compiler)
-{
- ShaderOutput *density_out = output("Density");
- ShaderOutput *color_out = output("Color");
-
- const bool use_density = !density_out->links.empty();
- const bool use_color = !color_out->links.empty();
-
- image_manager = compiler.image_manager;
-
- if(use_density || use_color) {
- add_image();
-
- if(slot != -1) {
- compiler.parameter("filename", string_printf("@i%d", slot).c_str());
- }
- if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
- compiler.parameter("mapping", tfm);
- compiler.parameter("use_mapping", 1);
- }
- compiler.parameter(this, "interpolation");
- compiler.add(this, "node_voxel_texture");
- }
+ if (slot == -1) {
+ ImageMetaData metadata;
+ slot = image_manager->add_image(
+ filename.string(), builtin_data, false, 0, interpolation, EXTENSION_CLIP, true, metadata);
+ }
+}
+
+void PointDensityTextureNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ const bool use_density = !density_out->links.empty();
+ const bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ add_image();
+
+ if (slot != -1) {
+ compiler.stack_assign(vector_in);
+ compiler.add_node(NODE_TEX_VOXEL,
+ slot,
+ compiler.encode_uchar4(compiler.stack_assign(vector_in),
+ compiler.stack_assign_if_linked(density_out),
+ compiler.stack_assign_if_linked(color_out),
+ space));
+ if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
+ compiler.add_node(tfm.x);
+ compiler.add_node(tfm.y);
+ compiler.add_node(tfm.z);
+ }
+ }
+ else {
+ if (use_density) {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(density_out));
+ }
+ if (use_color) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_VALUE_V,
+ make_float3(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B));
+ }
+ }
+ }
+}
+
+void PointDensityTextureNode::compile(OSLCompiler &compiler)
+{
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ const bool use_density = !density_out->links.empty();
+ const bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ add_image();
+
+ if (slot != -1) {
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
+ }
+ if (space == NODE_TEX_VOXEL_SPACE_WORLD) {
+ compiler.parameter("mapping", tfm);
+ compiler.parameter("use_mapping", 1);
+ }
+ compiler.parameter(this, "interpolation");
+ compiler.add(this, "node_voxel_texture");
+ }
}
/* Normal */
NODE_DEFINE(NormalNode)
{
- NodeType* type = NodeType::add("normal", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("normal", create, NodeType::SHADER);
- SOCKET_VECTOR(direction, "direction", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_VECTOR(direction, "direction", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_NORMAL(normal, "Normal");
- SOCKET_OUT_FLOAT(dot, "Dot");
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_FLOAT(dot, "Dot");
- return type;
+ return type;
}
-NormalNode::NormalNode()
-: ShaderNode(node_type)
+NormalNode::NormalNode() : ShaderNode(node_type)
{
}
-void NormalNode::compile(SVMCompiler& compiler)
+void NormalNode::compile(SVMCompiler &compiler)
{
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *normal_out = output("Normal");
- ShaderOutput *dot_out = output("Dot");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *normal_out = output("Normal");
+ ShaderOutput *dot_out = output("Dot");
- compiler.add_node(NODE_NORMAL,
- compiler.stack_assign(normal_in),
- compiler.stack_assign(normal_out),
- compiler.stack_assign(dot_out));
- compiler.add_node(
- __float_as_int(direction.x),
- __float_as_int(direction.y),
- __float_as_int(direction.z));
+ compiler.add_node(NODE_NORMAL,
+ compiler.stack_assign(normal_in),
+ compiler.stack_assign(normal_out),
+ compiler.stack_assign(dot_out));
+ compiler.add_node(
+ __float_as_int(direction.x), __float_as_int(direction.y), __float_as_int(direction.z));
}
-void NormalNode::compile(OSLCompiler& compiler)
+void NormalNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "direction");
- compiler.add(this, "node_normal");
+ compiler.parameter(this, "direction");
+ compiler.add(this, "node_normal");
}
/* Mapping */
NODE_DEFINE(MappingNode)
{
- NodeType* type = NodeType::add("mapping", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mapping", create, NodeType::SHADER);
- TEXTURE_MAPPING_DEFINE(MappingNode);
+ TEXTURE_MAPPING_DEFINE(MappingNode);
- SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_POINT(vector, "Vector");
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_POINT(vector, "Vector");
- return type;
+ return type;
}
-MappingNode::MappingNode()
-: ShaderNode(node_type)
+MappingNode::MappingNode() : ShaderNode(node_type)
{
}
-void MappingNode::compile(SVMCompiler& compiler)
+void MappingNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *vector_out = output("Vector");
- tex_mapping.compile(compiler, compiler.stack_assign(vector_in), compiler.stack_assign(vector_out));
+ tex_mapping.compile(
+ compiler, compiler.stack_assign(vector_in), compiler.stack_assign(vector_out));
}
-void MappingNode::compile(OSLCompiler& compiler)
+void MappingNode::compile(OSLCompiler &compiler)
{
- compiler.parameter("Matrix", tex_mapping.compute_transform());
- compiler.parameter_point("mapping_min", tex_mapping.min);
- compiler.parameter_point("mapping_max", tex_mapping.max);
- compiler.parameter("use_minmax", tex_mapping.use_minmax);
+ compiler.parameter("Matrix", tex_mapping.compute_transform());
+ compiler.parameter_point("mapping_min", tex_mapping.min);
+ compiler.parameter_point("mapping_max", tex_mapping.max);
+ compiler.parameter("use_minmax", tex_mapping.use_minmax);
- compiler.add(this, "node_mapping");
+ compiler.add(this, "node_mapping");
}
/* RGBToBW */
NODE_DEFINE(RGBToBWNode)
{
- NodeType* type = NodeType::add("rgb_to_bw", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("rgb_to_bw", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(val, "Val");
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_FLOAT(val, "Val");
- return type;
+ return type;
}
-RGBToBWNode::RGBToBWNode()
-: ShaderNode(node_type)
+RGBToBWNode::RGBToBWNode() : ShaderNode(node_type)
{
}
-void RGBToBWNode::constant_fold(const ConstantFolder& folder)
+void RGBToBWNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
- folder.make_constant(val);
- }
+ if (folder.all_inputs_constant()) {
+ float val = folder.scene->shader_manager->linear_rgb_to_gray(color);
+ folder.make_constant(val);
+ }
}
-void RGBToBWNode::compile(SVMCompiler& compiler)
+void RGBToBWNode::compile(SVMCompiler &compiler)
{
- compiler.add_node(NODE_CONVERT,
- NODE_CONVERT_CF,
- compiler.stack_assign(inputs[0]),
- compiler.stack_assign(outputs[0]));
+ compiler.add_node(NODE_CONVERT,
+ NODE_CONVERT_CF,
+ compiler.stack_assign(inputs[0]),
+ compiler.stack_assign(outputs[0]));
}
-void RGBToBWNode::compile(OSLCompiler& compiler)
+void RGBToBWNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_rgb_to_bw");
+ compiler.add(this, "node_rgb_to_bw");
}
/* Convert */
-const NodeType* ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
+const NodeType *ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
bool ConvertNode::initialized = ConvertNode::register_types();
-Node* ConvertNode::create(const NodeType *type)
+Node *ConvertNode::create(const NodeType *type)
{
- return new ConvertNode(type->inputs[0].type, type->outputs[0].type);
+ return new ConvertNode(type->inputs[0].type, type->outputs[0].type);
}
bool ConvertNode::register_types()
{
- const int num_types = 8;
- SocketType::Type types[num_types] = {SocketType::FLOAT,
- SocketType::INT,
- SocketType::COLOR,
- SocketType::VECTOR,
- SocketType::POINT,
- SocketType::NORMAL,
- SocketType::STRING,
- SocketType::CLOSURE};
-
- for(size_t i = 0; i < num_types; i++) {
- SocketType::Type from = types[i];
- ustring from_name(SocketType::type_name(from));
- ustring from_value_name("value_" + from_name.string());
-
- for(size_t j = 0; j < num_types; j++) {
- SocketType::Type to = types[j];
- ustring to_name(SocketType::type_name(to));
- ustring to_value_name("value_" + to_name.string());
-
- string node_name = "convert_" + from_name.string() + "_to_" + to_name.string();
- NodeType* type = NodeType::add(node_name.c_str(), create, NodeType::SHADER);
-
- type->register_input(from_value_name, from_value_name, from,
- SOCKET_OFFSETOF(ConvertNode, value_float), SocketType::zero_default_value(),
- NULL, NULL, SocketType::LINKABLE);
- type->register_output(to_value_name, to_value_name, to);
-
- assert(from < MAX_TYPE);
- assert(to < MAX_TYPE);
-
- node_types[from][to] = type;
- }
- }
-
- return true;
+ const int num_types = 8;
+ SocketType::Type types[num_types] = {SocketType::FLOAT,
+ SocketType::INT,
+ SocketType::COLOR,
+ SocketType::VECTOR,
+ SocketType::POINT,
+ SocketType::NORMAL,
+ SocketType::STRING,
+ SocketType::CLOSURE};
+
+ for (size_t i = 0; i < num_types; i++) {
+ SocketType::Type from = types[i];
+ ustring from_name(SocketType::type_name(from));
+ ustring from_value_name("value_" + from_name.string());
+
+ for (size_t j = 0; j < num_types; j++) {
+ SocketType::Type to = types[j];
+ ustring to_name(SocketType::type_name(to));
+ ustring to_value_name("value_" + to_name.string());
+
+ string node_name = "convert_" + from_name.string() + "_to_" + to_name.string();
+ NodeType *type = NodeType::add(node_name.c_str(), create, NodeType::SHADER);
+
+ type->register_input(from_value_name,
+ from_value_name,
+ from,
+ SOCKET_OFFSETOF(ConvertNode, value_float),
+ SocketType::zero_default_value(),
+ NULL,
+ NULL,
+ SocketType::LINKABLE);
+ type->register_output(to_value_name, to_value_name, to);
+
+ assert(from < MAX_TYPE);
+ assert(to < MAX_TYPE);
+
+ node_types[from][to] = type;
+ }
+ }
+
+ return true;
}
ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool autoconvert)
-: ShaderNode(node_types[from_][to_])
-{
- from = from_;
- to = to_;
-
- if(from == to)
- special_type = SHADER_SPECIAL_TYPE_PROXY;
- else if(autoconvert)
- special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
-}
-
-void ConvertNode::constant_fold(const ConstantFolder& folder)
-{
- /* proxy nodes should have been removed at this point */
- assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
-
- /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
-
- if(folder.all_inputs_constant()) {
- if(from == SocketType::FLOAT) {
- if(SocketType::is_float3(to)) {
- folder.make_constant(make_float3(value_float, value_float, value_float));
- }
- }
- else if(SocketType::is_float3(from)) {
- if(to == SocketType::FLOAT) {
- if(from == SocketType::COLOR) {
- /* color to float */
- float val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
- folder.make_constant(val);
- }
- else {
- /* vector/point/normal to float */
- folder.make_constant(average(value_vector));
- }
- }
- else if(SocketType::is_float3(to)) {
- folder.make_constant(value_color);
- }
- }
- }
- else {
- ShaderInput *in = inputs[0];
- ShaderNode *prev = in->link->parent;
-
- /* no-op conversion of A to B to A */
- if(prev->type == node_types[to][from]) {
- ShaderInput *prev_in = prev->inputs[0];
-
- if(SocketType::is_float3(from) && (to == SocketType::FLOAT || SocketType::is_float3(to)) && prev_in->link) {
- folder.bypass(prev_in->link);
- }
- }
- }
-}
-
-void ConvertNode::compile(SVMCompiler& compiler)
-{
- /* proxy nodes should have been removed at this point */
- assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
-
- ShaderInput *in = inputs[0];
- ShaderOutput *out = outputs[0];
-
- if(from == SocketType::FLOAT) {
- if(to == SocketType::INT)
- /* float to int */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* float to float3 */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else if(from == SocketType::INT) {
- if(to == SocketType::FLOAT)
- /* int to float */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* int to vector/point/normal */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else if(to == SocketType::FLOAT) {
- if(from == SocketType::COLOR)
- /* color to float */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* vector/point/normal to float */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else if(to == SocketType::INT) {
- if(from == SocketType::COLOR)
- /* color to int */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
- else
- /* vector/point/normal to int */
- compiler.add_node(NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
- }
- else {
- /* float3 to float3 */
- if(in->link) {
- /* no op in SVM */
- compiler.stack_link(in, out);
- }
- else {
- /* set 0,0,0 value */
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
- compiler.add_node(NODE_VALUE_V, value_color);
- }
- }
-}
-
-void ConvertNode::compile(OSLCompiler& compiler)
-{
- /* proxy nodes should have been removed at this point */
- assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
-
- if(from == SocketType::FLOAT)
- compiler.add(this, "node_convert_from_float");
- else if(from == SocketType::INT)
- compiler.add(this, "node_convert_from_int");
- else if(from == SocketType::COLOR)
- compiler.add(this, "node_convert_from_color");
- else if(from == SocketType::VECTOR)
- compiler.add(this, "node_convert_from_vector");
- else if(from == SocketType::POINT)
- compiler.add(this, "node_convert_from_point");
- else if(from == SocketType::NORMAL)
- compiler.add(this, "node_convert_from_normal");
- else
- assert(0);
+ : ShaderNode(node_types[from_][to_])
+{
+ from = from_;
+ to = to_;
+
+ if (from == to)
+ special_type = SHADER_SPECIAL_TYPE_PROXY;
+ else if (autoconvert)
+ special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
+}
+
+void ConvertNode::constant_fold(const ConstantFolder &folder)
+{
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
+
+ /* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
+
+ if (folder.all_inputs_constant()) {
+ if (from == SocketType::FLOAT) {
+ if (SocketType::is_float3(to)) {
+ folder.make_constant(make_float3(value_float, value_float, value_float));
+ }
+ }
+ else if (SocketType::is_float3(from)) {
+ if (to == SocketType::FLOAT) {
+ if (from == SocketType::COLOR) {
+ /* color to float */
+ float val = folder.scene->shader_manager->linear_rgb_to_gray(value_color);
+ folder.make_constant(val);
+ }
+ else {
+ /* vector/point/normal to float */
+ folder.make_constant(average(value_vector));
+ }
+ }
+ else if (SocketType::is_float3(to)) {
+ folder.make_constant(value_color);
+ }
+ }
+ }
+ else {
+ ShaderInput *in = inputs[0];
+ ShaderNode *prev = in->link->parent;
+
+ /* no-op conversion of A to B to A */
+ if (prev->type == node_types[to][from]) {
+ ShaderInput *prev_in = prev->inputs[0];
+
+ if (SocketType::is_float3(from) && (to == SocketType::FLOAT || SocketType::is_float3(to)) &&
+ prev_in->link) {
+ folder.bypass(prev_in->link);
+ }
+ }
+ }
+}
+
+void ConvertNode::compile(SVMCompiler &compiler)
+{
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
+
+ ShaderInput *in = inputs[0];
+ ShaderOutput *out = outputs[0];
+
+ if (from == SocketType::FLOAT) {
+ if (to == SocketType::INT)
+ /* float to int */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* float to float3 */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else if (from == SocketType::INT) {
+ if (to == SocketType::FLOAT)
+ /* int to float */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* int to vector/point/normal */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else if (to == SocketType::FLOAT) {
+ if (from == SocketType::COLOR)
+ /* color to float */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* vector/point/normal to float */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else if (to == SocketType::INT) {
+ if (from == SocketType::COLOR)
+ /* color to int */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
+ else
+ /* vector/point/normal to int */
+ compiler.add_node(
+ NODE_CONVERT, NODE_CONVERT_VI, compiler.stack_assign(in), compiler.stack_assign(out));
+ }
+ else {
+ /* float3 to float3 */
+ if (in->link) {
+ /* no op in SVM */
+ compiler.stack_link(in, out);
+ }
+ else {
+ /* set 0,0,0 value */
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
+ compiler.add_node(NODE_VALUE_V, value_color);
+ }
+ }
+}
+
+void ConvertNode::compile(OSLCompiler &compiler)
+{
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
+
+ if (from == SocketType::FLOAT)
+ compiler.add(this, "node_convert_from_float");
+ else if (from == SocketType::INT)
+ compiler.add(this, "node_convert_from_int");
+ else if (from == SocketType::COLOR)
+ compiler.add(this, "node_convert_from_color");
+ else if (from == SocketType::VECTOR)
+ compiler.add(this, "node_convert_from_vector");
+ else if (from == SocketType::POINT)
+ compiler.add(this, "node_convert_from_point");
+ else if (from == SocketType::NORMAL)
+ compiler.add(this, "node_convert_from_normal");
+ else
+ assert(0);
}
/* Base type for all closure-type nodes */
-BsdfBaseNode::BsdfBaseNode(const NodeType *node_type)
- : ShaderNode(node_type)
+BsdfBaseNode::BsdfBaseNode(const NodeType *node_type) : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_CLOSURE;
+ special_type = SHADER_SPECIAL_TYPE_CLOSURE;
}
bool BsdfBaseNode::has_bump()
{
- /* detect if anything is plugged into the normal input besides the default */
- ShaderInput *normal_in = input("Normal");
- return (normal_in && normal_in->link &&
- normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+ /* detect if anything is plugged into the normal input besides the default */
+ ShaderInput *normal_in = input("Normal");
+ return (normal_in && normal_in->link &&
+ normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
}
/* BSDF Closure */
-BsdfNode::BsdfNode(const NodeType *node_type)
-: BsdfBaseNode(node_type)
+BsdfNode::BsdfNode(const NodeType *node_type) : BsdfBaseNode(node_type)
{
}
-void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3, ShaderInput *param4)
+void BsdfNode::compile(SVMCompiler &compiler,
+ ShaderInput *param1,
+ ShaderInput *param2,
+ ShaderInput *param3,
+ ShaderInput *param4)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *tangent_in = input("Tangent");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *tangent_in = input("Tangent");
- if(color_in->link)
- compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+ if (color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
- int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID;
- int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) : SVM_STACK_INVALID;
- int param3_offset = (param3) ? compiler.stack_assign(param3) : SVM_STACK_INVALID;
- int param4_offset = (param4) ? compiler.stack_assign(param4) : SVM_STACK_INVALID;
+ int normal_offset = (normal_in) ? compiler.stack_assign_if_linked(normal_in) : SVM_STACK_INVALID;
+ int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) :
+ SVM_STACK_INVALID;
+ int param3_offset = (param3) ? compiler.stack_assign(param3) : SVM_STACK_INVALID;
+ int param4_offset = (param4) ? compiler.stack_assign(param4) : SVM_STACK_INVALID;
- compiler.add_node(NODE_CLOSURE_BSDF,
- compiler.encode_uchar4(closure,
- (param1)? compiler.stack_assign(param1): SVM_STACK_INVALID,
- (param2)? compiler.stack_assign(param2): SVM_STACK_INVALID,
- compiler.closure_mix_weight_offset()),
- __float_as_int((param1)? get_float(param1->socket_type): 0.0f),
- __float_as_int((param2)? get_float(param2->socket_type): 0.0f));
+ compiler.add_node(
+ NODE_CLOSURE_BSDF,
+ compiler.encode_uchar4(closure,
+ (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID,
+ (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID,
+ compiler.closure_mix_weight_offset()),
+ __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
+ __float_as_int((param2) ? get_float(param2->socket_type) : 0.0f));
- compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset);
+ compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset);
}
-void BsdfNode::compile(SVMCompiler& compiler)
+void BsdfNode::compile(SVMCompiler &compiler)
{
- compile(compiler, NULL, NULL);
+ compile(compiler, NULL, NULL);
}
-void BsdfNode::compile(OSLCompiler& /*compiler*/)
+void BsdfNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* Anisotropic BSDF Closure */
NODE_DEFINE(AnisotropicBsdfNode)
{
- NodeType* type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
- distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
+ distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
- SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
+ SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
- SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
- SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
+ SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-AnisotropicBsdfNode::AnisotropicBsdfNode()
-: BsdfNode(node_type)
+AnisotropicBsdfNode::AnisotropicBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
}
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- ShaderInput *tangent_in = input("Tangent");
+ if (shader->has_surface) {
+ ShaderInput *tangent_in = input("Tangent");
- if(!tangent_in->link)
- attributes->add(ATTR_STD_GENERATED);
- }
+ if (!tangent_in->link)
+ attributes->add(ATTR_STD_GENERATED);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void AnisotropicBsdfNode::compile(SVMCompiler& compiler)
+void AnisotropicBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
- BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
- else
- BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
+ if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
+ BsdfNode::compile(
+ compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
}
-void AnisotropicBsdfNode::compile(OSLCompiler& compiler)
+void AnisotropicBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_anisotropic_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_anisotropic_bsdf");
}
/* Glossy BSDF Closure */
NODE_DEFINE(GlossyBsdfNode)
{
- NodeType* type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
- distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("sharp", CLOSURE_BSDF_REFLECTION_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
+ distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
+ SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-GlossyBsdfNode::GlossyBsdfNode()
-: BsdfNode(node_type)
+GlossyBsdfNode::GlossyBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
void GlossyBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == NBUILTIN_CLOSURES) {
- roughness_orig = roughness;
- distribution_orig = distribution;
- }
- else {
- /* By default we use original values, so we don't worry about restoring
- * defaults later one and can only do override when needed.
- */
- roughness = roughness_orig;
- distribution = distribution_orig;
- }
- Integrator *integrator = scene->integrator;
- ShaderInput *roughness_input = input("Roughness");
- if(integrator->filter_glossy == 0.0f) {
- /* Fallback to Sharp closure for Roughness close to 0.
- * Note: Keep the epsilon in sync with kernel!
- */
- if(!roughness_input->link && roughness <= 1e-4f) {
- VLOG(1) << "Using sharp glossy BSDF.";
- distribution = CLOSURE_BSDF_REFLECTION_ID;
- }
- }
- else {
- /* If filter glossy is used we replace Sharp glossy with GGX so we can
- * benefit from closure blur to remove unwanted noise.
- */
- if(roughness_input->link == NULL &&
- distribution == CLOSURE_BSDF_REFLECTION_ID)
- {
- VLOG(1) << "Using GGX glossy with filter glossy.";
- distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
- roughness = 0.0f;
- }
- }
- closure = distribution;
+ if (distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
+ distribution_orig = distribution;
+ }
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
+ Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
+ if (integrator->filter_glossy == 0.0f) {
+ /* Fallback to Sharp closure for Roughness close to 0.
+ * Note: Keep the epsilon in sync with kernel!
+ */
+ if (!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp glossy BSDF.";
+ distribution = CLOSURE_BSDF_REFLECTION_ID;
+ }
+ }
+ else {
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFLECTION_ID) {
+ VLOG(1) << "Using GGX glossy with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ roughness = 0.0f;
+ }
+ }
+ closure = distribution;
}
bool GlossyBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link &&
- (distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
}
-void GlossyBsdfNode::compile(SVMCompiler& compiler)
+void GlossyBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_REFLECTION_ID)
- BsdfNode::compile(compiler, NULL, NULL);
- else if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
- BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
- else
- BsdfNode::compile(compiler, input("Roughness"), NULL);
+ if (closure == CLOSURE_BSDF_REFLECTION_ID)
+ BsdfNode::compile(compiler, NULL, NULL);
+ else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
+ BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), NULL);
}
-void GlossyBsdfNode::compile(OSLCompiler& compiler)
+void GlossyBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_glossy_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_glossy_bsdf");
}
/* Glass BSDF Closure */
NODE_DEFINE(GlassBsdfNode)
{
- NodeType* type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
- SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-GlassBsdfNode::GlassBsdfNode()
-: BsdfNode(node_type)
+GlassBsdfNode::GlassBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_SHARP_GLASS_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ closure = CLOSURE_BSDF_SHARP_GLASS_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
void GlassBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == NBUILTIN_CLOSURES) {
- roughness_orig = roughness;
- distribution_orig = distribution;
- }
- else {
- /* By default we use original values, so we don't worry about restoring
- * defaults later one and can only do override when needed.
- */
- roughness = roughness_orig;
- distribution = distribution_orig;
- }
- Integrator *integrator = scene->integrator;
- ShaderInput *roughness_input = input("Roughness");
- if(integrator->filter_glossy == 0.0f) {
- /* Fallback to Sharp closure for Roughness close to 0.
- * Note: Keep the epsilon in sync with kernel!
- */
- if(!roughness_input->link && roughness <= 1e-4f) {
- VLOG(1) << "Using sharp glass BSDF.";
- distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
- }
- }
- else {
- /* If filter glossy is used we replace Sharp glossy with GGX so we can
- * benefit from closure blur to remove unwanted noise.
- */
- if(roughness_input->link == NULL &&
- distribution == CLOSURE_BSDF_SHARP_GLASS_ID)
- {
- VLOG(1) << "Using GGX glass with filter glossy.";
- distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
- roughness = 0.0f;
- }
- }
- closure = distribution;
+ if (distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
+ distribution_orig = distribution;
+ }
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
+ Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
+ if (integrator->filter_glossy == 0.0f) {
+ /* Fallback to Sharp closure for Roughness close to 0.
+ * Note: Keep the epsilon in sync with kernel!
+ */
+ if (!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp glass BSDF.";
+ distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
+ }
+ }
+ else {
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_SHARP_GLASS_ID) {
+ VLOG(1) << "Using GGX glass with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ roughness = 0.0f;
+ }
+ }
+ closure = distribution;
}
bool GlassBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link &&
- (distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
}
-void GlassBsdfNode::compile(SVMCompiler& compiler)
+void GlassBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_SHARP_GLASS_ID)
- BsdfNode::compile(compiler, NULL, input("IOR"));
- else if(closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
- BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
- else
- BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
+ if (closure == CLOSURE_BSDF_SHARP_GLASS_ID)
+ BsdfNode::compile(compiler, NULL, input("IOR"));
+ else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"), input("Color"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
}
-void GlassBsdfNode::compile(OSLCompiler& compiler)
+void GlassBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_glass_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_glass_bsdf");
}
/* Refraction BSDF Closure */
NODE_DEFINE(RefractionBsdfNode)
{
- NodeType* type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum distribution_enum;
- distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
- distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("sharp", CLOSURE_BSDF_REFRACTION_ID);
+ distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
- SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_FLOAT(IOR, "IOR", 0.3f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-RefractionBsdfNode::RefractionBsdfNode()
-: BsdfNode(node_type)
+RefractionBsdfNode::RefractionBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_REFRACTION_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ closure = CLOSURE_BSDF_REFRACTION_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
void RefractionBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == NBUILTIN_CLOSURES) {
- roughness_orig = roughness;
- distribution_orig = distribution;
- }
- else {
- /* By default we use original values, so we don't worry about restoring
- * defaults later one and can only do override when needed.
- */
- roughness = roughness_orig;
- distribution = distribution_orig;
- }
- Integrator *integrator = scene->integrator;
- ShaderInput *roughness_input = input("Roughness");
- if(integrator->filter_glossy == 0.0f) {
- /* Fallback to Sharp closure for Roughness close to 0.
- * Note: Keep the epsilon in sync with kernel!
- */
- if(!roughness_input->link && roughness <= 1e-4f) {
- VLOG(1) << "Using sharp refraction BSDF.";
- distribution = CLOSURE_BSDF_REFRACTION_ID;
- }
- }
- else {
- /* If filter glossy is used we replace Sharp glossy with GGX so we can
- * benefit from closure blur to remove unwanted noise.
- */
- if(roughness_input->link == NULL &&
- distribution == CLOSURE_BSDF_REFRACTION_ID)
- {
- VLOG(1) << "Using GGX refraction with filter glossy.";
- distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- roughness = 0.0f;
- }
- }
- closure = distribution;
+ if (distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
+ distribution_orig = distribution;
+ }
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
+ Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
+ if (integrator->filter_glossy == 0.0f) {
+ /* Fallback to Sharp closure for Roughness close to 0.
+ * Note: Keep the epsilon in sync with kernel!
+ */
+ if (!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp refraction BSDF.";
+ distribution = CLOSURE_BSDF_REFRACTION_ID;
+ }
+ }
+ else {
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if (roughness_input->link == NULL && distribution == CLOSURE_BSDF_REFRACTION_ID) {
+ VLOG(1) << "Using GGX refraction with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ roughness = 0.0f;
+ }
+ }
+ closure = distribution;
}
bool RefractionBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link &&
- (distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
}
-void RefractionBsdfNode::compile(SVMCompiler& compiler)
+void RefractionBsdfNode::compile(SVMCompiler &compiler)
{
- closure = distribution;
+ closure = distribution;
- if(closure == CLOSURE_BSDF_REFRACTION_ID)
- BsdfNode::compile(compiler, NULL, input("IOR"));
- else
- BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
+ if (closure == CLOSURE_BSDF_REFRACTION_ID)
+ BsdfNode::compile(compiler, NULL, input("IOR"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
}
-void RefractionBsdfNode::compile(OSLCompiler& compiler)
+void RefractionBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.add(this, "node_refraction_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.add(this, "node_refraction_bsdf");
}
/* Toon BSDF Closure */
NODE_DEFINE(ToonBsdfNode)
{
- NodeType* type = NodeType::add("toon_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("toon_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum component_enum;
- component_enum.insert("diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
- component_enum.insert("glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
- SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID);
- SOCKET_IN_FLOAT(size, "Size", 0.5f);
- SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
+ static NodeEnum component_enum;
+ component_enum.insert("diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
+ component_enum.insert("glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
+ SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_DIFFUSE_TOON_ID);
+ SOCKET_IN_FLOAT(size, "Size", 0.5f);
+ SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-ToonBsdfNode::ToonBsdfNode()
-: BsdfNode(node_type)
+ToonBsdfNode::ToonBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
}
-void ToonBsdfNode::compile(SVMCompiler& compiler)
+void ToonBsdfNode::compile(SVMCompiler &compiler)
{
- closure = component;
+ closure = component;
- BsdfNode::compile(compiler, input("Size"), input("Smooth"));
+ BsdfNode::compile(compiler, input("Size"), input("Smooth"));
}
-void ToonBsdfNode::compile(OSLCompiler& compiler)
+void ToonBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "component");
- compiler.add(this, "node_toon_bsdf");
+ compiler.parameter(this, "component");
+ compiler.add(this, "node_toon_bsdf");
}
/* Velvet BSDF Closure */
NODE_DEFINE(VelvetBsdfNode)
{
- NodeType* type = NodeType::add("velvet_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("velvet_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_IN_FLOAT(sigma, "Sigma", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(sigma, "Sigma", 1.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-VelvetBsdfNode::VelvetBsdfNode()
-: BsdfNode(node_type)
+VelvetBsdfNode::VelvetBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+ closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
}
-void VelvetBsdfNode::compile(SVMCompiler& compiler)
+void VelvetBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, input("Sigma"), NULL);
+ BsdfNode::compile(compiler, input("Sigma"), NULL);
}
-void VelvetBsdfNode::compile(OSLCompiler& compiler)
+void VelvetBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_velvet_bsdf");
+ compiler.add(this, "node_velvet_bsdf");
}
/* Diffuse BSDF Closure */
NODE_DEFINE(DiffuseBsdfNode)
{
- NodeType* type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("diffuse_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-DiffuseBsdfNode::DiffuseBsdfNode()
-: BsdfNode(node_type)
+DiffuseBsdfNode::DiffuseBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_DIFFUSE_ID;
+ closure = CLOSURE_BSDF_DIFFUSE_ID;
}
-void DiffuseBsdfNode::compile(SVMCompiler& compiler)
+void DiffuseBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, input("Roughness"), NULL);
+ BsdfNode::compile(compiler, input("Roughness"), NULL);
}
-void DiffuseBsdfNode::compile(OSLCompiler& compiler)
+void DiffuseBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_diffuse_bsdf");
+ compiler.add(this, "node_diffuse_bsdf");
}
/* Disney principled BSDF Closure */
NODE_DEFINE(PrincipledBsdfNode)
{
- NodeType* type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
-
- static NodeEnum distribution_enum;
- distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
- distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
- SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
-
- static NodeEnum subsurface_method_enum;
- subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_PRINCIPLED_ID);
- subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
- SOCKET_ENUM(subsurface_method, "Subsurface Method", subsurface_method_enum, CLOSURE_BSSRDF_PRINCIPLED_ID);
-
- SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
- SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
- SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
- SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
- SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
- SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
- SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
- SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
- SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
- SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
- SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
- SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
- SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
- SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
-
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
-
- return type;
-}
-
-PrincipledBsdfNode::PrincipledBsdfNode()
- : BsdfBaseNode(node_type)
-{
- closure = CLOSURE_BSDF_PRINCIPLED_ID;
- distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
- distribution_orig = NBUILTIN_CLOSURES;
+ NodeType *type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
+
+ static NodeEnum distribution_enum;
+ distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+ SOCKET_ENUM(
+ distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+
+ static NodeEnum subsurface_method_enum;
+ subsurface_method_enum.insert("burley", CLOSURE_BSSRDF_PRINCIPLED_ID);
+ subsurface_method_enum.insert("random_walk", CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID);
+ SOCKET_ENUM(subsurface_method,
+ "Subsurface Method",
+ subsurface_method_enum,
+ CLOSURE_BSSRDF_PRINCIPLED_ID);
+
+ SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
+ SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
+ SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
+ SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.5f);
+ SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
+ SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
+ SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
+ SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
+ SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
+ SOCKET_IN_FLOAT(clearcoat_roughness, "Clearcoat Roughness", 0.03f);
+ SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
+ SOCKET_IN_FLOAT(transmission, "Transmission", 0.0f);
+ SOCKET_IN_FLOAT(transmission_roughness, "Transmission Roughness", 0.0f);
+ SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_NORMAL(clearcoat_normal,
+ "Clearcoat Normal",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL);
+ SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
+PrincipledBsdfNode::PrincipledBsdfNode() : BsdfBaseNode(node_type)
+{
+ closure = CLOSURE_BSDF_PRINCIPLED_ID;
+ distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
}
bool PrincipledBsdfNode::has_surface_bssrdf()
{
- ShaderInput *subsurface_in = input("Subsurface");
- return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
+ ShaderInput *subsurface_in = input("Subsurface");
+ return (subsurface_in->link != NULL || subsurface > CLOSURE_WEIGHT_CUTOFF);
}
void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- ShaderInput *tangent_in = input("Tangent");
-
- if(!tangent_in->link)
- attributes->add(ATTR_STD_GENERATED);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius,
- ShaderInput *p_specular, ShaderInput *p_roughness, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic,
- ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_roughness,
- ShaderInput *p_ior, ShaderInput *p_transmission, ShaderInput *p_anisotropic_rotation, ShaderInput *p_transmission_roughness)
-{
- ShaderInput *base_color_in = input("Base Color");
- ShaderInput *subsurface_color_in = input("Subsurface Color");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
- ShaderInput *tangent_in = input("Tangent");
-
- float3 weight = make_float3(1.0f, 1.0f, 1.0f);
-
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
-
- int normal_offset = compiler.stack_assign_if_linked(normal_in);
- int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
- int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
- int specular_offset = compiler.stack_assign(p_specular);
- int roughness_offset = compiler.stack_assign(p_roughness);
- int specular_tint_offset = compiler.stack_assign(p_specular_tint);
- int anisotropic_offset = compiler.stack_assign(p_anisotropic);
- int sheen_offset = compiler.stack_assign(p_sheen);
- int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
- int clearcoat_offset = compiler.stack_assign(p_clearcoat);
- int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
- int ior_offset = compiler.stack_assign(p_ior);
- int transmission_offset = compiler.stack_assign(p_transmission);
- int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
- int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
- int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
-
- compiler.add_node(NODE_CLOSURE_BSDF,
- compiler.encode_uchar4(closure,
- compiler.stack_assign(p_metallic),
- compiler.stack_assign(p_subsurface),
- compiler.closure_mix_weight_offset()),
- __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
- __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
-
- compiler.add_node(normal_offset, tangent_offset,
- compiler.encode_uchar4(specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
- compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
-
- compiler.add_node(compiler.encode_uchar4(ior_offset, transmission_offset, anisotropic_rotation_offset, transmission_roughness_offset),
- distribution, subsurface_method, SVM_STACK_INVALID);
-
- float3 bc_default = get_float3(base_color_in->socket_type);
-
- compiler.add_node(((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
- __float_as_int(bc_default.x), __float_as_int(bc_default.y), __float_as_int(bc_default.z));
-
- compiler.add_node(clearcoat_normal_offset, subsurface_radius_offset, SVM_STACK_INVALID, SVM_STACK_INVALID);
-
- float3 ss_default = get_float3(subsurface_color_in->socket_type);
-
- compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) : SVM_STACK_INVALID),
- __float_as_int(ss_default.x), __float_as_int(ss_default.y), __float_as_int(ss_default.z));
+ if (shader->has_surface) {
+ ShaderInput *tangent_in = input("Tangent");
+
+ if (!tangent_in->link)
+ attributes->add(ATTR_STD_GENERATED);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PrincipledBsdfNode::compile(SVMCompiler &compiler,
+ ShaderInput *p_metallic,
+ ShaderInput *p_subsurface,
+ ShaderInput *p_subsurface_radius,
+ ShaderInput *p_specular,
+ ShaderInput *p_roughness,
+ ShaderInput *p_specular_tint,
+ ShaderInput *p_anisotropic,
+ ShaderInput *p_sheen,
+ ShaderInput *p_sheen_tint,
+ ShaderInput *p_clearcoat,
+ ShaderInput *p_clearcoat_roughness,
+ ShaderInput *p_ior,
+ ShaderInput *p_transmission,
+ ShaderInput *p_anisotropic_rotation,
+ ShaderInput *p_transmission_roughness)
+{
+ ShaderInput *base_color_in = input("Base Color");
+ ShaderInput *subsurface_color_in = input("Subsurface Color");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
+ ShaderInput *tangent_in = input("Tangent");
+
+ float3 weight = make_float3(1.0f, 1.0f, 1.0f);
+
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
+
+ int normal_offset = compiler.stack_assign_if_linked(normal_in);
+ int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
+ int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
+ int specular_offset = compiler.stack_assign(p_specular);
+ int roughness_offset = compiler.stack_assign(p_roughness);
+ int specular_tint_offset = compiler.stack_assign(p_specular_tint);
+ int anisotropic_offset = compiler.stack_assign(p_anisotropic);
+ int sheen_offset = compiler.stack_assign(p_sheen);
+ int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
+ int clearcoat_offset = compiler.stack_assign(p_clearcoat);
+ int clearcoat_roughness_offset = compiler.stack_assign(p_clearcoat_roughness);
+ int ior_offset = compiler.stack_assign(p_ior);
+ int transmission_offset = compiler.stack_assign(p_transmission);
+ int transmission_roughness_offset = compiler.stack_assign(p_transmission_roughness);
+ int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
+ int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
+
+ compiler.add_node(NODE_CLOSURE_BSDF,
+ compiler.encode_uchar4(closure,
+ compiler.stack_assign(p_metallic),
+ compiler.stack_assign(p_subsurface),
+ compiler.closure_mix_weight_offset()),
+ __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
+ __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
+
+ compiler.add_node(
+ normal_offset,
+ tangent_offset,
+ compiler.encode_uchar4(
+ specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
+ compiler.encode_uchar4(
+ sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_roughness_offset));
+
+ compiler.add_node(compiler.encode_uchar4(ior_offset,
+ transmission_offset,
+ anisotropic_rotation_offset,
+ transmission_roughness_offset),
+ distribution,
+ subsurface_method,
+ SVM_STACK_INVALID);
+
+ float3 bc_default = get_float3(base_color_in->socket_type);
+
+ compiler.add_node(
+ ((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
+ __float_as_int(bc_default.x),
+ __float_as_int(bc_default.y),
+ __float_as_int(bc_default.z));
+
+ compiler.add_node(
+ clearcoat_normal_offset, subsurface_radius_offset, SVM_STACK_INVALID, SVM_STACK_INVALID);
+
+ float3 ss_default = get_float3(subsurface_color_in->socket_type);
+
+ compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) :
+ SVM_STACK_INVALID),
+ __float_as_int(ss_default.x),
+ __float_as_int(ss_default.y),
+ __float_as_int(ss_default.z));
}
bool PrincipledBsdfNode::has_integrator_dependency()
{
- ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness <= 1e-4f;
+ ShaderInput *roughness_input = input("Roughness");
+ return !roughness_input->link && roughness <= 1e-4f;
}
-void PrincipledBsdfNode::compile(SVMCompiler& compiler)
+void PrincipledBsdfNode::compile(SVMCompiler &compiler)
{
- compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"),
- input("Roughness"), input("Specular Tint"), input("Anisotropic"), input("Sheen"), input("Sheen Tint"),
- input("Clearcoat"), input("Clearcoat Roughness"), input("IOR"), input("Transmission"),
- input("Anisotropic Rotation"), input("Transmission Roughness"));
+ compile(compiler,
+ input("Metallic"),
+ input("Subsurface"),
+ input("Subsurface Radius"),
+ input("Specular"),
+ input("Roughness"),
+ input("Specular Tint"),
+ input("Anisotropic"),
+ input("Sheen"),
+ input("Sheen Tint"),
+ input("Clearcoat"),
+ input("Clearcoat Roughness"),
+ input("IOR"),
+ input("Transmission"),
+ input("Anisotropic Rotation"),
+ input("Transmission Roughness"));
}
-void PrincipledBsdfNode::compile(OSLCompiler& compiler)
+void PrincipledBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "distribution");
- compiler.parameter(this, "subsurface_method");
- compiler.add(this, "node_principled_bsdf");
+ compiler.parameter(this, "distribution");
+ compiler.parameter(this, "subsurface_method");
+ compiler.add(this, "node_principled_bsdf");
}
bool PrincipledBsdfNode::has_bssrdf_bump()
{
- return has_surface_bssrdf() && has_bump();
+ return has_surface_bssrdf() && has_bump();
}
/* Translucent BSDF Closure */
NODE_DEFINE(TranslucentBsdfNode)
{
- NodeType* type = NodeType::add("translucent_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("translucent_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-TranslucentBsdfNode::TranslucentBsdfNode()
-: BsdfNode(node_type)
+TranslucentBsdfNode::TranslucentBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_TRANSLUCENT_ID;
+ closure = CLOSURE_BSDF_TRANSLUCENT_ID;
}
-void TranslucentBsdfNode::compile(SVMCompiler& compiler)
+void TranslucentBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, NULL, NULL);
+ BsdfNode::compile(compiler, NULL, NULL);
}
-void TranslucentBsdfNode::compile(OSLCompiler& compiler)
+void TranslucentBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_translucent_bsdf");
+ compiler.add(this, "node_translucent_bsdf");
}
/* Transparent BSDF Closure */
NODE_DEFINE(TransparentBsdfNode)
{
- NodeType* type = NodeType::add("transparent_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("transparent_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-TransparentBsdfNode::TransparentBsdfNode()
-: BsdfNode(node_type)
+TransparentBsdfNode::TransparentBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_TRANSPARENT_ID;
+ closure = CLOSURE_BSDF_TRANSPARENT_ID;
}
-void TransparentBsdfNode::compile(SVMCompiler& compiler)
+void TransparentBsdfNode::compile(SVMCompiler &compiler)
{
- BsdfNode::compile(compiler, NULL, NULL);
+ BsdfNode::compile(compiler, NULL, NULL);
}
-void TransparentBsdfNode::compile(OSLCompiler& compiler)
+void TransparentBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_transparent_bsdf");
+ compiler.add(this, "node_transparent_bsdf");
}
/* Subsurface Scattering Closure */
NODE_DEFINE(SubsurfaceScatteringNode)
{
- NodeType* type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum falloff_enum;
- falloff_enum.insert("cubic", CLOSURE_BSSRDF_CUBIC_ID);
- falloff_enum.insert("gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID);
- falloff_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
- falloff_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
- SOCKET_ENUM(falloff, "Falloff", falloff_enum, CLOSURE_BSSRDF_BURLEY_ID);
- SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
- SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f));
- SOCKET_IN_FLOAT(sharpness, "Sharpness", 0.0f);
- SOCKET_IN_FLOAT(texture_blur, "Texture Blur", 1.0f);
+ static NodeEnum falloff_enum;
+ falloff_enum.insert("cubic", CLOSURE_BSSRDF_CUBIC_ID);
+ falloff_enum.insert("gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID);
+ falloff_enum.insert("burley", CLOSURE_BSSRDF_BURLEY_ID);
+ falloff_enum.insert("random_walk", CLOSURE_BSSRDF_RANDOM_WALK_ID);
+ SOCKET_ENUM(falloff, "Falloff", falloff_enum, CLOSURE_BSSRDF_BURLEY_ID);
+ SOCKET_IN_FLOAT(scale, "Scale", 0.01f);
+ SOCKET_IN_VECTOR(radius, "Radius", make_float3(0.1f, 0.1f, 0.1f));
+ SOCKET_IN_FLOAT(sharpness, "Sharpness", 0.0f);
+ SOCKET_IN_FLOAT(texture_blur, "Texture Blur", 1.0f);
- SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF");
+ SOCKET_OUT_CLOSURE(BSSRDF, "BSSRDF");
- return type;
+ return type;
}
-SubsurfaceScatteringNode::SubsurfaceScatteringNode()
-: BsdfNode(node_type)
+SubsurfaceScatteringNode::SubsurfaceScatteringNode() : BsdfNode(node_type)
{
- closure = falloff;
+ closure = falloff;
}
-void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
+void SubsurfaceScatteringNode::compile(SVMCompiler &compiler)
{
- closure = falloff;
- BsdfNode::compile(compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
+ closure = falloff;
+ BsdfNode::compile(
+ compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
}
-void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
+void SubsurfaceScatteringNode::compile(OSLCompiler &compiler)
{
- closure = falloff;
- compiler.parameter(this, "falloff");
- compiler.add(this, "node_subsurface_scattering");
+ closure = falloff;
+ compiler.parameter(this, "falloff");
+ compiler.add(this, "node_subsurface_scattering");
}
bool SubsurfaceScatteringNode::has_bssrdf_bump()
{
- /* detect if anything is plugged into the normal input besides the default */
- ShaderInput *normal_in = input("Normal");
- return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+ /* detect if anything is plugged into the normal input besides the default */
+ ShaderInput *normal_in = input("Normal");
+ return (normal_in->link &&
+ normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
}
/* Emissive Closure */
NODE_DEFINE(EmissionNode)
{
- NodeType* type = NodeType::add("emission", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("emission", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(strength, "Strength", 10.0f);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(strength, "Strength", 10.0f);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(emission, "Emission");
+ SOCKET_OUT_CLOSURE(emission, "Emission");
- return type;
+ return type;
}
-EmissionNode::EmissionNode()
-: ShaderNode(node_type)
+EmissionNode::EmissionNode() : ShaderNode(node_type)
{
}
-void EmissionNode::compile(SVMCompiler& compiler)
+void EmissionNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if(color_in->link || strength_in->link) {
- compiler.add_node(NODE_EMISSION_WEIGHT,
- compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in));
- }
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
+ if (color_in->link || strength_in->link) {
+ compiler.add_node(
+ NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
+ }
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
- compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
+ compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
}
-void EmissionNode::compile(OSLCompiler& compiler)
+void EmissionNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_emission");
+ compiler.add(this, "node_emission");
}
-void EmissionNode::constant_fold(const ConstantFolder& folder)
+void EmissionNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength == 0.0f))
- {
- folder.discard();
- }
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Background Closure */
NODE_DEFINE(BackgroundNode)
{
- NodeType* type = NodeType::add("background_shader", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("background_shader", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(background, "Background");
+ SOCKET_OUT_CLOSURE(background, "Background");
- return type;
+ return type;
}
-BackgroundNode::BackgroundNode()
-: ShaderNode(node_type)
+BackgroundNode::BackgroundNode() : ShaderNode(node_type)
{
}
-void BackgroundNode::compile(SVMCompiler& compiler)
+void BackgroundNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if(color_in->link || strength_in->link) {
- compiler.add_node(NODE_EMISSION_WEIGHT,
- compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in));
- }
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color*strength);
+ if (color_in->link || strength_in->link) {
+ compiler.add_node(
+ NODE_EMISSION_WEIGHT, compiler.stack_assign(color_in), compiler.stack_assign(strength_in));
+ }
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
- compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
+ compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
}
-void BackgroundNode::compile(OSLCompiler& compiler)
+void BackgroundNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_background");
+ compiler.add(this, "node_background");
}
-void BackgroundNode::constant_fold(const ConstantFolder& folder)
+void BackgroundNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
- if((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength == 0.0f))
- {
- folder.discard();
- }
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Holdout Closure */
NODE_DEFINE(HoldoutNode)
{
- NodeType* type = NodeType::add("holdout", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("holdout", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(holdout, "Holdout");
+ SOCKET_OUT_CLOSURE(holdout, "Holdout");
- return type;
+ return type;
}
-HoldoutNode::HoldoutNode()
-: ShaderNode(node_type)
+HoldoutNode::HoldoutNode() : ShaderNode(node_type)
{
}
-void HoldoutNode::compile(SVMCompiler& compiler)
+void HoldoutNode::compile(SVMCompiler &compiler)
{
- float3 value = make_float3(1.0f, 1.0f, 1.0f);
+ float3 value = make_float3(1.0f, 1.0f, 1.0f);
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value);
- compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, value);
+ compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
}
-void HoldoutNode::compile(OSLCompiler& compiler)
+void HoldoutNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_holdout");
+ compiler.add(this, "node_holdout");
}
/* Ambient Occlusion */
NODE_DEFINE(AmbientOcclusionNode)
{
- NodeType* type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
- SOCKET_INT(samples, "Samples", 16);
+ SOCKET_INT(samples, "Samples", 16);
- SOCKET_IN_COLOR(color, "Color", make_float3(1.0f, 1.0f, 1.0f));
- SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_BOOLEAN(inside, "Inside", false);
- SOCKET_BOOLEAN(only_local, "Only Local", false);
+ SOCKET_BOOLEAN(inside, "Inside", false);
+ SOCKET_BOOLEAN(only_local, "Only Local", false);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(ao, "AO");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(ao, "AO");
- return type;
+ return type;
}
-AmbientOcclusionNode::AmbientOcclusionNode()
-: ShaderNode(node_type)
+AmbientOcclusionNode::AmbientOcclusionNode() : ShaderNode(node_type)
{
}
-void AmbientOcclusionNode::compile(SVMCompiler& compiler)
+void AmbientOcclusionNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *distance_in = input("Distance");
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *ao_out = output("AO");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *distance_in = input("Distance");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *ao_out = output("AO");
- int flags = (inside? NODE_AO_INSIDE : 0) | (only_local? NODE_AO_ONLY_LOCAL : 0);
+ int flags = (inside ? NODE_AO_INSIDE : 0) | (only_local ? NODE_AO_ONLY_LOCAL : 0);
- if(!distance_in->link && distance == 0.0f) {
- flags |= NODE_AO_GLOBAL_RADIUS;
- }
+ if (!distance_in->link && distance == 0.0f) {
+ flags |= NODE_AO_GLOBAL_RADIUS;
+ }
- compiler.add_node(NODE_AMBIENT_OCCLUSION,
- compiler.encode_uchar4(flags,
- compiler.stack_assign_if_linked(distance_in),
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(ao_out)),
- compiler.encode_uchar4(compiler.stack_assign(color_in),
- compiler.stack_assign(color_out),
- samples),
- __float_as_uint(distance));
+ compiler.add_node(NODE_AMBIENT_OCCLUSION,
+ compiler.encode_uchar4(flags,
+ compiler.stack_assign_if_linked(distance_in),
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(ao_out)),
+ compiler.encode_uchar4(compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out),
+ samples),
+ __float_as_uint(distance));
}
-void AmbientOcclusionNode::compile(OSLCompiler& compiler)
+void AmbientOcclusionNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "samples");
- compiler.parameter(this, "inside");
- compiler.parameter(this, "only_local");
- compiler.add(this, "node_ambient_occlusion");
+ compiler.parameter(this, "samples");
+ compiler.parameter(this, "inside");
+ compiler.parameter(this, "only_local");
+ compiler.add(this, "node_ambient_occlusion");
}
/* Volume Closure */
-VolumeNode::VolumeNode(const NodeType *node_type)
-: ShaderNode(node_type)
+VolumeNode::VolumeNode(const NodeType *node_type) : ShaderNode(node_type)
{
- closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
}
-void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2)
+void VolumeNode::compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2)
{
- ShaderInput *color_in = input("Color");
+ ShaderInput *color_in = input("Color");
- if(color_in->link)
- compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+ if (color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
- compiler.add_node(NODE_CLOSURE_VOLUME,
- compiler.encode_uchar4(closure,
- (param1)? compiler.stack_assign(param1): SVM_STACK_INVALID,
- (param2)? compiler.stack_assign(param2): SVM_STACK_INVALID,
- compiler.closure_mix_weight_offset()),
- __float_as_int((param1)? get_float(param1->socket_type): 0.0f),
- __float_as_int((param2)? get_float(param2->socket_type): 0.0f));
+ compiler.add_node(
+ NODE_CLOSURE_VOLUME,
+ compiler.encode_uchar4(closure,
+ (param1) ? compiler.stack_assign(param1) : SVM_STACK_INVALID,
+ (param2) ? compiler.stack_assign(param2) : SVM_STACK_INVALID,
+ compiler.closure_mix_weight_offset()),
+ __float_as_int((param1) ? get_float(param1->socket_type) : 0.0f),
+ __float_as_int((param2) ? get_float(param2->socket_type) : 0.0f));
}
-void VolumeNode::compile(SVMCompiler& compiler)
+void VolumeNode::compile(SVMCompiler &compiler)
{
- compile(compiler, NULL, NULL);
+ compile(compiler, NULL, NULL);
}
-void VolumeNode::compile(OSLCompiler& /*compiler*/)
+void VolumeNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* Absorption Volume Closure */
NODE_DEFINE(AbsorptionVolumeNode)
{
- NodeType* type = NodeType::add("absorption_volume", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("absorption_volume", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(density, "Density", 1.0f);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(volume, "Volume");
+ SOCKET_OUT_CLOSURE(volume, "Volume");
- return type;
+ return type;
}
-AbsorptionVolumeNode::AbsorptionVolumeNode()
-: VolumeNode(node_type)
+AbsorptionVolumeNode::AbsorptionVolumeNode() : VolumeNode(node_type)
{
- closure = CLOSURE_VOLUME_ABSORPTION_ID;
+ closure = CLOSURE_VOLUME_ABSORPTION_ID;
}
-void AbsorptionVolumeNode::compile(SVMCompiler& compiler)
+void AbsorptionVolumeNode::compile(SVMCompiler &compiler)
{
- VolumeNode::compile(compiler, input("Density"), NULL);
+ VolumeNode::compile(compiler, input("Density"), NULL);
}
-void AbsorptionVolumeNode::compile(OSLCompiler& compiler)
+void AbsorptionVolumeNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_absorption_volume");
+ compiler.add(this, "node_absorption_volume");
}
/* Scatter Volume Closure */
NODE_DEFINE(ScatterVolumeNode)
{
- NodeType* type = NodeType::add("scatter_volume", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("scatter_volume", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_FLOAT(density, "Density", 1.0f);
- SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(volume, "Volume");
+ SOCKET_OUT_CLOSURE(volume, "Volume");
- return type;
+ return type;
}
-ScatterVolumeNode::ScatterVolumeNode()
-: VolumeNode(node_type)
+ScatterVolumeNode::ScatterVolumeNode() : VolumeNode(node_type)
{
- closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
}
-void ScatterVolumeNode::compile(SVMCompiler& compiler)
+void ScatterVolumeNode::compile(SVMCompiler &compiler)
{
- VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
+ VolumeNode::compile(compiler, input("Density"), input("Anisotropy"));
}
-void ScatterVolumeNode::compile(OSLCompiler& compiler)
+void ScatterVolumeNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_scatter_volume");
+ compiler.add(this, "node_scatter_volume");
}
/* Principled Volume Closure */
NODE_DEFINE(PrincipledVolumeNode)
{
- NodeType* type = NodeType::add("principled_volume", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("principled_volume", create, NodeType::SHADER);
- SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
- SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
- SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
+ SOCKET_IN_STRING(density_attribute, "Density Attribute", ustring());
+ SOCKET_IN_STRING(color_attribute, "Color Attribute", ustring());
+ SOCKET_IN_STRING(temperature_attribute, "Temperature Attribute", ustring());
- SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
- SOCKET_IN_FLOAT(density, "Density", 1.0f);
- SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
- SOCKET_IN_COLOR(absorption_color, "Absorption Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
- SOCKET_IN_COLOR(emission_color, "Emission Color", make_float3(1.0f, 1.0f, 1.0f));
- SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
- SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", make_float3(1.0f, 1.0f, 1.0f));
- SOCKET_IN_FLOAT(temperature, "Temperature", 1500.0f);
- SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 0.5f));
+ SOCKET_IN_FLOAT(density, "Density", 1.0f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.0f);
+ SOCKET_IN_COLOR(absorption_color, "Absorption Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(emission_strength, "Emission Strength", 0.0f);
+ SOCKET_IN_COLOR(emission_color, "Emission Color", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(blackbody_intensity, "Blackbody Intensity", 0.0f);
+ SOCKET_IN_COLOR(blackbody_tint, "Blackbody Tint", make_float3(1.0f, 1.0f, 1.0f));
+ SOCKET_IN_FLOAT(temperature, "Temperature", 1500.0f);
+ SOCKET_IN_FLOAT(volume_mix_weight, "VolumeMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(volume, "Volume");
+ SOCKET_OUT_CLOSURE(volume, "Volume");
- return type;
+ return type;
}
-PrincipledVolumeNode::PrincipledVolumeNode()
-: VolumeNode(node_type)
+PrincipledVolumeNode::PrincipledVolumeNode() : VolumeNode(node_type)
{
- closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
}
void PrincipledVolumeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_volume) {
- ShaderInput *density_in = input("Density");
- ShaderInput *blackbody_in = input("Blackbody Intensity");
-
- if(density_in->link || density > 0.0f) {
- attributes->add_standard(density_attribute);
- attributes->add_standard(color_attribute);
- }
-
- if(blackbody_in->link || blackbody_intensity > 0.0f) {
- attributes->add_standard(temperature_attribute);
- }
-
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void PrincipledVolumeNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *color_in = input("Color");
- ShaderInput *density_in = input("Density");
- ShaderInput *anisotropy_in = input("Anisotropy");
- ShaderInput *absorption_color_in = input("Absorption Color");
- ShaderInput *emission_in = input("Emission Strength");
- ShaderInput *emission_color_in = input("Emission Color");
- ShaderInput *blackbody_in = input("Blackbody Intensity");
- ShaderInput *blackbody_tint_in = input("Blackbody Tint");
- ShaderInput *temperature_in = input("Temperature");
-
- if(color_in->link)
- compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
- else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
-
- compiler.add_node(NODE_PRINCIPLED_VOLUME,
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(density_in),
- compiler.stack_assign_if_linked(anisotropy_in),
- compiler.stack_assign(absorption_color_in),
- compiler.closure_mix_weight_offset()),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(emission_in),
- compiler.stack_assign(emission_color_in),
- compiler.stack_assign_if_linked(blackbody_in),
- compiler.stack_assign(temperature_in)),
- compiler.stack_assign(blackbody_tint_in));
-
- int attr_density = compiler.attribute_standard(density_attribute);
- int attr_color = compiler.attribute_standard(color_attribute);
- int attr_temperature = compiler.attribute_standard(temperature_attribute);
-
- compiler.add_node(
- __float_as_int(density),
- __float_as_int(anisotropy),
- __float_as_int(emission_strength),
- __float_as_int(blackbody_intensity));
-
- compiler.add_node(
- attr_density,
- attr_color,
- attr_temperature);
-}
-
-void PrincipledVolumeNode::compile(OSLCompiler& compiler)
-{
- if(Attribute::name_standard(density_attribute.c_str())) {
- density_attribute = ustring("geom:" + density_attribute.string());
- }
- if(Attribute::name_standard(color_attribute.c_str())) {
- color_attribute = ustring("geom:" + color_attribute.string());
- }
- if(Attribute::name_standard(temperature_attribute.c_str())) {
- temperature_attribute = ustring("geom:" + temperature_attribute.string());
- }
-
- compiler.add(this, "node_principled_volume");
+ if (shader->has_volume) {
+ ShaderInput *density_in = input("Density");
+ ShaderInput *blackbody_in = input("Blackbody Intensity");
+
+ if (density_in->link || density > 0.0f) {
+ attributes->add_standard(density_attribute);
+ attributes->add_standard(color_attribute);
+ }
+
+ if (blackbody_in->link || blackbody_intensity > 0.0f) {
+ attributes->add_standard(temperature_attribute);
+ }
+
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PrincipledVolumeNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderInput *density_in = input("Density");
+ ShaderInput *anisotropy_in = input("Anisotropy");
+ ShaderInput *absorption_color_in = input("Absorption Color");
+ ShaderInput *emission_in = input("Emission Strength");
+ ShaderInput *emission_color_in = input("Emission Color");
+ ShaderInput *blackbody_in = input("Blackbody Intensity");
+ ShaderInput *blackbody_tint_in = input("Blackbody Tint");
+ ShaderInput *temperature_in = input("Temperature");
+
+ if (color_in->link)
+ compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+
+ compiler.add_node(NODE_PRINCIPLED_VOLUME,
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(density_in),
+ compiler.stack_assign_if_linked(anisotropy_in),
+ compiler.stack_assign(absorption_color_in),
+ compiler.closure_mix_weight_offset()),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(emission_in),
+ compiler.stack_assign(emission_color_in),
+ compiler.stack_assign_if_linked(blackbody_in),
+ compiler.stack_assign(temperature_in)),
+ compiler.stack_assign(blackbody_tint_in));
+
+ int attr_density = compiler.attribute_standard(density_attribute);
+ int attr_color = compiler.attribute_standard(color_attribute);
+ int attr_temperature = compiler.attribute_standard(temperature_attribute);
+
+ compiler.add_node(__float_as_int(density),
+ __float_as_int(anisotropy),
+ __float_as_int(emission_strength),
+ __float_as_int(blackbody_intensity));
+
+ compiler.add_node(attr_density, attr_color, attr_temperature);
+}
+
+void PrincipledVolumeNode::compile(OSLCompiler &compiler)
+{
+ if (Attribute::name_standard(density_attribute.c_str())) {
+ density_attribute = ustring("geom:" + density_attribute.string());
+ }
+ if (Attribute::name_standard(color_attribute.c_str())) {
+ color_attribute = ustring("geom:" + color_attribute.string());
+ }
+ if (Attribute::name_standard(temperature_attribute.c_str())) {
+ temperature_attribute = ustring("geom:" + temperature_attribute.string());
+ }
+
+ compiler.add(this, "node_principled_volume");
}
/* Principled Hair BSDF Closure */
NODE_DEFINE(PrincipledHairBsdfNode)
{
- NodeType* type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("principled_hair_bsdf", create, NodeType::SHADER);
- /* Color parametrization specified as enum. */
- static NodeEnum parametrization_enum;
- parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
- parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
- parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
- SOCKET_ENUM(parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ /* Color parametrization specified as enum. */
+ static NodeEnum parametrization_enum;
+ parametrization_enum.insert("Direct coloring", NODE_PRINCIPLED_HAIR_REFLECTANCE);
+ parametrization_enum.insert("Melanin concentration", NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION);
+ parametrization_enum.insert("Absorption coefficient", NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION);
+ SOCKET_ENUM(
+ parametrization, "Parametrization", parametrization_enum, NODE_PRINCIPLED_HAIR_REFLECTANCE);
- /* Initialize sockets to their default values. */
- SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
- SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
- SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
- SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
- SOCKET_IN_VECTOR(absorption_coefficient, "Absorption Coefficient", make_float3(0.245531f, 0.52f, 1.365f), SocketType::VECTOR);
+ /* Initialize sockets to their default values. */
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.017513f, 0.005763f, 0.002059f));
+ SOCKET_IN_FLOAT(melanin, "Melanin", 0.8f);
+ SOCKET_IN_FLOAT(melanin_redness, "Melanin Redness", 1.0f);
+ SOCKET_IN_COLOR(tint, "Tint", make_float3(1.f, 1.f, 1.f));
+ SOCKET_IN_VECTOR(absorption_coefficient,
+ "Absorption Coefficient",
+ make_float3(0.245531f, 0.52f, 1.365f),
+ SocketType::VECTOR);
- SOCKET_IN_FLOAT(offset, "Offset", 2.f*M_PI_F/180.f);
- SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
- SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
- SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
- SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
+ SOCKET_IN_FLOAT(offset, "Offset", 2.f * M_PI_F / 180.f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.3f);
+ SOCKET_IN_FLOAT(radial_roughness, "Radial Roughness", 0.3f);
+ SOCKET_IN_FLOAT(coat, "Coat", 0.0f);
+ SOCKET_IN_FLOAT(ior, "IOR", 1.55f);
- SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
- SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
- SOCKET_IN_FLOAT(random, "Random", 0.0f);
+ SOCKET_IN_FLOAT(random_roughness, "Random Roughness", 0.0f);
+ SOCKET_IN_FLOAT(random_color, "Random Color", 0.0f);
+ SOCKET_IN_FLOAT(random, "Random", 0.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-PrincipledHairBsdfNode::PrincipledHairBsdfNode()
-: BsdfBaseNode(node_type)
+PrincipledHairBsdfNode::PrincipledHairBsdfNode() : BsdfBaseNode(node_type)
{
- closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
+ closure = CLOSURE_BSDF_HAIR_PRINCIPLED_ID;
}
/* Enable retrieving Hair Info -> Random if Random isn't linked. */
void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(!input("Random")->link) {
- attributes->add(ATTR_STD_CURVE_RANDOM);
- }
- ShaderNode::attributes(shader, attributes);
+ if (!input("Random")->link) {
+ attributes->add(ATTR_STD_CURVE_RANDOM);
+ }
+ ShaderNode::attributes(shader, attributes);
}
/* Prepares the input data for the SVM shader. */
-void PrincipledHairBsdfNode::compile(SVMCompiler& compiler)
-{
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, make_float3(1.0f, 1.0f, 1.0f));
-
- ShaderInput *roughness_in = input("Roughness");
- ShaderInput *radial_roughness_in = input("Radial Roughness");
- ShaderInput *random_roughness_in = input("Random Roughness");
- ShaderInput *offset_in = input("Offset");
- ShaderInput *coat_in = input("Coat");
- ShaderInput *ior_in = input("IOR");
- ShaderInput *melanin_in = input("Melanin");
- ShaderInput *melanin_redness_in = input("Melanin Redness");
- ShaderInput *random_color_in = input("Random Color");
-
- int color_ofs = compiler.stack_assign(input("Color"));
- int tint_ofs = compiler.stack_assign(input("Tint"));
- int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
-
- ShaderInput *random_in = input("Random");
- int attr_random = random_in->link ? SVM_STACK_INVALID : compiler.attribute(ATTR_STD_CURVE_RANDOM);
-
- /* Encode all parameters into data nodes. */
- compiler.add_node(NODE_CLOSURE_BSDF,
- /* Socket IDs can be packed 4 at a time into a single data packet */
- compiler.encode_uchar4(closure,
- compiler.stack_assign_if_linked(roughness_in),
- compiler.stack_assign_if_linked(radial_roughness_in),
- compiler.closure_mix_weight_offset()),
- /* The rest are stored as unsigned integers */
- __float_as_uint(roughness),
- __float_as_uint(radial_roughness));
-
- compiler.add_node(compiler.stack_assign_if_linked(input("Normal")),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(offset_in),
- compiler.stack_assign_if_linked(ior_in),
- color_ofs,
- parametrization),
- __float_as_uint(offset),
- __float_as_uint(ior));
-
- compiler.add_node(
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(coat_in),
- compiler.stack_assign_if_linked(melanin_in),
- compiler.stack_assign_if_linked(melanin_redness_in),
- absorption_coefficient_ofs),
- __float_as_uint(coat),
- __float_as_uint(melanin),
- __float_as_uint(melanin_redness));
-
- compiler.add_node(
- compiler.encode_uchar4(
- tint_ofs,
- compiler.stack_assign_if_linked(random_in),
- compiler.stack_assign_if_linked(random_color_in),
- compiler.stack_assign_if_linked(random_roughness_in)),
- __float_as_uint(random),
- __float_as_uint(random_color),
- __float_as_uint(random_roughness));
-
- compiler.add_node(
- compiler.encode_uchar4(
- SVM_STACK_INVALID,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID),
- attr_random,
- SVM_STACK_INVALID,
- SVM_STACK_INVALID);
+void PrincipledHairBsdfNode::compile(SVMCompiler &compiler)
+{
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, make_float3(1.0f, 1.0f, 1.0f));
+
+ ShaderInput *roughness_in = input("Roughness");
+ ShaderInput *radial_roughness_in = input("Radial Roughness");
+ ShaderInput *random_roughness_in = input("Random Roughness");
+ ShaderInput *offset_in = input("Offset");
+ ShaderInput *coat_in = input("Coat");
+ ShaderInput *ior_in = input("IOR");
+ ShaderInput *melanin_in = input("Melanin");
+ ShaderInput *melanin_redness_in = input("Melanin Redness");
+ ShaderInput *random_color_in = input("Random Color");
+
+ int color_ofs = compiler.stack_assign(input("Color"));
+ int tint_ofs = compiler.stack_assign(input("Tint"));
+ int absorption_coefficient_ofs = compiler.stack_assign(input("Absorption Coefficient"));
+
+ ShaderInput *random_in = input("Random");
+ int attr_random = random_in->link ? SVM_STACK_INVALID :
+ compiler.attribute(ATTR_STD_CURVE_RANDOM);
+
+ /* Encode all parameters into data nodes. */
+ compiler.add_node(NODE_CLOSURE_BSDF,
+ /* Socket IDs can be packed 4 at a time into a single data packet */
+ compiler.encode_uchar4(closure,
+ compiler.stack_assign_if_linked(roughness_in),
+ compiler.stack_assign_if_linked(radial_roughness_in),
+ compiler.closure_mix_weight_offset()),
+ /* The rest are stored as unsigned integers */
+ __float_as_uint(roughness),
+ __float_as_uint(radial_roughness));
+
+ compiler.add_node(compiler.stack_assign_if_linked(input("Normal")),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(offset_in),
+ compiler.stack_assign_if_linked(ior_in),
+ color_ofs,
+ parametrization),
+ __float_as_uint(offset),
+ __float_as_uint(ior));
+
+ compiler.add_node(compiler.encode_uchar4(compiler.stack_assign_if_linked(coat_in),
+ compiler.stack_assign_if_linked(melanin_in),
+ compiler.stack_assign_if_linked(melanin_redness_in),
+ absorption_coefficient_ofs),
+ __float_as_uint(coat),
+ __float_as_uint(melanin),
+ __float_as_uint(melanin_redness));
+
+ compiler.add_node(compiler.encode_uchar4(tint_ofs,
+ compiler.stack_assign_if_linked(random_in),
+ compiler.stack_assign_if_linked(random_color_in),
+ compiler.stack_assign_if_linked(random_roughness_in)),
+ __float_as_uint(random),
+ __float_as_uint(random_color),
+ __float_as_uint(random_roughness));
+
+ compiler.add_node(
+ compiler.encode_uchar4(
+ SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID, SVM_STACK_INVALID),
+ attr_random,
+ SVM_STACK_INVALID,
+ SVM_STACK_INVALID);
}
/* Prepares the input data for the OSL shader. */
-void PrincipledHairBsdfNode::compile(OSLCompiler& compiler)
+void PrincipledHairBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "parametrization");
- compiler.add(this, "node_principled_hair_bsdf");
+ compiler.parameter(this, "parametrization");
+ compiler.add(this, "node_principled_hair_bsdf");
}
/* Hair BSDF Closure */
NODE_DEFINE(HairBsdfNode)
{
- NodeType* type = NodeType::add("hair_bsdf", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("hair_bsdf", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
- static NodeEnum component_enum;
- component_enum.insert("reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
- component_enum.insert("transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
- SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID);
- SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
- SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f);
- SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f);
- SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f));
+ static NodeEnum component_enum;
+ component_enum.insert("reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
+ component_enum.insert("transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
+ SOCKET_ENUM(component, "Component", component_enum, CLOSURE_BSDF_HAIR_REFLECTION_ID);
+ SOCKET_IN_FLOAT(offset, "Offset", 0.0f);
+ SOCKET_IN_FLOAT(roughness_u, "RoughnessU", 0.2f);
+ SOCKET_IN_FLOAT(roughness_v, "RoughnessV", 0.2f);
+ SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
- return type;
+ return type;
}
-HairBsdfNode::HairBsdfNode()
-: BsdfNode(node_type)
+HairBsdfNode::HairBsdfNode() : BsdfNode(node_type)
{
- closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
+ closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
}
-void HairBsdfNode::compile(SVMCompiler& compiler)
+void HairBsdfNode::compile(SVMCompiler &compiler)
{
- closure = component;
+ closure = component;
- BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
+ BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
}
-void HairBsdfNode::compile(OSLCompiler& compiler)
+void HairBsdfNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "component");
- compiler.add(this, "node_hair_bsdf");
+ compiler.parameter(this, "component");
+ compiler.add(this, "node_hair_bsdf");
}
/* Geometry */
NODE_DEFINE(GeometryNode)
{
- NodeType* type = NodeType::add("geometry", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("geometry", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_OUT_POINT(position, "Position");
- SOCKET_OUT_NORMAL(normal, "Normal");
- SOCKET_OUT_NORMAL(tangent, "Tangent");
- SOCKET_OUT_NORMAL(true_normal, "True Normal");
- SOCKET_OUT_VECTOR(incoming, "Incoming");
- SOCKET_OUT_POINT(parametric, "Parametric");
- SOCKET_OUT_FLOAT(backfacing, "Backfacing");
- SOCKET_OUT_FLOAT(pointiness, "Pointiness");
+ SOCKET_OUT_POINT(position, "Position");
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_NORMAL(tangent, "Tangent");
+ SOCKET_OUT_NORMAL(true_normal, "True Normal");
+ SOCKET_OUT_VECTOR(incoming, "Incoming");
+ SOCKET_OUT_POINT(parametric, "Parametric");
+ SOCKET_OUT_FLOAT(backfacing, "Backfacing");
+ SOCKET_OUT_FLOAT(pointiness, "Pointiness");
- return type;
+ return type;
}
-GeometryNode::GeometryNode()
-: ShaderNode(node_type)
+GeometryNode::GeometryNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
+ special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
}
void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(!output("Tangent")->links.empty()) {
- attributes->add(ATTR_STD_GENERATED);
- }
- if(!output("Pointiness")->links.empty()) {
- attributes->add(ATTR_STD_POINTINESS);
- }
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void GeometryNode::compile(SVMCompiler& compiler)
-{
- ShaderOutput *out;
- ShaderNodeType geom_node = NODE_GEOMETRY;
- ShaderNodeType attr_node = NODE_ATTR;
-
- if(bump == SHADER_BUMP_DX) {
- geom_node = NODE_GEOMETRY_BUMP_DX;
- attr_node = NODE_ATTR_BUMP_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- geom_node = NODE_GEOMETRY_BUMP_DY;
- attr_node = NODE_ATTR_BUMP_DY;
- }
-
- out = output("Position");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
- }
-
- out = output("Normal");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_N, compiler.stack_assign(out));
- }
-
- out = output("Tangent");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_T, compiler.stack_assign(out));
- }
-
- out = output("True Normal");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_Ng, compiler.stack_assign(out));
- }
-
- out = output("Incoming");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
- }
-
- out = output("Parametric");
- if(!out->links.empty()) {
- compiler.add_node(geom_node, NODE_GEOM_uv, compiler.stack_assign(out));
- }
-
- out = output("Backfacing");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, compiler.stack_assign(out));
- }
-
- out = output("Pointiness");
- if(!out->links.empty()) {
- if(compiler.output_type() != SHADER_TYPE_VOLUME) {
- compiler.add_node(attr_node,
- ATTR_STD_POINTINESS,
- compiler.stack_assign(out),
- NODE_ATTR_FLOAT);
- }
- else {
- compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
- }
- }
-}
-
-void GeometryNode::compile(OSLCompiler& compiler)
-{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
-
- compiler.add(this, "node_geometry");
+ if (shader->has_surface) {
+ if (!output("Tangent")->links.empty()) {
+ attributes->add(ATTR_STD_GENERATED);
+ }
+ if (!output("Pointiness")->links.empty()) {
+ attributes->add(ATTR_STD_POINTINESS);
+ }
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void GeometryNode::compile(SVMCompiler &compiler)
+{
+ ShaderOutput *out;
+ ShaderNodeType geom_node = NODE_GEOMETRY;
+ ShaderNodeType attr_node = NODE_ATTR;
+
+ if (bump == SHADER_BUMP_DX) {
+ geom_node = NODE_GEOMETRY_BUMP_DX;
+ attr_node = NODE_ATTR_BUMP_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ geom_node = NODE_GEOMETRY_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ }
+
+ out = output("Position");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
+ }
+
+ out = output("Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_N, compiler.stack_assign(out));
+ }
+
+ out = output("Tangent");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_T, compiler.stack_assign(out));
+ }
+
+ out = output("True Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_Ng, compiler.stack_assign(out));
+ }
+
+ out = output("Incoming");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
+ }
+
+ out = output("Parametric");
+ if (!out->links.empty()) {
+ compiler.add_node(geom_node, NODE_GEOM_uv, compiler.stack_assign(out));
+ }
+
+ out = output("Backfacing");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_backfacing, compiler.stack_assign(out));
+ }
+
+ out = output("Pointiness");
+ if (!out->links.empty()) {
+ if (compiler.output_type() != SHADER_TYPE_VOLUME) {
+ compiler.add_node(
+ attr_node, ATTR_STD_POINTINESS, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F, __float_as_int(0.0f), compiler.stack_assign(out));
+ }
+ }
+}
+
+void GeometryNode::compile(OSLCompiler &compiler)
+{
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
+
+ compiler.add(this, "node_geometry");
}
int GeometryNode::get_group()
{
- ShaderOutput *out;
- int result = ShaderNode::get_group();
+ ShaderOutput *out;
+ int result = ShaderNode::get_group();
- /* Backfacing uses NODE_LIGHT_PATH */
- out = output("Backfacing");
- if (!out->links.empty()) {
- result = max(result, NODE_GROUP_LEVEL_1);
- }
+ /* Backfacing uses NODE_LIGHT_PATH */
+ out = output("Backfacing");
+ if (!out->links.empty()) {
+ result = max(result, NODE_GROUP_LEVEL_1);
+ }
- return result;
+ return result;
}
/* TextureCoordinate */
NODE_DEFINE(TextureCoordinateNode)
{
- NodeType* type = NodeType::add("texture_coordinate", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("texture_coordinate", create, NodeType::SHADER);
- SOCKET_BOOLEAN(from_dupli, "From Dupli", false);
- SOCKET_BOOLEAN(use_transform, "Use Transform", false);
- SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
+ SOCKET_BOOLEAN(from_dupli, "From Dupli", false);
+ SOCKET_BOOLEAN(use_transform, "Use Transform", false);
+ SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_OUT_POINT(generated, "Generated");
- SOCKET_OUT_NORMAL(normal, "Normal");
- SOCKET_OUT_POINT(UV, "UV");
- SOCKET_OUT_POINT(object, "Object");
- SOCKET_OUT_POINT(camera, "Camera");
- SOCKET_OUT_POINT(window, "Window");
- SOCKET_OUT_NORMAL(reflection, "Reflection");
+ SOCKET_OUT_POINT(generated, "Generated");
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_POINT(UV, "UV");
+ SOCKET_OUT_POINT(object, "Object");
+ SOCKET_OUT_POINT(camera, "Camera");
+ SOCKET_OUT_POINT(window, "Window");
+ SOCKET_OUT_NORMAL(reflection, "Reflection");
- return type;
+ return type;
}
-TextureCoordinateNode::TextureCoordinateNode()
-: ShaderNode(node_type)
+TextureCoordinateNode::TextureCoordinateNode() : ShaderNode(node_type)
{
}
void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(!from_dupli) {
- if(!output("Generated")->links.empty())
- attributes->add(ATTR_STD_GENERATED);
- if(!output("UV")->links.empty())
- attributes->add(ATTR_STD_UV);
- }
- }
-
- if(shader->has_volume) {
- if(!from_dupli) {
- if(!output("Generated")->links.empty()) {
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
- }
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void TextureCoordinateNode::compile(SVMCompiler& compiler)
-{
- ShaderOutput *out;
- ShaderNodeType texco_node = NODE_TEX_COORD;
- ShaderNodeType attr_node = NODE_ATTR;
- ShaderNodeType geom_node = NODE_GEOMETRY;
-
- if(bump == SHADER_BUMP_DX) {
- texco_node = NODE_TEX_COORD_BUMP_DX;
- attr_node = NODE_ATTR_BUMP_DX;
- geom_node = NODE_GEOMETRY_BUMP_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- texco_node = NODE_TEX_COORD_BUMP_DY;
- attr_node = NODE_ATTR_BUMP_DY;
- geom_node = NODE_GEOMETRY_BUMP_DY;
- }
-
- out = output("Generated");
- if(!out->links.empty()) {
- if(compiler.background) {
- compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
- }
- else {
- if(from_dupli) {
- compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, compiler.stack_assign(out));
- }
- else if(compiler.output_type() == SHADER_TYPE_VOLUME) {
- compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, compiler.stack_assign(out));
- }
- else {
- int attr = compiler.attribute(ATTR_STD_GENERATED);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
- }
- }
- }
-
- out = output("Normal");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_NORMAL, compiler.stack_assign(out));
- }
-
- out = output("UV");
- if(!out->links.empty()) {
- if(from_dupli) {
- compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
- }
- else {
- int attr = compiler.attribute(ATTR_STD_UV);
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
- }
- }
-
- out = output("Object");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_OBJECT, compiler.stack_assign(out), use_transform);
- if(use_transform) {
- Transform ob_itfm = transform_inverse(ob_tfm);
- compiler.add_node(ob_itfm.x);
- compiler.add_node(ob_itfm.y);
- compiler.add_node(ob_itfm.z);
- }
- }
-
- out = output("Camera");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_CAMERA, compiler.stack_assign(out));
- }
-
- out = output("Window");
- if(!out->links.empty()) {
- compiler.add_node(texco_node, NODE_TEXCO_WINDOW, compiler.stack_assign(out));
- }
-
- out = output("Reflection");
- if(!out->links.empty()) {
- if(compiler.background) {
- compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
- }
- else {
- compiler.add_node(texco_node, NODE_TEXCO_REFLECTION, compiler.stack_assign(out));
- }
- }
-}
-
-void TextureCoordinateNode::compile(OSLCompiler& compiler)
-{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
-
- if(compiler.background)
- compiler.parameter("is_background", true);
- if(compiler.output_type() == SHADER_TYPE_VOLUME)
- compiler.parameter("is_volume", true);
- compiler.parameter(this, "use_transform");
- Transform ob_itfm = transform_inverse(ob_tfm);
- compiler.parameter("object_itfm", ob_itfm);
-
- compiler.parameter(this, "from_dupli");
-
- compiler.add(this, "node_texture_coordinate");
+ if (shader->has_surface) {
+ if (!from_dupli) {
+ if (!output("Generated")->links.empty())
+ attributes->add(ATTR_STD_GENERATED);
+ if (!output("UV")->links.empty())
+ attributes->add(ATTR_STD_UV);
+ }
+ }
+
+ if (shader->has_volume) {
+ if (!from_dupli) {
+ if (!output("Generated")->links.empty()) {
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
+ }
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void TextureCoordinateNode::compile(SVMCompiler &compiler)
+{
+ ShaderOutput *out;
+ ShaderNodeType texco_node = NODE_TEX_COORD;
+ ShaderNodeType attr_node = NODE_ATTR;
+ ShaderNodeType geom_node = NODE_GEOMETRY;
+
+ if (bump == SHADER_BUMP_DX) {
+ texco_node = NODE_TEX_COORD_BUMP_DX;
+ attr_node = NODE_ATTR_BUMP_DX;
+ geom_node = NODE_GEOMETRY_BUMP_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ texco_node = NODE_TEX_COORD_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ geom_node = NODE_GEOMETRY_BUMP_DY;
+ }
+
+ out = output("Generated");
+ if (!out->links.empty()) {
+ if (compiler.background) {
+ compiler.add_node(geom_node, NODE_GEOM_P, compiler.stack_assign(out));
+ }
+ else {
+ if (from_dupli) {
+ compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, compiler.stack_assign(out));
+ }
+ else if (compiler.output_type() == SHADER_TYPE_VOLUME) {
+ compiler.add_node(texco_node, NODE_TEXCO_VOLUME_GENERATED, compiler.stack_assign(out));
+ }
+ else {
+ int attr = compiler.attribute(ATTR_STD_GENERATED);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ }
+ }
+ }
+
+ out = output("Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_NORMAL, compiler.stack_assign(out));
+ }
+
+ out = output("UV");
+ if (!out->links.empty()) {
+ if (from_dupli) {
+ compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
+ }
+ else {
+ int attr = compiler.attribute(ATTR_STD_UV);
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ }
+ }
+
+ out = output("Object");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_OBJECT, compiler.stack_assign(out), use_transform);
+ if (use_transform) {
+ Transform ob_itfm = transform_inverse(ob_tfm);
+ compiler.add_node(ob_itfm.x);
+ compiler.add_node(ob_itfm.y);
+ compiler.add_node(ob_itfm.z);
+ }
+ }
+
+ out = output("Camera");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_CAMERA, compiler.stack_assign(out));
+ }
+
+ out = output("Window");
+ if (!out->links.empty()) {
+ compiler.add_node(texco_node, NODE_TEXCO_WINDOW, compiler.stack_assign(out));
+ }
+
+ out = output("Reflection");
+ if (!out->links.empty()) {
+ if (compiler.background) {
+ compiler.add_node(geom_node, NODE_GEOM_I, compiler.stack_assign(out));
+ }
+ else {
+ compiler.add_node(texco_node, NODE_TEXCO_REFLECTION, compiler.stack_assign(out));
+ }
+ }
+}
+
+void TextureCoordinateNode::compile(OSLCompiler &compiler)
+{
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
+
+ if (compiler.background)
+ compiler.parameter("is_background", true);
+ if (compiler.output_type() == SHADER_TYPE_VOLUME)
+ compiler.parameter("is_volume", true);
+ compiler.parameter(this, "use_transform");
+ Transform ob_itfm = transform_inverse(ob_tfm);
+ compiler.parameter("object_itfm", ob_itfm);
+
+ compiler.parameter(this, "from_dupli");
+
+ compiler.add(this, "node_texture_coordinate");
}
/* UV Map */
NODE_DEFINE(UVMapNode)
{
- NodeType* type = NodeType::add("uvmap", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("uvmap", create, NodeType::SHADER);
- SOCKET_STRING(attribute, "attribute", ustring());
- SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
+ SOCKET_STRING(attribute, "attribute", ustring());
+ SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
- SOCKET_OUT_POINT(UV, "UV");
+ SOCKET_OUT_POINT(UV, "UV");
- return type;
+ return type;
}
-UVMapNode::UVMapNode()
-: ShaderNode(node_type)
+UVMapNode::UVMapNode() : ShaderNode(node_type)
{
}
void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(!from_dupli) {
- if(!output("UV")->links.empty()) {
- if(attribute != "")
- attributes->add(attribute);
- else
- attributes->add(ATTR_STD_UV);
- }
- }
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void UVMapNode::compile(SVMCompiler& compiler)
-{
- ShaderOutput *out = output("UV");
- ShaderNodeType texco_node = NODE_TEX_COORD;
- ShaderNodeType attr_node = NODE_ATTR;
- int attr;
-
- if(bump == SHADER_BUMP_DX) {
- texco_node = NODE_TEX_COORD_BUMP_DX;
- attr_node = NODE_ATTR_BUMP_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- texco_node = NODE_TEX_COORD_BUMP_DY;
- attr_node = NODE_ATTR_BUMP_DY;
- }
-
- if(!out->links.empty()) {
- if(from_dupli) {
- compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
- }
- else {
- if(attribute != "")
- attr = compiler.attribute(attribute);
- else
- attr = compiler.attribute(ATTR_STD_UV);
-
- compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
- }
- }
-}
-
-void UVMapNode::compile(OSLCompiler& compiler)
-{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
-
- compiler.parameter(this, "from_dupli");
- compiler.parameter(this, "attribute");
- compiler.add(this, "node_uv_map");
+ if (shader->has_surface) {
+ if (!from_dupli) {
+ if (!output("UV")->links.empty()) {
+ if (attribute != "")
+ attributes->add(attribute);
+ else
+ attributes->add(ATTR_STD_UV);
+ }
+ }
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void UVMapNode::compile(SVMCompiler &compiler)
+{
+ ShaderOutput *out = output("UV");
+ ShaderNodeType texco_node = NODE_TEX_COORD;
+ ShaderNodeType attr_node = NODE_ATTR;
+ int attr;
+
+ if (bump == SHADER_BUMP_DX) {
+ texco_node = NODE_TEX_COORD_BUMP_DX;
+ attr_node = NODE_ATTR_BUMP_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ texco_node = NODE_TEX_COORD_BUMP_DY;
+ attr_node = NODE_ATTR_BUMP_DY;
+ }
+
+ if (!out->links.empty()) {
+ if (from_dupli) {
+ compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, compiler.stack_assign(out));
+ }
+ else {
+ if (attribute != "")
+ attr = compiler.attribute(attribute);
+ else
+ attr = compiler.attribute(ATTR_STD_UV);
+
+ compiler.add_node(attr_node, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT3);
+ }
+ }
+}
+
+void UVMapNode::compile(OSLCompiler &compiler)
+{
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
+
+ compiler.parameter(this, "from_dupli");
+ compiler.parameter(this, "attribute");
+ compiler.add(this, "node_uv_map");
}
/* Light Path */
NODE_DEFINE(LightPathNode)
{
- NodeType* type = NodeType::add("light_path", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("light_path", create, NodeType::SHADER);
- SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
- SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
- SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
- SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
- SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
- SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
- SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray");
- SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray");
- SOCKET_OUT_FLOAT(ray_length, "Ray Length");
- SOCKET_OUT_FLOAT(ray_depth, "Ray Depth");
- SOCKET_OUT_FLOAT(diffuse_depth, "Diffuse Depth");
- SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth");
- SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth");
- SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
+ SOCKET_OUT_FLOAT(is_camera_ray, "Is Camera Ray");
+ SOCKET_OUT_FLOAT(is_shadow_ray, "Is Shadow Ray");
+ SOCKET_OUT_FLOAT(is_diffuse_ray, "Is Diffuse Ray");
+ SOCKET_OUT_FLOAT(is_glossy_ray, "Is Glossy Ray");
+ SOCKET_OUT_FLOAT(is_singular_ray, "Is Singular Ray");
+ SOCKET_OUT_FLOAT(is_reflection_ray, "Is Reflection Ray");
+ SOCKET_OUT_FLOAT(is_transmission_ray, "Is Transmission Ray");
+ SOCKET_OUT_FLOAT(is_volume_scatter_ray, "Is Volume Scatter Ray");
+ SOCKET_OUT_FLOAT(ray_length, "Ray Length");
+ SOCKET_OUT_FLOAT(ray_depth, "Ray Depth");
+ SOCKET_OUT_FLOAT(diffuse_depth, "Diffuse Depth");
+ SOCKET_OUT_FLOAT(glossy_depth, "Glossy Depth");
+ SOCKET_OUT_FLOAT(transparent_depth, "Transparent Depth");
+ SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
- return type;
+ return type;
}
-LightPathNode::LightPathNode()
-: ShaderNode(node_type)
+LightPathNode::LightPathNode() : ShaderNode(node_type)
{
}
-void LightPathNode::compile(SVMCompiler& compiler)
+void LightPathNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out;
-
- out = output("Is Camera Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_camera, compiler.stack_assign(out));
- }
+ ShaderOutput *out;
- out = output("Is Shadow Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_shadow, compiler.stack_assign(out));
- }
+ out = output("Is Camera Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_camera, compiler.stack_assign(out));
+ }
- out = output("Is Diffuse Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_diffuse, compiler.stack_assign(out));
- }
+ out = output("Is Shadow Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_shadow, compiler.stack_assign(out));
+ }
- out = output("Is Glossy Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, compiler.stack_assign(out));
- }
+ out = output("Is Diffuse Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_diffuse, compiler.stack_assign(out));
+ }
- out = output("Is Singular Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, compiler.stack_assign(out));
- }
+ out = output("Is Glossy Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_glossy, compiler.stack_assign(out));
+ }
- out = output("Is Reflection Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, compiler.stack_assign(out));
- }
+ out = output("Is Singular Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_singular, compiler.stack_assign(out));
+ }
+ out = output("Is Reflection Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_reflection, compiler.stack_assign(out));
+ }
- out = output("Is Transmission Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, compiler.stack_assign(out));
- }
+ out = output("Is Transmission Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_transmission, compiler.stack_assign(out));
+ }
- out = output("Is Volume Scatter Ray");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, compiler.stack_assign(out));
- }
+ out = output("Is Volume Scatter Ray");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_volume_scatter, compiler.stack_assign(out));
+ }
- out = output("Ray Length");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, compiler.stack_assign(out));
- }
+ out = output("Ray Length");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_length, compiler.stack_assign(out));
+ }
- out = output("Ray Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, compiler.stack_assign(out));
- }
+ out = output("Ray Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_depth, compiler.stack_assign(out));
+ }
- out = output("Diffuse Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_diffuse, compiler.stack_assign(out));
- }
+ out = output("Diffuse Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_diffuse, compiler.stack_assign(out));
+ }
- out = output("Glossy Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_glossy, compiler.stack_assign(out));
- }
+ out = output("Glossy Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_glossy, compiler.stack_assign(out));
+ }
- out = output("Transparent Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, compiler.stack_assign(out));
- }
+ out = output("Transparent Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transparent, compiler.stack_assign(out));
+ }
- out = output("Transmission Depth");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out));
- }
+ out = output("Transmission Depth");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_PATH, NODE_LP_ray_transmission, compiler.stack_assign(out));
+ }
}
-void LightPathNode::compile(OSLCompiler& compiler)
+void LightPathNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_light_path");
+ compiler.add(this, "node_light_path");
}
/* Light Falloff */
NODE_DEFINE(LightFalloffNode)
{
- NodeType* type = NodeType::add("light_falloff", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("light_falloff", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(strength, "Strength", 100.0f);
- SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
+ SOCKET_IN_FLOAT(strength, "Strength", 100.0f);
+ SOCKET_IN_FLOAT(smooth, "Smooth", 0.0f);
- SOCKET_OUT_FLOAT(quadratic, "Quadratic");
- SOCKET_OUT_FLOAT(linear, "Linear");
- SOCKET_OUT_FLOAT(constant, "Constant");
+ SOCKET_OUT_FLOAT(quadratic, "Quadratic");
+ SOCKET_OUT_FLOAT(linear, "Linear");
+ SOCKET_OUT_FLOAT(constant, "Constant");
- return type;
+ return type;
}
-LightFalloffNode::LightFalloffNode()
-: ShaderNode(node_type)
+LightFalloffNode::LightFalloffNode() : ShaderNode(node_type)
{
}
-void LightFalloffNode::compile(SVMCompiler& compiler)
+void LightFalloffNode::compile(SVMCompiler &compiler)
{
- ShaderInput *strength_in = input("Strength");
- ShaderInput *smooth_in = input("Smooth");
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *smooth_in = input("Smooth");
- ShaderOutput *out = output("Quadratic");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_QUADRATIC,
- compiler.encode_uchar4(
- compiler.stack_assign(strength_in),
- compiler.stack_assign(smooth_in),
- compiler.stack_assign(out)));
- }
+ ShaderOutput *out = output("Quadratic");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_FALLOFF,
+ NODE_LIGHT_FALLOFF_QUADRATIC,
+ compiler.encode_uchar4(compiler.stack_assign(strength_in),
+ compiler.stack_assign(smooth_in),
+ compiler.stack_assign(out)));
+ }
- out = output("Linear");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_LINEAR,
- compiler.encode_uchar4(
- compiler.stack_assign(strength_in),
- compiler.stack_assign(smooth_in),
- compiler.stack_assign(out)));
- }
+ out = output("Linear");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_FALLOFF,
+ NODE_LIGHT_FALLOFF_LINEAR,
+ compiler.encode_uchar4(compiler.stack_assign(strength_in),
+ compiler.stack_assign(smooth_in),
+ compiler.stack_assign(out)));
+ }
- out = output("Constant");
- if(!out->links.empty()) {
- compiler.add_node(NODE_LIGHT_FALLOFF, NODE_LIGHT_FALLOFF_CONSTANT,
- compiler.encode_uchar4(
- compiler.stack_assign(strength_in),
- compiler.stack_assign(smooth_in),
- compiler.stack_assign(out)));
- }
+ out = output("Constant");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_LIGHT_FALLOFF,
+ NODE_LIGHT_FALLOFF_CONSTANT,
+ compiler.encode_uchar4(compiler.stack_assign(strength_in),
+ compiler.stack_assign(smooth_in),
+ compiler.stack_assign(out)));
+ }
}
-void LightFalloffNode::compile(OSLCompiler& compiler)
+void LightFalloffNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_light_falloff");
+ compiler.add(this, "node_light_falloff");
}
/* Object Info */
NODE_DEFINE(ObjectInfoNode)
{
- NodeType* type = NodeType::add("object_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("object_info", create, NodeType::SHADER);
- SOCKET_OUT_VECTOR(location, "Location");
- SOCKET_OUT_FLOAT(object_index, "Object Index");
- SOCKET_OUT_FLOAT(material_index, "Material Index");
- SOCKET_OUT_FLOAT(random, "Random");
+ SOCKET_OUT_VECTOR(location, "Location");
+ SOCKET_OUT_FLOAT(object_index, "Object Index");
+ SOCKET_OUT_FLOAT(material_index, "Material Index");
+ SOCKET_OUT_FLOAT(random, "Random");
- return type;
+ return type;
}
-ObjectInfoNode::ObjectInfoNode()
-: ShaderNode(node_type)
+ObjectInfoNode::ObjectInfoNode() : ShaderNode(node_type)
{
}
-void ObjectInfoNode::compile(SVMCompiler& compiler)
+void ObjectInfoNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out = output("Location");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, compiler.stack_assign(out));
- }
+ ShaderOutput *out = output("Location");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_LOCATION, compiler.stack_assign(out));
+ }
- out = output("Object Index");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
- }
+ out = output("Object Index");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_INDEX, compiler.stack_assign(out));
+ }
- out = output("Material Index");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, compiler.stack_assign(out));
- }
+ out = output("Material Index");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_MAT_INDEX, compiler.stack_assign(out));
+ }
- out = output("Random");
- if(!out->links.empty()) {
- compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, compiler.stack_assign(out));
- }
+ out = output("Random");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_OBJECT_INFO, NODE_INFO_OB_RANDOM, compiler.stack_assign(out));
+ }
}
-void ObjectInfoNode::compile(OSLCompiler& compiler)
+void ObjectInfoNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_object_info");
+ compiler.add(this, "node_object_info");
}
/* Particle Info */
NODE_DEFINE(ParticleInfoNode)
{
- NodeType* type = NodeType::add("particle_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("particle_info", create, NodeType::SHADER);
- SOCKET_OUT_FLOAT(index, "Index");
- SOCKET_OUT_FLOAT(random, "Random");
- SOCKET_OUT_FLOAT(age, "Age");
- SOCKET_OUT_FLOAT(lifetime, "Lifetime");
- SOCKET_OUT_POINT(location, "Location");
-#if 0 /* not yet supported */
- SOCKET_OUT_QUATERNION(rotation, "Rotation");
+ SOCKET_OUT_FLOAT(index, "Index");
+ SOCKET_OUT_FLOAT(random, "Random");
+ SOCKET_OUT_FLOAT(age, "Age");
+ SOCKET_OUT_FLOAT(lifetime, "Lifetime");
+ SOCKET_OUT_POINT(location, "Location");
+#if 0 /* not yet supported */
+ SOCKET_OUT_QUATERNION(rotation, "Rotation");
#endif
- SOCKET_OUT_FLOAT(size, "Size");
- SOCKET_OUT_VECTOR(velocity, "Velocity");
- SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
+ SOCKET_OUT_FLOAT(size, "Size");
+ SOCKET_OUT_VECTOR(velocity, "Velocity");
+ SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
- return type;
+ return type;
}
-ParticleInfoNode::ParticleInfoNode()
-: ShaderNode(node_type)
+ParticleInfoNode::ParticleInfoNode() : ShaderNode(node_type)
{
}
void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(!output("Index")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Random")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Age")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Lifetime")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Location")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
-#if 0 /* not yet supported */
- if(!output("Rotation")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Index")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Random")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Age")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Lifetime")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Location")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+#if 0 /* not yet supported */
+ if(!output("Rotation")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
#endif
- if(!output("Size")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Velocity")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
- if(!output("Angular Velocity")->links.empty())
- attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Size")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Velocity")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
+ if (!output("Angular Velocity")->links.empty())
+ attributes->add(ATTR_STD_PARTICLE);
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void ParticleInfoNode::compile(SVMCompiler& compiler)
+void ParticleInfoNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out;
+ ShaderOutput *out;
- out = output("Index");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
- }
+ out = output("Index");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_INDEX, compiler.stack_assign(out));
+ }
- out = output("Random");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
- }
+ out = output("Random");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_RANDOM, compiler.stack_assign(out));
+ }
- out = output("Age");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, compiler.stack_assign(out));
- }
+ out = output("Age");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_AGE, compiler.stack_assign(out));
+ }
- out = output("Lifetime");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, compiler.stack_assign(out));
- }
+ out = output("Lifetime");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LIFETIME, compiler.stack_assign(out));
+ }
- out = output("Location");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, compiler.stack_assign(out));
- }
+ out = output("Location");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, compiler.stack_assign(out));
+ }
- /* quaternion data is not yet supported by Cycles */
+ /* quaternion data is not yet supported by Cycles */
#if 0
- out = output("Rotation");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, compiler.stack_assign(out));
- }
+ out = output("Rotation");
+ if(!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, compiler.stack_assign(out));
+ }
#endif
- out = output("Size");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, compiler.stack_assign(out));
- }
+ out = output("Size");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_SIZE, compiler.stack_assign(out));
+ }
- out = output("Velocity");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, compiler.stack_assign(out));
- }
+ out = output("Velocity");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_VELOCITY, compiler.stack_assign(out));
+ }
- out = output("Angular Velocity");
- if(!out->links.empty()) {
- compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, compiler.stack_assign(out));
- }
+ out = output("Angular Velocity");
+ if (!out->links.empty()) {
+ compiler.add_node(
+ NODE_PARTICLE_INFO, NODE_INFO_PAR_ANGULAR_VELOCITY, compiler.stack_assign(out));
+ }
}
-void ParticleInfoNode::compile(OSLCompiler& compiler)
+void ParticleInfoNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_particle_info");
+ compiler.add(this, "node_particle_info");
}
/* Hair Info */
NODE_DEFINE(HairInfoNode)
{
- NodeType* type = NodeType::add("hair_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("hair_info", create, NodeType::SHADER);
- SOCKET_OUT_FLOAT(is_strand, "Is Strand");
- SOCKET_OUT_FLOAT(intercept, "Intercept");
- SOCKET_OUT_FLOAT(thickness, "Thickness");
- SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
+ SOCKET_OUT_FLOAT(is_strand, "Is Strand");
+ SOCKET_OUT_FLOAT(intercept, "Intercept");
+ SOCKET_OUT_FLOAT(thickness, "Thickness");
+ SOCKET_OUT_NORMAL(tangent_normal, "Tangent Normal");
#if 0 /*output for minimum hair width transparency - deactivated */
- SOCKET_OUT_FLOAT(fade, "Fade");
+ SOCKET_OUT_FLOAT(fade, "Fade");
#endif
- SOCKET_OUT_FLOAT(index, "Random");
+ SOCKET_OUT_FLOAT(index, "Random");
- return type;
+ return type;
}
-HairInfoNode::HairInfoNode()
-: ShaderNode(node_type)
+HairInfoNode::HairInfoNode() : ShaderNode(node_type)
{
}
void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- ShaderOutput *intercept_out = output("Intercept");
+ if (shader->has_surface) {
+ ShaderOutput *intercept_out = output("Intercept");
- if(!intercept_out->links.empty())
- attributes->add(ATTR_STD_CURVE_INTERCEPT);
+ if (!intercept_out->links.empty())
+ attributes->add(ATTR_STD_CURVE_INTERCEPT);
- if(!output("Random")->links.empty())
- attributes->add(ATTR_STD_CURVE_RANDOM);
- }
+ if (!output("Random")->links.empty())
+ attributes->add(ATTR_STD_CURVE_RANDOM);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void HairInfoNode::compile(SVMCompiler& compiler)
+void HairInfoNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *out;
+ ShaderOutput *out;
- out = output("Is Strand");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, compiler.stack_assign(out));
- }
+ out = output("Is Strand");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_IS_STRAND, compiler.stack_assign(out));
+ }
- out = output("Intercept");
- if(!out->links.empty()) {
- int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
- compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
- }
+ out = output("Intercept");
+ if (!out->links.empty()) {
+ int attr = compiler.attribute(ATTR_STD_CURVE_INTERCEPT);
+ compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ }
- out = output("Thickness");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, compiler.stack_assign(out));
- }
+ out = output("Thickness");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_THICKNESS, compiler.stack_assign(out));
+ }
- out = output("Tangent Normal");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
- }
+ out = output("Tangent Normal");
+ if (!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_TANGENT_NORMAL, compiler.stack_assign(out));
+ }
- /*out = output("Fade");
- if(!out->links.empty()) {
- compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
- }*/
+ /*out = output("Fade");
+ if(!out->links.empty()) {
+ compiler.add_node(NODE_HAIR_INFO, NODE_INFO_CURVE_FADE, compiler.stack_assign(out));
+ }*/
- out = output("Random");
- if(!out->links.empty()) {
- int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
- compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
- }
+ out = output("Random");
+ if (!out->links.empty()) {
+ int attr = compiler.attribute(ATTR_STD_CURVE_RANDOM);
+ compiler.add_node(NODE_ATTR, attr, compiler.stack_assign(out), NODE_ATTR_FLOAT);
+ }
}
-void HairInfoNode::compile(OSLCompiler& compiler)
+void HairInfoNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_hair_info");
+ compiler.add(this, "node_hair_info");
}
/* Value */
NODE_DEFINE(ValueNode)
{
- NodeType* type = NodeType::add("value", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("value", create, NodeType::SHADER);
- SOCKET_FLOAT(value, "Value", 0.0f);
- SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_FLOAT(value, "Value", 0.0f);
+ SOCKET_OUT_FLOAT(value, "Value");
- return type;
+ return type;
}
-ValueNode::ValueNode()
-: ShaderNode(node_type)
+ValueNode::ValueNode() : ShaderNode(node_type)
{
}
-void ValueNode::constant_fold(const ConstantFolder& folder)
+void ValueNode::constant_fold(const ConstantFolder &folder)
{
- folder.make_constant(value);
+ folder.make_constant(value);
}
-void ValueNode::compile(SVMCompiler& compiler)
+void ValueNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *val_out = output("Value");
+ ShaderOutput *val_out = output("Value");
- compiler.add_node(NODE_VALUE_F, __float_as_int(value), compiler.stack_assign(val_out));
+ compiler.add_node(NODE_VALUE_F, __float_as_int(value), compiler.stack_assign(val_out));
}
-void ValueNode::compile(OSLCompiler& compiler)
+void ValueNode::compile(OSLCompiler &compiler)
{
- compiler.parameter("value_value", value);
- compiler.add(this, "node_value");
+ compiler.parameter("value_value", value);
+ compiler.add(this, "node_value");
}
/* Color */
NODE_DEFINE(ColorNode)
{
- NodeType* type = NodeType::add("color", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("color", create, NodeType::SHADER);
- SOCKET_COLOR(value, "Value", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_COLOR(value, "Value", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-ColorNode::ColorNode()
-: ShaderNode(node_type)
+ColorNode::ColorNode() : ShaderNode(node_type)
{
}
-void ColorNode::constant_fold(const ConstantFolder& folder)
+void ColorNode::constant_fold(const ConstantFolder &folder)
{
- folder.make_constant(value);
+ folder.make_constant(value);
}
-void ColorNode::compile(SVMCompiler& compiler)
+void ColorNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *color_out = output("Color");
+ ShaderOutput *color_out = output("Color");
- if(!color_out->links.empty()) {
- compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
- compiler.add_node(NODE_VALUE_V, value);
- }
+ if (!color_out->links.empty()) {
+ compiler.add_node(NODE_VALUE_V, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_VALUE_V, value);
+ }
}
-void ColorNode::compile(OSLCompiler& compiler)
+void ColorNode::compile(OSLCompiler &compiler)
{
- compiler.parameter_color("color_value", value);
+ compiler.parameter_color("color_value", value);
- compiler.add(this, "node_value");
+ compiler.add(this, "node_value");
}
/* Add Closure */
NODE_DEFINE(AddClosureNode)
{
- NodeType* type = NodeType::add("add_closure", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("add_closure", create, NodeType::SHADER);
- SOCKET_IN_CLOSURE(closure1, "Closure1");
- SOCKET_IN_CLOSURE(closure2, "Closure2");
- SOCKET_OUT_CLOSURE(closure, "Closure");
+ SOCKET_IN_CLOSURE(closure1, "Closure1");
+ SOCKET_IN_CLOSURE(closure2, "Closure2");
+ SOCKET_OUT_CLOSURE(closure, "Closure");
- return type;
+ return type;
}
-AddClosureNode::AddClosureNode()
-: ShaderNode(node_type)
+AddClosureNode::AddClosureNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
+ special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
}
-void AddClosureNode::compile(SVMCompiler& /*compiler*/)
+void AddClosureNode::compile(SVMCompiler & /*compiler*/)
{
- /* handled in the SVM compiler */
+ /* handled in the SVM compiler */
}
-void AddClosureNode::compile(OSLCompiler& compiler)
+void AddClosureNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_add_closure");
+ compiler.add(this, "node_add_closure");
}
-void AddClosureNode::constant_fold(const ConstantFolder& folder)
+void AddClosureNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *closure1_in = input("Closure1");
- ShaderInput *closure2_in = input("Closure2");
+ ShaderInput *closure1_in = input("Closure1");
+ ShaderInput *closure2_in = input("Closure2");
- /* remove useless add closures nodes */
- if(!closure1_in->link) {
- folder.bypass_or_discard(closure2_in);
- }
- else if(!closure2_in->link) {
- folder.bypass_or_discard(closure1_in);
- }
+ /* remove useless add closures nodes */
+ if (!closure1_in->link) {
+ folder.bypass_or_discard(closure2_in);
+ }
+ else if (!closure2_in->link) {
+ folder.bypass_or_discard(closure1_in);
+ }
}
/* Mix Closure */
NODE_DEFINE(MixClosureNode)
{
- NodeType* type = NodeType::add("mix_closure", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mix_closure", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
- SOCKET_IN_CLOSURE(closure1, "Closure1");
- SOCKET_IN_CLOSURE(closure2, "Closure2");
+ SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
+ SOCKET_IN_CLOSURE(closure1, "Closure1");
+ SOCKET_IN_CLOSURE(closure2, "Closure2");
- SOCKET_OUT_CLOSURE(closure, "Closure");
+ SOCKET_OUT_CLOSURE(closure, "Closure");
- return type;
+ return type;
}
-MixClosureNode::MixClosureNode()
-: ShaderNode(node_type)
+MixClosureNode::MixClosureNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
+ special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
}
-void MixClosureNode::compile(SVMCompiler& /*compiler*/)
+void MixClosureNode::compile(SVMCompiler & /*compiler*/)
{
- /* handled in the SVM compiler */
+ /* handled in the SVM compiler */
}
-void MixClosureNode::compile(OSLCompiler& compiler)
+void MixClosureNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_mix_closure");
+ compiler.add(this, "node_mix_closure");
}
-void MixClosureNode::constant_fold(const ConstantFolder& folder)
+void MixClosureNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *closure1_in = input("Closure1");
- ShaderInput *closure2_in = input("Closure2");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *closure1_in = input("Closure1");
+ ShaderInput *closure2_in = input("Closure2");
- /* remove useless mix closures nodes */
- if(closure1_in->link == closure2_in->link) {
- folder.bypass_or_discard(closure1_in);
- }
- /* remove unused mix closure input when factor is 0.0 or 1.0
- * check for closure links and make sure factor link is disconnected */
- else if(!fac_in->link) {
- /* factor 0.0 */
- if(fac <= 0.0f) {
- folder.bypass_or_discard(closure1_in);
- }
- /* factor 1.0 */
- else if(fac >= 1.0f) {
- folder.bypass_or_discard(closure2_in);
- }
- }
+ /* remove useless mix closures nodes */
+ if (closure1_in->link == closure2_in->link) {
+ folder.bypass_or_discard(closure1_in);
+ }
+ /* remove unused mix closure input when factor is 0.0 or 1.0
+ * check for closure links and make sure factor link is disconnected */
+ else if (!fac_in->link) {
+ /* factor 0.0 */
+ if (fac <= 0.0f) {
+ folder.bypass_or_discard(closure1_in);
+ }
+ /* factor 1.0 */
+ else if (fac >= 1.0f) {
+ folder.bypass_or_discard(closure2_in);
+ }
+ }
}
/* Mix Closure */
NODE_DEFINE(MixClosureWeightNode)
{
- NodeType* type = NodeType::add("mix_closure_weight", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mix_closure_weight", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(weight, "Weight", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
+ SOCKET_IN_FLOAT(weight, "Weight", 1.0f);
+ SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
- SOCKET_OUT_FLOAT(weight1, "Weight1");
- SOCKET_OUT_FLOAT(weight2, "Weight2");
+ SOCKET_OUT_FLOAT(weight1, "Weight1");
+ SOCKET_OUT_FLOAT(weight2, "Weight2");
- return type;
+ return type;
}
-MixClosureWeightNode::MixClosureWeightNode()
-: ShaderNode(node_type)
+MixClosureWeightNode::MixClosureWeightNode() : ShaderNode(node_type)
{
}
-void MixClosureWeightNode::compile(SVMCompiler& compiler)
+void MixClosureWeightNode::compile(SVMCompiler &compiler)
{
- ShaderInput *weight_in = input("Weight");
- ShaderInput *fac_in = input("Fac");
- ShaderOutput *weight1_out = output("Weight1");
- ShaderOutput *weight2_out = output("Weight2");
+ ShaderInput *weight_in = input("Weight");
+ ShaderInput *fac_in = input("Fac");
+ ShaderOutput *weight1_out = output("Weight1");
+ ShaderOutput *weight2_out = output("Weight2");
- compiler.add_node(NODE_MIX_CLOSURE,
- compiler.encode_uchar4(
- compiler.stack_assign(fac_in),
- compiler.stack_assign(weight_in),
- compiler.stack_assign(weight1_out),
- compiler.stack_assign(weight2_out)));
+ compiler.add_node(NODE_MIX_CLOSURE,
+ compiler.encode_uchar4(compiler.stack_assign(fac_in),
+ compiler.stack_assign(weight_in),
+ compiler.stack_assign(weight1_out),
+ compiler.stack_assign(weight2_out)));
}
-void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/)
+void MixClosureWeightNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* Invert */
NODE_DEFINE(InvertNode)
{
- NodeType* type = NodeType::add("invert", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("invert", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-InvertNode::InvertNode()
-: ShaderNode(node_type)
+InvertNode::InvertNode() : ShaderNode(node_type)
{
}
-void InvertNode::constant_fold(const ConstantFolder& folder)
+void InvertNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color_in = input("Color");
- if(!fac_in->link) {
- /* evaluate fully constant node */
- if(!color_in->link) {
- folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
- }
- /* remove no-op node */
- else if(fac == 0.0f) {
- folder.bypass(color_in->link);
- }
- }
+ if (!fac_in->link) {
+ /* evaluate fully constant node */
+ if (!color_in->link) {
+ folder.make_constant(interp(color, make_float3(1.0f, 1.0f, 1.0f) - color, fac));
+ }
+ /* remove no-op node */
+ else if (fac == 0.0f) {
+ folder.bypass(color_in->link);
+ }
+ }
}
-void InvertNode::compile(SVMCompiler& compiler)
+void InvertNode::compile(SVMCompiler &compiler)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_INVERT,
- compiler.stack_assign(fac_in),
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(NODE_INVERT,
+ compiler.stack_assign(fac_in),
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out));
}
-void InvertNode::compile(OSLCompiler& compiler)
+void InvertNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_invert");
+ compiler.add(this, "node_invert");
}
/* Mix */
NODE_DEFINE(MixNode)
{
- NodeType* type = NodeType::add("mix", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("mix", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("mix", NODE_MIX_BLEND);
- type_enum.insert("add", NODE_MIX_ADD);
- type_enum.insert("multiply", NODE_MIX_MUL);
- type_enum.insert("screen", NODE_MIX_SCREEN);
- type_enum.insert("overlay", NODE_MIX_OVERLAY);
- type_enum.insert("subtract", NODE_MIX_SUB);
- type_enum.insert("divide", NODE_MIX_DIV);
- type_enum.insert("difference", NODE_MIX_DIFF);
- type_enum.insert("darken", NODE_MIX_DARK);
- type_enum.insert("lighten", NODE_MIX_LIGHT);
- type_enum.insert("dodge", NODE_MIX_DODGE);
- type_enum.insert("burn", NODE_MIX_BURN);
- type_enum.insert("hue", NODE_MIX_HUE);
- type_enum.insert("saturation", NODE_MIX_SAT);
- type_enum.insert("value", NODE_MIX_VAL);
- type_enum.insert("color", NODE_MIX_COLOR);
- type_enum.insert("soft_light", NODE_MIX_SOFT);
- type_enum.insert("linear_light", NODE_MIX_LINEAR);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND);
+ static NodeEnum type_enum;
+ type_enum.insert("mix", NODE_MIX_BLEND);
+ type_enum.insert("add", NODE_MIX_ADD);
+ type_enum.insert("multiply", NODE_MIX_MUL);
+ type_enum.insert("screen", NODE_MIX_SCREEN);
+ type_enum.insert("overlay", NODE_MIX_OVERLAY);
+ type_enum.insert("subtract", NODE_MIX_SUB);
+ type_enum.insert("divide", NODE_MIX_DIV);
+ type_enum.insert("difference", NODE_MIX_DIFF);
+ type_enum.insert("darken", NODE_MIX_DARK);
+ type_enum.insert("lighten", NODE_MIX_LIGHT);
+ type_enum.insert("dodge", NODE_MIX_DODGE);
+ type_enum.insert("burn", NODE_MIX_BURN);
+ type_enum.insert("hue", NODE_MIX_HUE);
+ type_enum.insert("saturation", NODE_MIX_SAT);
+ type_enum.insert("value", NODE_MIX_VAL);
+ type_enum.insert("color", NODE_MIX_COLOR);
+ type_enum.insert("soft_light", NODE_MIX_SOFT);
+ type_enum.insert("linear_light", NODE_MIX_LINEAR);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MIX_BLEND);
- SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
+ SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
- SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
- SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 0.5f);
+ SOCKET_IN_COLOR(color1, "Color1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color2, "Color2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-MixNode::MixNode()
-: ShaderNode(node_type)
+MixNode::MixNode() : ShaderNode(node_type)
{
}
-void MixNode::compile(SVMCompiler& compiler)
+void MixNode::compile(SVMCompiler &compiler)
{
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color1_in = input("Color1");
+ ShaderInput *color2_in = input("Color2");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_MIX,
- compiler.stack_assign(fac_in),
- compiler.stack_assign(color1_in),
- compiler.stack_assign(color2_in));
- compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_MIX,
+ compiler.stack_assign(fac_in),
+ compiler.stack_assign(color1_in),
+ compiler.stack_assign(color2_in));
+ compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out));
- if(use_clamp) {
- compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
- compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, compiler.stack_assign(color_out));
- }
+ if (use_clamp) {
+ compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
+ compiler.add_node(NODE_MIX, NODE_MIX_CLAMP, compiler.stack_assign(color_out));
+ }
}
-void MixNode::compile(OSLCompiler& compiler)
+void MixNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.parameter(this, "use_clamp");
- compiler.add(this, "node_mix");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "use_clamp");
+ compiler.add(this, "node_mix");
}
-void MixNode::constant_fold(const ConstantFolder& folder)
+void MixNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
- }
- else {
- folder.fold_mix(type, use_clamp);
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
+ }
+ else {
+ folder.fold_mix(type, use_clamp);
+ }
}
/* Combine RGB */
NODE_DEFINE(CombineRGBNode)
{
- NodeType* type = NodeType::add("combine_rgb", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("combine_rgb", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(r, "R", 0.0f);
- SOCKET_IN_FLOAT(g, "G", 0.0f);
- SOCKET_IN_FLOAT(b, "B", 0.0f);
+ SOCKET_IN_FLOAT(r, "R", 0.0f);
+ SOCKET_IN_FLOAT(g, "G", 0.0f);
+ SOCKET_IN_FLOAT(b, "B", 0.0f);
- SOCKET_OUT_COLOR(image, "Image");
+ SOCKET_OUT_COLOR(image, "Image");
- return type;
+ return type;
}
-CombineRGBNode::CombineRGBNode()
-: ShaderNode(node_type)
+CombineRGBNode::CombineRGBNode() : ShaderNode(node_type)
{
}
-void CombineRGBNode::constant_fold(const ConstantFolder& folder)
+void CombineRGBNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(make_float3(r, g, b));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(r, g, b));
+ }
}
-void CombineRGBNode::compile(SVMCompiler& compiler)
+void CombineRGBNode::compile(SVMCompiler &compiler)
{
- ShaderInput *red_in = input("R");
- ShaderInput *green_in = input("G");
- ShaderInput *blue_in = input("B");
- ShaderOutput *color_out = output("Image");
+ ShaderInput *red_in = input("R");
+ ShaderInput *green_in = input("G");
+ ShaderInput *blue_in = input("B");
+ ShaderOutput *color_out = output("Image");
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(red_in), 0,
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(red_in), 0, compiler.stack_assign(color_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(green_in), 1,
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(green_in), 1, compiler.stack_assign(color_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(blue_in), 2,
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(blue_in), 2, compiler.stack_assign(color_out));
}
-void CombineRGBNode::compile(OSLCompiler& compiler)
+void CombineRGBNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_combine_rgb");
+ compiler.add(this, "node_combine_rgb");
}
/* Combine XYZ */
NODE_DEFINE(CombineXYZNode)
{
- NodeType* type = NodeType::add("combine_xyz", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("combine_xyz", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(x, "X", 0.0f);
- SOCKET_IN_FLOAT(y, "Y", 0.0f);
- SOCKET_IN_FLOAT(z, "Z", 0.0f);
+ SOCKET_IN_FLOAT(x, "X", 0.0f);
+ SOCKET_IN_FLOAT(y, "Y", 0.0f);
+ SOCKET_IN_FLOAT(z, "Z", 0.0f);
- SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return type;
+ return type;
}
-CombineXYZNode::CombineXYZNode()
-: ShaderNode(node_type)
+CombineXYZNode::CombineXYZNode() : ShaderNode(node_type)
{
}
-void CombineXYZNode::constant_fold(const ConstantFolder& folder)
+void CombineXYZNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(make_float3(x, y, z));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(x, y, z));
+ }
}
-void CombineXYZNode::compile(SVMCompiler& compiler)
+void CombineXYZNode::compile(SVMCompiler &compiler)
{
- ShaderInput *x_in = input("X");
- ShaderInput *y_in = input("Y");
- ShaderInput *z_in = input("Z");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *x_in = input("X");
+ ShaderInput *y_in = input("Y");
+ ShaderInput *z_in = input("Z");
+ ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(x_in), 0,
- compiler.stack_assign(vector_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(x_in), 0, compiler.stack_assign(vector_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(y_in), 1,
- compiler.stack_assign(vector_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(y_in), 1, compiler.stack_assign(vector_out));
- compiler.add_node(NODE_COMBINE_VECTOR,
- compiler.stack_assign(z_in), 2,
- compiler.stack_assign(vector_out));
+ compiler.add_node(
+ NODE_COMBINE_VECTOR, compiler.stack_assign(z_in), 2, compiler.stack_assign(vector_out));
}
-void CombineXYZNode::compile(OSLCompiler& compiler)
+void CombineXYZNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_combine_xyz");
+ compiler.add(this, "node_combine_xyz");
}
/* Combine HSV */
NODE_DEFINE(CombineHSVNode)
{
- NodeType* type = NodeType::add("combine_hsv", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("combine_hsv", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(h, "H", 0.0f);
- SOCKET_IN_FLOAT(s, "S", 0.0f);
- SOCKET_IN_FLOAT(v, "V", 0.0f);
+ SOCKET_IN_FLOAT(h, "H", 0.0f);
+ SOCKET_IN_FLOAT(s, "S", 0.0f);
+ SOCKET_IN_FLOAT(v, "V", 0.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-CombineHSVNode::CombineHSVNode()
-: ShaderNode(node_type)
+CombineHSVNode::CombineHSVNode() : ShaderNode(node_type)
{
}
-void CombineHSVNode::constant_fold(const ConstantFolder& folder)
+void CombineHSVNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
+ }
}
-void CombineHSVNode::compile(SVMCompiler& compiler)
+void CombineHSVNode::compile(SVMCompiler &compiler)
{
- ShaderInput *hue_in = input("H");
- ShaderInput *saturation_in = input("S");
- ShaderInput *value_in = input("V");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *hue_in = input("H");
+ ShaderInput *saturation_in = input("S");
+ ShaderInput *value_in = input("V");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_COMBINE_HSV,
- compiler.stack_assign(hue_in),
- compiler.stack_assign(saturation_in),
- compiler.stack_assign(value_in));
- compiler.add_node(NODE_COMBINE_HSV,
- compiler.stack_assign(color_out));
+ compiler.add_node(NODE_COMBINE_HSV,
+ compiler.stack_assign(hue_in),
+ compiler.stack_assign(saturation_in),
+ compiler.stack_assign(value_in));
+ compiler.add_node(NODE_COMBINE_HSV, compiler.stack_assign(color_out));
}
-void CombineHSVNode::compile(OSLCompiler& compiler)
+void CombineHSVNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_combine_hsv");
+ compiler.add(this, "node_combine_hsv");
}
/* Gamma */
NODE_DEFINE(GammaNode)
{
- NodeType* type = NodeType::add("gamma", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("gamma", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(gamma, "Gamma", 1.0f);
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-GammaNode::GammaNode()
-: ShaderNode(node_type)
+GammaNode::GammaNode() : ShaderNode(node_type)
{
}
-void GammaNode::constant_fold(const ConstantFolder& folder)
+void GammaNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(svm_math_gamma_color(color, gamma));
- }
- else {
- ShaderInput *color_in = input("Color");
- ShaderInput *gamma_in = input("Gamma");
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_gamma_color(color, gamma));
+ }
+ else {
+ ShaderInput *color_in = input("Color");
+ ShaderInput *gamma_in = input("Gamma");
- /* 1 ^ X == X ^ 0 == 1 */
- if(folder.is_one(color_in) || folder.is_zero(gamma_in)) {
- folder.make_one();
- }
- /* X ^ 1 == X */
- else if(folder.is_one(gamma_in)) {
- folder.try_bypass_or_make_constant(color_in, false);
- }
- }
+ /* 1 ^ X == X ^ 0 == 1 */
+ if (folder.is_one(color_in) || folder.is_zero(gamma_in)) {
+ folder.make_one();
+ }
+ /* X ^ 1 == X */
+ else if (folder.is_one(gamma_in)) {
+ folder.try_bypass_or_make_constant(color_in, false);
+ }
+ }
}
-void GammaNode::compile(SVMCompiler& compiler)
+void GammaNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *gamma_in = input("Gamma");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *gamma_in = input("Gamma");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_GAMMA,
- compiler.stack_assign(gamma_in),
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(NODE_GAMMA,
+ compiler.stack_assign(gamma_in),
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out));
}
-void GammaNode::compile(OSLCompiler& compiler)
+void GammaNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_gamma");
+ compiler.add(this, "node_gamma");
}
/* Bright Contrast */
NODE_DEFINE(BrightContrastNode)
{
- NodeType* type = NodeType::add("brightness_contrast", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("brightness_contrast", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(bright, "Bright", 0.0f);
- SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(bright, "Bright", 0.0f);
+ SOCKET_IN_FLOAT(contrast, "Contrast", 0.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-BrightContrastNode::BrightContrastNode()
-: ShaderNode(node_type)
+BrightContrastNode::BrightContrastNode() : ShaderNode(node_type)
{
}
-void BrightContrastNode::constant_fold(const ConstantFolder& folder)
+void BrightContrastNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(svm_brightness_contrast(color, bright, contrast));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_brightness_contrast(color, bright, contrast));
+ }
}
-void BrightContrastNode::compile(SVMCompiler& compiler)
+void BrightContrastNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *bright_in = input("Bright");
- ShaderInput *contrast_in = input("Contrast");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *color_in = input("Color");
+ ShaderInput *bright_in = input("Bright");
+ ShaderInput *contrast_in = input("Contrast");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_BRIGHTCONTRAST,
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out),
- compiler.encode_uchar4(
- compiler.stack_assign(bright_in),
- compiler.stack_assign(contrast_in)));
+ compiler.add_node(NODE_BRIGHTCONTRAST,
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(color_out),
+ compiler.encode_uchar4(compiler.stack_assign(bright_in),
+ compiler.stack_assign(contrast_in)));
}
-void BrightContrastNode::compile(OSLCompiler& compiler)
+void BrightContrastNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_brightness");
+ compiler.add(this, "node_brightness");
}
/* Separate RGB */
NODE_DEFINE(SeparateRGBNode)
{
- NodeType* type = NodeType::add("separate_rgb", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("separate_rgb", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(r, "R");
- SOCKET_OUT_FLOAT(g, "G");
- SOCKET_OUT_FLOAT(b, "B");
+ SOCKET_OUT_FLOAT(r, "R");
+ SOCKET_OUT_FLOAT(g, "G");
+ SOCKET_OUT_FLOAT(b, "B");
- return type;
+ return type;
}
-SeparateRGBNode::SeparateRGBNode()
-: ShaderNode(node_type)
+SeparateRGBNode::SeparateRGBNode() : ShaderNode(node_type)
{
}
-void SeparateRGBNode::constant_fold(const ConstantFolder& folder)
+void SeparateRGBNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == folder.output) {
- folder.make_constant(color[channel]);
- return;
- }
- }
- }
+ if (folder.all_inputs_constant()) {
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(color[channel]);
+ return;
+ }
+ }
+ }
}
-void SeparateRGBNode::compile(SVMCompiler& compiler)
+void SeparateRGBNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Image");
- ShaderOutput *red_out = output("R");
- ShaderOutput *green_out = output("G");
- ShaderOutput *blue_out = output("B");
+ ShaderInput *color_in = input("Image");
+ ShaderOutput *red_out = output("R");
+ ShaderOutput *green_out = output("G");
+ ShaderOutput *blue_out = output("B");
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(color_in), 0,
- compiler.stack_assign(red_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 0, compiler.stack_assign(red_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(color_in), 1,
- compiler.stack_assign(green_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 1, compiler.stack_assign(green_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(color_in), 2,
- compiler.stack_assign(blue_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(color_in), 2, compiler.stack_assign(blue_out));
}
-void SeparateRGBNode::compile(OSLCompiler& compiler)
+void SeparateRGBNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_separate_rgb");
+ compiler.add(this, "node_separate_rgb");
}
/* Separate XYZ */
NODE_DEFINE(SeparateXYZNode)
{
- NodeType* type = NodeType::add("separate_xyz", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("separate_xyz", create, NodeType::SHADER);
- SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(x, "X");
- SOCKET_OUT_FLOAT(y, "Y");
- SOCKET_OUT_FLOAT(z, "Z");
+ SOCKET_OUT_FLOAT(x, "X");
+ SOCKET_OUT_FLOAT(y, "Y");
+ SOCKET_OUT_FLOAT(z, "Z");
- return type;
+ return type;
}
-SeparateXYZNode::SeparateXYZNode()
-: ShaderNode(node_type)
+SeparateXYZNode::SeparateXYZNode() : ShaderNode(node_type)
{
}
-void SeparateXYZNode::constant_fold(const ConstantFolder& folder)
+void SeparateXYZNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == folder.output) {
- folder.make_constant(vector[channel]);
- return;
- }
- }
- }
+ if (folder.all_inputs_constant()) {
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(vector[channel]);
+ return;
+ }
+ }
+ }
}
-void SeparateXYZNode::compile(SVMCompiler& compiler)
+void SeparateXYZNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *x_out = output("X");
- ShaderOutput *y_out = output("Y");
- ShaderOutput *z_out = output("Z");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *x_out = output("X");
+ ShaderOutput *y_out = output("Y");
+ ShaderOutput *z_out = output("Z");
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(vector_in), 0,
- compiler.stack_assign(x_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 0, compiler.stack_assign(x_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(vector_in), 1,
- compiler.stack_assign(y_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 1, compiler.stack_assign(y_out));
- compiler.add_node(NODE_SEPARATE_VECTOR,
- compiler.stack_assign(vector_in), 2,
- compiler.stack_assign(z_out));
+ compiler.add_node(
+ NODE_SEPARATE_VECTOR, compiler.stack_assign(vector_in), 2, compiler.stack_assign(z_out));
}
-void SeparateXYZNode::compile(OSLCompiler& compiler)
+void SeparateXYZNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_separate_xyz");
+ compiler.add(this, "node_separate_xyz");
}
/* Separate HSV */
NODE_DEFINE(SeparateHSVNode)
{
- NodeType* type = NodeType::add("separate_hsv", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("separate_hsv", create, NodeType::SHADER);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(h, "H");
- SOCKET_OUT_FLOAT(s, "S");
- SOCKET_OUT_FLOAT(v, "V");
+ SOCKET_OUT_FLOAT(h, "H");
+ SOCKET_OUT_FLOAT(s, "S");
+ SOCKET_OUT_FLOAT(v, "V");
- return type;
+ return type;
}
-SeparateHSVNode::SeparateHSVNode()
-: ShaderNode(node_type)
+SeparateHSVNode::SeparateHSVNode() : ShaderNode(node_type)
{
}
-void SeparateHSVNode::constant_fold(const ConstantFolder& folder)
+void SeparateHSVNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- float3 hsv = rgb_to_hsv(color);
+ if (folder.all_inputs_constant()) {
+ float3 hsv = rgb_to_hsv(color);
- for(int channel = 0; channel < 3; channel++) {
- if(outputs[channel] == folder.output) {
- folder.make_constant(hsv[channel]);
- return;
- }
- }
- }
+ for (int channel = 0; channel < 3; channel++) {
+ if (outputs[channel] == folder.output) {
+ folder.make_constant(hsv[channel]);
+ return;
+ }
+ }
+ }
}
-void SeparateHSVNode::compile(SVMCompiler& compiler)
+void SeparateHSVNode::compile(SVMCompiler &compiler)
{
- ShaderInput *color_in = input("Color");
- ShaderOutput *hue_out = output("H");
- ShaderOutput *saturation_out = output("S");
- ShaderOutput *value_out = output("V");
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *hue_out = output("H");
+ ShaderOutput *saturation_out = output("S");
+ ShaderOutput *value_out = output("V");
- compiler.add_node(NODE_SEPARATE_HSV,
- compiler.stack_assign(color_in),
- compiler.stack_assign(hue_out),
- compiler.stack_assign(saturation_out));
- compiler.add_node(NODE_SEPARATE_HSV,
- compiler.stack_assign(value_out));
+ compiler.add_node(NODE_SEPARATE_HSV,
+ compiler.stack_assign(color_in),
+ compiler.stack_assign(hue_out),
+ compiler.stack_assign(saturation_out));
+ compiler.add_node(NODE_SEPARATE_HSV, compiler.stack_assign(value_out));
}
-void SeparateHSVNode::compile(OSLCompiler& compiler)
+void SeparateHSVNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_separate_hsv");
+ compiler.add(this, "node_separate_hsv");
}
/* Hue Saturation Value */
NODE_DEFINE(HSVNode)
{
- NodeType* type = NodeType::add("hsv", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("hsv", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(hue, "Hue", 0.5f);
- SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f);
- SOCKET_IN_FLOAT(value, "Value", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(hue, "Hue", 0.5f);
+ SOCKET_IN_FLOAT(saturation, "Saturation", 1.0f);
+ SOCKET_IN_FLOAT(value, "Value", 1.0f);
+ SOCKET_IN_FLOAT(fac, "Fac", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-HSVNode::HSVNode()
-: ShaderNode(node_type)
+HSVNode::HSVNode() : ShaderNode(node_type)
{
}
-void HSVNode::compile(SVMCompiler& compiler)
+void HSVNode::compile(SVMCompiler &compiler)
{
- ShaderInput *hue_in = input("Hue");
- ShaderInput *saturation_in = input("Saturation");
- ShaderInput *value_in = input("Value");
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *hue_in = input("Hue");
+ ShaderInput *saturation_in = input("Saturation");
+ ShaderInput *value_in = input("Value");
+ ShaderInput *fac_in = input("Fac");
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_HSV,
- compiler.encode_uchar4(
- compiler.stack_assign(color_in),
- compiler.stack_assign(fac_in),
- compiler.stack_assign(color_out)),
- compiler.encode_uchar4(
- compiler.stack_assign(hue_in),
- compiler.stack_assign(saturation_in),
- compiler.stack_assign(value_in)));
+ compiler.add_node(NODE_HSV,
+ compiler.encode_uchar4(compiler.stack_assign(color_in),
+ compiler.stack_assign(fac_in),
+ compiler.stack_assign(color_out)),
+ compiler.encode_uchar4(compiler.stack_assign(hue_in),
+ compiler.stack_assign(saturation_in),
+ compiler.stack_assign(value_in)));
}
-void HSVNode::compile(OSLCompiler& compiler)
+void HSVNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_hsv");
+ compiler.add(this, "node_hsv");
}
/* Attribute */
NODE_DEFINE(AttributeNode)
{
- NodeType* type = NodeType::add("attribute", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("attribute", create, NodeType::SHADER);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_VECTOR(vector, "Vector");
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-AttributeNode::AttributeNode()
-: ShaderNode(node_type)
+AttributeNode::AttributeNode() : ShaderNode(node_type)
{
}
void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- ShaderOutput *color_out = output("Color");
- ShaderOutput *vector_out = output("Vector");
- ShaderOutput *fac_out = output("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *vector_out = output("Vector");
+ ShaderOutput *fac_out = output("Fac");
- if(!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
- attributes->add_standard(attribute);
- }
+ if (!color_out->links.empty() || !vector_out->links.empty() || !fac_out->links.empty()) {
+ attributes->add_standard(attribute);
+ }
- if(shader->has_volume) {
- attributes->add(ATTR_STD_GENERATED_TRANSFORM);
- }
+ if (shader->has_volume) {
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void AttributeNode::compile(SVMCompiler& compiler)
+void AttributeNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *color_out = output("Color");
- ShaderOutput *vector_out = output("Vector");
- ShaderOutput *fac_out = output("Fac");
- ShaderNodeType attr_node = NODE_ATTR;
- int attr = compiler.attribute_standard(attribute);
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *vector_out = output("Vector");
+ ShaderOutput *fac_out = output("Fac");
+ ShaderNodeType attr_node = NODE_ATTR;
+ int attr = compiler.attribute_standard(attribute);
- if(bump == SHADER_BUMP_DX)
- attr_node = NODE_ATTR_BUMP_DX;
- else if(bump == SHADER_BUMP_DY)
- attr_node = NODE_ATTR_BUMP_DY;
+ if (bump == SHADER_BUMP_DX)
+ attr_node = NODE_ATTR_BUMP_DX;
+ else if (bump == SHADER_BUMP_DY)
+ attr_node = NODE_ATTR_BUMP_DY;
- if(!color_out->links.empty() || !vector_out->links.empty()) {
- if(!color_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3);
- }
- if(!vector_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3);
- }
- }
+ if (!color_out->links.empty() || !vector_out->links.empty()) {
+ if (!color_out->links.empty()) {
+ compiler.add_node(attr_node, attr, compiler.stack_assign(color_out), NODE_ATTR_FLOAT3);
+ }
+ if (!vector_out->links.empty()) {
+ compiler.add_node(attr_node, attr, compiler.stack_assign(vector_out), NODE_ATTR_FLOAT3);
+ }
+ }
- if(!fac_out->links.empty()) {
- compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT);
- }
+ if (!fac_out->links.empty()) {
+ compiler.add_node(attr_node, attr, compiler.stack_assign(fac_out), NODE_ATTR_FLOAT);
+ }
}
-void AttributeNode::compile(OSLCompiler& compiler)
+void AttributeNode::compile(OSLCompiler &compiler)
{
- if(bump == SHADER_BUMP_DX)
- compiler.parameter("bump_offset", "dx");
- else if(bump == SHADER_BUMP_DY)
- compiler.parameter("bump_offset", "dy");
- else
- compiler.parameter("bump_offset", "center");
+ if (bump == SHADER_BUMP_DX)
+ compiler.parameter("bump_offset", "dx");
+ else if (bump == SHADER_BUMP_DY)
+ compiler.parameter("bump_offset", "dy");
+ else
+ compiler.parameter("bump_offset", "center");
- if(Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE)
- compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
- else
- compiler.parameter("name", attribute.c_str());
+ if (Attribute::name_standard(attribute.c_str()) != ATTR_STD_NONE)
+ compiler.parameter("name", (string("geom:") + attribute.c_str()).c_str());
+ else
+ compiler.parameter("name", attribute.c_str());
- compiler.add(this, "node_attribute");
+ compiler.add(this, "node_attribute");
}
/* Camera */
NODE_DEFINE(CameraNode)
{
- NodeType* type = NodeType::add("camera_info", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("camera_info", create, NodeType::SHADER);
- SOCKET_OUT_VECTOR(view_vector, "View Vector");
- SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth");
- SOCKET_OUT_FLOAT(view_distance, "View Distance");
+ SOCKET_OUT_VECTOR(view_vector, "View Vector");
+ SOCKET_OUT_FLOAT(view_z_depth, "View Z Depth");
+ SOCKET_OUT_FLOAT(view_distance, "View Distance");
- return type;
+ return type;
}
-CameraNode::CameraNode()
-: ShaderNode(node_type)
+CameraNode::CameraNode() : ShaderNode(node_type)
{
}
-void CameraNode::compile(SVMCompiler& compiler)
+void CameraNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *vector_out = output("View Vector");
- ShaderOutput *z_depth_out = output("View Z Depth");
- ShaderOutput *distance_out = output("View Distance");
+ ShaderOutput *vector_out = output("View Vector");
+ ShaderOutput *z_depth_out = output("View Z Depth");
+ ShaderOutput *distance_out = output("View Distance");
- compiler.add_node(NODE_CAMERA,
- compiler.stack_assign(vector_out),
- compiler.stack_assign(z_depth_out),
- compiler.stack_assign(distance_out));
+ compiler.add_node(NODE_CAMERA,
+ compiler.stack_assign(vector_out),
+ compiler.stack_assign(z_depth_out),
+ compiler.stack_assign(distance_out));
}
-void CameraNode::compile(OSLCompiler& compiler)
+void CameraNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_camera");
+ compiler.add(this, "node_camera");
}
/* Fresnel */
NODE_DEFINE(FresnelNode)
{
- NodeType* type = NodeType::add("fresnel", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("fresnel", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_IN_FLOAT(IOR, "IOR", 1.45f);
+ SOCKET_IN_NORMAL(normal,
+ "Normal",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_FLOAT(IOR, "IOR", 1.45f);
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-FresnelNode::FresnelNode()
-: ShaderNode(node_type)
+FresnelNode::FresnelNode() : ShaderNode(node_type)
{
}
-void FresnelNode::compile(SVMCompiler& compiler)
+void FresnelNode::compile(SVMCompiler &compiler)
{
- ShaderInput *normal_in = input("Normal");
- ShaderInput *IOR_in = input("IOR");
- ShaderOutput *fac_out = output("Fac");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *IOR_in = input("IOR");
+ ShaderOutput *fac_out = output("Fac");
- compiler.add_node(NODE_FRESNEL,
- compiler.stack_assign(IOR_in),
- __float_as_int(IOR),
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(fac_out)));
+ compiler.add_node(NODE_FRESNEL,
+ compiler.stack_assign(IOR_in),
+ __float_as_int(IOR),
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(fac_out)));
}
-void FresnelNode::compile(OSLCompiler& compiler)
+void FresnelNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_fresnel");
+ compiler.add(this, "node_fresnel");
}
/* Layer Weight */
NODE_DEFINE(LayerWeightNode)
{
- NodeType* type = NodeType::add("layer_weight", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("layer_weight", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_IN_FLOAT(blend, "Blend", 0.5f);
+ SOCKET_IN_NORMAL(normal,
+ "Normal",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_FLOAT(blend, "Blend", 0.5f);
- SOCKET_OUT_FLOAT(fresnel, "Fresnel");
- SOCKET_OUT_FLOAT(facing, "Facing");
+ SOCKET_OUT_FLOAT(fresnel, "Fresnel");
+ SOCKET_OUT_FLOAT(facing, "Facing");
- return type;
+ return type;
}
-LayerWeightNode::LayerWeightNode()
-: ShaderNode(node_type)
+LayerWeightNode::LayerWeightNode() : ShaderNode(node_type)
{
}
-void LayerWeightNode::compile(SVMCompiler& compiler)
+void LayerWeightNode::compile(SVMCompiler &compiler)
{
- ShaderInput *normal_in = input("Normal");
- ShaderInput *blend_in = input("Blend");
- ShaderOutput *fresnel_out = output("Fresnel");
- ShaderOutput *facing_out = output("Facing");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *blend_in = input("Blend");
+ ShaderOutput *fresnel_out = output("Fresnel");
+ ShaderOutput *facing_out = output("Facing");
- if(!fresnel_out->links.empty()) {
- compiler.add_node(NODE_LAYER_WEIGHT,
- compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL,
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(fresnel_out)));
- }
+ if (!fresnel_out->links.empty()) {
+ compiler.add_node(NODE_LAYER_WEIGHT,
+ compiler.stack_assign_if_linked(blend_in),
+ __float_as_int(blend),
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL,
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(fresnel_out)));
+ }
- if(!facing_out->links.empty()) {
- compiler.add_node(NODE_LAYER_WEIGHT,
- compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend),
- compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING,
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(facing_out)));
- }
+ if (!facing_out->links.empty()) {
+ compiler.add_node(NODE_LAYER_WEIGHT,
+ compiler.stack_assign_if_linked(blend_in),
+ __float_as_int(blend),
+ compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING,
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(facing_out)));
+ }
}
-void LayerWeightNode::compile(OSLCompiler& compiler)
+void LayerWeightNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_layer_weight");
+ compiler.add(this, "node_layer_weight");
}
/* Wireframe */
NODE_DEFINE(WireframeNode)
{
- NodeType* type = NodeType::add("wireframe", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("wireframe", create, NodeType::SHADER);
- SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false);
- SOCKET_IN_FLOAT(size, "Size", 0.01f);
- SOCKET_OUT_FLOAT(fac, "Fac");
+ SOCKET_BOOLEAN(use_pixel_size, "Use Pixel Size", false);
+ SOCKET_IN_FLOAT(size, "Size", 0.01f);
+ SOCKET_OUT_FLOAT(fac, "Fac");
- return type;
+ return type;
}
-WireframeNode::WireframeNode()
-: ShaderNode(node_type)
+WireframeNode::WireframeNode() : ShaderNode(node_type)
{
}
-void WireframeNode::compile(SVMCompiler& compiler)
+void WireframeNode::compile(SVMCompiler &compiler)
{
- ShaderInput *size_in = input("Size");
- ShaderOutput *fac_out = output("Fac");
- NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
- if(bump == SHADER_BUMP_DX) {
- bump_offset = NODE_BUMP_OFFSET_DX;
- }
- else if(bump == SHADER_BUMP_DY) {
- bump_offset = NODE_BUMP_OFFSET_DY;
- }
- compiler.add_node(NODE_WIREFRAME,
- compiler.stack_assign(size_in),
- compiler.stack_assign(fac_out),
- compiler.encode_uchar4(use_pixel_size,
- bump_offset,
- 0, 0));
+ ShaderInput *size_in = input("Size");
+ ShaderOutput *fac_out = output("Fac");
+ NodeBumpOffset bump_offset = NODE_BUMP_OFFSET_CENTER;
+ if (bump == SHADER_BUMP_DX) {
+ bump_offset = NODE_BUMP_OFFSET_DX;
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ bump_offset = NODE_BUMP_OFFSET_DY;
+ }
+ compiler.add_node(NODE_WIREFRAME,
+ compiler.stack_assign(size_in),
+ compiler.stack_assign(fac_out),
+ compiler.encode_uchar4(use_pixel_size, bump_offset, 0, 0));
}
-void WireframeNode::compile(OSLCompiler& compiler)
+void WireframeNode::compile(OSLCompiler &compiler)
{
- if(bump == SHADER_BUMP_DX) {
- compiler.parameter("bump_offset", "dx");
- }
- else if(bump == SHADER_BUMP_DY) {
- compiler.parameter("bump_offset", "dy");
- }
- else {
- compiler.parameter("bump_offset", "center");
- }
- compiler.parameter(this, "use_pixel_size");
- compiler.add(this, "node_wireframe");
+ if (bump == SHADER_BUMP_DX) {
+ compiler.parameter("bump_offset", "dx");
+ }
+ else if (bump == SHADER_BUMP_DY) {
+ compiler.parameter("bump_offset", "dy");
+ }
+ else {
+ compiler.parameter("bump_offset", "center");
+ }
+ compiler.parameter(this, "use_pixel_size");
+ compiler.add(this, "node_wireframe");
}
/* Wavelength */
NODE_DEFINE(WavelengthNode)
{
- NodeType* type = NodeType::add("wavelength", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("wavelength", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-WavelengthNode::WavelengthNode()
-: ShaderNode(node_type)
+WavelengthNode::WavelengthNode() : ShaderNode(node_type)
{
}
-void WavelengthNode::compile(SVMCompiler& compiler)
+void WavelengthNode::compile(SVMCompiler &compiler)
{
- ShaderInput *wavelength_in = input("Wavelength");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *wavelength_in = input("Wavelength");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_WAVELENGTH,
- compiler.stack_assign(wavelength_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_WAVELENGTH, compiler.stack_assign(wavelength_in), compiler.stack_assign(color_out));
}
-void WavelengthNode::compile(OSLCompiler& compiler)
+void WavelengthNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_wavelength");
+ compiler.add(this, "node_wavelength");
}
/* Blackbody */
NODE_DEFINE(BlackbodyNode)
{
- NodeType* type = NodeType::add("blackbody", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("blackbody", create, NodeType::SHADER);
- SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
- SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
+ SOCKET_OUT_COLOR(color, "Color");
- return type;
+ return type;
}
-BlackbodyNode::BlackbodyNode()
-: ShaderNode(node_type)
+BlackbodyNode::BlackbodyNode() : ShaderNode(node_type)
{
}
-void BlackbodyNode::constant_fold(const ConstantFolder& folder)
+void BlackbodyNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant(svm_math_blackbody_color(temperature));
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_blackbody_color(temperature));
+ }
}
-void BlackbodyNode::compile(SVMCompiler& compiler)
+void BlackbodyNode::compile(SVMCompiler &compiler)
{
- ShaderInput *temperature_in = input("Temperature");
- ShaderOutput *color_out = output("Color");
+ ShaderInput *temperature_in = input("Temperature");
+ ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_BLACKBODY,
- compiler.stack_assign(temperature_in),
- compiler.stack_assign(color_out));
+ compiler.add_node(
+ NODE_BLACKBODY, compiler.stack_assign(temperature_in), compiler.stack_assign(color_out));
}
-void BlackbodyNode::compile(OSLCompiler& compiler)
+void BlackbodyNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_blackbody");
+ compiler.add(this, "node_blackbody");
}
/* Output */
NODE_DEFINE(OutputNode)
{
- NodeType* type = NodeType::add("output", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("output", create, NodeType::SHADER);
- SOCKET_IN_CLOSURE(surface, "Surface");
- SOCKET_IN_CLOSURE(volume, "Volume");
- SOCKET_IN_VECTOR(displacement, "Displacement", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_CLOSURE(surface, "Surface");
+ SOCKET_IN_CLOSURE(volume, "Volume");
+ SOCKET_IN_VECTOR(displacement, "Displacement", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
- return type;
+ return type;
}
-OutputNode::OutputNode()
-: ShaderNode(node_type)
+OutputNode::OutputNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_OUTPUT;
+ special_type = SHADER_SPECIAL_TYPE_OUTPUT;
}
-void OutputNode::compile(SVMCompiler& compiler)
+void OutputNode::compile(SVMCompiler &compiler)
{
- if(compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
- ShaderInput *displacement_in = input("Displacement");
+ if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT) {
+ ShaderInput *displacement_in = input("Displacement");
- if(displacement_in->link) {
- compiler.add_node(NODE_SET_DISPLACEMENT, compiler.stack_assign(displacement_in));
- }
- }
+ if (displacement_in->link) {
+ compiler.add_node(NODE_SET_DISPLACEMENT, compiler.stack_assign(displacement_in));
+ }
+ }
}
-void OutputNode::compile(OSLCompiler& compiler)
+void OutputNode::compile(OSLCompiler &compiler)
{
- if(compiler.output_type() == SHADER_TYPE_SURFACE)
- compiler.add(this, "node_output_surface");
- else if(compiler.output_type() == SHADER_TYPE_VOLUME)
- compiler.add(this, "node_output_volume");
- else if(compiler.output_type() == SHADER_TYPE_DISPLACEMENT)
- compiler.add(this, "node_output_displacement");
+ if (compiler.output_type() == SHADER_TYPE_SURFACE)
+ compiler.add(this, "node_output_surface");
+ else if (compiler.output_type() == SHADER_TYPE_VOLUME)
+ compiler.add(this, "node_output_volume");
+ else if (compiler.output_type() == SHADER_TYPE_DISPLACEMENT)
+ compiler.add(this, "node_output_displacement");
}
/* Math */
NODE_DEFINE(MathNode)
{
- NodeType* type = NodeType::add("math", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("math", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("add", NODE_MATH_ADD);
- type_enum.insert("subtract", NODE_MATH_SUBTRACT);
- type_enum.insert("multiply", NODE_MATH_MULTIPLY);
- type_enum.insert("divide", NODE_MATH_DIVIDE);
- type_enum.insert("sine", NODE_MATH_SINE);
- type_enum.insert("cosine", NODE_MATH_COSINE);
- type_enum.insert("tangent", NODE_MATH_TANGENT);
- type_enum.insert("arcsine", NODE_MATH_ARCSINE);
- type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
- type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
- type_enum.insert("power", NODE_MATH_POWER);
- type_enum.insert("logarithm", NODE_MATH_LOGARITHM);
- type_enum.insert("minimum", NODE_MATH_MINIMUM);
- type_enum.insert("maximum", NODE_MATH_MAXIMUM);
- type_enum.insert("round", NODE_MATH_ROUND);
- type_enum.insert("less_than", NODE_MATH_LESS_THAN);
- type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
- type_enum.insert("modulo", NODE_MATH_MODULO);
- type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
- type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
- type_enum.insert("floor", NODE_MATH_FLOOR);
- type_enum.insert("ceil", NODE_MATH_CEIL);
- type_enum.insert("fract", NODE_MATH_FRACT);
- type_enum.insert("sqrt", NODE_MATH_SQRT);
- SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
+ static NodeEnum type_enum;
+ type_enum.insert("add", NODE_MATH_ADD);
+ type_enum.insert("subtract", NODE_MATH_SUBTRACT);
+ type_enum.insert("multiply", NODE_MATH_MULTIPLY);
+ type_enum.insert("divide", NODE_MATH_DIVIDE);
+ type_enum.insert("sine", NODE_MATH_SINE);
+ type_enum.insert("cosine", NODE_MATH_COSINE);
+ type_enum.insert("tangent", NODE_MATH_TANGENT);
+ type_enum.insert("arcsine", NODE_MATH_ARCSINE);
+ type_enum.insert("arccosine", NODE_MATH_ARCCOSINE);
+ type_enum.insert("arctangent", NODE_MATH_ARCTANGENT);
+ type_enum.insert("power", NODE_MATH_POWER);
+ type_enum.insert("logarithm", NODE_MATH_LOGARITHM);
+ type_enum.insert("minimum", NODE_MATH_MINIMUM);
+ type_enum.insert("maximum", NODE_MATH_MAXIMUM);
+ type_enum.insert("round", NODE_MATH_ROUND);
+ type_enum.insert("less_than", NODE_MATH_LESS_THAN);
+ type_enum.insert("greater_than", NODE_MATH_GREATER_THAN);
+ type_enum.insert("modulo", NODE_MATH_MODULO);
+ type_enum.insert("absolute", NODE_MATH_ABSOLUTE);
+ type_enum.insert("arctan2", NODE_MATH_ARCTAN2);
+ type_enum.insert("floor", NODE_MATH_FLOOR);
+ type_enum.insert("ceil", NODE_MATH_CEIL);
+ type_enum.insert("fract", NODE_MATH_FRACT);
+ type_enum.insert("sqrt", NODE_MATH_SQRT);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
- SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
+ SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
- SOCKET_IN_FLOAT(value1, "Value1", 0.0f);
- SOCKET_IN_FLOAT(value2, "Value2", 0.0f);
+ SOCKET_IN_FLOAT(value1, "Value1", 0.0f);
+ SOCKET_IN_FLOAT(value2, "Value2", 0.0f);
- SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_OUT_FLOAT(value, "Value");
- return type;
+ return type;
}
-MathNode::MathNode()
-: ShaderNode(node_type)
+MathNode::MathNode() : ShaderNode(node_type)
{
}
-void MathNode::constant_fold(const ConstantFolder& folder)
+void MathNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
- }
- else {
- folder.fold_math(type, use_clamp);
- }
+ if (folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_math(type, value1, value2), use_clamp);
+ }
+ else {
+ folder.fold_math(type, use_clamp);
+ }
}
-void MathNode::compile(SVMCompiler& compiler)
+void MathNode::compile(SVMCompiler &compiler)
{
- ShaderInput *value1_in = input("Value1");
- ShaderInput *value2_in = input("Value2");
- ShaderOutput *value_out = output("Value");
+ ShaderInput *value1_in = input("Value1");
+ ShaderInput *value2_in = input("Value2");
+ ShaderOutput *value_out = output("Value");
- compiler.add_node(NODE_MATH, type, compiler.stack_assign(value1_in), compiler.stack_assign(value2_in));
- compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
+ compiler.add_node(
+ NODE_MATH, type, compiler.stack_assign(value1_in), compiler.stack_assign(value2_in));
+ compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
- if(use_clamp) {
- compiler.add_node(NODE_MATH, NODE_MATH_CLAMP, compiler.stack_assign(value_out));
- compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
- }
+ if (use_clamp) {
+ compiler.add_node(NODE_MATH, NODE_MATH_CLAMP, compiler.stack_assign(value_out));
+ compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
+ }
}
-void MathNode::compile(OSLCompiler& compiler)
+void MathNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.parameter(this, "use_clamp");
- compiler.add(this, "node_math");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "use_clamp");
+ compiler.add(this, "node_math");
}
/* VectorMath */
NODE_DEFINE(VectorMathNode)
{
- NodeType* type = NodeType::add("vector_math", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_math", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("add", NODE_VECTOR_MATH_ADD);
- type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
- type_enum.insert("average", NODE_VECTOR_MATH_AVERAGE);
- type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
- type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
- type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
+ static NodeEnum type_enum;
+ type_enum.insert("add", NODE_VECTOR_MATH_ADD);
+ type_enum.insert("subtract", NODE_VECTOR_MATH_SUBTRACT);
+ type_enum.insert("average", NODE_VECTOR_MATH_AVERAGE);
+ type_enum.insert("dot_product", NODE_VECTOR_MATH_DOT_PRODUCT);
+ type_enum.insert("cross_product", NODE_VECTOR_MATH_CROSS_PRODUCT);
+ type_enum.insert("normalize", NODE_VECTOR_MATH_NORMALIZE);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_MATH_ADD);
- SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_VECTOR(vector1, "Vector1", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_VECTOR(vector2, "Vector2", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(value, "Value");
- SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return type;
+ return type;
}
-VectorMathNode::VectorMathNode()
-: ShaderNode(node_type)
+VectorMathNode::VectorMathNode() : ShaderNode(node_type)
{
}
-void VectorMathNode::constant_fold(const ConstantFolder& folder)
+void VectorMathNode::constant_fold(const ConstantFolder &folder)
{
- float value;
- float3 vector;
+ float value;
+ float3 vector;
- if(folder.all_inputs_constant()) {
- svm_vector_math(&value,
- &vector,
- type,
- vector1,
- vector2);
+ if (folder.all_inputs_constant()) {
+ svm_vector_math(&value, &vector, type, vector1, vector2);
- if(folder.output == output("Value")) {
- folder.make_constant(value);
- }
- else if(folder.output == output("Vector")) {
- folder.make_constant(vector);
- }
- }
- else {
- folder.fold_vector_math(type);
- }
+ if (folder.output == output("Value")) {
+ folder.make_constant(value);
+ }
+ else if (folder.output == output("Vector")) {
+ folder.make_constant(vector);
+ }
+ }
+ else {
+ folder.fold_vector_math(type);
+ }
}
-void VectorMathNode::compile(SVMCompiler& compiler)
+void VectorMathNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector1_in = input("Vector1");
- ShaderInput *vector2_in = input("Vector2");
- ShaderOutput *value_out = output("Value");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *vector1_in = input("Vector1");
+ ShaderInput *vector2_in = input("Vector2");
+ ShaderOutput *value_out = output("Value");
+ ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_VECTOR_MATH,
- type,
- compiler.stack_assign(vector1_in),
- compiler.stack_assign(vector2_in));
- compiler.add_node(NODE_VECTOR_MATH,
- compiler.stack_assign(value_out),
- compiler.stack_assign(vector_out));
+ compiler.add_node(NODE_VECTOR_MATH,
+ type,
+ compiler.stack_assign(vector1_in),
+ compiler.stack_assign(vector2_in));
+ compiler.add_node(
+ NODE_VECTOR_MATH, compiler.stack_assign(value_out), compiler.stack_assign(vector_out));
}
-void VectorMathNode::compile(OSLCompiler& compiler)
+void VectorMathNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.add(this, "node_vector_math");
+ compiler.parameter(this, "type");
+ compiler.add(this, "node_vector_math");
}
/* VectorTransform */
NODE_DEFINE(VectorTransformNode)
{
- NodeType* type = NodeType::add("vector_transform", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_transform", create, NodeType::SHADER);
- static NodeEnum type_enum;
- type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
- type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
- type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
- SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
+ static NodeEnum type_enum;
+ type_enum.insert("vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
+ type_enum.insert("point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
+ type_enum.insert("normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
- static NodeEnum space_enum;
- space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
- space_enum.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
- space_enum.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA);
- SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
- SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
+ static NodeEnum space_enum;
+ space_enum.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
+ space_enum.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
+ space_enum.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA);
+ SOCKET_ENUM(convert_from, "Convert From", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
+ SOCKET_ENUM(convert_to, "Convert To", space_enum, NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
- SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return type;
+ return type;
}
-VectorTransformNode::VectorTransformNode()
-: ShaderNode(node_type)
+VectorTransformNode::VectorTransformNode() : ShaderNode(node_type)
{
}
-void VectorTransformNode::compile(SVMCompiler& compiler)
+void VectorTransformNode::compile(SVMCompiler &compiler)
{
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *vector_out = output("Vector");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *vector_out = output("Vector");
- compiler.add_node(NODE_VECTOR_TRANSFORM,
- compiler.encode_uchar4(type, convert_from, convert_to),
- compiler.encode_uchar4(compiler.stack_assign(vector_in),
- compiler.stack_assign(vector_out)));
+ compiler.add_node(
+ NODE_VECTOR_TRANSFORM,
+ compiler.encode_uchar4(type, convert_from, convert_to),
+ compiler.encode_uchar4(compiler.stack_assign(vector_in), compiler.stack_assign(vector_out)));
}
-void VectorTransformNode::compile(OSLCompiler& compiler)
+void VectorTransformNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "type");
- compiler.parameter(this, "convert_from");
- compiler.parameter(this, "convert_to");
- compiler.add(this, "node_vector_transform");
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "convert_from");
+ compiler.parameter(this, "convert_to");
+ compiler.add(this, "node_vector_transform");
}
/* BumpNode */
NODE_DEFINE(BumpNode)
{
- NodeType* type = NodeType::add("bump", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("bump", create, NodeType::SHADER);
- SOCKET_BOOLEAN(invert, "Invert", false);
- SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
+ SOCKET_BOOLEAN(invert, "Invert", false);
+ SOCKET_BOOLEAN(use_object_space, "UseObjectSpace", false);
- /* this input is used by the user, but after graph transform it is no longer
- * used and moved to sampler center/x/y instead */
- SOCKET_IN_FLOAT(height, "Height", 1.0f);
+ /* this input is used by the user, but after graph transform it is no longer
+ * used and moved to sampler center/x/y instead */
+ SOCKET_IN_FLOAT(height, "Height", 1.0f);
- SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f);
- SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f);
- SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
+ SOCKET_IN_FLOAT(sample_center, "SampleCenter", 0.0f);
+ SOCKET_IN_FLOAT(sample_x, "SampleX", 0.0f);
+ SOCKET_IN_FLOAT(sample_y, "SampleY", 0.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_FLOAT(distance, "Distance", 0.1f);
- SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_NORMAL(normal, "Normal");
- return type;
+ return type;
}
-BumpNode::BumpNode()
-: ShaderNode(node_type)
+BumpNode::BumpNode() : ShaderNode(node_type)
{
- special_type = SHADER_SPECIAL_TYPE_BUMP;
+ special_type = SHADER_SPECIAL_TYPE_BUMP;
}
-void BumpNode::compile(SVMCompiler& compiler)
+void BumpNode::compile(SVMCompiler &compiler)
{
- ShaderInput *center_in = input("SampleCenter");
- ShaderInput *dx_in = input("SampleX");
- ShaderInput *dy_in = input("SampleY");
- ShaderInput *normal_in = input("Normal");
- ShaderInput *strength_in = input("Strength");
- ShaderInput *distance_in = input("Distance");
- ShaderOutput *normal_out = output("Normal");
+ ShaderInput *center_in = input("SampleCenter");
+ ShaderInput *dx_in = input("SampleX");
+ ShaderInput *dy_in = input("SampleY");
+ ShaderInput *normal_in = input("Normal");
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *distance_in = input("Distance");
+ ShaderOutput *normal_out = output("Normal");
- /* pack all parameters in the node */
- compiler.add_node(NODE_SET_BUMP,
- compiler.encode_uchar4(
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(distance_in),
- invert,
- use_object_space),
- compiler.encode_uchar4(
- compiler.stack_assign(center_in),
- compiler.stack_assign(dx_in),
- compiler.stack_assign(dy_in),
- compiler.stack_assign(strength_in)),
- compiler.stack_assign(normal_out));
+ /* pack all parameters in the node */
+ compiler.add_node(NODE_SET_BUMP,
+ compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(distance_in),
+ invert,
+ use_object_space),
+ compiler.encode_uchar4(compiler.stack_assign(center_in),
+ compiler.stack_assign(dx_in),
+ compiler.stack_assign(dy_in),
+ compiler.stack_assign(strength_in)),
+ compiler.stack_assign(normal_out));
}
-void BumpNode::compile(OSLCompiler& compiler)
+void BumpNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "invert");
- compiler.parameter(this, "use_object_space");
- compiler.add(this, "node_bump");
+ compiler.parameter(this, "invert");
+ compiler.parameter(this, "use_object_space");
+ compiler.add(this, "node_bump");
}
-void BumpNode::constant_fold(const ConstantFolder& folder)
+void BumpNode::constant_fold(const ConstantFolder &folder)
{
- ShaderInput *height_in = input("Height");
- ShaderInput *normal_in = input("Normal");
+ ShaderInput *height_in = input("Height");
+ ShaderInput *normal_in = input("Normal");
- if(height_in->link == NULL) {
- if(normal_in->link == NULL) {
- GeometryNode *geom = new GeometryNode();
- folder.graph->add(geom);
- folder.bypass(geom->output("Normal"));
- }
- else {
- folder.bypass(normal_in->link);
- }
- }
+ if (height_in->link == NULL) {
+ if (normal_in->link == NULL) {
+ GeometryNode *geom = new GeometryNode();
+ folder.graph->add(geom);
+ folder.bypass(geom->output("Normal"));
+ }
+ else {
+ folder.bypass(normal_in->link);
+ }
+ }
- /* TODO(sergey): Ignore bump with zero strength. */
+ /* TODO(sergey): Ignore bump with zero strength. */
}
-
/* Curve node */
-CurvesNode::CurvesNode(const NodeType *node_type)
-: ShaderNode(node_type)
+CurvesNode::CurvesNode(const NodeType *node_type) : ShaderNode(node_type)
{
}
-void CurvesNode::constant_fold(const ConstantFolder& folder, ShaderInput *value_in)
+void CurvesNode::constant_fold(const ConstantFolder &folder, ShaderInput *value_in)
{
- ShaderInput *fac_in = input("Fac");
+ ShaderInput *fac_in = input("Fac");
- /* evaluate fully constant node */
- if(folder.all_inputs_constant()) {
- if(curves.size() == 0) {
- return;
- }
+ /* evaluate fully constant node */
+ if (folder.all_inputs_constant()) {
+ if (curves.size() == 0) {
+ return;
+ }
- float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
- float3 result;
+ float3 pos = (value - make_float3(min_x, min_x, min_x)) / (max_x - min_x);
+ float3 result;
- result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, true, curves.size()).x;
- result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, true, curves.size()).y;
- result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, true, curves.size()).z;
+ result[0] = rgb_ramp_lookup(curves.data(), pos[0], true, true, curves.size()).x;
+ result[1] = rgb_ramp_lookup(curves.data(), pos[1], true, true, curves.size()).y;
+ result[2] = rgb_ramp_lookup(curves.data(), pos[2], true, true, curves.size()).z;
- folder.make_constant(interp(value, result, fac));
- }
- /* remove no-op node */
- else if(!fac_in->link && fac == 0.0f) {
- /* link is not null because otherwise all inputs are constant */
- folder.bypass(value_in->link);
- }
+ folder.make_constant(interp(value, result, fac));
+ }
+ /* remove no-op node */
+ else if (!fac_in->link && fac == 0.0f) {
+ /* link is not null because otherwise all inputs are constant */
+ folder.bypass(value_in->link);
+ }
}
-void CurvesNode::compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out)
+void CurvesNode::compile(SVMCompiler &compiler,
+ int type,
+ ShaderInput *value_in,
+ ShaderOutput *value_out)
{
- if(curves.size() == 0)
- return;
+ if (curves.size() == 0)
+ return;
- ShaderInput *fac_in = input("Fac");
+ ShaderInput *fac_in = input("Fac");
- compiler.add_node(type,
- compiler.encode_uchar4(compiler.stack_assign(fac_in),
- compiler.stack_assign(value_in),
- compiler.stack_assign(value_out)),
- __float_as_int(min_x),
- __float_as_int(max_x));
+ compiler.add_node(type,
+ compiler.encode_uchar4(compiler.stack_assign(fac_in),
+ compiler.stack_assign(value_in),
+ compiler.stack_assign(value_out)),
+ __float_as_int(min_x),
+ __float_as_int(max_x));
- compiler.add_node(curves.size());
- for(int i = 0; i < curves.size(); i++)
- compiler.add_node(float3_to_float4(curves[i]));
+ compiler.add_node(curves.size());
+ for (int i = 0; i < curves.size(); i++)
+ compiler.add_node(float3_to_float4(curves[i]));
}
-void CurvesNode::compile(OSLCompiler& compiler, const char* name)
+void CurvesNode::compile(OSLCompiler &compiler, const char *name)
{
- if(curves.size() == 0)
- return;
+ if (curves.size() == 0)
+ return;
- compiler.parameter_color_array("ramp", curves);
- compiler.parameter(this, "min_x");
- compiler.parameter(this, "max_x");
- compiler.add(this, name);
+ compiler.parameter_color_array("ramp", curves);
+ compiler.parameter(this, "min_x");
+ compiler.parameter(this, "max_x");
+ compiler.add(this, name);
}
-void CurvesNode::compile(SVMCompiler& /*compiler*/)
+void CurvesNode::compile(SVMCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
-void CurvesNode::compile(OSLCompiler& /*compiler*/)
+void CurvesNode::compile(OSLCompiler & /*compiler*/)
{
- assert(0);
+ assert(0);
}
/* RGBCurvesNode */
NODE_DEFINE(RGBCurvesNode)
{
- NodeType* type = NodeType::add("rgb_curves", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("rgb_curves", create, NodeType::SHADER);
- SOCKET_COLOR_ARRAY(curves, "Curves", array<float3>());
- SOCKET_FLOAT(min_x, "Min X", 0.0f);
- SOCKET_FLOAT(max_x, "Max X", 1.0f);
+ SOCKET_COLOR_ARRAY(curves, "Curves", array<float3>());
+ SOCKET_FLOAT(min_x, "Min X", 0.0f);
+ SOCKET_FLOAT(max_x, "Max X", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
- SOCKET_IN_COLOR(value, "Color", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
+ SOCKET_IN_COLOR(value, "Color", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_COLOR(value, "Color");
+ SOCKET_OUT_COLOR(value, "Color");
- return type;
+ return type;
}
-RGBCurvesNode::RGBCurvesNode()
-: CurvesNode(node_type)
+RGBCurvesNode::RGBCurvesNode() : CurvesNode(node_type)
{
}
-void RGBCurvesNode::constant_fold(const ConstantFolder& folder)
+void RGBCurvesNode::constant_fold(const ConstantFolder &folder)
{
- CurvesNode::constant_fold(folder, input("Color"));
+ CurvesNode::constant_fold(folder, input("Color"));
}
-void RGBCurvesNode::compile(SVMCompiler& compiler)
+void RGBCurvesNode::compile(SVMCompiler &compiler)
{
- CurvesNode::compile(compiler, NODE_RGB_CURVES, input("Color"), output("Color"));
+ CurvesNode::compile(compiler, NODE_RGB_CURVES, input("Color"), output("Color"));
}
-void RGBCurvesNode::compile(OSLCompiler& compiler)
+void RGBCurvesNode::compile(OSLCompiler &compiler)
{
- CurvesNode::compile(compiler, "node_rgb_curves");
+ CurvesNode::compile(compiler, "node_rgb_curves");
}
/* VectorCurvesNode */
NODE_DEFINE(VectorCurvesNode)
{
- NodeType* type = NodeType::add("vector_curves", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_curves", create, NodeType::SHADER);
- SOCKET_VECTOR_ARRAY(curves, "Curves", array<float3>());
- SOCKET_FLOAT(min_x, "Min X", 0.0f);
- SOCKET_FLOAT(max_x, "Max X", 1.0f);
+ SOCKET_VECTOR_ARRAY(curves, "Curves", array<float3>());
+ SOCKET_FLOAT(min_x, "Min X", 0.0f);
+ SOCKET_FLOAT(max_x, "Max X", 1.0f);
- SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
- SOCKET_IN_VECTOR(value, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
+ SOCKET_IN_VECTOR(value, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_VECTOR(value, "Vector");
+ SOCKET_OUT_VECTOR(value, "Vector");
- return type;
+ return type;
}
-VectorCurvesNode::VectorCurvesNode()
-: CurvesNode(node_type)
+VectorCurvesNode::VectorCurvesNode() : CurvesNode(node_type)
{
}
-void VectorCurvesNode::constant_fold(const ConstantFolder& folder)
+void VectorCurvesNode::constant_fold(const ConstantFolder &folder)
{
- CurvesNode::constant_fold(folder, input("Vector"));
+ CurvesNode::constant_fold(folder, input("Vector"));
}
-void VectorCurvesNode::compile(SVMCompiler& compiler)
+void VectorCurvesNode::compile(SVMCompiler &compiler)
{
- CurvesNode::compile(compiler, NODE_VECTOR_CURVES, input("Vector"), output("Vector"));
+ CurvesNode::compile(compiler, NODE_VECTOR_CURVES, input("Vector"), output("Vector"));
}
-void VectorCurvesNode::compile(OSLCompiler& compiler)
+void VectorCurvesNode::compile(OSLCompiler &compiler)
{
- CurvesNode::compile(compiler, "node_vector_curves");
+ CurvesNode::compile(compiler, "node_vector_curves");
}
/* RGBRampNode */
NODE_DEFINE(RGBRampNode)
{
- NodeType* type = NodeType::add("rgb_ramp", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("rgb_ramp", create, NodeType::SHADER);
- SOCKET_COLOR_ARRAY(ramp, "Ramp", array<float3>());
- SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array<float>());
- SOCKET_BOOLEAN(interpolate, "Interpolate", true);
+ SOCKET_COLOR_ARRAY(ramp, "Ramp", array<float3>());
+ SOCKET_FLOAT_ARRAY(ramp_alpha, "Ramp Alpha", array<float>());
+ SOCKET_BOOLEAN(interpolate, "Interpolate", true);
- SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
+ SOCKET_IN_FLOAT(fac, "Fac", 0.0f);
- SOCKET_OUT_COLOR(color, "Color");
- SOCKET_OUT_FLOAT(alpha, "Alpha");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
- return type;
+ return type;
}
-RGBRampNode::RGBRampNode()
-: ShaderNode(node_type)
+RGBRampNode::RGBRampNode() : ShaderNode(node_type)
{
}
-void RGBRampNode::constant_fold(const ConstantFolder& folder)
+void RGBRampNode::constant_fold(const ConstantFolder &folder)
{
- if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
- return;
+ if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+ return;
- if(folder.all_inputs_constant()) {
- float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
+ if (folder.all_inputs_constant()) {
+ float f = clamp(fac, 0.0f, 1.0f) * (ramp.size() - 1);
- /* clamp int as well in case of NaN */
- int i = clamp((int)f, 0, ramp.size()-1);
- float t = f - (float)i;
+ /* clamp int as well in case of NaN */
+ int i = clamp((int)f, 0, ramp.size() - 1);
+ float t = f - (float)i;
- bool use_lerp = interpolate && t > 0.0f;
+ bool use_lerp = interpolate && t > 0.0f;
- if(folder.output == output("Color")) {
- float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
- folder.make_constant(color);
- }
- else if(folder.output == output("Alpha")) {
- float alpha = float_ramp_lookup(ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
- folder.make_constant(alpha);
- }
- }
+ if (folder.output == output("Color")) {
+ float3 color = rgb_ramp_lookup(ramp.data(), fac, use_lerp, false, ramp.size());
+ folder.make_constant(color);
+ }
+ else if (folder.output == output("Alpha")) {
+ float alpha = float_ramp_lookup(ramp_alpha.data(), fac, use_lerp, false, ramp_alpha.size());
+ folder.make_constant(alpha);
+ }
+ }
}
-void RGBRampNode::compile(SVMCompiler& compiler)
+void RGBRampNode::compile(SVMCompiler &compiler)
{
- if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
- return;
+ if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+ return;
- ShaderInput *fac_in = input("Fac");
- ShaderOutput *color_out = output("Color");
- ShaderOutput *alpha_out = output("Alpha");
+ ShaderInput *fac_in = input("Fac");
+ ShaderOutput *color_out = output("Color");
+ ShaderOutput *alpha_out = output("Alpha");
- compiler.add_node(NODE_RGB_RAMP,
- compiler.encode_uchar4(
- compiler.stack_assign(fac_in),
- compiler.stack_assign_if_linked(color_out),
- compiler.stack_assign_if_linked(alpha_out)),
- interpolate);
+ compiler.add_node(NODE_RGB_RAMP,
+ compiler.encode_uchar4(compiler.stack_assign(fac_in),
+ compiler.stack_assign_if_linked(color_out),
+ compiler.stack_assign_if_linked(alpha_out)),
+ interpolate);
- compiler.add_node(ramp.size());
- for(int i = 0; i < ramp.size(); i++)
- compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i]));
+ compiler.add_node(ramp.size());
+ for (int i = 0; i < ramp.size(); i++)
+ compiler.add_node(make_float4(ramp[i].x, ramp[i].y, ramp[i].z, ramp_alpha[i]));
}
-void RGBRampNode::compile(OSLCompiler& compiler)
+void RGBRampNode::compile(OSLCompiler &compiler)
{
- if(ramp.size() == 0 || ramp.size() != ramp_alpha.size())
- return;
+ if (ramp.size() == 0 || ramp.size() != ramp_alpha.size())
+ return;
- compiler.parameter_color_array("ramp_color", ramp);
- compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
- compiler.parameter(this, "interpolate");
+ compiler.parameter_color_array("ramp_color", ramp);
+ compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
+ compiler.parameter(this, "interpolate");
- compiler.add(this, "node_rgb_ramp");
+ compiler.add(this, "node_rgb_ramp");
}
/* Set Normal Node */
NODE_DEFINE(SetNormalNode)
{
- NodeType* type = NodeType::add("set_normal", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("set_normal", create, NodeType::SHADER);
- SOCKET_IN_VECTOR(direction, "Direction", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_IN_VECTOR(direction, "Direction", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_NORMAL(normal, "Normal");
- return type;
+ return type;
}
-SetNormalNode::SetNormalNode()
-: ShaderNode(node_type)
+SetNormalNode::SetNormalNode() : ShaderNode(node_type)
{
}
-void SetNormalNode::compile(SVMCompiler& compiler)
+void SetNormalNode::compile(SVMCompiler &compiler)
{
- ShaderInput *direction_in = input("Direction");
- ShaderOutput *normal_out = output("Normal");
+ ShaderInput *direction_in = input("Direction");
+ ShaderOutput *normal_out = output("Normal");
- compiler.add_node(NODE_CLOSURE_SET_NORMAL,
- compiler.stack_assign(direction_in),
- compiler.stack_assign(normal_out));
+ compiler.add_node(NODE_CLOSURE_SET_NORMAL,
+ compiler.stack_assign(direction_in),
+ compiler.stack_assign(normal_out));
}
-void SetNormalNode::compile(OSLCompiler& compiler)
+void SetNormalNode::compile(OSLCompiler &compiler)
{
- compiler.add(this, "node_set_normal");
+ compiler.add(this, "node_set_normal");
}
/* OSLNode */
-OSLNode::OSLNode()
-: ShaderNode(new NodeType(NodeType::SHADER))
+OSLNode::OSLNode() : ShaderNode(new NodeType(NodeType::SHADER))
{
- special_type = SHADER_SPECIAL_TYPE_SCRIPT;
+ special_type = SHADER_SPECIAL_TYPE_SCRIPT;
}
OSLNode::~OSLNode()
{
- delete type;
+ delete type;
}
ShaderNode *OSLNode::clone() const
{
- return OSLNode::create(this->inputs.size(), this);
+ return OSLNode::create(this->inputs.size(), this);
}
-OSLNode* OSLNode::create(size_t num_inputs, const OSLNode *from)
+OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
{
- /* allocate space for the node itself and parameters, aligned to 16 bytes
- * assuming that's the most parameter types need */
- size_t node_size = align_up(sizeof(OSLNode), 16);
- size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
+ /* allocate space for the node itself and parameters, aligned to 16 bytes
+ * assuming that's the most parameter types need */
+ size_t node_size = align_up(sizeof(OSLNode), 16);
+ size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
- char *node_memory = (char*) operator new(node_size + inputs_size);
- memset(node_memory, 0, node_size + inputs_size);
+ char *node_memory = (char *)operator new(node_size + inputs_size);
+ memset(node_memory, 0, node_size + inputs_size);
- if(!from) {
- return new(node_memory) OSLNode();
- }
- else {
- /* copy input default values and node type for cloning */
- memcpy(node_memory + node_size, (char*)from + node_size, inputs_size);
+ if (!from) {
+ return new (node_memory) OSLNode();
+ }
+ else {
+ /* copy input default values and node type for cloning */
+ memcpy(node_memory + node_size, (char *)from + node_size, inputs_size);
- OSLNode *node = new(node_memory) OSLNode(*from);
- node->type = new NodeType(*(from->type));
- return node;
- }
+ OSLNode *node = new (node_memory) OSLNode(*from);
+ node->type = new NodeType(*(from->type));
+ return node;
+ }
}
-char* OSLNode::input_default_value()
+char *OSLNode::input_default_value()
{
- /* pointer to default value storage, which is the same as our actual value */
- size_t num_inputs = type->inputs.size();
- size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
- return (char*)this + align_up(sizeof(OSLNode), 16) + inputs_size;
+ /* pointer to default value storage, which is the same as our actual value */
+ size_t num_inputs = type->inputs.size();
+ size_t inputs_size = align_up(SocketType::max_size(), 16) * num_inputs;
+ return (char *)this + align_up(sizeof(OSLNode), 16) + inputs_size;
}
void OSLNode::add_input(ustring name, SocketType::Type socket_type)
{
- char *memory = input_default_value();
- size_t offset = memory - (char*)this;
- const_cast<NodeType*>(type)->register_input(name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE);
+ char *memory = input_default_value();
+ size_t offset = memory - (char *)this;
+ const_cast<NodeType *>(type)->register_input(
+ name, name, socket_type, offset, memory, NULL, NULL, SocketType::LINKABLE);
}
void OSLNode::add_output(ustring name, SocketType::Type socket_type)
{
- const_cast<NodeType*>(type)->register_output(name, name, socket_type);
+ const_cast<NodeType *>(type)->register_output(name, name, socket_type);
}
-void OSLNode::compile(SVMCompiler&)
+void OSLNode::compile(SVMCompiler &)
{
- /* doesn't work for SVM, obviously ... */
+ /* doesn't work for SVM, obviously ... */
}
-void OSLNode::compile(OSLCompiler& compiler)
+void OSLNode::compile(OSLCompiler &compiler)
{
- if(!filepath.empty())
- compiler.add(this, filepath.c_str(), true);
- else
- compiler.add(this, bytecode_hash.c_str(), false);
+ if (!filepath.empty())
+ compiler.add(this, filepath.c_str(), true);
+ else
+ compiler.add(this, bytecode_hash.c_str(), false);
}
/* Normal Map */
NODE_DEFINE(NormalMapNode)
{
- NodeType* type = NodeType::add("normal_map", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("normal_map", create, NodeType::SHADER);
- static NodeEnum space_enum;
- space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
- space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
- space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
- space_enum.insert("blender_object", NODE_NORMAL_MAP_BLENDER_OBJECT);
- space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
+ static NodeEnum space_enum;
+ space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
+ space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
+ space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
+ space_enum.insert("blender_object", NODE_NORMAL_MAP_BLENDER_OBJECT);
+ space_enum.insert("blender_world", NODE_NORMAL_MAP_BLENDER_WORLD);
+ SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
- SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
- SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_NORMAL(normal, "Normal");
- return type;
+ return type;
}
-NormalMapNode::NormalMapNode()
-: ShaderNode(node_type)
+NormalMapNode::NormalMapNode() : ShaderNode(node_type)
{
}
void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attributes->add(ATTR_STD_UV_TANGENT);
- attributes->add(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
-
- attributes->add(ATTR_STD_VERTEX_NORMAL);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void NormalMapNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *color_in = input("Color");
- ShaderInput *strength_in = input("Strength");
- ShaderOutput *normal_out = output("Normal");
- int attr = 0, attr_sign = 0;
-
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attr = compiler.attribute(ATTR_STD_UV_TANGENT);
- attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.add_node(NODE_NORMAL_MAP,
- compiler.encode_uchar4(
- compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in),
- compiler.stack_assign(normal_out),
- space),
- attr, attr_sign);
-}
-
-void NormalMapNode::compile(OSLCompiler& compiler)
-{
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- compiler.parameter("attr_name", ustring("geom:tangent"));
- compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
- }
- else {
- compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
- compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.parameter(this, "space");
- compiler.add(this, "node_normal_map");
+ if (shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attributes->add(ATTR_STD_UV_TANGENT);
+ attributes->add(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+
+ attributes->add(ATTR_STD_VERTEX_NORMAL);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void NormalMapNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderInput *strength_in = input("Strength");
+ ShaderOutput *normal_out = output("Normal");
+ int attr = 0, attr_sign = 0;
+
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attr_sign = compiler.attribute(
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.add_node(NODE_NORMAL_MAP,
+ compiler.encode_uchar4(compiler.stack_assign(color_in),
+ compiler.stack_assign(strength_in),
+ compiler.stack_assign(normal_out),
+ space),
+ attr,
+ attr_sign);
+}
+
+void NormalMapNode::compile(OSLCompiler &compiler)
+{
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
+ }
+ else {
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ compiler.parameter("attr_sign_name",
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.parameter(this, "space");
+ compiler.add(this, "node_normal_map");
}
/* Tangent */
NODE_DEFINE(TangentNode)
{
- NodeType* type = NodeType::add("tangent", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("tangent", create, NodeType::SHADER);
- static NodeEnum direction_type_enum;
- direction_type_enum.insert("radial", NODE_TANGENT_RADIAL);
- direction_type_enum.insert("uv_map", NODE_TANGENT_UVMAP);
- SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL);
+ static NodeEnum direction_type_enum;
+ direction_type_enum.insert("radial", NODE_TANGENT_RADIAL);
+ direction_type_enum.insert("uv_map", NODE_TANGENT_UVMAP);
+ SOCKET_ENUM(direction_type, "Direction Type", direction_type_enum, NODE_TANGENT_RADIAL);
- static NodeEnum axis_enum;
- axis_enum.insert("x", NODE_TANGENT_AXIS_X);
- axis_enum.insert("y", NODE_TANGENT_AXIS_Y);
- axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
- SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
+ static NodeEnum axis_enum;
+ axis_enum.insert("x", NODE_TANGENT_AXIS_X);
+ axis_enum.insert("y", NODE_TANGENT_AXIS_Y);
+ axis_enum.insert("z", NODE_TANGENT_AXIS_Z);
+ SOCKET_ENUM(axis, "Axis", axis_enum, NODE_TANGENT_AXIS_X);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- SOCKET_OUT_NORMAL(tangent, "Tangent");
+ SOCKET_IN_NORMAL(normal_osl,
+ "NormalIn",
+ make_float3(0.0f, 0.0f, 0.0f),
+ SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ SOCKET_OUT_NORMAL(tangent, "Tangent");
- return type;
+ return type;
}
-TangentNode::TangentNode()
-: ShaderNode(node_type)
+TangentNode::TangentNode() : ShaderNode(node_type)
{
}
void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface) {
- if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute.empty())
- attributes->add(ATTR_STD_UV_TANGENT);
- else
- attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- }
- else
- attributes->add(ATTR_STD_GENERATED);
- }
+ if (shader->has_surface) {
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ if (attribute.empty())
+ attributes->add(ATTR_STD_UV_TANGENT);
+ else
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+ else
+ attributes->add(ATTR_STD_GENERATED);
+ }
- ShaderNode::attributes(shader, attributes);
+ ShaderNode::attributes(shader, attributes);
}
-void TangentNode::compile(SVMCompiler& compiler)
+void TangentNode::compile(SVMCompiler &compiler)
{
- ShaderOutput *tangent_out = output("Tangent");
- int attr;
+ ShaderOutput *tangent_out = output("Tangent");
+ int attr;
- if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute.empty())
- attr = compiler.attribute(ATTR_STD_UV_TANGENT);
- else
- attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- }
- else
- attr = compiler.attribute(ATTR_STD_GENERATED);
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ if (attribute.empty())
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ else
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+ else
+ attr = compiler.attribute(ATTR_STD_GENERATED);
- compiler.add_node(NODE_TANGENT,
- compiler.encode_uchar4(
- compiler.stack_assign(tangent_out),
- direction_type,
- axis), attr);
+ compiler.add_node(
+ NODE_TANGENT,
+ compiler.encode_uchar4(compiler.stack_assign(tangent_out), direction_type, axis),
+ attr);
}
-void TangentNode::compile(OSLCompiler& compiler)
+void TangentNode::compile(OSLCompiler &compiler)
{
- if(direction_type == NODE_TANGENT_UVMAP) {
- if(attribute.empty())
- compiler.parameter("attr_name", ustring("geom:tangent"));
- else
- compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
- }
+ if (direction_type == NODE_TANGENT_UVMAP) {
+ if (attribute.empty())
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ else
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
- compiler.parameter(this, "direction_type");
- compiler.parameter(this, "axis");
- compiler.add(this, "node_tangent");
+ compiler.parameter(this, "direction_type");
+ compiler.parameter(this, "axis");
+ compiler.add(this, "node_tangent");
}
/* Bevel */
NODE_DEFINE(BevelNode)
{
- NodeType* type = NodeType::add("bevel", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("bevel", create, NodeType::SHADER);
- SOCKET_INT(samples, "Samples", 4);
+ SOCKET_INT(samples, "Samples", 4);
- SOCKET_IN_FLOAT(radius, "Radius", 0.05f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(radius, "Radius", 0.05f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_OUT_NORMAL(bevel, "Normal");
+ SOCKET_OUT_NORMAL(bevel, "Normal");
- return type;
+ return type;
}
-BevelNode::BevelNode()
-: ShaderNode(node_type)
+BevelNode::BevelNode() : ShaderNode(node_type)
{
}
-void BevelNode::compile(SVMCompiler& compiler)
+void BevelNode::compile(SVMCompiler &compiler)
{
- ShaderInput *radius_in = input("Radius");
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *normal_out = output("Normal");
+ ShaderInput *radius_in = input("Radius");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *normal_out = output("Normal");
- compiler.add_node(NODE_BEVEL,
- compiler.encode_uchar4(samples,
- compiler.stack_assign(radius_in),
- compiler.stack_assign_if_linked(normal_in),
- compiler.stack_assign(normal_out)));
+ compiler.add_node(NODE_BEVEL,
+ compiler.encode_uchar4(samples,
+ compiler.stack_assign(radius_in),
+ compiler.stack_assign_if_linked(normal_in),
+ compiler.stack_assign(normal_out)));
}
-void BevelNode::compile(OSLCompiler& compiler)
+void BevelNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "samples");
- compiler.add(this, "node_bevel");
+ compiler.parameter(this, "samples");
+ compiler.add(this, "node_bevel");
}
/* Displacement */
NODE_DEFINE(DisplacementNode)
{
- NodeType* type = NodeType::add("displacement", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("displacement", create, NodeType::SHADER);
- static NodeEnum space_enum;
- space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
- space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
+ static NodeEnum space_enum;
+ space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
+ space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_OBJECT);
+ SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_OBJECT);
- SOCKET_IN_FLOAT(height, "Height", 0.0f);
- SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.5f);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_FLOAT(height, "Height", 0.0f);
+ SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.5f);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
- SOCKET_OUT_VECTOR(displacement, "Displacement");
+ SOCKET_OUT_VECTOR(displacement, "Displacement");
- return type;
+ return type;
}
-DisplacementNode::DisplacementNode()
-: ShaderNode(node_type)
+DisplacementNode::DisplacementNode() : ShaderNode(node_type)
{
}
-void DisplacementNode::constant_fold(const ConstantFolder& folder)
+void DisplacementNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- if((height - midlevel == 0.0f) || (scale == 0.0f)) {
- folder.make_zero();
- }
- }
+ if (folder.all_inputs_constant()) {
+ if ((height - midlevel == 0.0f) || (scale == 0.0f)) {
+ folder.make_zero();
+ }
+ }
}
-void DisplacementNode::compile(SVMCompiler& compiler)
+void DisplacementNode::compile(SVMCompiler &compiler)
{
- ShaderInput *height_in = input("Height");
- ShaderInput *midlevel_in = input("Midlevel");
- ShaderInput *scale_in = input("Scale");
- ShaderInput *normal_in = input("Normal");
- ShaderOutput *displacement_out = output("Displacement");
+ ShaderInput *height_in = input("Height");
+ ShaderInput *midlevel_in = input("Midlevel");
+ ShaderInput *scale_in = input("Scale");
+ ShaderInput *normal_in = input("Normal");
+ ShaderOutput *displacement_out = output("Displacement");
- compiler.add_node(NODE_DISPLACEMENT,
- compiler.encode_uchar4(compiler.stack_assign(height_in),
- compiler.stack_assign(midlevel_in),
- compiler.stack_assign(scale_in),
- compiler.stack_assign_if_linked(normal_in)),
- compiler.stack_assign(displacement_out),
- space);
+ compiler.add_node(NODE_DISPLACEMENT,
+ compiler.encode_uchar4(compiler.stack_assign(height_in),
+ compiler.stack_assign(midlevel_in),
+ compiler.stack_assign(scale_in),
+ compiler.stack_assign_if_linked(normal_in)),
+ compiler.stack_assign(displacement_out),
+ space);
}
-void DisplacementNode::compile(OSLCompiler& compiler)
+void DisplacementNode::compile(OSLCompiler &compiler)
{
- compiler.parameter(this, "space");
- compiler.add(this, "node_displacement");
+ compiler.parameter(this, "space");
+ compiler.add(this, "node_displacement");
}
/* Vector Displacement */
NODE_DEFINE(VectorDisplacementNode)
{
- NodeType* type = NodeType::add("vector_displacement", create, NodeType::SHADER);
+ NodeType *type = NodeType::add("vector_displacement", create, NodeType::SHADER);
- static NodeEnum space_enum;
- space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
- space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
- space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
+ static NodeEnum space_enum;
+ space_enum.insert("tangent", NODE_NORMAL_MAP_TANGENT);
+ space_enum.insert("object", NODE_NORMAL_MAP_OBJECT);
+ space_enum.insert("world", NODE_NORMAL_MAP_WORLD);
- SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
- SOCKET_STRING(attribute, "Attribute", ustring());
+ SOCKET_ENUM(space, "Space", space_enum, NODE_NORMAL_MAP_TANGENT);
+ SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
- SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_COLOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_IN_FLOAT(midlevel, "Midlevel", 0.0f);
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
- SOCKET_OUT_VECTOR(displacement, "Displacement");
+ SOCKET_OUT_VECTOR(displacement, "Displacement");
- return type;
+ return type;
}
-VectorDisplacementNode::VectorDisplacementNode()
-: ShaderNode(node_type)
+VectorDisplacementNode::VectorDisplacementNode() : ShaderNode(node_type)
{
}
-void VectorDisplacementNode::constant_fold(const ConstantFolder& folder)
+void VectorDisplacementNode::constant_fold(const ConstantFolder &folder)
{
- if(folder.all_inputs_constant()) {
- if((vector == make_float3(0.0f, 0.0f, 0.0f) && midlevel == 0.0f) ||
- (scale == 0.0f)) {
- folder.make_zero();
- }
- }
+ if (folder.all_inputs_constant()) {
+ if ((vector == make_float3(0.0f, 0.0f, 0.0f) && midlevel == 0.0f) || (scale == 0.0f)) {
+ folder.make_zero();
+ }
+ }
}
void VectorDisplacementNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attributes->add(ATTR_STD_UV_TANGENT);
- attributes->add(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
-
- attributes->add(ATTR_STD_VERTEX_NORMAL);
- }
-
- ShaderNode::attributes(shader, attributes);
-}
-
-void VectorDisplacementNode::compile(SVMCompiler& compiler)
-{
- ShaderInput *vector_in = input("Vector");
- ShaderInput *midlevel_in = input("Midlevel");
- ShaderInput *scale_in = input("Scale");
- ShaderOutput *displacement_out = output("Displacement");
- int attr = 0, attr_sign = 0;
-
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- attr = compiler.attribute(ATTR_STD_UV_TANGENT);
- attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
- }
- else {
- attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
- attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.add_node(NODE_VECTOR_DISPLACEMENT,
- compiler.encode_uchar4(compiler.stack_assign(vector_in),
- compiler.stack_assign(midlevel_in),
- compiler.stack_assign(scale_in),
- compiler.stack_assign(displacement_out)),
- attr, attr_sign);
-
- compiler.add_node(space);
-}
-
-void VectorDisplacementNode::compile(OSLCompiler& compiler)
-{
- if(space == NODE_NORMAL_MAP_TANGENT) {
- if(attribute.empty()) {
- compiler.parameter("attr_name", ustring("geom:tangent"));
- compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
- }
- else {
- compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
- compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
- }
- }
-
- compiler.parameter(this, "space");
- compiler.add(this, "node_vector_displacement");
+ if (shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attributes->add(ATTR_STD_UV_TANGENT);
+ attributes->add(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+
+ attributes->add(ATTR_STD_VERTEX_NORMAL);
+ }
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void VectorDisplacementNode::compile(SVMCompiler &compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderInput *midlevel_in = input("Midlevel");
+ ShaderInput *scale_in = input("Scale");
+ ShaderOutput *displacement_out = output("Displacement");
+ int attr = 0, attr_sign = 0;
+
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attr_sign = compiler.attribute(
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.add_node(NODE_VECTOR_DISPLACEMENT,
+ compiler.encode_uchar4(compiler.stack_assign(vector_in),
+ compiler.stack_assign(midlevel_in),
+ compiler.stack_assign(scale_in),
+ compiler.stack_assign(displacement_out)),
+ attr,
+ attr_sign);
+
+ compiler.add_node(space);
+}
+
+void VectorDisplacementNode::compile(OSLCompiler &compiler)
+{
+ if (space == NODE_NORMAL_MAP_TANGENT) {
+ if (attribute.empty()) {
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
+ }
+ else {
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ compiler.parameter("attr_sign_name",
+ ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.parameter(this, "space");
+ compiler.add(this, "node_vector_displacement");
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 5571c525e9a..7796711115e 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -33,1137 +33,1459 @@ class Shader;
/* Texture Mapping */
class TextureMapping {
-public:
- TextureMapping();
- Transform compute_transform();
- bool skip();
- void compile(SVMCompiler& compiler, int offset_in, int offset_out);
- int compile(SVMCompiler& compiler, ShaderInput *vector_in);
- void compile(OSLCompiler &compiler);
+ public:
+ TextureMapping();
+ Transform compute_transform();
+ bool skip();
+ void compile(SVMCompiler &compiler, int offset_in, int offset_out);
+ int compile(SVMCompiler &compiler, ShaderInput *vector_in);
+ void compile(OSLCompiler &compiler);
- int compile_begin(SVMCompiler& compiler, ShaderInput *vector_in);
- void compile_end(SVMCompiler& compiler, ShaderInput *vector_in, int vector_offset);
+ int compile_begin(SVMCompiler &compiler, ShaderInput *vector_in);
+ void compile_end(SVMCompiler &compiler, ShaderInput *vector_in, int vector_offset);
- float3 translation;
- float3 rotation;
- float3 scale;
+ float3 translation;
+ float3 rotation;
+ float3 scale;
- float3 min, max;
- bool use_minmax;
+ float3 min, max;
+ bool use_minmax;
- enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
- Type type;
+ enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
+ Type type;
- enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
- Mapping x_mapping, y_mapping, z_mapping;
+ enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
+ Mapping x_mapping, y_mapping, z_mapping;
- enum Projection { FLAT, CUBE, TUBE, SPHERE };
- Projection projection;
+ enum Projection { FLAT, CUBE, TUBE, SPHERE };
+ Projection projection;
};
/* Nodes */
class TextureNode : public ShaderNode {
-public:
- explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type) {}
- TextureMapping tex_mapping;
+ public:
+ explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type)
+ {
+ }
+ TextureMapping tex_mapping;
};
/* Any node which uses image manager's slot should be a subclass of this one. */
class ImageSlotTextureNode : public TextureNode {
-public:
- explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) {
- special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
- }
- int slot;
+ public:
+ explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type)
+ {
+ special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
+ }
+ int slot;
};
class ImageTextureNode : public ImageSlotTextureNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
- ~ImageTextureNode();
- ShaderNode *clone() const;
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
-
- ImageManager *image_manager;
- int is_float;
- bool is_linear;
- bool use_alpha;
- ustring filename;
- void *builtin_data;
- NodeImageColorSpace color_space;
- NodeImageProjection projection;
- InterpolationType interpolation;
- ExtensionType extension;
- float projection_blend;
- bool animated;
- float3 vector;
-
- virtual bool equals(const ShaderNode& other)
- {
- const ImageTextureNode& image_node = (const ImageTextureNode&)other;
- return ImageSlotTextureNode::equals(other) &&
- builtin_data == image_node.builtin_data &&
- animated == image_node.animated;
- }
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
+ ~ImageTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ ImageManager *image_manager;
+ int is_float;
+ bool is_linear;
+ bool use_alpha;
+ ustring filename;
+ void *builtin_data;
+ NodeImageColorSpace color_space;
+ NodeImageProjection projection;
+ InterpolationType interpolation;
+ ExtensionType extension;
+ float projection_blend;
+ bool animated;
+ float3 vector;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const ImageTextureNode &image_node = (const ImageTextureNode &)other;
+ return ImageSlotTextureNode::equals(other) && builtin_data == image_node.builtin_data &&
+ animated == image_node.animated;
+ }
};
class EnvironmentTextureNode : public ImageSlotTextureNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
- ~EnvironmentTextureNode();
- ShaderNode *clone() const;
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
-
- ImageManager *image_manager;
- int is_float;
- bool is_linear;
- bool use_alpha;
- ustring filename;
- void *builtin_data;
- NodeImageColorSpace color_space;
- NodeEnvironmentProjection projection;
- InterpolationType interpolation;
- bool animated;
- float3 vector;
-
- virtual bool equals(const ShaderNode& other)
- {
- const EnvironmentTextureNode& env_node = (const EnvironmentTextureNode&)other;
- return ImageSlotTextureNode::equals(other) &&
- builtin_data == env_node.builtin_data &&
- animated == env_node.animated;
- }
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
+ ~EnvironmentTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
+
+ ImageManager *image_manager;
+ int is_float;
+ bool is_linear;
+ bool use_alpha;
+ ustring filename;
+ void *builtin_data;
+ NodeImageColorSpace color_space;
+ NodeEnvironmentProjection projection;
+ InterpolationType interpolation;
+ bool animated;
+ float3 vector;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const EnvironmentTextureNode &env_node = (const EnvironmentTextureNode &)other;
+ return ImageSlotTextureNode::equals(other) && builtin_data == env_node.builtin_data &&
+ animated == env_node.animated;
+ }
};
class SkyTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(SkyTextureNode)
+ public:
+ SHADER_NODE_CLASS(SkyTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeSkyType type;
- float3 sun_direction;
- float turbidity;
- float ground_albedo;
- float3 vector;
+ NodeSkyType type;
+ float3 sun_direction;
+ float turbidity;
+ float ground_albedo;
+ float3 vector;
};
class OutputNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(OutputNode)
+ public:
+ SHADER_NODE_CLASS(OutputNode)
- void *surface;
- void *volume;
- float3 displacement;
- float3 normal;
+ void *surface;
+ void *volume;
+ float3 displacement;
+ float3 normal;
- /* Don't allow output node de-duplication. */
- virtual bool equals(const ShaderNode& /*other*/) { return false; }
+ /* Don't allow output node de-duplication. */
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
};
class GradientTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(GradientTextureNode)
+ public:
+ SHADER_NODE_CLASS(GradientTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeGradientType type;
- float3 vector;
+ NodeGradientType type;
+ float3 vector;
};
class NoiseTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(NoiseTextureNode)
+ public:
+ SHADER_NODE_CLASS(NoiseTextureNode)
- float scale, detail, distortion;
- float3 vector;
+ float scale, detail, distortion;
+ float3 vector;
};
class VoronoiTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(VoronoiTextureNode)
+ public:
+ SHADER_NODE_CLASS(VoronoiTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeVoronoiColoring coloring;
- NodeVoronoiDistanceMetric metric;
- NodeVoronoiFeature feature;
- float scale, exponent;
- float3 vector;
+ NodeVoronoiColoring coloring;
+ NodeVoronoiDistanceMetric metric;
+ NodeVoronoiFeature feature;
+ float scale, exponent;
+ float3 vector;
};
class MusgraveTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(MusgraveTextureNode)
+ public:
+ SHADER_NODE_CLASS(MusgraveTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeMusgraveType type;
- float scale, detail, dimension, lacunarity, offset, gain;
- float3 vector;
+ NodeMusgraveType type;
+ float scale, detail, dimension, lacunarity, offset, gain;
+ float3 vector;
};
class WaveTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(WaveTextureNode)
+ public:
+ SHADER_NODE_CLASS(WaveTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- NodeWaveType type;
- NodeWaveProfile profile;
+ NodeWaveType type;
+ NodeWaveProfile profile;
- float scale, distortion, detail, detail_scale;
- float3 vector;
+ float scale, distortion, detail, detail_scale;
+ float3 vector;
};
class MagicTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(MagicTextureNode)
+ public:
+ SHADER_NODE_CLASS(MagicTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- int depth;
- float3 vector;
- float scale, distortion;
+ int depth;
+ float3 vector;
+ float scale, distortion;
};
class CheckerTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(CheckerTextureNode)
+ public:
+ SHADER_NODE_CLASS(CheckerTextureNode)
- float3 vector, color1, color2;
- float scale;
+ float3 vector, color1, color2;
+ float scale;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
};
class BrickTextureNode : public TextureNode {
-public:
- SHADER_NODE_CLASS(BrickTextureNode)
+ public:
+ SHADER_NODE_CLASS(BrickTextureNode)
- float offset, squash;
- int offset_frequency, squash_frequency;
+ float offset, squash;
+ int offset_frequency, squash_frequency;
- float3 color1, color2, mortar;
- float scale, mortar_size, mortar_smooth, bias, brick_width, row_height;
- float3 vector;
+ float3 color1, color2, mortar;
+ float scale, mortar_size, mortar_smooth, bias, brick_width, row_height;
+ float3 vector;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
};
class PointDensityTextureNode : public ShaderNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
-
- ~PointDensityTextureNode();
- ShaderNode *clone() const;
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
-
- bool has_spatial_varying() { return true; }
- bool has_object_dependency() { return true; }
-
- void add_image();
-
- ustring filename;
- NodeTexVoxelSpace space;
- InterpolationType interpolation;
- Transform tfm;
- float3 vector;
-
- ImageManager *image_manager;
- int slot;
- void *builtin_data;
-
- virtual bool equals(const ShaderNode& other) {
- const PointDensityTextureNode& point_dendity_node = (const PointDensityTextureNode&)other;
- return ShaderNode::equals(other) &&
- builtin_data == point_dendity_node.builtin_data;
- }
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+
+ ~PointDensityTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_object_dependency()
+ {
+ return true;
+ }
+
+ void add_image();
+
+ ustring filename;
+ NodeTexVoxelSpace space;
+ InterpolationType interpolation;
+ Transform tfm;
+ float3 vector;
+
+ ImageManager *image_manager;
+ int slot;
+ void *builtin_data;
+
+ virtual bool equals(const ShaderNode &other)
+ {
+ const PointDensityTextureNode &point_dendity_node = (const PointDensityTextureNode &)other;
+ return ShaderNode::equals(other) && builtin_data == point_dendity_node.builtin_data;
+ }
};
class IESLightNode : public TextureNode {
-public:
- SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
+ public:
+ SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
- ~IESLightNode();
- ShaderNode *clone() const;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ ~IESLightNode();
+ ShaderNode *clone() const;
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- ustring filename;
- ustring ies;
+ ustring filename;
+ ustring ies;
- float strength;
- float3 vector;
+ float strength;
+ float3 vector;
-private:
- LightManager *light_manager;
- int slot;
+ private:
+ LightManager *light_manager;
+ int slot;
- void get_slot();
+ void get_slot();
};
class MappingNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MappingNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(MappingNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- float3 vector;
- TextureMapping tex_mapping;
+ float3 vector;
+ TextureMapping tex_mapping;
};
class RGBToBWNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(RGBToBWNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(RGBToBWNode)
+ void constant_fold(const ConstantFolder &folder);
- float3 color;
+ float3 color;
};
class ConvertNode : public ShaderNode {
-public:
- ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
- SHADER_NODE_BASE_CLASS(ConvertNode)
+ public:
+ ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
+ SHADER_NODE_BASE_CLASS(ConvertNode)
- void constant_fold(const ConstantFolder& folder);
+ void constant_fold(const ConstantFolder &folder);
- SocketType::Type from, to;
+ SocketType::Type from, to;
- union {
- float value_float;
- int value_int;
- float3 value_color;
- float3 value_vector;
- float3 value_point;
- float3 value_normal;
- };
- ustring value_string;
+ union {
+ float value_float;
+ int value_int;
+ float3 value_color;
+ float3 value_vector;
+ float3 value_point;
+ float3 value_normal;
+ };
+ ustring value_string;
-private:
- static const int MAX_TYPE = 12;
- static bool register_types();
- static Node* create(const NodeType *type);
- static const NodeType *node_types[MAX_TYPE][MAX_TYPE];
- static bool initialized;
+ private:
+ static const int MAX_TYPE = 12;
+ static bool register_types();
+ static Node *create(const NodeType *type);
+ static const NodeType *node_types[MAX_TYPE][MAX_TYPE];
+ static bool initialized;
};
class BsdfBaseNode : public ShaderNode {
-public:
- BsdfBaseNode(const NodeType *node_type);
+ public:
+ BsdfBaseNode(const NodeType *node_type);
- bool has_spatial_varying() { return true; }
- virtual ClosureType get_closure_type() { return closure; }
- virtual bool has_bump();
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return closure;
+ }
+ virtual bool has_bump();
- virtual bool equals(const ShaderNode& /*other*/)
- {
- /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
- return false;
- }
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
+ return false;
+ }
- ClosureType closure;
+ ClosureType closure;
};
class BsdfNode : public BsdfBaseNode {
-public:
- explicit BsdfNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(BsdfNode)
+ public:
+ explicit BsdfNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(BsdfNode)
- void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
+ void compile(SVMCompiler &compiler,
+ ShaderInput *param1,
+ ShaderInput *param2,
+ ShaderInput *param3 = NULL,
+ ShaderInput *param4 = NULL);
- float3 color;
- float3 normal;
- float surface_mix_weight;
+ float3 color;
+ float3 normal;
+ float surface_mix_weight;
};
class AnisotropicBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(AnisotropicBsdfNode)
+ public:
+ SHADER_NODE_CLASS(AnisotropicBsdfNode)
- float3 tangent;
- float roughness, anisotropy, rotation;
- ClosureType distribution;
+ float3 tangent;
+ float roughness, anisotropy, rotation;
+ ClosureType distribution;
- ClosureType get_closure_type() { return distribution; }
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
};
class DiffuseBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(DiffuseBsdfNode)
+ public:
+ SHADER_NODE_CLASS(DiffuseBsdfNode)
- float roughness;
+ float roughness;
};
/* Disney principled BRDF */
class PrincipledBsdfNode : public BsdfBaseNode {
-public:
- SHADER_NODE_CLASS(PrincipledBsdfNode)
-
- bool has_surface_bssrdf();
- bool has_bssrdf_bump();
- void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius,
- ShaderInput *specular, ShaderInput *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic,
- ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_roughness,
- ShaderInput *ior, ShaderInput *transmission, ShaderInput *anisotropic_rotation, ShaderInput *transmission_roughness);
-
- float3 base_color;
- float3 subsurface_color, subsurface_radius;
- float metallic, subsurface, specular, roughness, specular_tint, anisotropic,
- sheen, sheen_tint, clearcoat, clearcoat_roughness, ior, transmission,
- anisotropic_rotation, transmission_roughness;
- float3 normal, clearcoat_normal, tangent;
- float surface_mix_weight;
- ClosureType distribution, distribution_orig;
- ClosureType subsurface_method;
-
- bool has_integrator_dependency();
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
+ public:
+ SHADER_NODE_CLASS(PrincipledBsdfNode)
+
+ bool has_surface_bssrdf();
+ bool has_bssrdf_bump();
+ void compile(SVMCompiler &compiler,
+ ShaderInput *metallic,
+ ShaderInput *subsurface,
+ ShaderInput *subsurface_radius,
+ ShaderInput *specular,
+ ShaderInput *roughness,
+ ShaderInput *specular_tint,
+ ShaderInput *anisotropic,
+ ShaderInput *sheen,
+ ShaderInput *sheen_tint,
+ ShaderInput *clearcoat,
+ ShaderInput *clearcoat_roughness,
+ ShaderInput *ior,
+ ShaderInput *transmission,
+ ShaderInput *anisotropic_rotation,
+ ShaderInput *transmission_roughness);
+
+ float3 base_color;
+ float3 subsurface_color, subsurface_radius;
+ float metallic, subsurface, specular, roughness, specular_tint, anisotropic, sheen, sheen_tint,
+ clearcoat, clearcoat_roughness, ior, transmission, anisotropic_rotation,
+ transmission_roughness;
+ float3 normal, clearcoat_normal, tangent;
+ float surface_mix_weight;
+ ClosureType distribution, distribution_orig;
+ ClosureType subsurface_method;
+
+ bool has_integrator_dependency();
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
};
class TranslucentBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(TranslucentBsdfNode)
+ public:
+ SHADER_NODE_CLASS(TranslucentBsdfNode)
};
class TransparentBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(TransparentBsdfNode)
+ public:
+ SHADER_NODE_CLASS(TransparentBsdfNode)
- bool has_surface_transparent() { return true; }
+ bool has_surface_transparent()
+ {
+ return true;
+ }
};
class VelvetBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(VelvetBsdfNode)
+ public:
+ SHADER_NODE_CLASS(VelvetBsdfNode)
- float sigma;
+ float sigma;
};
class GlossyBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(GlossyBsdfNode)
+ public:
+ SHADER_NODE_CLASS(GlossyBsdfNode)
- void simplify_settings(Scene *scene);
- bool has_integrator_dependency();
- ClosureType get_closure_type() { return distribution; }
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
- float roughness, roughness_orig;
- ClosureType distribution, distribution_orig;
+ float roughness, roughness_orig;
+ ClosureType distribution, distribution_orig;
};
class GlassBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(GlassBsdfNode)
+ public:
+ SHADER_NODE_CLASS(GlassBsdfNode)
- void simplify_settings(Scene *scene);
- bool has_integrator_dependency();
- ClosureType get_closure_type() { return distribution; }
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
- float roughness, roughness_orig, IOR;
- ClosureType distribution, distribution_orig;
+ float roughness, roughness_orig, IOR;
+ ClosureType distribution, distribution_orig;
};
class RefractionBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(RefractionBsdfNode)
+ public:
+ SHADER_NODE_CLASS(RefractionBsdfNode)
- void simplify_settings(Scene *scene);
- bool has_integrator_dependency();
- ClosureType get_closure_type() { return distribution; }
+ void simplify_settings(Scene *scene);
+ bool has_integrator_dependency();
+ ClosureType get_closure_type()
+ {
+ return distribution;
+ }
- float roughness, roughness_orig, IOR;
- ClosureType distribution, distribution_orig;
+ float roughness, roughness_orig, IOR;
+ ClosureType distribution, distribution_orig;
};
class ToonBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(ToonBsdfNode)
+ public:
+ SHADER_NODE_CLASS(ToonBsdfNode)
- float smooth, size;
- ClosureType component;
+ float smooth, size;
+ ClosureType component;
};
class SubsurfaceScatteringNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(SubsurfaceScatteringNode)
- bool has_surface_bssrdf() { return true; }
- bool has_bssrdf_bump();
- ClosureType get_closure_type() { return falloff; }
-
- float scale;
- float3 radius;
- float sharpness;
- float texture_blur;
- ClosureType falloff;
+ public:
+ SHADER_NODE_CLASS(SubsurfaceScatteringNode)
+ bool has_surface_bssrdf()
+ {
+ return true;
+ }
+ bool has_bssrdf_bump();
+ ClosureType get_closure_type()
+ {
+ return falloff;
+ }
+
+ float scale;
+ float3 radius;
+ float sharpness;
+ float texture_blur;
+ ClosureType falloff;
};
class EmissionNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(EmissionNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(EmissionNode)
+ void constant_fold(const ConstantFolder &folder);
- bool has_surface_emission() { return true; }
- bool has_volume_support() { return true; }
+ bool has_surface_emission()
+ {
+ return true;
+ }
+ bool has_volume_support()
+ {
+ return true;
+ }
- float3 color;
- float strength;
- float surface_mix_weight;
+ float3 color;
+ float strength;
+ float surface_mix_weight;
};
class BackgroundNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BackgroundNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(BackgroundNode)
+ void constant_fold(const ConstantFolder &folder);
- float3 color;
- float strength;
- float surface_mix_weight;
+ float3 color;
+ float strength;
+ float surface_mix_weight;
};
class HoldoutNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(HoldoutNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual ClosureType get_closure_type() { return CLOSURE_HOLDOUT_ID; }
+ public:
+ SHADER_NODE_CLASS(HoldoutNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return CLOSURE_HOLDOUT_ID;
+ }
- float surface_mix_weight;
- float volume_mix_weight;
+ float surface_mix_weight;
+ float volume_mix_weight;
};
class AmbientOcclusionNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(AmbientOcclusionNode)
-
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- virtual bool has_raytrace() { return true; }
-
- float3 color;
- float distance;
- float3 normal;
- int samples;
-
- bool only_local;
- bool inside;
+ public:
+ SHADER_NODE_CLASS(AmbientOcclusionNode)
+
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+ virtual bool has_raytrace()
+ {
+ return true;
+ }
+
+ float3 color;
+ float distance;
+ float3 normal;
+ int samples;
+
+ bool only_local;
+ bool inside;
};
class VolumeNode : public ShaderNode {
-public:
- VolumeNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(VolumeNode)
-
- void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual int get_feature() {
- return ShaderNode::get_feature() | NODE_FEATURE_VOLUME;
- }
- virtual ClosureType get_closure_type() { return closure; }
- virtual bool has_volume_support() { return true; }
-
- float3 color;
- float density;
- float volume_mix_weight;
- ClosureType closure;
-
- virtual bool equals(const ShaderNode& /*other*/)
- {
- /* TODO(sergey): With some care Volume nodes can be de-duplicated. */
- return false;
- }
+ public:
+ VolumeNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(VolumeNode)
+
+ void compile(SVMCompiler &compiler, ShaderInput *param1, ShaderInput *param2);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | NODE_FEATURE_VOLUME;
+ }
+ virtual ClosureType get_closure_type()
+ {
+ return closure;
+ }
+ virtual bool has_volume_support()
+ {
+ return true;
+ }
+
+ float3 color;
+ float density;
+ float volume_mix_weight;
+ ClosureType closure;
+
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ /* TODO(sergey): With some care Volume nodes can be de-duplicated. */
+ return false;
+ }
};
class AbsorptionVolumeNode : public VolumeNode {
-public:
- SHADER_NODE_CLASS(AbsorptionVolumeNode)
+ public:
+ SHADER_NODE_CLASS(AbsorptionVolumeNode)
};
class ScatterVolumeNode : public VolumeNode {
-public:
- SHADER_NODE_CLASS(ScatterVolumeNode)
+ public:
+ SHADER_NODE_CLASS(ScatterVolumeNode)
- float anisotropy;
+ float anisotropy;
};
class PrincipledVolumeNode : public VolumeNode {
-public:
- SHADER_NODE_CLASS(PrincipledVolumeNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
-
- ustring density_attribute;
- ustring color_attribute;
- ustring temperature_attribute;
-
- float anisotropy;
- float3 absorption_color;
- float emission_strength;
- float3 emission_color;
- float blackbody_intensity;
- float3 blackbody_tint;
- float temperature;
+ public:
+ SHADER_NODE_CLASS(PrincipledVolumeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+
+ ustring density_attribute;
+ ustring color_attribute;
+ ustring temperature_attribute;
+
+ float anisotropy;
+ float3 absorption_color;
+ float emission_strength;
+ float3 emission_color;
+ float blackbody_intensity;
+ float3 blackbody_tint;
+ float temperature;
};
/* Interface between the I/O sockets and the SVM/OSL backend. */
class PrincipledHairBsdfNode : public BsdfBaseNode {
-public:
- SHADER_NODE_CLASS(PrincipledHairBsdfNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
-
- /* Longitudinal roughness. */
- float roughness;
- /* Azimuthal roughness. */
- float radial_roughness;
- /* Randomization factor for roughnesses. */
- float random_roughness;
- /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
- float coat;
- /* Index of reflection. */
- float ior;
- /* Cuticle tilt angle. */
- float offset;
- /* Direct coloring's color. */
- float3 color;
- /* Melanin concentration. */
- float melanin;
- /* Melanin redness ratio. */
- float melanin_redness;
- /* Dye color. */
- float3 tint;
- /* Randomization factor for melanin quantities. */
- float random_color;
- /* Absorption coefficient (unfiltered). */
- float3 absorption_coefficient;
-
- float3 normal;
- float surface_mix_weight;
- /* If linked, here will be the given random number. */
- float random;
- /* Selected coloring parametrization. */
- NodePrincipledHairParametrization parametrization;
+ public:
+ SHADER_NODE_CLASS(PrincipledHairBsdfNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ /* Longitudinal roughness. */
+ float roughness;
+ /* Azimuthal roughness. */
+ float radial_roughness;
+ /* Randomization factor for roughnesses. */
+ float random_roughness;
+ /* Longitudinal roughness factor for only the diffuse bounce (shiny undercoat). */
+ float coat;
+ /* Index of reflection. */
+ float ior;
+ /* Cuticle tilt angle. */
+ float offset;
+ /* Direct coloring's color. */
+ float3 color;
+ /* Melanin concentration. */
+ float melanin;
+ /* Melanin redness ratio. */
+ float melanin_redness;
+ /* Dye color. */
+ float3 tint;
+ /* Randomization factor for melanin quantities. */
+ float random_color;
+ /* Absorption coefficient (unfiltered). */
+ float3 absorption_coefficient;
+
+ float3 normal;
+ float surface_mix_weight;
+ /* If linked, here will be the given random number. */
+ float random;
+ /* Selected coloring parametrization. */
+ NodePrincipledHairParametrization parametrization;
};
class HairBsdfNode : public BsdfNode {
-public:
- SHADER_NODE_CLASS(HairBsdfNode)
- ClosureType get_closure_type() { return component; }
+ public:
+ SHADER_NODE_CLASS(HairBsdfNode)
+ ClosureType get_closure_type()
+ {
+ return component;
+ }
- ClosureType component;
- float offset;
- float roughness_u;
- float roughness_v;
- float3 tangent;
+ ClosureType component;
+ float offset;
+ float roughness_u;
+ float roughness_v;
+ float3 tangent;
};
class GeometryNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(GeometryNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- int get_group();
-
- float3 normal_osl;
+ public:
+ SHADER_NODE_CLASS(GeometryNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ int get_group();
+
+ float3 normal_osl;
};
class TextureCoordinateNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(TextureCoordinateNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- bool has_object_dependency() { return use_transform; }
-
- float3 normal_osl;
- bool from_dupli;
- bool use_transform;
- Transform ob_tfm;
+ public:
+ SHADER_NODE_CLASS(TextureCoordinateNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_object_dependency()
+ {
+ return use_transform;
+ }
+
+ float3 normal_osl;
+ bool from_dupli;
+ bool use_transform;
+ Transform ob_tfm;
};
class UVMapNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(UVMapNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
-
- ustring attribute;
- bool from_dupli;
+ public:
+ SHADER_NODE_CLASS(UVMapNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+
+ ustring attribute;
+ bool from_dupli;
};
class LightPathNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(LightPathNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(LightPathNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
};
class LightFalloffNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(LightFalloffNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(LightFalloffNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- float strength;
- float smooth;
+ float strength;
+ float smooth;
};
class ObjectInfoNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ObjectInfoNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(ObjectInfoNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
};
class ParticleInfoNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ParticleInfoNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(ParticleInfoNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
};
class HairInfoNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(HairInfoNode)
-
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual int get_feature() {
- return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
- }
+ public:
+ SHADER_NODE_CLASS(HairInfoNode)
+
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ virtual int get_feature()
+ {
+ return ShaderNode::get_feature() | NODE_FEATURE_HAIR;
+ }
};
class ValueNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ValueNode)
+ public:
+ SHADER_NODE_CLASS(ValueNode)
- void constant_fold(const ConstantFolder& folder);
+ void constant_fold(const ConstantFolder &folder);
- float value;
+ float value;
};
class ColorNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(ColorNode)
+ public:
+ SHADER_NODE_CLASS(ColorNode)
- void constant_fold(const ConstantFolder& folder);
+ void constant_fold(const ConstantFolder &folder);
- float3 value;
+ float3 value;
};
class AddClosureNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(AddClosureNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(AddClosureNode)
+ void constant_fold(const ConstantFolder &folder);
};
class MixClosureNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MixClosureNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(MixClosureNode)
+ void constant_fold(const ConstantFolder &folder);
- float fac;
+ float fac;
};
class MixClosureWeightNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MixClosureWeightNode)
+ public:
+ SHADER_NODE_CLASS(MixClosureWeightNode)
- float weight;
- float fac;
+ float weight;
+ float fac;
};
class InvertNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(InvertNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(InvertNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float fac;
- float3 color;
+ float fac;
+ float3 color;
};
class MixNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MixNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(MixNode)
+ void constant_fold(const ConstantFolder &folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- NodeMix type;
- bool use_clamp;
- float3 color1;
- float3 color2;
- float fac;
+ NodeMix type;
+ bool use_clamp;
+ float3 color1;
+ float3 color2;
+ float fac;
};
class CombineRGBNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CombineRGBNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(CombineRGBNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float r, g, b;
+ float r, g, b;
};
class CombineHSVNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CombineHSVNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(CombineHSVNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float h, s, v;
+ float h, s, v;
};
class CombineXYZNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CombineXYZNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(CombineXYZNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float x, y, z;
+ float x, y, z;
};
class GammaNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(GammaNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(GammaNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 color;
- float gamma;
+ float3 color;
+ float gamma;
};
class BrightContrastNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BrightContrastNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(BrightContrastNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 color;
- float bright;
- float contrast;
+ float3 color;
+ float bright;
+ float contrast;
};
class SeparateRGBNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SeparateRGBNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(SeparateRGBNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float3 color;
+ float3 color;
};
class SeparateHSVNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SeparateHSVNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(SeparateHSVNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float3 color;
+ float3 color;
};
class SeparateXYZNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SeparateXYZNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(SeparateXYZNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float3 vector;
+ float3 vector;
};
class HSVNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(HSVNode)
+ public:
+ SHADER_NODE_CLASS(HSVNode)
- float hue;
- float saturation;
- float value;
- float fac;
- float3 color;
+ float hue;
+ float saturation;
+ float value;
+ float fac;
+ float3 color;
};
class AttributeNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(AttributeNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
+ public:
+ SHADER_NODE_CLASS(AttributeNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
- ustring attribute;
+ ustring attribute;
};
class CameraNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(CameraNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(CameraNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
};
class FresnelNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(FresnelNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(FresnelNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 normal;
- float IOR;
+ float3 normal;
+ float IOR;
};
class LayerWeightNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(LayerWeightNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(LayerWeightNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- float3 normal;
- float blend;
+ float3 normal;
+ float blend;
};
class WireframeNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(WireframeNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(WireframeNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float size;
- bool use_pixel_size;
+ float size;
+ bool use_pixel_size;
};
class WavelengthNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(WavelengthNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(WavelengthNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float wavelength;
+ float wavelength;
};
class BlackbodyNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BlackbodyNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ public:
+ SHADER_NODE_CLASS(BlackbodyNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- float temperature;
+ float temperature;
};
class MathNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(MathNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(MathNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ void constant_fold(const ConstantFolder &folder);
- float value1;
- float value2;
- NodeMath type;
- bool use_clamp;
+ float value1;
+ float value2;
+ NodeMath type;
+ bool use_clamp;
};
class NormalNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(NormalNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ public:
+ SHADER_NODE_CLASS(NormalNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_2;
+ }
- float3 direction;
- float3 normal;
+ float3 direction;
+ float3 normal;
};
class VectorMathNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(VectorMathNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(VectorMathNode)
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
+ void constant_fold(const ConstantFolder &folder);
- float3 vector1;
- float3 vector2;
- NodeVectorMath type;
+ float3 vector1;
+ float3 vector2;
+ NodeVectorMath type;
};
class VectorTransformNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(VectorTransformNode)
+ public:
+ SHADER_NODE_CLASS(VectorTransformNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- NodeVectorTransformType type;
- NodeVectorTransformConvertSpace convert_from;
- NodeVectorTransformConvertSpace convert_to;
- float3 vector;
+ NodeVectorTransformType type;
+ NodeVectorTransformConvertSpace convert_from;
+ NodeVectorTransformConvertSpace convert_to;
+ float3 vector;
};
class BumpNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BumpNode)
- void constant_fold(const ConstantFolder& folder);
- bool has_spatial_varying() { return true; }
- virtual int get_feature() {
- return NODE_FEATURE_BUMP;
- }
-
- bool invert;
- bool use_object_space;
- float height;
- float sample_center;
- float sample_x;
- float sample_y;
- float3 normal;
- float strength;
- float distance;
+ public:
+ SHADER_NODE_CLASS(BumpNode)
+ void constant_fold(const ConstantFolder &folder);
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_feature()
+ {
+ return NODE_FEATURE_BUMP;
+ }
+
+ bool invert;
+ bool use_object_space;
+ float height;
+ float sample_center;
+ float sample_x;
+ float sample_y;
+ float3 normal;
+ float strength;
+ float distance;
};
class CurvesNode : public ShaderNode {
-public:
- explicit CurvesNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(CurvesNode)
+ public:
+ explicit CurvesNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(CurvesNode)
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
- array<float3> curves;
- float min_x, max_x, fac;
- float3 value;
+ array<float3> curves;
+ float min_x, max_x, fac;
+ float3 value;
-protected:
- using ShaderNode::constant_fold;
- void constant_fold(const ConstantFolder& folder, ShaderInput *value_in);
- void compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out);
- void compile(OSLCompiler& compiler, const char *name);
+ protected:
+ using ShaderNode::constant_fold;
+ void constant_fold(const ConstantFolder &folder, ShaderInput *value_in);
+ void compile(SVMCompiler &compiler, int type, ShaderInput *value_in, ShaderOutput *value_out);
+ void compile(OSLCompiler &compiler, const char *name);
};
class RGBCurvesNode : public CurvesNode {
-public:
- SHADER_NODE_CLASS(RGBCurvesNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(RGBCurvesNode)
+ void constant_fold(const ConstantFolder &folder);
};
class VectorCurvesNode : public CurvesNode {
-public:
- SHADER_NODE_CLASS(VectorCurvesNode)
- void constant_fold(const ConstantFolder& folder);
+ public:
+ SHADER_NODE_CLASS(VectorCurvesNode)
+ void constant_fold(const ConstantFolder &folder);
};
class RGBRampNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(RGBRampNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+ public:
+ SHADER_NODE_CLASS(RGBRampNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_1;
+ }
- array<float3> ramp;
- array<float> ramp_alpha;
- float fac;
- bool interpolate;
+ array<float3> ramp;
+ array<float> ramp_alpha;
+ float fac;
+ bool interpolate;
};
class SetNormalNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(SetNormalNode)
- float3 direction;
+ public:
+ SHADER_NODE_CLASS(SetNormalNode)
+ float3 direction;
};
class OSLNode : public ShaderNode {
-public:
- static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
- ~OSLNode();
+ public:
+ static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
+ ~OSLNode();
- ShaderNode *clone() const;
+ ShaderNode *clone() const;
- char* input_default_value();
- void add_input(ustring name, SocketType::Type type);
- void add_output(ustring name, SocketType::Type type);
+ char *input_default_value();
+ void add_input(ustring name, SocketType::Type type);
+ void add_output(ustring name, SocketType::Type type);
- SHADER_NODE_NO_CLONE_CLASS(OSLNode)
+ SHADER_NODE_NO_CLONE_CLASS(OSLNode)
- /* ideally we could beter detect this, but we can't query this now */
- bool has_spatial_varying() { return true; }
- bool has_volume_support() { return true; }
+ /* ideally we could beter detect this, but we can't query this now */
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ bool has_volume_support()
+ {
+ return true;
+ }
- virtual bool equals(const ShaderNode& /*other*/) { return false; }
+ virtual bool equals(const ShaderNode & /*other*/)
+ {
+ return false;
+ }
- string filepath;
- string bytecode_hash;
+ string filepath;
+ string bytecode_hash;
};
class NormalMapNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(NormalMapNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
-
- NodeNormalMapSpace space;
- ustring attribute;
- float strength;
- float3 color;
- float3 normal_osl;
+ public:
+ SHADER_NODE_CLASS(NormalMapNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+
+ NodeNormalMapSpace space;
+ ustring attribute;
+ float strength;
+ float3 color;
+ float3 normal_osl;
};
class TangentNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(TangentNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
-
- NodeTangentDirectionType direction_type;
- NodeTangentAxis axis;
- ustring attribute;
- float3 normal_osl;
+ public:
+ SHADER_NODE_CLASS(TangentNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+
+ NodeTangentDirectionType direction_type;
+ NodeTangentAxis axis;
+ ustring attribute;
+ float3 normal_osl;
};
class BevelNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(BevelNode)
- bool has_spatial_varying() { return true; }
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- virtual bool has_raytrace() { return true; }
-
- float radius;
- float3 normal;
- int samples;
+ public:
+ SHADER_NODE_CLASS(BevelNode)
+ bool has_spatial_varying()
+ {
+ return true;
+ }
+ virtual int get_group()
+ {
+ return NODE_GROUP_LEVEL_3;
+ }
+ virtual bool has_raytrace()
+ {
+ return true;
+ }
+
+ float radius;
+ float3 normal;
+ int samples;
};
class DisplacementNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(DisplacementNode)
- void constant_fold(const ConstantFolder& folder);
- virtual int get_feature() {
- return NODE_FEATURE_BUMP;
- }
+ public:
+ SHADER_NODE_CLASS(DisplacementNode)
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_feature()
+ {
+ return NODE_FEATURE_BUMP;
+ }
- NodeNormalMapSpace space;
- float height;
- float midlevel;
- float scale;
- float3 normal;
+ NodeNormalMapSpace space;
+ float height;
+ float midlevel;
+ float scale;
+ float3 normal;
};
class VectorDisplacementNode : public ShaderNode {
-public:
- SHADER_NODE_CLASS(VectorDisplacementNode)
- void attributes(Shader *shader, AttributeRequestSet *attributes);
- bool has_attribute_dependency() { return true; }
- void constant_fold(const ConstantFolder& folder);
- virtual int get_feature() {
- return NODE_FEATURE_BUMP;
- }
-
- NodeNormalMapSpace space;
- ustring attribute;
- float3 vector;
- float midlevel;
- float scale;
+ public:
+ SHADER_NODE_CLASS(VectorDisplacementNode)
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+ bool has_attribute_dependency()
+ {
+ return true;
+ }
+ void constant_fold(const ConstantFolder &folder);
+ virtual int get_feature()
+ {
+ return NODE_FEATURE_BUMP;
+ }
+
+ NodeNormalMapSpace space;
+ ustring attribute;
+ float3 vector;
+ float midlevel;
+ float scale;
};
CCL_NAMESPACE_END
-#endif /* __NODES_H__ */
+#endif /* __NODES_H__ */
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index b34d16c438b..6c6f8810412 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -38,77 +38,76 @@ CCL_NAMESPACE_BEGIN
/* Global state of object transform update. */
struct UpdateObjectTransformState {
- /* Global state used by device_update_object_transform().
- * Common for both threaded and non-threaded update.
- */
+ /* Global state used by device_update_object_transform().
+ * Common for both threaded and non-threaded update.
+ */
- /* Type of the motion required by the scene settings. */
- Scene::MotionType need_motion;
+ /* Type of the motion required by the scene settings. */
+ Scene::MotionType need_motion;
- /* Mapping from particle system to a index in packed particle array.
- * Only used for read.
- */
- map<ParticleSystem*, int> particle_offset;
+ /* Mapping from particle system to a index in packed particle array.
+ * Only used for read.
+ */
+ map<ParticleSystem *, int> particle_offset;
- /* Mesh area.
- * Used to avoid calculation of mesh area multiple times. Used for both
- * read and write. Acquire surface_area_lock to keep it all thread safe.
- */
- map<Mesh*, float> surface_area_map;
+ /* Mesh area.
+ * Used to avoid calculation of mesh area multiple times. Used for both
+ * read and write. Acquire surface_area_lock to keep it all thread safe.
+ */
+ map<Mesh *, float> surface_area_map;
- /* Motion offsets for each object. */
- array<uint> motion_offset;
+ /* Motion offsets for each object. */
+ array<uint> motion_offset;
- /* Packed object arrays. Those will be filled in. */
- uint *object_flag;
- KernelObject *objects;
- Transform *object_motion_pass;
- DecomposedTransform *object_motion;
+ /* Packed object arrays. Those will be filled in. */
+ uint *object_flag;
+ KernelObject *objects;
+ Transform *object_motion_pass;
+ DecomposedTransform *object_motion;
- /* Flags which will be synchronized to Integrator. */
- bool have_motion;
- bool have_curves;
+ /* Flags which will be synchronized to Integrator. */
+ bool have_motion;
+ bool have_curves;
- /* ** Scheduling queue. ** */
+ /* ** Scheduling queue. ** */
- Scene *scene;
+ Scene *scene;
- /* Some locks to keep everything thread-safe. */
- thread_spin_lock queue_lock;
- thread_spin_lock surface_area_lock;
+ /* Some locks to keep everything thread-safe. */
+ thread_spin_lock queue_lock;
+ thread_spin_lock surface_area_lock;
- /* First unused object index in the queue. */
- int queue_start_object;
+ /* First unused object index in the queue. */
+ int queue_start_object;
};
/* Object */
NODE_DEFINE(Object)
{
- NodeType* type = NodeType::add("object", create);
-
- SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
- SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
- SOCKET_UINT(visibility, "Visibility", ~0);
- SOCKET_UINT(random_id, "Random ID", 0);
- SOCKET_INT(pass_id, "Pass ID", 0);
- SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
- SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false);
- SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
- SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
-
- SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
-
- return type;
+ NodeType *type = NodeType::add("object", create);
+
+ SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_UINT(visibility, "Visibility", ~0);
+ SOCKET_UINT(random_id, "Random ID", 0);
+ SOCKET_INT(pass_id, "Pass ID", 0);
+ SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
+ SOCKET_BOOLEAN(hide_on_missing_motion, "Hide on Missing Motion", false);
+ SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
+ SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
+
+ SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
+
+ return type;
}
-Object::Object()
-: Node(node_type)
+Object::Object() : Node(node_type)
{
- particle_system = NULL;
- particle_index = 0;
- bounds = BoundBox::empty;
+ particle_system = NULL;
+ particle_index = 0;
+ bounds = BoundBox::empty;
}
Object::~Object()
@@ -117,768 +116,762 @@ Object::~Object()
void Object::update_motion()
{
- if(!use_motion()) {
- return;
- }
-
- bool have_motion = false;
-
- for(size_t i = 0; i < motion.size(); i++) {
- if(motion[i] == transform_empty()) {
- if(hide_on_missing_motion) {
- /* Hide objects that have no valid previous or next
- * transform, for example particle that stop existing. It
- * would be better to handle this in the kernel and make
- * objects invisible outside certain motion steps. */
- tfm = transform_empty();
- motion.clear();
- return;
- }
- else {
- /* Otherwise just copy center motion. */
- motion[i] = tfm;
- }
- }
-
- /* Test if any of the transforms are actually different. */
- have_motion = have_motion || motion[i] != tfm;
- }
-
- /* Clear motion array if there is no actual motion. */
- if(!have_motion) {
- motion.clear();
- }
+ if (!use_motion()) {
+ return;
+ }
+
+ bool have_motion = false;
+
+ for (size_t i = 0; i < motion.size(); i++) {
+ if (motion[i] == transform_empty()) {
+ if (hide_on_missing_motion) {
+ /* Hide objects that have no valid previous or next
+ * transform, for example particle that stop existing. It
+ * would be better to handle this in the kernel and make
+ * objects invisible outside certain motion steps. */
+ tfm = transform_empty();
+ motion.clear();
+ return;
+ }
+ else {
+ /* Otherwise just copy center motion. */
+ motion[i] = tfm;
+ }
+ }
+
+ /* Test if any of the transforms are actually different. */
+ have_motion = have_motion || motion[i] != tfm;
+ }
+
+ /* Clear motion array if there is no actual motion. */
+ if (!have_motion) {
+ motion.clear();
+ }
}
void Object::compute_bounds(bool motion_blur)
{
- BoundBox mbounds = mesh->bounds;
-
- if(motion_blur && use_motion()) {
- array<DecomposedTransform> decomp(motion.size());
- transform_motion_decompose(decomp.data(), motion.data(), motion.size());
-
- bounds = BoundBox::empty;
-
- /* todo: this is really terrible. according to pbrt there is a better
- * way to find this iteratively, but did not find implementation yet
- * or try to implement myself */
- for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) {
- Transform ttfm;
-
- transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t);
- bounds.grow(mbounds.transformed(&ttfm));
- }
- }
- else {
- /* No motion blur case. */
- if(mesh->transform_applied) {
- bounds = mbounds;
- }
- else {
- bounds = mbounds.transformed(&tfm);
- }
- }
+ BoundBox mbounds = mesh->bounds;
+
+ if (motion_blur && use_motion()) {
+ array<DecomposedTransform> decomp(motion.size());
+ transform_motion_decompose(decomp.data(), motion.data(), motion.size());
+
+ bounds = BoundBox::empty;
+
+ /* todo: this is really terrible. according to pbrt there is a better
+ * way to find this iteratively, but did not find implementation yet
+ * or try to implement myself */
+ for (float t = 0.0f; t < 1.0f; t += (1.0f / 128.0f)) {
+ Transform ttfm;
+
+ transform_motion_array_interpolate(&ttfm, decomp.data(), motion.size(), t);
+ bounds.grow(mbounds.transformed(&ttfm));
+ }
+ }
+ else {
+ /* No motion blur case. */
+ if (mesh->transform_applied) {
+ bounds = mbounds;
+ }
+ else {
+ bounds = mbounds.transformed(&tfm);
+ }
+ }
}
void Object::apply_transform(bool apply_to_motion)
{
- if(!mesh || tfm == transform_identity())
- return;
-
- /* triangles */
- if(mesh->verts.size()) {
- /* store matrix to transform later. when accessing these as attributes we
- * do not want the transform to be applied for consistency between static
- * and dynamic BVH, so we do it on packing. */
- mesh->transform_normal = transform_transposed_inverse(tfm);
-
- /* apply to mesh vertices */
- for(size_t i = 0; i < mesh->verts.size(); i++)
- mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
-
- if(apply_to_motion) {
- Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(attr) {
- size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
- float3 *vert_steps = attr->data_float3();
-
- for(size_t i = 0; i < steps_size; i++)
- vert_steps[i] = transform_point(&tfm, vert_steps[i]);
- }
-
- Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
-
- if(attr_N) {
- Transform ntfm = mesh->transform_normal;
- size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
- float3 *normal_steps = attr_N->data_float3();
-
- for(size_t i = 0; i < steps_size; i++)
- normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
- }
- }
- }
-
- /* curves */
- if(mesh->curve_keys.size()) {
- /* compute uniform scale */
- float3 c0 = transform_get_column(&tfm, 0);
- float3 c1 = transform_get_column(&tfm, 1);
- float3 c2 = transform_get_column(&tfm, 2);
- float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
-
- /* apply transform to curve keys */
- for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
- float3 co = transform_point(&tfm, mesh->curve_keys[i]);
- float radius = mesh->curve_radius[i] * scalar;
-
- /* scale for curve radius is only correct for uniform scale */
- mesh->curve_keys[i] = co;
- mesh->curve_radius[i] = radius;
- }
-
- if(apply_to_motion) {
- Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
- if(curve_attr) {
- /* apply transform to motion curve keys */
- size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
- float4 *key_steps = curve_attr->data_float4();
-
- for(size_t i = 0; i < steps_size; i++) {
- float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
- float radius = key_steps[i].w * scalar;
-
- /* scale for curve radius is only correct for uniform scale */
- key_steps[i] = float3_to_float4(co);
- key_steps[i].w = radius;
- }
- }
- }
- }
-
- /* we keep normals pointing in same direction on negative scale, notify
- * mesh about this in it (re)calculates normals */
- if(transform_negative_scale(tfm))
- mesh->transform_negative_scaled = true;
-
- if(bounds.valid()) {
- mesh->compute_bounds();
- compute_bounds(false);
- }
-
- /* tfm is not reset to identity, all code that uses it needs to check the
- * transform_applied boolean */
+ if (!mesh || tfm == transform_identity())
+ return;
+
+ /* triangles */
+ if (mesh->verts.size()) {
+ /* store matrix to transform later. when accessing these as attributes we
+ * do not want the transform to be applied for consistency between static
+ * and dynamic BVH, so we do it on packing. */
+ mesh->transform_normal = transform_transposed_inverse(tfm);
+
+ /* apply to mesh vertices */
+ for (size_t i = 0; i < mesh->verts.size(); i++)
+ mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
+
+ if (apply_to_motion) {
+ Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (attr) {
+ size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
+ float3 *vert_steps = attr->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ vert_steps[i] = transform_point(&tfm, vert_steps[i]);
+ }
+
+ Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+
+ if (attr_N) {
+ Transform ntfm = mesh->transform_normal;
+ size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
+ float3 *normal_steps = attr_N->data_float3();
+
+ for (size_t i = 0; i < steps_size; i++)
+ normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
+ }
+ }
+ }
+
+ /* curves */
+ if (mesh->curve_keys.size()) {
+ /* compute uniform scale */
+ float3 c0 = transform_get_column(&tfm, 0);
+ float3 c1 = transform_get_column(&tfm, 1);
+ float3 c2 = transform_get_column(&tfm, 2);
+ float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
+
+ /* apply transform to curve keys */
+ for (size_t i = 0; i < mesh->curve_keys.size(); i++) {
+ float3 co = transform_point(&tfm, mesh->curve_keys[i]);
+ float radius = mesh->curve_radius[i] * scalar;
+
+ /* scale for curve radius is only correct for uniform scale */
+ mesh->curve_keys[i] = co;
+ mesh->curve_radius[i] = radius;
+ }
+
+ if (apply_to_motion) {
+ Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ if (curve_attr) {
+ /* apply transform to motion curve keys */
+ size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
+ float4 *key_steps = curve_attr->data_float4();
+
+ for (size_t i = 0; i < steps_size; i++) {
+ float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
+ float radius = key_steps[i].w * scalar;
+
+ /* scale for curve radius is only correct for uniform scale */
+ key_steps[i] = float3_to_float4(co);
+ key_steps[i].w = radius;
+ }
+ }
+ }
+ }
+
+ /* we keep normals pointing in same direction on negative scale, notify
+ * mesh about this in it (re)calculates normals */
+ if (transform_negative_scale(tfm))
+ mesh->transform_negative_scaled = true;
+
+ if (bounds.valid()) {
+ mesh->compute_bounds();
+ compute_bounds(false);
+ }
+
+ /* tfm is not reset to identity, all code that uses it needs to check the
+ * transform_applied boolean */
}
void Object::tag_update(Scene *scene)
{
- if(mesh) {
- if(mesh->transform_applied)
- mesh->need_update = true;
-
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->use_mis && shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
- }
-
- scene->camera->need_flags_update = true;
- scene->curve_system_manager->need_update = true;
- scene->mesh_manager->need_update = true;
- scene->object_manager->need_update = true;
+ if (mesh) {
+ if (mesh->transform_applied)
+ mesh->need_update = true;
+
+ foreach (Shader *shader, mesh->used_shaders) {
+ if (shader->use_mis && shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
+ }
+
+ scene->camera->need_flags_update = true;
+ scene->curve_system_manager->need_update = true;
+ scene->mesh_manager->need_update = true;
+ scene->object_manager->need_update = true;
}
bool Object::use_motion() const
{
- return (motion.size() > 1);
+ return (motion.size() > 1);
}
float Object::motion_time(int step) const
{
- return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
+ return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f;
}
int Object::motion_step(float time) const
{
- if(use_motion()) {
- for(size_t step = 0; step < motion.size(); step++) {
- if(time == motion_time(step)) {
- return step;
- }
- }
- }
-
- return -1;
+ if (use_motion()) {
+ for (size_t step = 0; step < motion.size(); step++) {
+ if (time == motion_time(step)) {
+ return step;
+ }
+ }
+ }
+
+ return -1;
}
bool Object::is_traceable() const
{
- /* Mesh itself can be empty,can skip all such objects. */
- if(!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
- return false;
- }
- /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
- return true;
+ /* Mesh itself can be empty,can skip all such objects. */
+ if (!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
+ return false;
+ }
+ /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
+ return true;
}
-uint Object::visibility_for_tracing() const {
- uint trace_visibility = visibility;
- if(is_shadow_catcher) {
- trace_visibility &= ~PATH_RAY_SHADOW_NON_CATCHER;
- }
- else {
- trace_visibility &= ~PATH_RAY_SHADOW_CATCHER;
- }
- return trace_visibility;
+uint Object::visibility_for_tracing() const
+{
+ uint trace_visibility = visibility;
+ if (is_shadow_catcher) {
+ trace_visibility &= ~PATH_RAY_SHADOW_NON_CATCHER;
+ }
+ else {
+ trace_visibility &= ~PATH_RAY_SHADOW_CATCHER;
+ }
+ return trace_visibility;
}
int Object::get_device_index() const
{
- return index;
+ return index;
}
/* Object Manager */
ObjectManager::ObjectManager()
{
- need_update = true;
- need_flags_update = true;
+ need_update = true;
+ need_flags_update = true;
}
ObjectManager::~ObjectManager()
{
}
-void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state,
- Object *ob)
+void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob)
{
- KernelObject& kobject = state->objects[ob->index];
- Transform *object_motion_pass = state->object_motion_pass;
-
- Mesh *mesh = ob->mesh;
- uint flag = 0;
-
- /* Compute transformations. */
- Transform tfm = ob->tfm;
- Transform itfm = transform_inverse(tfm);
-
- /* Compute surface area. for uniform scale we can do avoid the many
- * transform calls and share computation for instances.
- *
- * TODO(brecht): Correct for displacement, and move to a better place.
- */
- float uniform_scale;
- float surface_area = 0.0f;
- float pass_id = ob->pass_id;
- float random_number = (float)ob->random_id * (1.0f/(float)0xFFFFFFFF);
- int particle_index = (ob->particle_system)
- ? ob->particle_index + state->particle_offset[ob->particle_system]
- : 0;
-
- if(transform_uniform_scale(tfm, uniform_scale)) {
- map<Mesh*, float>::iterator it;
-
- /* NOTE: This isn't fully optimal and could in theory lead to multiple
- * threads calculating area of the same mesh in parallel. However, this
- * also prevents suspending all the threads when some mesh's area is
- * not yet known.
- */
- state->surface_area_lock.lock();
- it = state->surface_area_map.find(mesh);
- state->surface_area_lock.unlock();
-
- if(it == state->surface_area_map.end()) {
- size_t num_triangles = mesh->num_triangles();
- for(size_t j = 0; j < num_triangles; j++) {
- Mesh::Triangle t = mesh->get_triangle(j);
- float3 p1 = mesh->verts[t.v[0]];
- float3 p2 = mesh->verts[t.v[1]];
- float3 p3 = mesh->verts[t.v[2]];
-
- surface_area += triangle_area(p1, p2, p3);
- }
-
- state->surface_area_lock.lock();
- state->surface_area_map[mesh] = surface_area;
- state->surface_area_lock.unlock();
- }
- else {
- surface_area = it->second;
- }
-
- surface_area *= uniform_scale;
- }
- else {
- size_t num_triangles = mesh->num_triangles();
- for(size_t j = 0; j < num_triangles; j++) {
- Mesh::Triangle t = mesh->get_triangle(j);
- float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
- float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
- float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
-
- surface_area += triangle_area(p1, p2, p3);
- }
- }
-
- kobject.tfm = tfm;
- kobject.itfm = itfm;
- kobject.surface_area = surface_area;
- kobject.pass_id = pass_id;
- kobject.random_number = random_number;
- kobject.particle_index = particle_index;
- kobject.motion_offset = 0;
-
- if(mesh->use_motion_blur) {
- state->have_motion = true;
- }
- if(mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
- flag |= SD_OBJECT_HAS_VERTEX_MOTION;
- }
-
- if(state->need_motion == Scene::MOTION_PASS) {
- /* Clear motion array if there is no actual motion. */
- ob->update_motion();
-
- /* Compute motion transforms. */
- Transform tfm_pre, tfm_post;
- if(ob->use_motion()) {
- tfm_pre = ob->motion[0];
- tfm_post = ob->motion[ob->motion.size() - 1];
- }
- else {
- tfm_pre = tfm;
- tfm_post = tfm;
- }
-
- /* Motion transformations, is world/object space depending if mesh
- * comes with deformed position in object space, or if we transform
- * the shading point in world space. */
- if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
- tfm_pre = tfm_pre * itfm;
- tfm_post = tfm_post * itfm;
- }
-
- int motion_pass_offset = ob->index*OBJECT_MOTION_PASS_SIZE;
- object_motion_pass[motion_pass_offset + 0] = tfm_pre;
- object_motion_pass[motion_pass_offset + 1] = tfm_post;
- }
- else if(state->need_motion == Scene::MOTION_BLUR) {
- if(ob->use_motion()) {
- kobject.motion_offset = state->motion_offset[ob->index];
-
- /* Decompose transforms for interpolation. */
- DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
- transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
- flag |= SD_OBJECT_MOTION;
- state->have_motion = true;
- }
- }
-
- /* Dupli object coords and motion info. */
- kobject.dupli_generated[0] = ob->dupli_generated[0];
- kobject.dupli_generated[1] = ob->dupli_generated[1];
- kobject.dupli_generated[2] = ob->dupli_generated[2];
- kobject.numkeys = mesh->curve_keys.size();
- kobject.dupli_uv[0] = ob->dupli_uv[0];
- kobject.dupli_uv[1] = ob->dupli_uv[1];
- int totalsteps = mesh->motion_steps;
- kobject.numsteps = (totalsteps - 1)/2;
- kobject.numverts = mesh->verts.size();
- kobject.patch_map_offset = 0;
- kobject.attribute_map_offset = 0;
- uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
- uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
- kobject.cryptomatte_object = util_hash_to_float(hash_name);
- kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
-
- /* Object flag. */
- if(ob->use_holdout) {
- flag |= SD_OBJECT_HOLDOUT_MASK;
- }
- state->object_flag[ob->index] = flag;
-
- /* Have curves. */
- if(mesh->num_curves()) {
- state->have_curves = true;
- }
+ KernelObject &kobject = state->objects[ob->index];
+ Transform *object_motion_pass = state->object_motion_pass;
+
+ Mesh *mesh = ob->mesh;
+ uint flag = 0;
+
+ /* Compute transformations. */
+ Transform tfm = ob->tfm;
+ Transform itfm = transform_inverse(tfm);
+
+ /* Compute surface area. for uniform scale we can do avoid the many
+ * transform calls and share computation for instances.
+ *
+ * TODO(brecht): Correct for displacement, and move to a better place.
+ */
+ float uniform_scale;
+ float surface_area = 0.0f;
+ float pass_id = ob->pass_id;
+ float random_number = (float)ob->random_id * (1.0f / (float)0xFFFFFFFF);
+ int particle_index = (ob->particle_system) ?
+ ob->particle_index + state->particle_offset[ob->particle_system] :
+ 0;
+
+ if (transform_uniform_scale(tfm, uniform_scale)) {
+ map<Mesh *, float>::iterator it;
+
+ /* NOTE: This isn't fully optimal and could in theory lead to multiple
+ * threads calculating area of the same mesh in parallel. However, this
+ * also prevents suspending all the threads when some mesh's area is
+ * not yet known.
+ */
+ state->surface_area_lock.lock();
+ it = state->surface_area_map.find(mesh);
+ state->surface_area_lock.unlock();
+
+ if (it == state->surface_area_map.end()) {
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ float3 p1 = mesh->verts[t.v[0]];
+ float3 p2 = mesh->verts[t.v[1]];
+ float3 p3 = mesh->verts[t.v[2]];
+
+ surface_area += triangle_area(p1, p2, p3);
+ }
+
+ state->surface_area_lock.lock();
+ state->surface_area_map[mesh] = surface_area;
+ state->surface_area_lock.unlock();
+ }
+ else {
+ surface_area = it->second;
+ }
+
+ surface_area *= uniform_scale;
+ }
+ else {
+ size_t num_triangles = mesh->num_triangles();
+ for (size_t j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
+ float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
+ float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
+
+ surface_area += triangle_area(p1, p2, p3);
+ }
+ }
+
+ kobject.tfm = tfm;
+ kobject.itfm = itfm;
+ kobject.surface_area = surface_area;
+ kobject.pass_id = pass_id;
+ kobject.random_number = random_number;
+ kobject.particle_index = particle_index;
+ kobject.motion_offset = 0;
+
+ if (mesh->use_motion_blur) {
+ state->have_motion = true;
+ }
+ if (mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ flag |= SD_OBJECT_HAS_VERTEX_MOTION;
+ }
+
+ if (state->need_motion == Scene::MOTION_PASS) {
+ /* Clear motion array if there is no actual motion. */
+ ob->update_motion();
+
+ /* Compute motion transforms. */
+ Transform tfm_pre, tfm_post;
+ if (ob->use_motion()) {
+ tfm_pre = ob->motion[0];
+ tfm_post = ob->motion[ob->motion.size() - 1];
+ }
+ else {
+ tfm_pre = tfm;
+ tfm_post = tfm;
+ }
+
+ /* Motion transformations, is world/object space depending if mesh
+ * comes with deformed position in object space, or if we transform
+ * the shading point in world space. */
+ if (!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
+ tfm_pre = tfm_pre * itfm;
+ tfm_post = tfm_post * itfm;
+ }
+
+ int motion_pass_offset = ob->index * OBJECT_MOTION_PASS_SIZE;
+ object_motion_pass[motion_pass_offset + 0] = tfm_pre;
+ object_motion_pass[motion_pass_offset + 1] = tfm_post;
+ }
+ else if (state->need_motion == Scene::MOTION_BLUR) {
+ if (ob->use_motion()) {
+ kobject.motion_offset = state->motion_offset[ob->index];
+
+ /* Decompose transforms for interpolation. */
+ DecomposedTransform *decomp = state->object_motion + kobject.motion_offset;
+ transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size());
+ flag |= SD_OBJECT_MOTION;
+ state->have_motion = true;
+ }
+ }
+
+ /* Dupli object coords and motion info. */
+ kobject.dupli_generated[0] = ob->dupli_generated[0];
+ kobject.dupli_generated[1] = ob->dupli_generated[1];
+ kobject.dupli_generated[2] = ob->dupli_generated[2];
+ kobject.numkeys = mesh->curve_keys.size();
+ kobject.dupli_uv[0] = ob->dupli_uv[0];
+ kobject.dupli_uv[1] = ob->dupli_uv[1];
+ int totalsteps = mesh->motion_steps;
+ kobject.numsteps = (totalsteps - 1) / 2;
+ kobject.numverts = mesh->verts.size();
+ kobject.patch_map_offset = 0;
+ kobject.attribute_map_offset = 0;
+ uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0);
+ uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
+ kobject.cryptomatte_object = util_hash_to_float(hash_name);
+ kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
+
+ /* Object flag. */
+ if (ob->use_holdout) {
+ flag |= SD_OBJECT_HOLDOUT_MASK;
+ }
+ state->object_flag[ob->index] = flag;
+
+ /* Have curves. */
+ if (mesh->num_curves()) {
+ state->have_curves = true;
+ }
}
-bool ObjectManager::device_update_object_transform_pop_work(
- UpdateObjectTransformState *state,
- int *start_index,
- int *num_objects)
+bool ObjectManager::device_update_object_transform_pop_work(UpdateObjectTransformState *state,
+ int *start_index,
+ int *num_objects)
{
- /* Tweakable parameter, number of objects per chunk.
- * Too small value will cause some extra overhead due to spin lock,
- * too big value might not use all threads nicely.
- */
- static const int OBJECTS_PER_TASK = 32;
- bool have_work = false;
- state->queue_lock.lock();
- int num_scene_objects = state->scene->objects.size();
- if(state->queue_start_object < num_scene_objects) {
- int count = min(OBJECTS_PER_TASK,
- num_scene_objects - state->queue_start_object);
- *start_index = state->queue_start_object;
- *num_objects = count;
- state->queue_start_object += count;
- have_work = true;
- }
- state->queue_lock.unlock();
- return have_work;
+ /* Tweakable parameter, number of objects per chunk.
+ * Too small value will cause some extra overhead due to spin lock,
+ * too big value might not use all threads nicely.
+ */
+ static const int OBJECTS_PER_TASK = 32;
+ bool have_work = false;
+ state->queue_lock.lock();
+ int num_scene_objects = state->scene->objects.size();
+ if (state->queue_start_object < num_scene_objects) {
+ int count = min(OBJECTS_PER_TASK, num_scene_objects - state->queue_start_object);
+ *start_index = state->queue_start_object;
+ *num_objects = count;
+ state->queue_start_object += count;
+ have_work = true;
+ }
+ state->queue_lock.unlock();
+ return have_work;
}
-void ObjectManager::device_update_object_transform_task(
- UpdateObjectTransformState *state)
+void ObjectManager::device_update_object_transform_task(UpdateObjectTransformState *state)
{
- int start_index, num_objects;
- while(device_update_object_transform_pop_work(state,
- &start_index,
- &num_objects))
- {
- for(int i = 0; i < num_objects; ++i) {
- const int object_index = start_index + i;
- Object *ob = state->scene->objects[object_index];
- device_update_object_transform(state, ob);
- }
- }
+ int start_index, num_objects;
+ while (device_update_object_transform_pop_work(state, &start_index, &num_objects)) {
+ for (int i = 0; i < num_objects; ++i) {
+ const int object_index = start_index + i;
+ Object *ob = state->scene->objects[object_index];
+ device_update_object_transform(state, ob);
+ }
+ }
}
-void ObjectManager::device_update_transforms(DeviceScene *dscene,
- Scene *scene,
- Progress& progress)
+void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
{
- UpdateObjectTransformState state;
- state.need_motion = scene->need_motion();
- state.have_motion = false;
- state.have_curves = false;
- state.scene = scene;
- state.queue_start_object = 0;
-
- state.objects = dscene->objects.alloc(scene->objects.size());
- state.object_flag = dscene->object_flag.alloc(scene->objects.size());
- state.object_motion = NULL;
- state.object_motion_pass = NULL;
-
- if(state.need_motion == Scene::MOTION_PASS) {
- state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE*scene->objects.size());
- }
- else if(state.need_motion == Scene::MOTION_BLUR) {
- /* Set object offsets into global object motion array. */
- uint *motion_offsets = state.motion_offset.resize(scene->objects.size());
- uint motion_offset = 0;
-
- foreach(Object *ob, scene->objects) {
- *motion_offsets = motion_offset;
- motion_offsets++;
-
- /* Clear motion array if there is no actual motion. */
- ob->update_motion();
- motion_offset += ob->motion.size();
- }
-
- state.object_motion = dscene->object_motion.alloc(motion_offset);
- }
-
- /* Particle system device offsets
- * 0 is dummy particle, index starts at 1.
- */
- int numparticles = 1;
- foreach(ParticleSystem *psys, scene->particle_systems) {
- state.particle_offset[psys] = numparticles;
- numparticles += psys->particles.size();
- }
-
- /* NOTE: If it's just a handful of objects we deal with them in a single
- * thread to avoid threading overhead. However, this threshold is might
- * need some tweaks to make mid-complex scenes optimal.
- */
- if(scene->objects.size() < 64) {
- foreach(Object *ob, scene->objects) {
- device_update_object_transform(&state, ob);
- if(progress.get_cancel()) {
- return;
- }
- }
- }
- else {
- const int num_threads = TaskScheduler::num_threads();
- TaskPool pool;
- for(int i = 0; i < num_threads; ++i) {
- pool.push(function_bind(
- &ObjectManager::device_update_object_transform_task,
- this,
- &state));
- }
- pool.wait_work();
- if(progress.get_cancel()) {
- return;
- }
- }
-
- dscene->objects.copy_to_device();
- if(state.need_motion == Scene::MOTION_PASS) {
- dscene->object_motion_pass.copy_to_device();
- }
- else if(state.need_motion == Scene::MOTION_BLUR) {
- dscene->object_motion.copy_to_device();
- }
-
- dscene->data.bvh.have_motion = state.have_motion;
- dscene->data.bvh.have_curves = state.have_curves;
- dscene->data.bvh.have_instancing = true;
+ UpdateObjectTransformState state;
+ state.need_motion = scene->need_motion();
+ state.have_motion = false;
+ state.have_curves = false;
+ state.scene = scene;
+ state.queue_start_object = 0;
+
+ state.objects = dscene->objects.alloc(scene->objects.size());
+ state.object_flag = dscene->object_flag.alloc(scene->objects.size());
+ state.object_motion = NULL;
+ state.object_motion_pass = NULL;
+
+ if (state.need_motion == Scene::MOTION_PASS) {
+ state.object_motion_pass = dscene->object_motion_pass.alloc(OBJECT_MOTION_PASS_SIZE *
+ scene->objects.size());
+ }
+ else if (state.need_motion == Scene::MOTION_BLUR) {
+ /* Set object offsets into global object motion array. */
+ uint *motion_offsets = state.motion_offset.resize(scene->objects.size());
+ uint motion_offset = 0;
+
+ foreach (Object *ob, scene->objects) {
+ *motion_offsets = motion_offset;
+ motion_offsets++;
+
+ /* Clear motion array if there is no actual motion. */
+ ob->update_motion();
+ motion_offset += ob->motion.size();
+ }
+
+ state.object_motion = dscene->object_motion.alloc(motion_offset);
+ }
+
+ /* Particle system device offsets
+ * 0 is dummy particle, index starts at 1.
+ */
+ int numparticles = 1;
+ foreach (ParticleSystem *psys, scene->particle_systems) {
+ state.particle_offset[psys] = numparticles;
+ numparticles += psys->particles.size();
+ }
+
+ /* NOTE: If it's just a handful of objects we deal with them in a single
+ * thread to avoid threading overhead. However, this threshold is might
+ * need some tweaks to make mid-complex scenes optimal.
+ */
+ if (scene->objects.size() < 64) {
+ foreach (Object *ob, scene->objects) {
+ device_update_object_transform(&state, ob);
+ if (progress.get_cancel()) {
+ return;
+ }
+ }
+ }
+ else {
+ const int num_threads = TaskScheduler::num_threads();
+ TaskPool pool;
+ for (int i = 0; i < num_threads; ++i) {
+ pool.push(function_bind(&ObjectManager::device_update_object_transform_task, this, &state));
+ }
+ pool.wait_work();
+ if (progress.get_cancel()) {
+ return;
+ }
+ }
+
+ dscene->objects.copy_to_device();
+ if (state.need_motion == Scene::MOTION_PASS) {
+ dscene->object_motion_pass.copy_to_device();
+ }
+ else if (state.need_motion == Scene::MOTION_BLUR) {
+ dscene->object_motion.copy_to_device();
+ }
+
+ dscene->data.bvh.have_motion = state.have_motion;
+ dscene->data.bvh.have_curves = state.have_curves;
+ dscene->data.bvh.have_instancing = true;
}
-void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ObjectManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->objects.size() << " objects.";
+ VLOG(1) << "Total " << scene->objects.size() << " objects.";
- device_free(device, dscene);
+ device_free(device, dscene);
- if(scene->objects.size() == 0)
- return;
+ if (scene->objects.size() == 0)
+ return;
- /* Assign object IDs. */
- int index = 0;
- foreach(Object *object, scene->objects) {
- object->index = index++;
- }
+ /* Assign object IDs. */
+ int index = 0;
+ foreach (Object *object, scene->objects) {
+ object->index = index++;
+ }
- /* set object transform matrices, before applying static transforms */
- progress.set_status("Updating Objects", "Copying Transformations to device");
- device_update_transforms(dscene, scene, progress);
+ /* set object transform matrices, before applying static transforms */
+ progress.set_status("Updating Objects", "Copying Transformations to device");
+ device_update_transforms(dscene, scene, progress);
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- /* prepare for static BVH building */
- /* todo: do before to support getting object level coords? */
- if(scene->params.bvh_type == SceneParams::BVH_STATIC) {
- progress.set_status("Updating Objects", "Applying Static Transformations");
- apply_static_transforms(dscene, scene, progress);
- }
+ /* prepare for static BVH building */
+ /* todo: do before to support getting object level coords? */
+ if (scene->params.bvh_type == SceneParams::BVH_STATIC) {
+ progress.set_status("Updating Objects", "Applying Static Transformations");
+ apply_static_transforms(dscene, scene, progress);
+ }
}
-void ObjectManager::device_update_flags(Device *,
- DeviceScene *dscene,
- Scene *scene,
- Progress& /*progress*/,
- bool bounds_valid)
+void ObjectManager::device_update_flags(
+ Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid)
{
- if(!need_update && !need_flags_update)
- return;
-
- need_update = false;
- need_flags_update = false;
-
- if(scene->objects.size() == 0)
- return;
-
- /* Object info flag. */
- uint *object_flag = dscene->object_flag.data();
-
- /* Object volume intersection. */
- vector<Object *> volume_objects;
- bool has_volume_objects = false;
- foreach(Object *object, scene->objects) {
- if(object->mesh->has_volume) {
- if(bounds_valid) {
- volume_objects.push_back(object);
- }
- has_volume_objects = true;
- }
- }
-
- foreach(Object *object, scene->objects) {
- if(object->mesh->has_volume) {
- object_flag[object->index] |= SD_OBJECT_HAS_VOLUME;
- object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
-
- foreach(Attribute& attr, object->mesh->attributes.attributes) {
- if(attr.element == ATTR_ELEMENT_VOXEL) {
- object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
- }
- }
- }
- else {
- object_flag[object->index] &= ~(SD_OBJECT_HAS_VOLUME|SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
- }
- if(object->is_shadow_catcher) {
- object_flag[object->index] |= SD_OBJECT_SHADOW_CATCHER;
- }
- else {
- object_flag[object->index] &= ~SD_OBJECT_SHADOW_CATCHER;
- }
-
- if(bounds_valid) {
- foreach(Object *volume_object, volume_objects) {
- if(object == volume_object) {
- continue;
- }
- if(object->bounds.intersects(volume_object->bounds)) {
- object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
- break;
- }
- }
- }
- else if(has_volume_objects) {
- /* Not really valid, but can't make more reliable in the case
- * of bounds not being up to date.
- */
- object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
- }
- }
-
- /* Copy object flag. */
- dscene->object_flag.copy_to_device();
+ if (!need_update && !need_flags_update)
+ return;
+
+ need_update = false;
+ need_flags_update = false;
+
+ if (scene->objects.size() == 0)
+ return;
+
+ /* Object info flag. */
+ uint *object_flag = dscene->object_flag.data();
+
+ /* Object volume intersection. */
+ vector<Object *> volume_objects;
+ bool has_volume_objects = false;
+ foreach (Object *object, scene->objects) {
+ if (object->mesh->has_volume) {
+ if (bounds_valid) {
+ volume_objects.push_back(object);
+ }
+ has_volume_objects = true;
+ }
+ }
+
+ foreach (Object *object, scene->objects) {
+ if (object->mesh->has_volume) {
+ object_flag[object->index] |= SD_OBJECT_HAS_VOLUME;
+ object_flag[object->index] &= ~SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+
+ foreach (Attribute &attr, object->mesh->attributes.attributes) {
+ if (attr.element == ATTR_ELEMENT_VOXEL) {
+ object_flag[object->index] |= SD_OBJECT_HAS_VOLUME_ATTRIBUTES;
+ }
+ }
+ }
+ else {
+ object_flag[object->index] &= ~(SD_OBJECT_HAS_VOLUME | SD_OBJECT_HAS_VOLUME_ATTRIBUTES);
+ }
+ if (object->is_shadow_catcher) {
+ object_flag[object->index] |= SD_OBJECT_SHADOW_CATCHER;
+ }
+ else {
+ object_flag[object->index] &= ~SD_OBJECT_SHADOW_CATCHER;
+ }
+
+ if (bounds_valid) {
+ foreach (Object *volume_object, volume_objects) {
+ if (object == volume_object) {
+ continue;
+ }
+ if (object->bounds.intersects(volume_object->bounds)) {
+ object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ break;
+ }
+ }
+ }
+ else if (has_volume_objects) {
+ /* Not really valid, but can't make more reliable in the case
+ * of bounds not being up to date.
+ */
+ object_flag[object->index] |= SD_OBJECT_INTERSECTS_VOLUME;
+ }
+ }
+
+ /* Copy object flag. */
+ dscene->object_flag.copy_to_device();
}
void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene)
{
- if(dscene->objects.size() == 0) {
- return;
- }
+ if (dscene->objects.size() == 0) {
+ return;
+ }
- KernelObject *kobjects = dscene->objects.data();
+ KernelObject *kobjects = dscene->objects.data();
- bool update = false;
+ bool update = false;
- foreach(Object *object, scene->objects) {
- Mesh* mesh = object->mesh;
+ foreach (Object *object, scene->objects) {
+ Mesh *mesh = object->mesh;
- if(mesh->patch_table) {
- uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() -
- mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - mesh->patch_offset;
+ if (mesh->patch_table) {
+ uint patch_map_offset = 2 * (mesh->patch_table_offset + mesh->patch_table->total_size() -
+ mesh->patch_table->num_nodes * PATCH_NODE_SIZE) -
+ mesh->patch_offset;
- if(kobjects[object->index].patch_map_offset != patch_map_offset) {
- kobjects[object->index].patch_map_offset = patch_map_offset;
- update = true;
- }
- }
+ if (kobjects[object->index].patch_map_offset != patch_map_offset) {
+ kobjects[object->index].patch_map_offset = patch_map_offset;
+ update = true;
+ }
+ }
- if(kobjects[object->index].attribute_map_offset != mesh->attr_map_offset) {
- kobjects[object->index].attribute_map_offset = mesh->attr_map_offset;
- update = true;
- }
- }
+ if (kobjects[object->index].attribute_map_offset != mesh->attr_map_offset) {
+ kobjects[object->index].attribute_map_offset = mesh->attr_map_offset;
+ update = true;
+ }
+ }
- if(update) {
- dscene->objects.copy_to_device();
- }
+ if (update) {
+ dscene->objects.copy_to_device();
+ }
}
void ObjectManager::device_free(Device *, DeviceScene *dscene)
{
- dscene->objects.free();
- dscene->object_motion_pass.free();
- dscene->object_motion.free();
- dscene->object_flag.free();
+ dscene->objects.free();
+ dscene->object_motion_pass.free();
+ dscene->object_motion.free();
+ dscene->object_flag.free();
}
-void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress)
+void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress)
{
- /* todo: normals and displacement should be done before applying transform! */
- /* todo: create objects/meshes in right order! */
-
- /* counter mesh users */
- map<Mesh*, int> mesh_users;
- Scene::MotionType need_motion = scene->need_motion();
- bool motion_blur = need_motion == Scene::MOTION_BLUR;
- bool apply_to_motion = need_motion != Scene::MOTION_PASS;
- int i = 0;
- bool have_instancing = false;
-
- foreach(Object *object, scene->objects) {
- map<Mesh*, int>::iterator it = mesh_users.find(object->mesh);
-
- if(it == mesh_users.end())
- mesh_users[object->mesh] = 1;
- else
- it->second++;
- }
-
- if(progress.get_cancel()) return;
-
- uint *object_flag = dscene->object_flag.data();
-
- /* apply transforms for objects with single user meshes */
- foreach(Object *object, scene->objects) {
- /* Annoying feedback loop here: we can't use is_instanced() because
- * it'll use uninitialized transform_applied flag.
- *
- * Could be solved by moving reference counter to Mesh.
- */
- if((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
- !object->mesh->has_true_displacement() && object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
- {
- if(!(motion_blur && object->use_motion())) {
- if(!object->mesh->transform_applied) {
- object->apply_transform(apply_to_motion);
- object->mesh->transform_applied = true;
-
- if(progress.get_cancel()) return;
- }
-
- object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
- if(object->mesh->transform_negative_scaled)
- object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
- }
- else
- have_instancing = true;
- }
- else
- have_instancing = true;
-
- i++;
- }
-
- dscene->data.bvh.have_instancing = have_instancing;
+ /* todo: normals and displacement should be done before applying transform! */
+ /* todo: create objects/meshes in right order! */
+
+ /* counter mesh users */
+ map<Mesh *, int> mesh_users;
+ Scene::MotionType need_motion = scene->need_motion();
+ bool motion_blur = need_motion == Scene::MOTION_BLUR;
+ bool apply_to_motion = need_motion != Scene::MOTION_PASS;
+ int i = 0;
+ bool have_instancing = false;
+
+ foreach (Object *object, scene->objects) {
+ map<Mesh *, int>::iterator it = mesh_users.find(object->mesh);
+
+ if (it == mesh_users.end())
+ mesh_users[object->mesh] = 1;
+ else
+ it->second++;
+ }
+
+ if (progress.get_cancel())
+ return;
+
+ uint *object_flag = dscene->object_flag.data();
+
+ /* apply transforms for objects with single user meshes */
+ foreach (Object *object, scene->objects) {
+ /* Annoying feedback loop here: we can't use is_instanced() because
+ * it'll use uninitialized transform_applied flag.
+ *
+ * Could be solved by moving reference counter to Mesh.
+ */
+ if ((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
+ !object->mesh->has_true_displacement() &&
+ object->mesh->subdivision_type == Mesh::SUBDIVISION_NONE) {
+ if (!(motion_blur && object->use_motion())) {
+ if (!object->mesh->transform_applied) {
+ object->apply_transform(apply_to_motion);
+ object->mesh->transform_applied = true;
+
+ if (progress.get_cancel())
+ return;
+ }
+
+ object_flag[i] |= SD_OBJECT_TRANSFORM_APPLIED;
+ if (object->mesh->transform_negative_scaled)
+ object_flag[i] |= SD_OBJECT_NEGATIVE_SCALE_APPLIED;
+ }
+ else
+ have_instancing = true;
+ }
+ else
+ have_instancing = true;
+
+ i++;
+ }
+
+ dscene->data.bvh.have_instancing = have_instancing;
}
void ObjectManager::tag_update(Scene *scene)
{
- need_update = true;
- scene->curve_system_manager->need_update = true;
- scene->mesh_manager->need_update = true;
- scene->light_manager->need_update = true;
+ need_update = true;
+ scene->curve_system_manager->need_update = true;
+ scene->mesh_manager->need_update = true;
+ scene->light_manager->need_update = true;
}
string ObjectManager::get_cryptomatte_objects(Scene *scene)
{
- string manifest = "{";
-
- unordered_set<ustring, ustringHash> objects;
- foreach(Object *object, scene->objects) {
- if(objects.count(object->name)) {
- continue;
- }
- objects.insert(object->name);
- uint32_t hash_name = util_murmur_hash3(object->name.c_str(), object->name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", object->name.c_str(), hash_name);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+
+ unordered_set<ustring, ustringHash> objects;
+ foreach (Object *object, scene->objects) {
+ if (objects.count(object->name)) {
+ continue;
+ }
+ objects.insert(object->name);
+ uint32_t hash_name = util_murmur_hash3(object->name.c_str(), object->name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", object->name.c_str(), hash_name);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
string ObjectManager::get_cryptomatte_assets(Scene *scene)
{
- string manifest = "{";
- unordered_set<ustring, ustringHash> assets;
- foreach(Object *ob, scene->objects) {
- if(assets.count(ob->asset_name)) {
- continue;
- }
- assets.insert(ob->asset_name);
- uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", ob->asset_name.c_str(), hash_asset);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+ unordered_set<ustring, ustringHash> assets;
+ foreach (Object *ob, scene->objects) {
+ if (assets.count(ob->asset_name)) {
+ continue;
+ }
+ assets.insert(ob->asset_name);
+ uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", ob->asset_name.c_str(), hash_asset);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 134f0bc3577..2fd43900da1 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -43,105 +43,101 @@ class ObjectManager;
/* Object */
class Object : public Node {
-public:
- NODE_DECLARE
-
- Mesh *mesh;
- Transform tfm;
- BoundBox bounds;
- uint random_id;
- int pass_id;
- ustring asset_name;
- vector<ParamValue> attributes;
- uint visibility;
- array<Transform> motion;
- bool hide_on_missing_motion;
- bool use_holdout;
- bool is_shadow_catcher;
-
- float3 dupli_generated;
- float2 dupli_uv;
-
- ParticleSystem *particle_system;
- int particle_index;
-
- Object();
- ~Object();
-
- void tag_update(Scene *scene);
-
- void compute_bounds(bool motion_blur);
- void apply_transform(bool apply_to_motion);
-
- /* Convert between normalized -1..1 motion time and index
- * in the motion array. */
- bool use_motion() const;
- float motion_time(int step) const;
- int motion_step(float time) const;
- void update_motion();
-
- /* Check whether object is traceable and it worth adding it to
- * kernel scene.
- */
- bool is_traceable() const;
-
- /* Combine object's visibility with all possible internal run-time
- * determined flags which denotes trace-time visibility.
- */
- uint visibility_for_tracing() const;
-
- /* Returns the index that is used in the kernel for this object. */
- int get_device_index() const;
-
-protected:
- /* Specifies the position of the object in scene->objects and
- * in the device vectors. Gets set in device_update. */
- int index;
-
- friend class ObjectManager;
+ public:
+ NODE_DECLARE
+
+ Mesh *mesh;
+ Transform tfm;
+ BoundBox bounds;
+ uint random_id;
+ int pass_id;
+ ustring asset_name;
+ vector<ParamValue> attributes;
+ uint visibility;
+ array<Transform> motion;
+ bool hide_on_missing_motion;
+ bool use_holdout;
+ bool is_shadow_catcher;
+
+ float3 dupli_generated;
+ float2 dupli_uv;
+
+ ParticleSystem *particle_system;
+ int particle_index;
+
+ Object();
+ ~Object();
+
+ void tag_update(Scene *scene);
+
+ void compute_bounds(bool motion_blur);
+ void apply_transform(bool apply_to_motion);
+
+ /* Convert between normalized -1..1 motion time and index
+ * in the motion array. */
+ bool use_motion() const;
+ float motion_time(int step) const;
+ int motion_step(float time) const;
+ void update_motion();
+
+ /* Check whether object is traceable and it worth adding it to
+ * kernel scene.
+ */
+ bool is_traceable() const;
+
+ /* Combine object's visibility with all possible internal run-time
+ * determined flags which denotes trace-time visibility.
+ */
+ uint visibility_for_tracing() const;
+
+ /* Returns the index that is used in the kernel for this object. */
+ int get_device_index() const;
+
+ protected:
+ /* Specifies the position of the object in scene->objects and
+ * in the device vectors. Gets set in device_update. */
+ int index;
+
+ friend class ObjectManager;
};
/* Object Manager */
class ObjectManager {
-public:
- bool need_update;
- bool need_flags_update;
-
- ObjectManager();
- ~ObjectManager();
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_update_transforms(DeviceScene *dscene,
- Scene *scene,
- Progress& progress);
-
- void device_update_flags(Device *device,
- DeviceScene *dscene,
- Scene *scene,
- Progress& progress,
- bool bounds_valid = true);
- void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
-
- void device_free(Device *device, DeviceScene *dscene);
-
- void tag_update(Scene *scene);
-
- void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress& progress);
-
- string get_cryptomatte_objects(Scene *scene);
- string get_cryptomatte_assets(Scene *scene);
-
-protected:
- void device_update_object_transform(UpdateObjectTransformState *state,
- Object *ob);
- void device_update_object_transform_task(UpdateObjectTransformState *state);
- bool device_update_object_transform_pop_work(
- UpdateObjectTransformState *state,
- int *start_index,
- int *num_objects);
+ public:
+ bool need_update;
+ bool need_flags_update;
+
+ ObjectManager();
+ ~ObjectManager();
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_update_transforms(DeviceScene *dscene, Scene *scene, Progress &progress);
+
+ void device_update_flags(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress,
+ bool bounds_valid = true);
+ void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene);
+
+ void device_free(Device *device, DeviceScene *dscene);
+
+ void tag_update(Scene *scene);
+
+ void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress);
+
+ string get_cryptomatte_objects(Scene *scene);
+ string get_cryptomatte_assets(Scene *scene);
+
+ protected:
+ void device_update_object_transform(UpdateObjectTransformState *state, Object *ob);
+ void device_update_object_transform_task(UpdateObjectTransformState *state);
+ bool device_update_object_transform_pop_work(UpdateObjectTransformState *state,
+ int *start_index,
+ int *num_objects);
};
CCL_NAMESPACE_END
-#endif /* __OBJECT_H__ */
+#endif /* __OBJECT_H__ */
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index c603dc69a16..b66a46938be 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -25,16 +25,16 @@
#ifdef WITH_OSL
-#include "kernel/osl/osl_globals.h"
-#include "kernel/osl/osl_services.h"
-#include "kernel/osl/osl_shader.h"
+# include "kernel/osl/osl_globals.h"
+# include "kernel/osl/osl_services.h"
+# include "kernel/osl/osl_shader.h"
-#include "util/util_foreach.h"
-#include "util/util_logging.h"
-#include "util/util_md5.h"
-#include "util/util_path.h"
-#include "util/util_progress.h"
-#include "util/util_projection.h"
+# include "util/util_foreach.h"
+# include "util/util_logging.h"
+# include "util/util_md5.h"
+# include "util/util_path.h"
+# include "util/util_progress.h"
+# include "util/util_projection.h"
#endif
@@ -58,1151 +58,1140 @@ thread_mutex OSLShaderManager::ss_mutex;
OSLShaderManager::OSLShaderManager()
{
- texture_system_init();
- shading_system_init();
+ texture_system_init();
+ shading_system_init();
}
OSLShaderManager::~OSLShaderManager()
{
- shading_system_free();
- texture_system_free();
+ shading_system_free();
+ texture_system_free();
}
void OSLShaderManager::free_memory()
{
-#ifdef OSL_HAS_BLENDER_CLEANUP_FIX
- /* There is a problem with llvm+osl: The order global destructors across
- * different compilation units run cannot be guaranteed, on windows this means
- * that the llvm destructors run before the osl destructors, causing a crash
- * when the process exits. the OSL in svn has a special cleanup hack to
- * sidestep this behavior */
- OSL::pvt::LLVM_Util::Cleanup();
-#endif
+# ifdef OSL_HAS_BLENDER_CLEANUP_FIX
+ /* There is a problem with llvm+osl: The order global destructors across
+ * different compilation units run cannot be guaranteed, on windows this means
+ * that the llvm destructors run before the osl destructors, causing a crash
+ * when the process exits. the OSL in svn has a special cleanup hack to
+ * sidestep this behavior */
+ OSL::pvt::LLVM_Util::Cleanup();
+# endif
}
void OSLShaderManager::reset(Scene * /*scene*/)
{
- shading_system_free();
- shading_system_init();
+ shading_system_free();
+ shading_system_init();
}
-void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void OSLShaderManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
- device_free(device, dscene, scene);
+ device_free(device, dscene, scene);
- /* determine which shaders are in use */
- device_update_shaders_used(scene);
+ /* determine which shaders are in use */
+ device_update_shaders_used(scene);
- /* create shaders */
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ /* create shaders */
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
- foreach(Shader *shader, scene->shaders) {
- assert(shader->graph);
+ foreach (Shader *shader, scene->shaders) {
+ assert(shader->graph);
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- /* we can only compile one shader at the time as the OSL ShadingSytem
- * has a single state, but we put the lock here so different renders can
- * compile shaders alternating */
- thread_scoped_lock lock(ss_mutex);
+ /* we can only compile one shader at the time as the OSL ShadingSytem
+ * has a single state, but we put the lock here so different renders can
+ * compile shaders alternating */
+ thread_scoped_lock lock(ss_mutex);
- OSLCompiler compiler((void*)this, (void*)ss,
- scene->image_manager,
- scene->light_manager);
- compiler.background = (shader == scene->default_background);
- compiler.compile(scene, og, shader);
+ OSLCompiler compiler((void *)this, (void *)ss, scene->image_manager, scene->light_manager);
+ compiler.background = (shader == scene->default_background);
+ compiler.compile(scene, og, shader);
- if(shader->use_mis && shader->has_surface_emission)
- scene->light_manager->need_update = true;
- }
+ if (shader->use_mis && shader->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
- /* setup shader engine */
- og->ss = ss;
- og->ts = ts;
- og->services = services;
+ /* setup shader engine */
+ og->ss = ss;
+ og->ts = ts;
+ og->services = services;
- int background_id = scene->shader_manager->get_shader_id(scene->default_background);
- og->background_state = og->surface_state[background_id & SHADER_MASK];
- og->use = true;
+ int background_id = scene->shader_manager->get_shader_id(scene->default_background);
+ og->background_state = og->surface_state[background_id & SHADER_MASK];
+ og->use = true;
- foreach(Shader *shader, scene->shaders)
- shader->need_update = false;
+ foreach (Shader *shader, scene->shaders)
+ shader->need_update = false;
- need_update = false;
+ need_update = false;
- /* set texture system */
- scene->image_manager->set_osl_texture_system((void*)ts);
+ /* set texture system */
+ scene->image_manager->set_osl_texture_system((void *)ts);
- device_update_common(device, dscene, scene, progress);
+ device_update_common(device, dscene, scene, progress);
- {
- /* Perform greedyjit optimization.
- *
- * This might waste time on optimizing gorups which are never actually
- * used, but this prevents OSL from allocating data on TLS at render
- * time.
- *
- * This is much better for us because this way we aren't required to
- * stop task scheduler threads to make sure all TLS is clean and don't
- * have issues with TLS data free accessing freed memory if task scheduler
- * is being freed after the Session is freed.
- */
- thread_scoped_lock lock(ss_shared_mutex);
- ss->optimize_all_groups();
- }
+ {
+ /* Perform greedyjit optimization.
+ *
+ * This might waste time on optimizing gorups which are never actually
+ * used, but this prevents OSL from allocating data on TLS at render
+ * time.
+ *
+ * This is much better for us because this way we aren't required to
+ * stop task scheduler threads to make sure all TLS is clean and don't
+ * have issues with TLS data free accessing freed memory if task scheduler
+ * is being freed after the Session is freed.
+ */
+ thread_scoped_lock lock(ss_shared_mutex);
+ ss->optimize_all_groups();
+ }
}
void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
- OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ OSLGlobals *og = (OSLGlobals *)device->osl_memory();
- device_free_common(device, dscene, scene);
+ device_free_common(device, dscene, scene);
- /* clear shader engine */
- og->use = false;
- og->ss = NULL;
- og->ts = NULL;
+ /* clear shader engine */
+ og->use = false;
+ og->ss = NULL;
+ og->ts = NULL;
- og->surface_state.clear();
- og->volume_state.clear();
- og->displacement_state.clear();
- og->bump_state.clear();
- og->background_state.reset();
+ og->surface_state.clear();
+ og->volume_state.clear();
+ og->displacement_state.clear();
+ og->bump_state.clear();
+ og->background_state.reset();
}
void OSLShaderManager::texture_system_init()
{
- /* create texture system, shared between different renders to reduce memory usage */
- thread_scoped_lock lock(ts_shared_mutex);
+ /* create texture system, shared between different renders to reduce memory usage */
+ thread_scoped_lock lock(ts_shared_mutex);
- if(ts_shared_users == 0) {
- ts_shared = TextureSystem::create(true);
+ if (ts_shared_users == 0) {
+ ts_shared = TextureSystem::create(true);
- ts_shared->attribute("automip", 1);
- ts_shared->attribute("autotile", 64);
- ts_shared->attribute("gray_to_rgb", 1);
+ ts_shared->attribute("automip", 1);
+ ts_shared->attribute("autotile", 64);
+ ts_shared->attribute("gray_to_rgb", 1);
- /* effectively unlimited for now, until we support proper mipmap lookups */
- ts_shared->attribute("max_memory_MB", 16384);
- }
+ /* effectively unlimited for now, until we support proper mipmap lookups */
+ ts_shared->attribute("max_memory_MB", 16384);
+ }
- ts = ts_shared;
- ts_shared_users++;
+ ts = ts_shared;
+ ts_shared_users++;
}
void OSLShaderManager::texture_system_free()
{
- /* shared texture system decrease users and destroy if no longer used */
- thread_scoped_lock lock(ts_shared_mutex);
- ts_shared_users--;
+ /* shared texture system decrease users and destroy if no longer used */
+ thread_scoped_lock lock(ts_shared_mutex);
+ ts_shared_users--;
- if(ts_shared_users == 0) {
- ts_shared->invalidate_all(true);
- OSL::TextureSystem::destroy(ts_shared);
- ts_shared = NULL;
- }
+ if (ts_shared_users == 0) {
+ ts_shared->invalidate_all(true);
+ OSL::TextureSystem::destroy(ts_shared);
+ ts_shared = NULL;
+ }
- ts = NULL;
+ ts = NULL;
}
void OSLShaderManager::shading_system_init()
{
- /* create shading system, shared between different renders to reduce memory usage */
- thread_scoped_lock lock(ss_shared_mutex);
-
- if(ss_shared_users == 0) {
- services_shared = new OSLRenderServices();
-
- string shader_path = path_get("shader");
-#ifdef _WIN32
- /* Annoying thing, Cycles stores paths in UTF-8 codepage, so it can
- * operate with file paths with any character. This requires to use wide
- * char functions, but OSL uses old fashioned ANSI functions which means:
- *
- * - We have to convert our paths to ANSI before passing to OSL
- * - OSL can't be used when there's a multi-byte character in the path
- * to the shaders folder.
- */
- shader_path = string_to_ansi(shader_path);
-#endif
-
- ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler);
- ss_shared->attribute("lockgeom", 1);
- ss_shared->attribute("commonspace", "world");
- ss_shared->attribute("searchpath:shader", shader_path);
- ss_shared->attribute("greedyjit", 1);
-
- VLOG(1) << "Using shader search path: " << shader_path;
-
- /* our own ray types */
- static const char *raytypes[] = {
- "camera", /* PATH_RAY_CAMERA */
- "reflection", /* PATH_RAY_REFLECT */
- "refraction", /* PATH_RAY_TRANSMIT */
- "diffuse", /* PATH_RAY_DIFFUSE */
- "glossy", /* PATH_RAY_GLOSSY */
- "singular", /* PATH_RAY_SINGULAR */
- "transparent", /* PATH_RAY_TRANSPARENT */
-
- "shadow", /* PATH_RAY_SHADOW_OPAQUE_NON_CATCHER */
- "shadow", /* PATH_RAY_SHADOW_OPAQUE_CATCHER */
- "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER */
- "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_CATCHER */
-
- "__unused__",
- "volume_scatter", /* PATH_RAY_VOLUME_SCATTER */
- "__unused__",
-
- "__unused__",
- "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- "__unused__",
- };
-
- const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]);
- ss_shared->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
-
- OSLShader::register_closures((OSLShadingSystem*)ss_shared);
-
- loaded_shaders.clear();
- }
-
- ss = ss_shared;
- services = services_shared;
- ss_shared_users++;
+ /* create shading system, shared between different renders to reduce memory usage */
+ thread_scoped_lock lock(ss_shared_mutex);
+
+ if (ss_shared_users == 0) {
+ services_shared = new OSLRenderServices();
+
+ string shader_path = path_get("shader");
+# ifdef _WIN32
+ /* Annoying thing, Cycles stores paths in UTF-8 codepage, so it can
+ * operate with file paths with any character. This requires to use wide
+ * char functions, but OSL uses old fashioned ANSI functions which means:
+ *
+ * - We have to convert our paths to ANSI before passing to OSL
+ * - OSL can't be used when there's a multi-byte character in the path
+ * to the shaders folder.
+ */
+ shader_path = string_to_ansi(shader_path);
+# endif
+
+ ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler);
+ ss_shared->attribute("lockgeom", 1);
+ ss_shared->attribute("commonspace", "world");
+ ss_shared->attribute("searchpath:shader", shader_path);
+ ss_shared->attribute("greedyjit", 1);
+
+ VLOG(1) << "Using shader search path: " << shader_path;
+
+ /* our own ray types */
+ static const char *raytypes[] = {
+ "camera", /* PATH_RAY_CAMERA */
+ "reflection", /* PATH_RAY_REFLECT */
+ "refraction", /* PATH_RAY_TRANSMIT */
+ "diffuse", /* PATH_RAY_DIFFUSE */
+ "glossy", /* PATH_RAY_GLOSSY */
+ "singular", /* PATH_RAY_SINGULAR */
+ "transparent", /* PATH_RAY_TRANSPARENT */
+
+ "shadow", /* PATH_RAY_SHADOW_OPAQUE_NON_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_OPAQUE_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER */
+ "shadow", /* PATH_RAY_SHADOW_TRANSPARENT_CATCHER */
+
+ "__unused__", "volume_scatter", /* PATH_RAY_VOLUME_SCATTER */
+ "__unused__",
+
+ "__unused__", "diffuse_ancestor", /* PATH_RAY_DIFFUSE_ANCESTOR */
+ "__unused__", "__unused__", "__unused__", "__unused__",
+ "__unused__", "__unused__", "__unused__",
+ };
+
+ const int nraytypes = sizeof(raytypes) / sizeof(raytypes[0]);
+ ss_shared->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
+
+ OSLShader::register_closures((OSLShadingSystem *)ss_shared);
+
+ loaded_shaders.clear();
+ }
+
+ ss = ss_shared;
+ services = services_shared;
+ ss_shared_users++;
}
void OSLShaderManager::shading_system_free()
{
- /* shared shading system decrease users and destroy if no longer used */
- thread_scoped_lock lock(ss_shared_mutex);
- ss_shared_users--;
+ /* shared shading system decrease users and destroy if no longer used */
+ thread_scoped_lock lock(ss_shared_mutex);
+ ss_shared_users--;
- if(ss_shared_users == 0) {
- delete ss_shared;
- ss_shared = NULL;
+ if (ss_shared_users == 0) {
+ delete ss_shared;
+ ss_shared = NULL;
- delete services_shared;
- services_shared = NULL;
- }
+ delete services_shared;
+ services_shared = NULL;
+ }
- ss = NULL;
- services = NULL;
+ ss = NULL;
+ services = NULL;
}
-bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
+bool OSLShaderManager::osl_compile(const string &inputfile, const string &outputfile)
{
- vector<string> options;
- string stdosl_path;
- string shader_path = path_get("shader");
+ vector<string> options;
+ string stdosl_path;
+ string shader_path = path_get("shader");
- /* specify output file name */
- options.push_back("-o");
- options.push_back(outputfile);
+ /* specify output file name */
+ options.push_back("-o");
+ options.push_back(outputfile);
- /* specify standard include path */
- string include_path_arg = string("-I") + shader_path;
- options.push_back(include_path_arg);
+ /* specify standard include path */
+ string include_path_arg = string("-I") + shader_path;
+ options.push_back(include_path_arg);
- stdosl_path = path_get("shader/stdosl.h");
+ stdosl_path = path_get("shader/stdosl.h");
- /* compile */
- OSL::OSLCompiler *compiler = new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
- bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
- delete compiler;
+ /* compile */
+ OSL::OSLCompiler *compiler = new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
+ bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
+ delete compiler;
- return ok;
+ return ok;
}
-bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath)
+bool OSLShaderManager::osl_query(OSL::OSLQuery &query, const string &filepath)
{
- string searchpath = path_user_get("shaders");
- return query.open(filepath, searchpath);
+ string searchpath = path_user_get("shaders");
+ return query.open(filepath, searchpath);
}
-static string shader_filepath_hash(const string& filepath, uint64_t modified_time)
+static string shader_filepath_hash(const string &filepath, uint64_t modified_time)
{
- /* compute a hash from filepath and modified time to detect changes */
- MD5Hash md5;
- md5.append((const uint8_t*)filepath.c_str(), filepath.size());
- md5.append((const uint8_t*)&modified_time, sizeof(modified_time));
+ /* compute a hash from filepath and modified time to detect changes */
+ MD5Hash md5;
+ md5.append((const uint8_t *)filepath.c_str(), filepath.size());
+ md5.append((const uint8_t *)&modified_time, sizeof(modified_time));
- return md5.get_hex();
+ return md5.get_hex();
}
-const char *OSLShaderManager::shader_test_loaded(const string& hash)
+const char *OSLShaderManager::shader_test_loaded(const string &hash)
{
- map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
- return (it == loaded_shaders.end())? NULL: it->first.c_str();
+ map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
+ return (it == loaded_shaders.end()) ? NULL : it->first.c_str();
}
-OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string& hash)
+OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string &hash)
{
- map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
- return (it == loaded_shaders.end())? NULL: &it->second;
+ map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
+ return (it == loaded_shaders.end()) ? NULL : &it->second;
}
const char *OSLShaderManager::shader_load_filepath(string filepath)
{
- size_t len = filepath.size();
- string extension = filepath.substr(len - 4);
- uint64_t modified_time = path_modified_time(filepath);
-
- if(extension == ".osl") {
- /* .OSL File */
- string osopath = filepath.substr(0, len - 4) + ".oso";
- uint64_t oso_modified_time = path_modified_time(osopath);
-
- /* test if we have loaded the corresponding .OSO already */
- if(oso_modified_time != 0) {
- const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
-
- if(hash)
- return hash;
- }
-
- /* autocompile .OSL to .OSO if needed */
- if(oso_modified_time == 0 || (oso_modified_time < modified_time)) {
- OSLShaderManager::osl_compile(filepath, osopath);
- modified_time = path_modified_time(osopath);
- }
- else
- modified_time = oso_modified_time;
-
- filepath = osopath;
- }
- else {
- if(extension == ".oso") {
- /* .OSO File, nothing to do */
- }
- else if(path_dirname(filepath) == "") {
- /* .OSO File in search path */
- filepath = path_join(path_user_get("shaders"), filepath + ".oso");
- }
- else {
- /* unknown file */
- return NULL;
- }
-
- /* test if we have loaded this .OSO already */
- const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
-
- if(hash)
- return hash;
- }
-
- /* read oso bytecode from file */
- string bytecode_hash = shader_filepath_hash(filepath, modified_time);
- string bytecode;
-
- if(!path_read_text(filepath, bytecode)) {
- fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
- OSLShaderInfo info;
- loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
- return NULL;
- }
-
- return shader_load_bytecode(bytecode_hash, bytecode);
+ size_t len = filepath.size();
+ string extension = filepath.substr(len - 4);
+ uint64_t modified_time = path_modified_time(filepath);
+
+ if (extension == ".osl") {
+ /* .OSL File */
+ string osopath = filepath.substr(0, len - 4) + ".oso";
+ uint64_t oso_modified_time = path_modified_time(osopath);
+
+ /* test if we have loaded the corresponding .OSO already */
+ if (oso_modified_time != 0) {
+ const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
+
+ if (hash)
+ return hash;
+ }
+
+ /* autocompile .OSL to .OSO if needed */
+ if (oso_modified_time == 0 || (oso_modified_time < modified_time)) {
+ OSLShaderManager::osl_compile(filepath, osopath);
+ modified_time = path_modified_time(osopath);
+ }
+ else
+ modified_time = oso_modified_time;
+
+ filepath = osopath;
+ }
+ else {
+ if (extension == ".oso") {
+ /* .OSO File, nothing to do */
+ }
+ else if (path_dirname(filepath) == "") {
+ /* .OSO File in search path */
+ filepath = path_join(path_user_get("shaders"), filepath + ".oso");
+ }
+ else {
+ /* unknown file */
+ return NULL;
+ }
+
+ /* test if we have loaded this .OSO already */
+ const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
+
+ if (hash)
+ return hash;
+ }
+
+ /* read oso bytecode from file */
+ string bytecode_hash = shader_filepath_hash(filepath, modified_time);
+ string bytecode;
+
+ if (!path_read_text(filepath, bytecode)) {
+ fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
+ OSLShaderInfo info;
+ loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
+ return NULL;
+ }
+
+ return shader_load_bytecode(bytecode_hash, bytecode);
}
-const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode)
+const char *OSLShaderManager::shader_load_bytecode(const string &hash, const string &bytecode)
{
- ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
+ ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
- OSLShaderInfo info;
+ OSLShaderInfo info;
- if(!info.query.open_bytecode(bytecode)) {
- fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str());
- }
+ if (!info.query.open_bytecode(bytecode)) {
+ fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str());
+ }
- /* this is a bit weak, but works */
- info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
- info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
- info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
+ /* this is a bit weak, but works */
+ info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
+ info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
+ info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
- loaded_shaders[hash] = info;
+ loaded_shaders[hash] = info;
- return loaded_shaders.find(hash)->first.c_str();
+ return loaded_shaders.find(hash)->first.c_str();
}
-OSLNode *OSLShaderManager::osl_node(const std::string& filepath,
- const std::string& bytecode_hash,
- const std::string& bytecode)
+OSLNode *OSLShaderManager::osl_node(const std::string &filepath,
+ const std::string &bytecode_hash,
+ const std::string &bytecode)
{
- /* create query */
- const char *hash;
-
- if(!filepath.empty()) {
- hash = shader_load_filepath(filepath);
- }
- else {
- hash = shader_test_loaded(bytecode_hash);
- if(!hash)
- hash = shader_load_bytecode(bytecode_hash, bytecode);
- }
-
- if(!hash) {
- return NULL;
- }
-
- OSLShaderInfo *info = shader_loaded_info(hash);
-
- /* count number of inputs */
- size_t num_inputs = 0;
-
- for(int i = 0; i < info->query.nparams(); i++) {
- const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
-
- /* skip unsupported types */
- if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
- continue;
-
- if(!param->isoutput)
- num_inputs++;
- }
-
- /* create node */
- OSLNode *node = OSLNode::create(num_inputs);
-
- /* add new sockets from parameters */
- set<void*> used_sockets;
-
- for(int i = 0; i < info->query.nparams(); i++) {
- const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
-
- /* skip unsupported types */
- if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
- continue;
-
- SocketType::Type socket_type;
-
- if(param->isclosure) {
- socket_type = SocketType::CLOSURE;
- }
- else if(param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
- if(param->type.vecsemantics == TypeDesc::COLOR)
- socket_type = SocketType::COLOR;
- else if(param->type.vecsemantics == TypeDesc::POINT)
- socket_type = SocketType::POINT;
- else if(param->type.vecsemantics == TypeDesc::VECTOR)
- socket_type = SocketType::VECTOR;
- else if(param->type.vecsemantics == TypeDesc::NORMAL)
- socket_type = SocketType::NORMAL;
- else
- continue;
-
- if(!param->isoutput && param->validdefault) {
- float3 *default_value = (float3*)node->input_default_value();
- default_value->x = param->fdefault[0];
- default_value->y = param->fdefault[1];
- default_value->z = param->fdefault[2];
- }
- }
- else if(param->type.aggregate == TypeDesc::SCALAR) {
- if(param->type.basetype == TypeDesc::INT) {
- socket_type = SocketType::INT;
-
- if(!param->isoutput && param->validdefault) {
- *(int*)node->input_default_value() = param->idefault[0];
- }
- }
- else if(param->type.basetype == TypeDesc::FLOAT) {
- socket_type = SocketType::FLOAT;
-
- if(!param->isoutput && param->validdefault) {
- *(float*)node->input_default_value() = param->fdefault[0];
- }
- }
- else if(param->type.basetype == TypeDesc::STRING) {
- socket_type = SocketType::STRING;
-
- if(!param->isoutput && param->validdefault) {
- *(ustring*)node->input_default_value() = param->sdefault[0];
- }
- }
- else
- continue;
- }
- else
- continue;
-
- if(param->isoutput) {
- node->add_output(param->name, socket_type);
- }
- else {
- node->add_input(param->name, socket_type);
- }
- }
-
- /* set bytcode hash or filepath */
- if(!bytecode_hash.empty()) {
- node->bytecode_hash = bytecode_hash;
- }
- else {
- node->filepath = filepath;
- }
-
- /* Generate inputs and outputs */
- node->create_inputs_outputs(node->type);
-
- return node;
+ /* create query */
+ const char *hash;
+
+ if (!filepath.empty()) {
+ hash = shader_load_filepath(filepath);
+ }
+ else {
+ hash = shader_test_loaded(bytecode_hash);
+ if (!hash)
+ hash = shader_load_bytecode(bytecode_hash, bytecode);
+ }
+
+ if (!hash) {
+ return NULL;
+ }
+
+ OSLShaderInfo *info = shader_loaded_info(hash);
+
+ /* count number of inputs */
+ size_t num_inputs = 0;
+
+ for (int i = 0; i < info->query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
+
+ /* skip unsupported types */
+ if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ if (!param->isoutput)
+ num_inputs++;
+ }
+
+ /* create node */
+ OSLNode *node = OSLNode::create(num_inputs);
+
+ /* add new sockets from parameters */
+ set<void *> used_sockets;
+
+ for (int i = 0; i < info->query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
+
+ /* skip unsupported types */
+ if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ SocketType::Type socket_type;
+
+ if (param->isclosure) {
+ socket_type = SocketType::CLOSURE;
+ }
+ else if (param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
+ if (param->type.vecsemantics == TypeDesc::COLOR)
+ socket_type = SocketType::COLOR;
+ else if (param->type.vecsemantics == TypeDesc::POINT)
+ socket_type = SocketType::POINT;
+ else if (param->type.vecsemantics == TypeDesc::VECTOR)
+ socket_type = SocketType::VECTOR;
+ else if (param->type.vecsemantics == TypeDesc::NORMAL)
+ socket_type = SocketType::NORMAL;
+ else
+ continue;
+
+ if (!param->isoutput && param->validdefault) {
+ float3 *default_value = (float3 *)node->input_default_value();
+ default_value->x = param->fdefault[0];
+ default_value->y = param->fdefault[1];
+ default_value->z = param->fdefault[2];
+ }
+ }
+ else if (param->type.aggregate == TypeDesc::SCALAR) {
+ if (param->type.basetype == TypeDesc::INT) {
+ socket_type = SocketType::INT;
+
+ if (!param->isoutput && param->validdefault) {
+ *(int *)node->input_default_value() = param->idefault[0];
+ }
+ }
+ else if (param->type.basetype == TypeDesc::FLOAT) {
+ socket_type = SocketType::FLOAT;
+
+ if (!param->isoutput && param->validdefault) {
+ *(float *)node->input_default_value() = param->fdefault[0];
+ }
+ }
+ else if (param->type.basetype == TypeDesc::STRING) {
+ socket_type = SocketType::STRING;
+
+ if (!param->isoutput && param->validdefault) {
+ *(ustring *)node->input_default_value() = param->sdefault[0];
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ if (param->isoutput) {
+ node->add_output(param->name, socket_type);
+ }
+ else {
+ node->add_input(param->name, socket_type);
+ }
+ }
+
+ /* set bytcode hash or filepath */
+ if (!bytecode_hash.empty()) {
+ node->bytecode_hash = bytecode_hash;
+ }
+ else {
+ node->filepath = filepath;
+ }
+
+ /* Generate inputs and outputs */
+ node->create_inputs_outputs(node->type);
+
+ return node;
}
/* Graph Compiler */
-OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_,
+OSLCompiler::OSLCompiler(void *manager_,
+ void *shadingsys_,
ImageManager *image_manager_,
LightManager *light_manager_)
{
- manager = manager_;
- shadingsys = shadingsys_;
- image_manager = image_manager_;
- light_manager = light_manager_;
- current_type = SHADER_TYPE_SURFACE;
- current_shader = NULL;
- background = false;
+ manager = manager_;
+ shadingsys = shadingsys_;
+ image_manager = image_manager_;
+ light_manager = light_manager_;
+ current_type = SHADER_TYPE_SURFACE;
+ current_shader = NULL;
+ background = false;
}
string OSLCompiler::id(ShaderNode *node)
{
- /* assign layer unique name based on pointer address + bump mode */
- stringstream stream;
- stream << "node_" << node->type->name << "_" << node;
+ /* assign layer unique name based on pointer address + bump mode */
+ stringstream stream;
+ stream << "node_" << node->type->name << "_" << node;
- return stream.str();
+ return stream.str();
}
string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
{
- string sname(input->name().string());
- size_t i;
-
- /* strip whitespace */
- while((i = sname.find(" ")) != string::npos)
- sname.replace(i, 1, "");
-
- /* if output exists with the same name, add "In" suffix */
- foreach(ShaderOutput *output, node->outputs) {
- if(input->name() == output->name()) {
- sname += "In";
- break;
- }
- }
-
- return sname;
+ string sname(input->name().string());
+ size_t i;
+
+ /* strip whitespace */
+ while ((i = sname.find(" ")) != string::npos)
+ sname.replace(i, 1, "");
+
+ /* if output exists with the same name, add "In" suffix */
+ foreach (ShaderOutput *output, node->outputs) {
+ if (input->name() == output->name()) {
+ sname += "In";
+ break;
+ }
+ }
+
+ return sname;
}
string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
{
- string sname(output->name().string());
- size_t i;
-
- /* strip whitespace */
- while((i = sname.find(" ")) != string::npos)
- sname.replace(i, 1, "");
-
- /* if input exists with the same name, add "Out" suffix */
- foreach(ShaderInput *input, node->inputs) {
- if(input->name() == output->name()) {
- sname += "Out";
- break;
- }
- }
-
- return sname;
+ string sname(output->name().string());
+ size_t i;
+
+ /* strip whitespace */
+ while ((i = sname.find(" ")) != string::npos)
+ sname.replace(i, 1, "");
+
+ /* if input exists with the same name, add "Out" suffix */
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->name() == output->name()) {
+ sname += "Out";
+ break;
+ }
+ }
+
+ return sname;
}
bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
{
- /* exception for output node, only one input is actually used
- * depending on the current shader type */
-
- if(input->flags() & SocketType::SVM_INTERNAL)
- return true;
-
- if(node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
- if(input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
- return true;
- if(input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
- return true;
- if(input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
- return true;
- if(input->name() == "Normal" && current_type != SHADER_TYPE_BUMP)
- return true;
- }
- else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
- if(input->name() == "Height")
- return true;
- }
- else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
- return true;
-
- return false;
+ /* exception for output node, only one input is actually used
+ * depending on the current shader type */
+
+ if (input->flags() & SocketType::SVM_INTERNAL)
+ return true;
+
+ if (node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
+ if (input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
+ return true;
+ if (input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
+ return true;
+ if (input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
+ return true;
+ if (input->name() == "Normal" && current_type != SHADER_TYPE_BUMP)
+ return true;
+ }
+ else if (node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
+ if (input->name() == "Height")
+ return true;
+ }
+ else if (current_type == SHADER_TYPE_DISPLACEMENT && input->link &&
+ input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
+ return true;
+
+ return false;
}
void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
-
- /* load filepath */
- if(isfilepath) {
- name = ((OSLShaderManager*)manager)->shader_load_filepath(name);
-
- if(name == NULL)
- return;
- }
-
- /* pass in fixed parameter values */
- foreach(ShaderInput *input, node->inputs) {
- if(!input->link) {
- /* checks to untangle graphs */
- if(node_skip_input(node, input))
- continue;
- /* already has default value assigned */
- else if(input->flags() & SocketType::DEFAULT_LINK_MASK)
- continue;
-
- string param_name = compatible_name(node, input);
- const SocketType& socket = input->socket_type;
- switch(input->type()) {
- case SocketType::COLOR:
- parameter_color(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::POINT:
- parameter_point(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::VECTOR:
- parameter_vector(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::NORMAL:
- parameter_normal(param_name.c_str(), node->get_float3(socket));
- break;
- case SocketType::FLOAT:
- parameter(param_name.c_str(), node->get_float(socket));
- break;
- case SocketType::INT:
- parameter(param_name.c_str(), node->get_int(socket));
- break;
- case SocketType::STRING:
- parameter(param_name.c_str(), node->get_string(socket));
- break;
- case SocketType::CLOSURE:
- case SocketType::UNDEFINED:
- default:
- break;
- }
- }
- }
-
- /* create shader of the appropriate type. OSL only distinguishes between "surface"
- * and "displacement" atm */
- if(current_type == SHADER_TYPE_SURFACE)
- ss->Shader("surface", name, id(node).c_str());
- else if(current_type == SHADER_TYPE_VOLUME)
- ss->Shader("surface", name, id(node).c_str());
- else if(current_type == SHADER_TYPE_DISPLACEMENT)
- ss->Shader("displacement", name, id(node).c_str());
- else if(current_type == SHADER_TYPE_BUMP)
- ss->Shader("displacement", name, id(node).c_str());
- else
- assert(0);
-
- /* link inputs to other nodes */
- foreach(ShaderInput *input, node->inputs) {
- if(input->link) {
- if(node_skip_input(node, input))
- continue;
-
- /* connect shaders */
- string id_from = id(input->link->parent);
- string id_to = id(node);
- string param_from = compatible_name(input->link->parent, input->link);
- string param_to = compatible_name(node, input);
-
- ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
- }
- }
-
- /* test if we shader contains specific closures */
- OSLShaderInfo *info = ((OSLShaderManager*)manager)->shader_loaded_info(name);
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(info) {
- if(info->has_surface_emission)
- current_shader->has_surface_emission = true;
- if(info->has_surface_transparent)
- current_shader->has_surface_transparent = true;
- if(info->has_surface_bssrdf) {
- current_shader->has_surface_bssrdf = true;
- current_shader->has_bssrdf_bump = true; /* can't detect yet */
- }
- current_shader->has_bump = true; /* can't detect yet */
- }
-
- if(node->has_spatial_varying()) {
- current_shader->has_surface_spatial_varying = true;
- }
- }
- else if(current_type == SHADER_TYPE_VOLUME) {
- if(node->has_spatial_varying())
- current_shader->has_volume_spatial_varying = true;
- }
-
- if(node->has_object_dependency()) {
- current_shader->has_object_dependency = true;
- }
-
- if(node->has_attribute_dependency()) {
- current_shader->has_attribute_dependency = true;
- }
-
- if(node->has_integrator_dependency()) {
- current_shader->has_integrator_dependency = true;
- }
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+
+ /* load filepath */
+ if (isfilepath) {
+ name = ((OSLShaderManager *)manager)->shader_load_filepath(name);
+
+ if (name == NULL)
+ return;
+ }
+
+ /* pass in fixed parameter values */
+ foreach (ShaderInput *input, node->inputs) {
+ if (!input->link) {
+ /* checks to untangle graphs */
+ if (node_skip_input(node, input))
+ continue;
+ /* already has default value assigned */
+ else if (input->flags() & SocketType::DEFAULT_LINK_MASK)
+ continue;
+
+ string param_name = compatible_name(node, input);
+ const SocketType &socket = input->socket_type;
+ switch (input->type()) {
+ case SocketType::COLOR:
+ parameter_color(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::POINT:
+ parameter_point(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::VECTOR:
+ parameter_vector(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::NORMAL:
+ parameter_normal(param_name.c_str(), node->get_float3(socket));
+ break;
+ case SocketType::FLOAT:
+ parameter(param_name.c_str(), node->get_float(socket));
+ break;
+ case SocketType::INT:
+ parameter(param_name.c_str(), node->get_int(socket));
+ break;
+ case SocketType::STRING:
+ parameter(param_name.c_str(), node->get_string(socket));
+ break;
+ case SocketType::CLOSURE:
+ case SocketType::UNDEFINED:
+ default:
+ break;
+ }
+ }
+ }
+
+ /* create shader of the appropriate type. OSL only distinguishes between "surface"
+ * and "displacement" atm */
+ if (current_type == SHADER_TYPE_SURFACE)
+ ss->Shader("surface", name, id(node).c_str());
+ else if (current_type == SHADER_TYPE_VOLUME)
+ ss->Shader("surface", name, id(node).c_str());
+ else if (current_type == SHADER_TYPE_DISPLACEMENT)
+ ss->Shader("displacement", name, id(node).c_str());
+ else if (current_type == SHADER_TYPE_BUMP)
+ ss->Shader("displacement", name, id(node).c_str());
+ else
+ assert(0);
+
+ /* link inputs to other nodes */
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link) {
+ if (node_skip_input(node, input))
+ continue;
+
+ /* connect shaders */
+ string id_from = id(input->link->parent);
+ string id_to = id(node);
+ string param_from = compatible_name(input->link->parent, input->link);
+ string param_to = compatible_name(node, input);
+
+ ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
+ }
+ }
+
+ /* test if we shader contains specific closures */
+ OSLShaderInfo *info = ((OSLShaderManager *)manager)->shader_loaded_info(name);
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (info) {
+ if (info->has_surface_emission)
+ current_shader->has_surface_emission = true;
+ if (info->has_surface_transparent)
+ current_shader->has_surface_transparent = true;
+ if (info->has_surface_bssrdf) {
+ current_shader->has_surface_bssrdf = true;
+ current_shader->has_bssrdf_bump = true; /* can't detect yet */
+ }
+ current_shader->has_bump = true; /* can't detect yet */
+ }
+
+ if (node->has_spatial_varying()) {
+ current_shader->has_surface_spatial_varying = true;
+ }
+ }
+ else if (current_type == SHADER_TYPE_VOLUME) {
+ if (node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
+ }
+
+ if (node->has_object_dependency()) {
+ current_shader->has_object_dependency = true;
+ }
+
+ if (node->has_attribute_dependency()) {
+ current_shader->has_attribute_dependency = true;
+ }
+
+ if (node->has_integrator_dependency()) {
+ current_shader->has_integrator_dependency = true;
+ }
}
static TypeDesc array_typedesc(TypeDesc typedesc, int arraylength)
{
- return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
- (TypeDesc::AGGREGATE)typedesc.aggregate,
- (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
- arraylength);
+ return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
+ (TypeDesc::AGGREGATE)typedesc.aggregate,
+ (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
+ arraylength);
}
-void OSLCompiler::parameter(ShaderNode* node, const char *name)
+void OSLCompiler::parameter(ShaderNode *node, const char *name)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ustring uname = ustring(name);
- const SocketType& socket = *(node->type->find_input(uname));
-
- switch(socket.type)
- {
- case SocketType::BOOLEAN:
- {
- int value = node->get_bool(socket);
- ss->Parameter(name, TypeDesc::TypeInt, &value);
- break;
- }
- case SocketType::FLOAT:
- {
- float value = node->get_float(socket);
- ss->Parameter(uname, TypeDesc::TypeFloat, &value);
- break;
- }
- case SocketType::INT:
- {
- int value = node->get_int(socket);
- ss->Parameter(uname, TypeDesc::TypeInt, &value);
- break;
- }
- case SocketType::COLOR:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypeColor, &value);
- break;
- }
- case SocketType::VECTOR:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypeVector, &value);
- break;
- }
- case SocketType::POINT:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypePoint, &value);
- break;
- }
- case SocketType::NORMAL:
- {
- float3 value = node->get_float3(socket);
- ss->Parameter(uname, TypeDesc::TypeNormal, &value);
- break;
- }
- case SocketType::POINT2:
- {
- float2 value = node->get_float2(socket);
- ss->Parameter(uname, TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value);
- break;
- }
- case SocketType::STRING:
- {
- ustring value = node->get_string(socket);
- ss->Parameter(uname, TypeDesc::TypeString, &value);
- break;
- }
- case SocketType::ENUM:
- {
- ustring value = node->get_string(socket);
- ss->Parameter(uname, TypeDesc::TypeString, &value);
- break;
- }
- case SocketType::TRANSFORM:
- {
- Transform value = node->get_transform(socket);
- ProjectionTransform projection(value);
- projection = projection_transpose(projection);
- ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
- break;
- }
- case SocketType::BOOLEAN_ARRAY:
- {
- // OSL does not support booleans, so convert to int
- const array<bool>& value = node->get_bool_array(socket);
- array<int> intvalue(value.size());
- for(size_t i = 0; i < value.size(); i++)
- intvalue[i] = value[i];
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), intvalue.data());
- break;
- }
- case SocketType::FLOAT_ARRAY:
- {
- const array<float>& value = node->get_float_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data());
- break;
- }
- case SocketType::INT_ARRAY:
- {
- const array<int>& value = node->get_int_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), value.data());
- break;
- }
- case SocketType::COLOR_ARRAY:
- case SocketType::VECTOR_ARRAY:
- case SocketType::POINT_ARRAY:
- case SocketType::NORMAL_ARRAY:
- {
- TypeDesc typedesc;
-
- switch(socket.type)
- {
- case SocketType::COLOR_ARRAY: typedesc = TypeDesc::TypeColor; break;
- case SocketType::VECTOR_ARRAY: typedesc = TypeDesc::TypeVector; break;
- case SocketType::POINT_ARRAY: typedesc = TypeDesc::TypePoint; break;
- case SocketType::NORMAL_ARRAY: typedesc = TypeDesc::TypeNormal; break;
- default: assert(0); break;
- }
-
- // convert to tightly packed array since float3 has padding
- const array<float3>& value = node->get_float3_array(socket);
- array<float> fvalue(value.size() * 3);
- for(size_t i = 0, j = 0; i < value.size(); i++) {
- fvalue[j++] = value[i].x;
- fvalue[j++] = value[i].y;
- fvalue[j++] = value[i].z;
- }
-
- ss->Parameter(uname, array_typedesc(typedesc, value.size()), fvalue.data());
- break;
- }
- case SocketType::POINT2_ARRAY:
- {
- const array<float2>& value = node->get_float2_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.size()), value.data());
- break;
- }
- case SocketType::STRING_ARRAY:
- {
- const array<ustring>& value = node->get_string_array(socket);
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data());
- break;
- }
- case SocketType::TRANSFORM_ARRAY:
- {
- const array<Transform>& value = node->get_transform_array(socket);
- array<ProjectionTransform> fvalue(value.size());
- for(size_t i = 0; i < value.size(); i++) {
- fvalue[i] = projection_transpose(ProjectionTransform(value[i]));
- }
- ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
- break;
- }
- case SocketType::CLOSURE:
- case SocketType::NODE:
- case SocketType::NODE_ARRAY:
- case SocketType::UNDEFINED:
- case SocketType::UINT:
- {
- assert(0);
- break;
- }
- }
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ustring uname = ustring(name);
+ const SocketType &socket = *(node->type->find_input(uname));
+
+ switch (socket.type) {
+ case SocketType::BOOLEAN: {
+ int value = node->get_bool(socket);
+ ss->Parameter(name, TypeDesc::TypeInt, &value);
+ break;
+ }
+ case SocketType::FLOAT: {
+ float value = node->get_float(socket);
+ ss->Parameter(uname, TypeDesc::TypeFloat, &value);
+ break;
+ }
+ case SocketType::INT: {
+ int value = node->get_int(socket);
+ ss->Parameter(uname, TypeDesc::TypeInt, &value);
+ break;
+ }
+ case SocketType::COLOR: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypeColor, &value);
+ break;
+ }
+ case SocketType::VECTOR: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypeVector, &value);
+ break;
+ }
+ case SocketType::POINT: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypePoint, &value);
+ break;
+ }
+ case SocketType::NORMAL: {
+ float3 value = node->get_float3(socket);
+ ss->Parameter(uname, TypeDesc::TypeNormal, &value);
+ break;
+ }
+ case SocketType::POINT2: {
+ float2 value = node->get_float2(socket);
+ ss->Parameter(uname, TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value);
+ break;
+ }
+ case SocketType::STRING: {
+ ustring value = node->get_string(socket);
+ ss->Parameter(uname, TypeDesc::TypeString, &value);
+ break;
+ }
+ case SocketType::ENUM: {
+ ustring value = node->get_string(socket);
+ ss->Parameter(uname, TypeDesc::TypeString, &value);
+ break;
+ }
+ case SocketType::TRANSFORM: {
+ Transform value = node->get_transform(socket);
+ ProjectionTransform projection(value);
+ projection = projection_transpose(projection);
+ ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
+ break;
+ }
+ case SocketType::BOOLEAN_ARRAY: {
+ // OSL does not support booleans, so convert to int
+ const array<bool> &value = node->get_bool_array(socket);
+ array<int> intvalue(value.size());
+ for (size_t i = 0; i < value.size(); i++)
+ intvalue[i] = value[i];
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), intvalue.data());
+ break;
+ }
+ case SocketType::FLOAT_ARRAY: {
+ const array<float> &value = node->get_float_array(socket);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data());
+ break;
+ }
+ case SocketType::INT_ARRAY: {
+ const array<int> &value = node->get_int_array(socket);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), value.data());
+ break;
+ }
+ case SocketType::COLOR_ARRAY:
+ case SocketType::VECTOR_ARRAY:
+ case SocketType::POINT_ARRAY:
+ case SocketType::NORMAL_ARRAY: {
+ TypeDesc typedesc;
+
+ switch (socket.type) {
+ case SocketType::COLOR_ARRAY:
+ typedesc = TypeDesc::TypeColor;
+ break;
+ case SocketType::VECTOR_ARRAY:
+ typedesc = TypeDesc::TypeVector;
+ break;
+ case SocketType::POINT_ARRAY:
+ typedesc = TypeDesc::TypePoint;
+ break;
+ case SocketType::NORMAL_ARRAY:
+ typedesc = TypeDesc::TypeNormal;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ // convert to tightly packed array since float3 has padding
+ const array<float3> &value = node->get_float3_array(socket);
+ array<float> fvalue(value.size() * 3);
+ for (size_t i = 0, j = 0; i < value.size(); i++) {
+ fvalue[j++] = value[i].x;
+ fvalue[j++] = value[i].y;
+ fvalue[j++] = value[i].z;
+ }
+
+ ss->Parameter(uname, array_typedesc(typedesc, value.size()), fvalue.data());
+ break;
+ }
+ case SocketType::POINT2_ARRAY: {
+ const array<float2> &value = node->get_float2_array(socket);
+ ss->Parameter(
+ uname,
+ array_typedesc(TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.size()),
+ value.data());
+ break;
+ }
+ case SocketType::STRING_ARRAY: {
+ const array<ustring> &value = node->get_string_array(socket);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data());
+ break;
+ }
+ case SocketType::TRANSFORM_ARRAY: {
+ const array<Transform> &value = node->get_transform_array(socket);
+ array<ProjectionTransform> fvalue(value.size());
+ for (size_t i = 0; i < value.size(); i++) {
+ fvalue[i] = projection_transpose(ProjectionTransform(value[i]));
+ }
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
+ break;
+ }
+ case SocketType::CLOSURE:
+ case SocketType::NODE:
+ case SocketType::NODE_ARRAY:
+ case SocketType::UNDEFINED:
+ case SocketType::UINT: {
+ assert(0);
+ break;
+ }
+ }
}
void OSLCompiler::parameter(const char *name, float f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeFloat, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeFloat, &f);
}
void OSLCompiler::parameter_color(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeColor, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeColor, &f);
}
void OSLCompiler::parameter_point(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypePoint, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypePoint, &f);
}
void OSLCompiler::parameter_normal(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeNormal, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeNormal, &f);
}
void OSLCompiler::parameter_vector(const char *name, float3 f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeVector, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeVector, &f);
}
void OSLCompiler::parameter(const char *name, int f)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeInt, &f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeInt, &f);
}
void OSLCompiler::parameter(const char *name, const char *s)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ss->Parameter(name, TypeDesc::TypeString, &s);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ss->Parameter(name, TypeDesc::TypeString, &s);
}
void OSLCompiler::parameter(const char *name, ustring s)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- const char *str = s.c_str();
- ss->Parameter(name, TypeDesc::TypeString, &str);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ const char *str = s.c_str();
+ ss->Parameter(name, TypeDesc::TypeString, &str);
}
-void OSLCompiler::parameter(const char *name, const Transform& tfm)
+void OSLCompiler::parameter(const char *name, const Transform &tfm)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- ProjectionTransform projection(tfm);
- projection = projection_transpose(projection);
- ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&projection);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ ProjectionTransform projection(tfm);
+ projection = projection_transpose(projection);
+ ss->Parameter(name, TypeDesc::TypeMatrix, (float *)&projection);
}
void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- TypeDesc type = TypeDesc::TypeFloat;
- type.arraylen = arraylen;
- ss->Parameter(name, type, f);
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ TypeDesc type = TypeDesc::TypeFloat;
+ type.arraylen = arraylen;
+ ss->Parameter(name, type, f);
}
-void OSLCompiler::parameter_color_array(const char *name, const array<float3>& f)
+void OSLCompiler::parameter_color_array(const char *name, const array<float3> &f)
{
- /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
- array<float[3]> table(f.size());
-
- for(int i = 0; i < f.size(); ++i) {
- table[i][0] = f[i].x;
- table[i][1] = f[i].y;
- table[i][2] = f[i].z;
- }
-
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
- TypeDesc type = TypeDesc::TypeColor;
- type.arraylen = table.size();
- ss->Parameter(name, type, table.data());
+ /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
+ array<float[3]> table(f.size());
+
+ for (int i = 0; i < f.size(); ++i) {
+ table[i][0] = f[i].x;
+ table[i][1] = f[i].y;
+ table[i][2] = f[i].z;
+ }
+
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+ TypeDesc type = TypeDesc::TypeColor;
+ type.arraylen = table.size();
+ ss->Parameter(name, type, table.data());
}
void OSLCompiler::parameter_attribute(const char *name, ustring s)
{
- if(Attribute::name_standard(s.c_str()))
- parameter(name, (string("geom:") + s.c_str()).c_str());
- else
- parameter(name, s.c_str());
+ if (Attribute::name_standard(s.c_str()))
+ parameter(name, (string("geom:") + s.c_str()).c_str());
+ else
+ parameter(name, s.c_str());
}
-void OSLCompiler::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
+void OSLCompiler::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input)
{
- ShaderNode *node = (input->link)? input->link->parent: NULL;
+ ShaderNode *node = (input->link) ? input->link->parent : NULL;
- if(node != NULL && dependencies.find(node) == dependencies.end()) {
- foreach(ShaderInput *in, node->inputs)
- if(!node_skip_input(node, in))
- find_dependencies(dependencies, in);
+ if (node != NULL && dependencies.find(node) == dependencies.end()) {
+ foreach (ShaderInput *in, node->inputs)
+ if (!node_skip_input(node, in))
+ find_dependencies(dependencies, in);
- dependencies.insert(node);
- }
+ dependencies.insert(node);
+ }
}
-void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes)
+void OSLCompiler::generate_nodes(const ShaderNodeSet &nodes)
{
- ShaderNodeSet done;
- bool nodes_done;
-
- do {
- nodes_done = true;
-
- foreach(ShaderNode *node, nodes) {
- if(done.find(node) == done.end()) {
- bool inputs_done = true;
-
- foreach(ShaderInput *input, node->inputs)
- if(!node_skip_input(node, input))
- if(input->link && done.find(input->link->parent) == done.end())
- inputs_done = false;
-
- if(inputs_done) {
- node->compile(*this);
- done.insert(node);
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(node->has_surface_emission())
- current_shader->has_surface_emission = true;
- if(node->has_surface_transparent())
- current_shader->has_surface_transparent = true;
- if(node->has_spatial_varying())
- current_shader->has_surface_spatial_varying = true;
- if(node->has_surface_bssrdf()) {
- current_shader->has_surface_bssrdf = true;
- if(node->has_bssrdf_bump())
- current_shader->has_bssrdf_bump = true;
- }
- if(node->has_bump()) {
- current_shader->has_bump = true;
- }
- }
- else if(current_type == SHADER_TYPE_VOLUME) {
- if(node->has_spatial_varying())
- current_shader->has_volume_spatial_varying = true;
- }
- }
- else
- nodes_done = false;
- }
- }
- } while(!nodes_done);
+ ShaderNodeSet done;
+ bool nodes_done;
+
+ do {
+ nodes_done = true;
+
+ foreach (ShaderNode *node, nodes) {
+ if (done.find(node) == done.end()) {
+ bool inputs_done = true;
+
+ foreach (ShaderInput *input, node->inputs)
+ if (!node_skip_input(node, input))
+ if (input->link && done.find(input->link->parent) == done.end())
+ inputs_done = false;
+
+ if (inputs_done) {
+ node->compile(*this);
+ done.insert(node);
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (node->has_surface_emission())
+ current_shader->has_surface_emission = true;
+ if (node->has_surface_transparent())
+ current_shader->has_surface_transparent = true;
+ if (node->has_spatial_varying())
+ current_shader->has_surface_spatial_varying = true;
+ if (node->has_surface_bssrdf()) {
+ current_shader->has_surface_bssrdf = true;
+ if (node->has_bssrdf_bump())
+ current_shader->has_bssrdf_bump = true;
+ }
+ if (node->has_bump()) {
+ current_shader->has_bump = true;
+ }
+ }
+ else if (current_type == SHADER_TYPE_VOLUME) {
+ if (node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
+ }
+ }
+ else
+ nodes_done = false;
+ }
+ }
+ } while (!nodes_done);
}
OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
- OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
-
- current_type = type;
-
- OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->name.c_str());
-
- ShaderNode *output = graph->output();
- ShaderNodeSet dependencies;
-
- if(type == SHADER_TYPE_SURFACE) {
- /* generate surface shader */
- find_dependencies(dependencies, output->input("Surface"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else if(type == SHADER_TYPE_BUMP) {
- /* generate bump shader */
- find_dependencies(dependencies, output->input("Normal"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else if(type == SHADER_TYPE_VOLUME) {
- /* generate volume shader */
- find_dependencies(dependencies, output->input("Volume"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else if(type == SHADER_TYPE_DISPLACEMENT) {
- /* generate displacement shader */
- find_dependencies(dependencies, output->input("Displacement"));
- generate_nodes(dependencies);
- output->compile(*this);
- }
- else
- assert(0);
-
- ss->ShaderGroupEnd();
-
- return group;
+ OSL::ShadingSystem *ss = (OSL::ShadingSystem *)shadingsys;
+
+ current_type = type;
+
+ OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->name.c_str());
+
+ ShaderNode *output = graph->output();
+ ShaderNodeSet dependencies;
+
+ if (type == SHADER_TYPE_SURFACE) {
+ /* generate surface shader */
+ find_dependencies(dependencies, output->input("Surface"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else if (type == SHADER_TYPE_BUMP) {
+ /* generate bump shader */
+ find_dependencies(dependencies, output->input("Normal"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else if (type == SHADER_TYPE_VOLUME) {
+ /* generate volume shader */
+ find_dependencies(dependencies, output->input("Volume"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else if (type == SHADER_TYPE_DISPLACEMENT) {
+ /* generate displacement shader */
+ find_dependencies(dependencies, output->input("Displacement"));
+ generate_nodes(dependencies);
+ output->compile(*this);
+ }
+ else
+ assert(0);
+
+ ss->ShaderGroupEnd();
+
+ return group;
}
void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
{
- if(shader->need_update) {
- ShaderGraph *graph = shader->graph;
- ShaderNode *output = (graph)? graph->output(): NULL;
-
- bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
- output->input("Surface")->link && output->input("Displacement")->link;
-
- /* finalize */
- shader->graph->finalize(scene,
- has_bump,
- shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
-
- current_shader = shader;
-
- shader->has_surface = false;
- shader->has_surface_emission = false;
- shader->has_surface_transparent = false;
- shader->has_surface_bssrdf = false;
- shader->has_bump = has_bump;
- shader->has_bssrdf_bump = has_bump;
- shader->has_volume = false;
- shader->has_displacement = false;
- shader->has_surface_spatial_varying = false;
- shader->has_volume_spatial_varying = false;
- shader->has_object_dependency = false;
- shader->has_attribute_dependency = false;
- shader->has_integrator_dependency = false;
-
- /* generate surface shader */
- if(shader->used && graph && output->input("Surface")->link) {
- shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
-
- if(has_bump)
- shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
- else
- shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
-
- shader->has_surface = true;
- }
- else {
- shader->osl_surface_ref = OSL::ShaderGroupRef();
- shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
- }
-
- /* generate volume shader */
- if(shader->used && graph && output->input("Volume")->link) {
- shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
- shader->has_volume = true;
- }
- else
- shader->osl_volume_ref = OSL::ShaderGroupRef();
-
- /* generate displacement shader */
- if(shader->used && graph && output->input("Displacement")->link) {
- shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
- shader->has_displacement = true;
- }
- else
- shader->osl_displacement_ref = OSL::ShaderGroupRef();
- }
-
- /* push state to array for lookup */
- og->surface_state.push_back(shader->osl_surface_ref);
- og->volume_state.push_back(shader->osl_volume_ref);
- og->displacement_state.push_back(shader->osl_displacement_ref);
- og->bump_state.push_back(shader->osl_surface_bump_ref);
+ if (shader->need_update) {
+ ShaderGraph *graph = shader->graph;
+ ShaderNode *output = (graph) ? graph->output() : NULL;
+
+ bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ output->input("Surface")->link && output->input("Displacement")->link;
+
+ /* finalize */
+ shader->graph->finalize(scene,
+ has_bump,
+ shader->has_integrator_dependency,
+ shader->displacement_method == DISPLACE_BOTH);
+
+ current_shader = shader;
+
+ shader->has_surface = false;
+ shader->has_surface_emission = false;
+ shader->has_surface_transparent = false;
+ shader->has_surface_bssrdf = false;
+ shader->has_bump = has_bump;
+ shader->has_bssrdf_bump = has_bump;
+ shader->has_volume = false;
+ shader->has_displacement = false;
+ shader->has_surface_spatial_varying = false;
+ shader->has_volume_spatial_varying = false;
+ shader->has_object_dependency = false;
+ shader->has_attribute_dependency = false;
+ shader->has_integrator_dependency = false;
+
+ /* generate surface shader */
+ if (shader->used && graph && output->input("Surface")->link) {
+ shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
+
+ if (has_bump)
+ shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
+ else
+ shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
+
+ shader->has_surface = true;
+ }
+ else {
+ shader->osl_surface_ref = OSL::ShaderGroupRef();
+ shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
+ }
+
+ /* generate volume shader */
+ if (shader->used && graph && output->input("Volume")->link) {
+ shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ shader->has_volume = true;
+ }
+ else
+ shader->osl_volume_ref = OSL::ShaderGroupRef();
+
+ /* generate displacement shader */
+ if (shader->used && graph && output->input("Displacement")->link) {
+ shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ shader->has_displacement = true;
+ }
+ else
+ shader->osl_displacement_ref = OSL::ShaderGroupRef();
+ }
+
+ /* push state to array for lookup */
+ og->surface_state.push_back(shader->osl_surface_ref);
+ og->volume_state.push_back(shader->osl_volume_ref);
+ og->displacement_state.push_back(shader->osl_displacement_ref);
+ og->bump_state.push_back(shader->osl_surface_bump_ref);
}
#else
@@ -1247,7 +1236,7 @@ void OSLCompiler::parameter(const char * /*name*/, ustring /*s*/)
{
}
-void OSLCompiler::parameter(const char * /*name*/, const Transform& /*tfm*/)
+void OSLCompiler::parameter(const char * /*name*/, const Transform & /*tfm*/)
{
}
@@ -1255,10 +1244,10 @@ void OSLCompiler::parameter_array(const char * /*name*/, const float /*f*/[], in
{
}
-void OSLCompiler::parameter_color_array(const char * /*name*/, const array<float3>& /*f*/)
+void OSLCompiler::parameter_color_array(const char * /*name*/, const array<float3> & /*f*/)
{
}
-#endif /* WITH_OSL */
+#endif /* WITH_OSL */
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 93cc3139608..aec518a6c2b 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -27,10 +27,10 @@
#include "render/shader.h"
#ifdef WITH_OSL
-#include <OSL/llvm_util.h>
-#include <OSL/oslcomp.h>
-#include <OSL/oslexec.h>
-#include <OSL/oslquery.h>
+# include <OSL/llvm_util.h>
+# include <OSL/oslcomp.h>
+# include <OSL/oslexec.h>
+# include <OSL/oslquery.h>
#endif
CCL_NAMESPACE_BEGIN
@@ -52,70 +52,73 @@ class ShaderOutput;
* to auto detect closures in the shader for MIS and transparent shadows */
struct OSLShaderInfo {
- OSLShaderInfo()
- : has_surface_emission(false), has_surface_transparent(false),
- has_surface_bssrdf(false)
- {}
-
- OSL::OSLQuery query;
- bool has_surface_emission;
- bool has_surface_transparent;
- bool has_surface_bssrdf;
+ OSLShaderInfo()
+ : has_surface_emission(false), has_surface_transparent(false), has_surface_bssrdf(false)
+ {
+ }
+
+ OSL::OSLQuery query;
+ bool has_surface_emission;
+ bool has_surface_transparent;
+ bool has_surface_bssrdf;
};
/* Shader Manage */
class OSLShaderManager : public ShaderManager {
-public:
- OSLShaderManager();
- ~OSLShaderManager();
-
- static void free_memory();
-
- void reset(Scene *scene);
-
- bool use_osl() { return true; }
-
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
-
- /* osl compile and query */
- static bool osl_compile(const string& inputfile, const string& outputfile);
- static bool osl_query(OSL::OSLQuery& query, const string& filepath);
-
- /* shader file loading, all functions return pointer to hash string if found */
- const char *shader_test_loaded(const string& hash);
- const char *shader_load_bytecode(const string& hash, const string& bytecode);
- const char *shader_load_filepath(string filepath);
- OSLShaderInfo *shader_loaded_info(const string& hash);
-
- /* create OSL node using OSLQuery */
- OSLNode *osl_node(const std::string& filepath,
- const std::string& bytecode_hash = "",
- const std::string& bytecode = "");
-
-protected:
- void texture_system_init();
- void texture_system_free();
-
- void shading_system_init();
- void shading_system_free();
-
- OSL::ShadingSystem *ss;
- OSL::TextureSystem *ts;
- OSLRenderServices *services;
- OSL::ErrorHandler errhandler;
- map<string, OSLShaderInfo> loaded_shaders;
-
- static OSL::TextureSystem *ts_shared;
- static thread_mutex ts_shared_mutex;
- static int ts_shared_users;
-
- static OSL::ShadingSystem *ss_shared;
- static OSLRenderServices *services_shared;
- static thread_mutex ss_shared_mutex;
- static thread_mutex ss_mutex;
- static int ss_shared_users;
+ public:
+ OSLShaderManager();
+ ~OSLShaderManager();
+
+ static void free_memory();
+
+ void reset(Scene *scene);
+
+ bool use_osl()
+ {
+ return true;
+ }
+
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+
+ /* osl compile and query */
+ static bool osl_compile(const string &inputfile, const string &outputfile);
+ static bool osl_query(OSL::OSLQuery &query, const string &filepath);
+
+ /* shader file loading, all functions return pointer to hash string if found */
+ const char *shader_test_loaded(const string &hash);
+ const char *shader_load_bytecode(const string &hash, const string &bytecode);
+ const char *shader_load_filepath(string filepath);
+ OSLShaderInfo *shader_loaded_info(const string &hash);
+
+ /* create OSL node using OSLQuery */
+ OSLNode *osl_node(const std::string &filepath,
+ const std::string &bytecode_hash = "",
+ const std::string &bytecode = "");
+
+ protected:
+ void texture_system_init();
+ void texture_system_free();
+
+ void shading_system_init();
+ void shading_system_free();
+
+ OSL::ShadingSystem *ss;
+ OSL::TextureSystem *ts;
+ OSLRenderServices *services;
+ OSL::ErrorHandler errhandler;
+ map<string, OSLShaderInfo> loaded_shaders;
+
+ static OSL::TextureSystem *ts_shared;
+ static thread_mutex ts_shared_mutex;
+ static int ts_shared_users;
+
+ static OSL::ShadingSystem *ss_shared;
+ static OSLRenderServices *services_shared;
+ static thread_mutex ss_shared_mutex;
+ static thread_mutex ss_mutex;
+ static int ss_shared_users;
};
#endif
@@ -123,55 +126,59 @@ protected:
/* Graph Compiler */
class OSLCompiler {
-public:
- OSLCompiler(void *manager, void *shadingsys,
- ImageManager *image_manager,
- LightManager *light_manager);
- void compile(Scene *scene, OSLGlobals *og, Shader *shader);
-
- void add(ShaderNode *node, const char *name, bool isfilepath = false);
-
- void parameter(ShaderNode *node, const char *name);
-
- void parameter(const char *name, float f);
- void parameter_color(const char *name, float3 f);
- void parameter_vector(const char *name, float3 f);
- void parameter_normal(const char *name, float3 f);
- void parameter_point(const char *name, float3 f);
- void parameter(const char *name, int f);
- void parameter(const char *name, const char *s);
- void parameter(const char *name, ustring str);
- void parameter(const char *name, const Transform& tfm);
-
- void parameter_array(const char *name, const float f[], int arraylen);
- void parameter_color_array(const char *name, const array<float3>& f);
-
- void parameter_attribute(const char *name, ustring s);
-
- ShaderType output_type() { return current_type; }
-
- bool background;
- ImageManager *image_manager;
- LightManager *light_manager;
-
-private:
+ public:
+ OSLCompiler(void *manager,
+ void *shadingsys,
+ ImageManager *image_manager,
+ LightManager *light_manager);
+ void compile(Scene *scene, OSLGlobals *og, Shader *shader);
+
+ void add(ShaderNode *node, const char *name, bool isfilepath = false);
+
+ void parameter(ShaderNode *node, const char *name);
+
+ void parameter(const char *name, float f);
+ void parameter_color(const char *name, float3 f);
+ void parameter_vector(const char *name, float3 f);
+ void parameter_normal(const char *name, float3 f);
+ void parameter_point(const char *name, float3 f);
+ void parameter(const char *name, int f);
+ void parameter(const char *name, const char *s);
+ void parameter(const char *name, ustring str);
+ void parameter(const char *name, const Transform &tfm);
+
+ void parameter_array(const char *name, const float f[], int arraylen);
+ void parameter_color_array(const char *name, const array<float3> &f);
+
+ void parameter_attribute(const char *name, ustring s);
+
+ ShaderType output_type()
+ {
+ return current_type;
+ }
+
+ bool background;
+ ImageManager *image_manager;
+ LightManager *light_manager;
+
+ private:
#ifdef WITH_OSL
- string id(ShaderNode *node);
- OSL::ShaderGroupRef compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
- bool node_skip_input(ShaderNode *node, ShaderInput *input);
- string compatible_name(ShaderNode *node, ShaderInput *input);
- string compatible_name(ShaderNode *node, ShaderOutput *output);
-
- void find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input);
- void generate_nodes(const ShaderNodeSet& nodes);
+ string id(ShaderNode *node);
+ OSL::ShaderGroupRef compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
+ bool node_skip_input(ShaderNode *node, ShaderInput *input);
+ string compatible_name(ShaderNode *node, ShaderInput *input);
+ string compatible_name(ShaderNode *node, ShaderOutput *output);
+
+ void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
+ void generate_nodes(const ShaderNodeSet &nodes);
#endif
- void *shadingsys;
- void *manager;
- ShaderType current_type;
- Shader *current_shader;
+ void *shadingsys;
+ void *manager;
+ ShaderType current_type;
+ Shader *current_shader;
};
CCL_NAMESPACE_END
-#endif /* __OSL_H__ */
+#endif /* __OSL_H__ */
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 0583556c8a9..8335404b197 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -39,86 +39,93 @@ ParticleSystem::~ParticleSystem()
void ParticleSystem::tag_update(Scene *scene)
{
- scene->particle_system_manager->need_update = true;
+ scene->particle_system_manager->need_update = true;
}
/* Particle System Manager */
ParticleSystemManager::ParticleSystemManager()
{
- need_update = true;
+ need_update = true;
}
ParticleSystemManager::~ParticleSystemManager()
{
}
-void ParticleSystemManager::device_update_particles(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ParticleSystemManager::device_update_particles(Device *,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- /* count particles.
- * adds one dummy particle at the beginning to avoid invalid lookups,
- * in case a shader uses particle info without actual particle data. */
- int num_particles = 1;
- for(size_t j = 0; j < scene->particle_systems.size(); j++)
- num_particles += scene->particle_systems[j]->particles.size();
-
- KernelParticle *kparticles = dscene->particles.alloc(num_particles);
-
- /* dummy particle */
- memset(kparticles, 0, sizeof(KernelParticle));
-
- int i = 1;
- for(size_t j = 0; j < scene->particle_systems.size(); j++) {
- ParticleSystem *psys = scene->particle_systems[j];
-
- for(size_t k = 0; k < psys->particles.size(); k++) {
- /* pack in texture */
- Particle& pa = psys->particles[k];
-
- kparticles[i].index = pa.index;
- kparticles[i].age = pa.age;
- kparticles[i].lifetime = pa.lifetime;
- kparticles[i].size = pa.size;
- kparticles[i].rotation = pa.rotation;
- kparticles[i].location = float3_to_float4(pa.location);
- kparticles[i].velocity = float3_to_float4(pa.velocity);
- kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity);
-
- i++;
-
- if(progress.get_cancel()) return;
- }
- }
-
- dscene->particles.copy_to_device();
+ /* count particles.
+ * adds one dummy particle at the beginning to avoid invalid lookups,
+ * in case a shader uses particle info without actual particle data. */
+ int num_particles = 1;
+ for (size_t j = 0; j < scene->particle_systems.size(); j++)
+ num_particles += scene->particle_systems[j]->particles.size();
+
+ KernelParticle *kparticles = dscene->particles.alloc(num_particles);
+
+ /* dummy particle */
+ memset(kparticles, 0, sizeof(KernelParticle));
+
+ int i = 1;
+ for (size_t j = 0; j < scene->particle_systems.size(); j++) {
+ ParticleSystem *psys = scene->particle_systems[j];
+
+ for (size_t k = 0; k < psys->particles.size(); k++) {
+ /* pack in texture */
+ Particle &pa = psys->particles[k];
+
+ kparticles[i].index = pa.index;
+ kparticles[i].age = pa.age;
+ kparticles[i].lifetime = pa.lifetime;
+ kparticles[i].size = pa.size;
+ kparticles[i].rotation = pa.rotation;
+ kparticles[i].location = float3_to_float4(pa.location);
+ kparticles[i].velocity = float3_to_float4(pa.velocity);
+ kparticles[i].angular_velocity = float3_to_float4(pa.angular_velocity);
+
+ i++;
+
+ if (progress.get_cancel())
+ return;
+ }
+ }
+
+ dscene->particles.copy_to_device();
}
-void ParticleSystemManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void ParticleSystemManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->particle_systems.size()
- << " particle systems.";
+ VLOG(1) << "Total " << scene->particle_systems.size() << " particle systems.";
- device_free(device, dscene);
+ device_free(device, dscene);
- progress.set_status("Updating Particle Systems", "Copying Particles to device");
- device_update_particles(device, dscene, scene, progress);
+ progress.set_status("Updating Particle Systems", "Copying Particles to device");
+ device_update_particles(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
+ if (progress.get_cancel())
+ return;
- need_update = false;
+ need_update = false;
}
void ParticleSystemManager::device_free(Device *, DeviceScene *dscene)
{
- dscene->particles.free();
+ dscene->particles.free();
}
void ParticleSystemManager::tag_update(Scene * /*scene*/)
{
- need_update = true;
+ need_update = true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index 27821907af0..65663c31c37 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -30,42 +30,45 @@ class Scene;
/* Particle System */
struct Particle {
- int index;
- float age;
- float lifetime;
- float3 location;
- float4 rotation;
- float size;
- float3 velocity;
- float3 angular_velocity;
+ int index;
+ float age;
+ float lifetime;
+ float3 location;
+ float4 rotation;
+ float size;
+ float3 velocity;
+ float3 angular_velocity;
};
class ParticleSystem {
-public:
- ParticleSystem();
- ~ParticleSystem();
+ public:
+ ParticleSystem();
+ ~ParticleSystem();
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
- array<Particle> particles;
+ array<Particle> particles;
};
/* ParticleSystem Manager */
class ParticleSystemManager {
-public:
- bool need_update;
+ public:
+ bool need_update;
- ParticleSystemManager();
- ~ParticleSystemManager();
+ ParticleSystemManager();
+ ~ParticleSystemManager();
- void device_update_particles(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update_particles(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene);
- void tag_update(Scene *scene);
+ void tag_update(Scene *scene);
};
CCL_NAMESPACE_END
-#endif /* __PARTICLES_H__ */
+#endif /* __PARTICLES_H__ */
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 1f551f206ef..1e75fa0f99b 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -41,352 +41,359 @@
CCL_NAMESPACE_BEGIN
DeviceScene::DeviceScene(Device *device)
-: bvh_nodes(device, "__bvh_nodes", MEM_TEXTURE),
- bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_TEXTURE),
- object_node(device, "__object_node", MEM_TEXTURE),
- prim_tri_index(device, "__prim_tri_index", MEM_TEXTURE),
- prim_tri_verts(device, "__prim_tri_verts", MEM_TEXTURE),
- prim_type(device, "__prim_type", MEM_TEXTURE),
- prim_visibility(device, "__prim_visibility", MEM_TEXTURE),
- prim_index(device, "__prim_index", MEM_TEXTURE),
- prim_object(device, "__prim_object", MEM_TEXTURE),
- prim_time(device, "__prim_time", MEM_TEXTURE),
- tri_shader(device, "__tri_shader", MEM_TEXTURE),
- tri_vnormal(device, "__tri_vnormal", MEM_TEXTURE),
- tri_vindex(device, "__tri_vindex", MEM_TEXTURE),
- tri_patch(device, "__tri_patch", MEM_TEXTURE),
- tri_patch_uv(device, "__tri_patch_uv", MEM_TEXTURE),
- curves(device, "__curves", MEM_TEXTURE),
- curve_keys(device, "__curve_keys", MEM_TEXTURE),
- patches(device, "__patches", MEM_TEXTURE),
- objects(device, "__objects", MEM_TEXTURE),
- object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE),
- object_motion(device, "__object_motion", MEM_TEXTURE),
- object_flag(device, "__object_flag", MEM_TEXTURE),
- camera_motion(device, "__camera_motion", MEM_TEXTURE),
- attributes_map(device, "__attributes_map", MEM_TEXTURE),
- attributes_float(device, "__attributes_float", MEM_TEXTURE),
- attributes_float2(device, "__attributes_float2", MEM_TEXTURE),
- attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
- attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
- light_distribution(device, "__light_distribution", MEM_TEXTURE),
- lights(device, "__lights", MEM_TEXTURE),
- light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
- light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
- particles(device, "__particles", MEM_TEXTURE),
- svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
- shaders(device, "__shaders", MEM_TEXTURE),
- lookup_table(device, "__lookup_table", MEM_TEXTURE),
- sobol_directions(device, "__sobol_directions", MEM_TEXTURE),
- ies_lights(device, "__ies", MEM_TEXTURE)
+ : bvh_nodes(device, "__bvh_nodes", MEM_TEXTURE),
+ bvh_leaf_nodes(device, "__bvh_leaf_nodes", MEM_TEXTURE),
+ object_node(device, "__object_node", MEM_TEXTURE),
+ prim_tri_index(device, "__prim_tri_index", MEM_TEXTURE),
+ prim_tri_verts(device, "__prim_tri_verts", MEM_TEXTURE),
+ prim_type(device, "__prim_type", MEM_TEXTURE),
+ prim_visibility(device, "__prim_visibility", MEM_TEXTURE),
+ prim_index(device, "__prim_index", MEM_TEXTURE),
+ prim_object(device, "__prim_object", MEM_TEXTURE),
+ prim_time(device, "__prim_time", MEM_TEXTURE),
+ tri_shader(device, "__tri_shader", MEM_TEXTURE),
+ tri_vnormal(device, "__tri_vnormal", MEM_TEXTURE),
+ tri_vindex(device, "__tri_vindex", MEM_TEXTURE),
+ tri_patch(device, "__tri_patch", MEM_TEXTURE),
+ tri_patch_uv(device, "__tri_patch_uv", MEM_TEXTURE),
+ curves(device, "__curves", MEM_TEXTURE),
+ curve_keys(device, "__curve_keys", MEM_TEXTURE),
+ patches(device, "__patches", MEM_TEXTURE),
+ objects(device, "__objects", MEM_TEXTURE),
+ object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE),
+ object_motion(device, "__object_motion", MEM_TEXTURE),
+ object_flag(device, "__object_flag", MEM_TEXTURE),
+ camera_motion(device, "__camera_motion", MEM_TEXTURE),
+ attributes_map(device, "__attributes_map", MEM_TEXTURE),
+ attributes_float(device, "__attributes_float", MEM_TEXTURE),
+ attributes_float2(device, "__attributes_float2", MEM_TEXTURE),
+ attributes_float3(device, "__attributes_float3", MEM_TEXTURE),
+ attributes_uchar4(device, "__attributes_uchar4", MEM_TEXTURE),
+ light_distribution(device, "__light_distribution", MEM_TEXTURE),
+ lights(device, "__lights", MEM_TEXTURE),
+ light_background_marginal_cdf(device, "__light_background_marginal_cdf", MEM_TEXTURE),
+ light_background_conditional_cdf(device, "__light_background_conditional_cdf", MEM_TEXTURE),
+ particles(device, "__particles", MEM_TEXTURE),
+ svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
+ shaders(device, "__shaders", MEM_TEXTURE),
+ lookup_table(device, "__lookup_table", MEM_TEXTURE),
+ sobol_directions(device, "__sobol_directions", MEM_TEXTURE),
+ ies_lights(device, "__ies", MEM_TEXTURE)
{
- memset((void*)&data, 0, sizeof(data));
+ memset((void *)&data, 0, sizeof(data));
}
-Scene::Scene(const SceneParams& params_, Device *device)
- : name("Scene"),
- device(device),
- dscene(device),
- params(params_)
+Scene::Scene(const SceneParams &params_, Device *device)
+ : name("Scene"), device(device), dscene(device), params(params_)
{
- memset((void *)&dscene.data, 0, sizeof(dscene.data));
-
- camera = new Camera();
- dicing_camera = new Camera();
- lookup_tables = new LookupTables();
- film = new Film();
- background = new Background();
- light_manager = new LightManager();
- mesh_manager = new MeshManager();
- object_manager = new ObjectManager();
- integrator = new Integrator();
- image_manager = new ImageManager(device->info);
- particle_system_manager = new ParticleSystemManager();
- curve_system_manager = new CurveSystemManager();
- bake_manager = new BakeManager();
-
- /* OSL only works on the CPU */
- if(device->info.has_osl)
- shader_manager = ShaderManager::create(this, params.shadingsystem);
- else
- shader_manager = ShaderManager::create(this, SHADINGSYSTEM_SVM);
+ memset((void *)&dscene.data, 0, sizeof(dscene.data));
+
+ camera = new Camera();
+ dicing_camera = new Camera();
+ lookup_tables = new LookupTables();
+ film = new Film();
+ background = new Background();
+ light_manager = new LightManager();
+ mesh_manager = new MeshManager();
+ object_manager = new ObjectManager();
+ integrator = new Integrator();
+ image_manager = new ImageManager(device->info);
+ particle_system_manager = new ParticleSystemManager();
+ curve_system_manager = new CurveSystemManager();
+ bake_manager = new BakeManager();
+
+ /* OSL only works on the CPU */
+ if (device->info.has_osl)
+ shader_manager = ShaderManager::create(this, params.shadingsystem);
+ else
+ shader_manager = ShaderManager::create(this, SHADINGSYSTEM_SVM);
}
Scene::~Scene()
{
- free_memory(true);
+ free_memory(true);
}
void Scene::free_memory(bool final)
{
- foreach(Shader *s, shaders)
- delete s;
- foreach(Mesh *m, meshes)
- delete m;
- foreach(Object *o, objects)
- delete o;
- foreach(Light *l, lights)
- delete l;
- foreach(ParticleSystem *p, particle_systems)
- delete p;
-
- shaders.clear();
- meshes.clear();
- objects.clear();
- lights.clear();
- particle_systems.clear();
-
- if(device) {
- camera->device_free(device, &dscene, this);
- film->device_free(device, &dscene, this);
- background->device_free(device, &dscene);
- integrator->device_free(device, &dscene);
-
- object_manager->device_free(device, &dscene);
- mesh_manager->device_free(device, &dscene);
- shader_manager->device_free(device, &dscene, this);
- light_manager->device_free(device, &dscene);
-
- particle_system_manager->device_free(device, &dscene);
- curve_system_manager->device_free(device, &dscene);
-
- bake_manager->device_free(device, &dscene);
-
- if(!params.persistent_data || final)
- image_manager->device_free(device);
- else
- image_manager->device_free_builtin(device);
-
- lookup_tables->device_free(device, &dscene);
- }
-
- if(final) {
- delete lookup_tables;
- delete camera;
- delete dicing_camera;
- delete film;
- delete background;
- delete integrator;
- delete object_manager;
- delete mesh_manager;
- delete shader_manager;
- delete light_manager;
- delete particle_system_manager;
- delete curve_system_manager;
- delete image_manager;
- delete bake_manager;
- }
+ foreach (Shader *s, shaders)
+ delete s;
+ foreach (Mesh *m, meshes)
+ delete m;
+ foreach (Object *o, objects)
+ delete o;
+ foreach (Light *l, lights)
+ delete l;
+ foreach (ParticleSystem *p, particle_systems)
+ delete p;
+
+ shaders.clear();
+ meshes.clear();
+ objects.clear();
+ lights.clear();
+ particle_systems.clear();
+
+ if (device) {
+ camera->device_free(device, &dscene, this);
+ film->device_free(device, &dscene, this);
+ background->device_free(device, &dscene);
+ integrator->device_free(device, &dscene);
+
+ object_manager->device_free(device, &dscene);
+ mesh_manager->device_free(device, &dscene);
+ shader_manager->device_free(device, &dscene, this);
+ light_manager->device_free(device, &dscene);
+
+ particle_system_manager->device_free(device, &dscene);
+ curve_system_manager->device_free(device, &dscene);
+
+ bake_manager->device_free(device, &dscene);
+
+ if (!params.persistent_data || final)
+ image_manager->device_free(device);
+ else
+ image_manager->device_free_builtin(device);
+
+ lookup_tables->device_free(device, &dscene);
+ }
+
+ if (final) {
+ delete lookup_tables;
+ delete camera;
+ delete dicing_camera;
+ delete film;
+ delete background;
+ delete integrator;
+ delete object_manager;
+ delete mesh_manager;
+ delete shader_manager;
+ delete light_manager;
+ delete particle_system_manager;
+ delete curve_system_manager;
+ delete image_manager;
+ delete bake_manager;
+ }
}
-void Scene::device_update(Device *device_, Progress& progress)
+void Scene::device_update(Device *device_, Progress &progress)
{
- if(!device)
- device = device_;
+ if (!device)
+ device = device_;
- bool print_stats = need_data_update();
+ bool print_stats = need_data_update();
- /* The order of updates is important, because there's dependencies between
- * the different managers, using data computed by previous managers.
- *
- * - Image manager uploads images used by shaders.
- * - Camera may be used for adaptive subdivision.
- * - Displacement shader must have all shader data available.
- * - Light manager needs lookup tables and final mesh data to compute emission CDF.
- * - Film needs light manager to run for use_light_visibility
- * - Lookup tables are done a second time to handle film tables
- */
+ /* The order of updates is important, because there's dependencies between
+ * the different managers, using data computed by previous managers.
+ *
+ * - Image manager uploads images used by shaders.
+ * - Camera may be used for adaptive subdivision.
+ * - Displacement shader must have all shader data available.
+ * - Light manager needs lookup tables and final mesh data to compute emission CDF.
+ * - Film needs light manager to run for use_light_visibility
+ * - Lookup tables are done a second time to handle film tables
+ */
- progress.set_status("Updating Shaders");
- shader_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Shaders");
+ shader_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Background");
- background->device_update(device, &dscene, this);
+ progress.set_status("Updating Background");
+ background->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Camera");
- camera->device_update(device, &dscene, this);
+ progress.set_status("Updating Camera");
+ camera->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- mesh_manager->device_update_preprocess(device, this, progress);
+ mesh_manager->device_update_preprocess(device, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Objects");
- object_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Objects");
+ object_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Hair Systems");
- curve_system_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Hair Systems");
+ curve_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Particle Systems");
- particle_system_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Particle Systems");
+ particle_system_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Meshes");
- mesh_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Meshes");
+ mesh_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Objects Flags");
- object_manager->device_update_flags(device, &dscene, this, progress);
+ progress.set_status("Updating Objects Flags");
+ object_manager->device_update_flags(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Images");
- image_manager->device_update(device, this, progress);
+ progress.set_status("Updating Images");
+ image_manager->device_update(device, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Camera Volume");
- camera->device_update_volume(device, &dscene, this);
+ progress.set_status("Updating Camera Volume");
+ camera->device_update_volume(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Lookup Tables");
- lookup_tables->device_update(device, &dscene);
+ progress.set_status("Updating Lookup Tables");
+ lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Lights");
- light_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Lights");
+ light_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Integrator");
- integrator->device_update(device, &dscene, this);
+ progress.set_status("Updating Integrator");
+ integrator->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Film");
- film->device_update(device, &dscene, this);
+ progress.set_status("Updating Film");
+ film->device_update(device, &dscene, this);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Lookup Tables");
- lookup_tables->device_update(device, &dscene);
+ progress.set_status("Updating Lookup Tables");
+ lookup_tables->device_update(device, &dscene);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- progress.set_status("Updating Baking");
- bake_manager->device_update(device, &dscene, this, progress);
+ progress.set_status("Updating Baking");
+ bake_manager->device_update(device, &dscene, this, progress);
- if(progress.get_cancel() || device->have_error()) return;
+ if (progress.get_cancel() || device->have_error())
+ return;
- if(device->have_error() == false) {
- progress.set_status("Updating Device", "Writing constant memory");
- device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
- }
+ if (device->have_error() == false) {
+ progress.set_status("Updating Device", "Writing constant memory");
+ device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
+ }
- if(print_stats) {
- size_t mem_used = util_guarded_get_mem_used();
- size_t mem_peak = util_guarded_get_mem_peak();
+ if (print_stats) {
+ size_t mem_used = util_guarded_get_mem_used();
+ size_t mem_peak = util_guarded_get_mem_peak();
- VLOG(1) << "System memory statistics after full device sync:\n"
- << " Usage: " << string_human_readable_number(mem_used)
- << " (" << string_human_readable_size(mem_used) << ")\n"
- << " Peak: " << string_human_readable_number(mem_peak)
- << " (" << string_human_readable_size(mem_peak) << ")";
- }
+ VLOG(1) << "System memory statistics after full device sync:\n"
+ << " Usage: " << string_human_readable_number(mem_used) << " ("
+ << string_human_readable_size(mem_used) << ")\n"
+ << " Peak: " << string_human_readable_number(mem_peak) << " ("
+ << string_human_readable_size(mem_peak) << ")";
+ }
}
Scene::MotionType Scene::need_motion()
{
- if(integrator->motion_blur)
- return MOTION_BLUR;
- else if(Pass::contains(film->passes, PASS_MOTION))
- return MOTION_PASS;
- else
- return MOTION_NONE;
+ if (integrator->motion_blur)
+ return MOTION_BLUR;
+ else if (Pass::contains(film->passes, PASS_MOTION))
+ return MOTION_PASS;
+ else
+ return MOTION_NONE;
}
float Scene::motion_shutter_time()
{
- if(need_motion() == Scene::MOTION_PASS)
- return 2.0f;
- else
- return camera->shuttertime;
+ if (need_motion() == Scene::MOTION_PASS)
+ return 2.0f;
+ else
+ return camera->shuttertime;
}
bool Scene::need_global_attribute(AttributeStandard std)
{
- if(std == ATTR_STD_UV)
- return Pass::contains(film->passes, PASS_UV);
- else if(std == ATTR_STD_MOTION_VERTEX_POSITION)
- return need_motion() != MOTION_NONE;
- else if(std == ATTR_STD_MOTION_VERTEX_NORMAL)
- return need_motion() == MOTION_BLUR;
-
- return false;
+ if (std == ATTR_STD_UV)
+ return Pass::contains(film->passes, PASS_UV);
+ else if (std == ATTR_STD_MOTION_VERTEX_POSITION)
+ return need_motion() != MOTION_NONE;
+ else if (std == ATTR_STD_MOTION_VERTEX_NORMAL)
+ return need_motion() == MOTION_BLUR;
+
+ return false;
}
-void Scene::need_global_attributes(AttributeRequestSet& attributes)
+void Scene::need_global_attributes(AttributeRequestSet &attributes)
{
- for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
- if(need_global_attribute((AttributeStandard)std))
- attributes.add((AttributeStandard)std);
+ for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
+ if (need_global_attribute((AttributeStandard)std))
+ attributes.add((AttributeStandard)std);
}
bool Scene::need_update()
{
- return (need_reset() || film->need_update);
+ return (need_reset() || film->need_update);
}
bool Scene::need_data_update()
{
- return (background->need_update
- || image_manager->need_update
- || object_manager->need_update
- || mesh_manager->need_update
- || light_manager->need_update
- || lookup_tables->need_update
- || integrator->need_update
- || shader_manager->need_update
- || particle_system_manager->need_update
- || curve_system_manager->need_update
- || bake_manager->need_update
- || film->need_update);
+ return (background->need_update || image_manager->need_update || object_manager->need_update ||
+ mesh_manager->need_update || light_manager->need_update || lookup_tables->need_update ||
+ integrator->need_update || shader_manager->need_update ||
+ particle_system_manager->need_update || curve_system_manager->need_update ||
+ bake_manager->need_update || film->need_update);
}
bool Scene::need_reset()
{
- return need_data_update() || camera->need_update;
+ return need_data_update() || camera->need_update;
}
void Scene::reset()
{
- shader_manager->reset(this);
- shader_manager->add_default(this);
-
- /* ensure all objects are updated */
- camera->tag_update();
- dicing_camera->tag_update();
- film->tag_update(this);
- background->tag_update(this);
- integrator->tag_update(this);
- object_manager->tag_update(this);
- mesh_manager->tag_update(this);
- light_manager->tag_update(this);
- particle_system_manager->tag_update(this);
- curve_system_manager->tag_update(this);
+ shader_manager->reset(this);
+ shader_manager->add_default(this);
+
+ /* ensure all objects are updated */
+ camera->tag_update();
+ dicing_camera->tag_update();
+ film->tag_update(this);
+ background->tag_update(this);
+ integrator->tag_update(this);
+ object_manager->tag_update(this);
+ mesh_manager->tag_update(this);
+ light_manager->tag_update(this);
+ particle_system_manager->tag_update(this);
+ curve_system_manager->tag_update(this);
}
void Scene::device_free()
{
- free_memory(false);
+ free_memory(false);
}
void Scene::collect_statistics(RenderStats *stats)
{
- mesh_manager->collect_statistics(this, stats);
- image_manager->collect_statistics(stats);
+ mesh_manager->collect_statistics(this, stats);
+ image_manager->collect_statistics(stats);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index e43800fe5c4..45997bccf5d 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -61,215 +61,215 @@ class RenderStats;
/* Scene Device Data */
class DeviceScene {
-public:
- /* BVH */
- device_vector<int4> bvh_nodes;
- device_vector<int4> bvh_leaf_nodes;
- device_vector<int> object_node;
- device_vector<uint> prim_tri_index;
- device_vector<float4> prim_tri_verts;
- device_vector<int> prim_type;
- device_vector<uint> prim_visibility;
- device_vector<int> prim_index;
- device_vector<int> prim_object;
- device_vector<float2> prim_time;
-
- /* mesh */
- device_vector<uint> tri_shader;
- device_vector<float4> tri_vnormal;
- device_vector<uint4> tri_vindex;
- device_vector<uint> tri_patch;
- device_vector<float2> tri_patch_uv;
-
- device_vector<float4> curves;
- device_vector<float4> curve_keys;
-
- device_vector<uint> patches;
-
- /* objects */
- device_vector<KernelObject> objects;
- device_vector<Transform> object_motion_pass;
- device_vector<DecomposedTransform> object_motion;
- device_vector<uint> object_flag;
-
- /* cameras */
- device_vector<DecomposedTransform> camera_motion;
-
- /* attributes */
- device_vector<uint4> attributes_map;
- device_vector<float> attributes_float;
- device_vector<float2> attributes_float2;
- device_vector<float4> attributes_float3;
- device_vector<uchar4> attributes_uchar4;
-
- /* lights */
- device_vector<KernelLightDistribution> light_distribution;
- device_vector<KernelLight> lights;
- device_vector<float2> light_background_marginal_cdf;
- device_vector<float2> light_background_conditional_cdf;
-
- /* particles */
- device_vector<KernelParticle> particles;
-
- /* shaders */
- device_vector<int4> svm_nodes;
- device_vector<KernelShader> shaders;
-
- /* lookup tables */
- device_vector<float> lookup_table;
-
- /* integrator */
- device_vector<uint> sobol_directions;
-
- /* ies lights */
- device_vector<float> ies_lights;
-
- KernelData data;
-
- DeviceScene(Device *device);
+ public:
+ /* BVH */
+ device_vector<int4> bvh_nodes;
+ device_vector<int4> bvh_leaf_nodes;
+ device_vector<int> object_node;
+ device_vector<uint> prim_tri_index;
+ device_vector<float4> prim_tri_verts;
+ device_vector<int> prim_type;
+ device_vector<uint> prim_visibility;
+ device_vector<int> prim_index;
+ device_vector<int> prim_object;
+ device_vector<float2> prim_time;
+
+ /* mesh */
+ device_vector<uint> tri_shader;
+ device_vector<float4> tri_vnormal;
+ device_vector<uint4> tri_vindex;
+ device_vector<uint> tri_patch;
+ device_vector<float2> tri_patch_uv;
+
+ device_vector<float4> curves;
+ device_vector<float4> curve_keys;
+
+ device_vector<uint> patches;
+
+ /* objects */
+ device_vector<KernelObject> objects;
+ device_vector<Transform> object_motion_pass;
+ device_vector<DecomposedTransform> object_motion;
+ device_vector<uint> object_flag;
+
+ /* cameras */
+ device_vector<DecomposedTransform> camera_motion;
+
+ /* attributes */
+ device_vector<uint4> attributes_map;
+ device_vector<float> attributes_float;
+ device_vector<float2> attributes_float2;
+ device_vector<float4> attributes_float3;
+ device_vector<uchar4> attributes_uchar4;
+
+ /* lights */
+ device_vector<KernelLightDistribution> light_distribution;
+ device_vector<KernelLight> lights;
+ device_vector<float2> light_background_marginal_cdf;
+ device_vector<float2> light_background_conditional_cdf;
+
+ /* particles */
+ device_vector<KernelParticle> particles;
+
+ /* shaders */
+ device_vector<int4> svm_nodes;
+ device_vector<KernelShader> shaders;
+
+ /* lookup tables */
+ device_vector<float> lookup_table;
+
+ /* integrator */
+ device_vector<uint> sobol_directions;
+
+ /* ies lights */
+ device_vector<float> ies_lights;
+
+ KernelData data;
+
+ DeviceScene(Device *device);
};
/* Scene Parameters */
class SceneParams {
-public:
- /* Type of BVH, in terms whether it is supported dynamic updates of meshes
- * or whether modifying geometry requires full BVH rebuild.
- */
- enum BVHType {
- /* BVH supports dynamic updates of geometry.
- *
- * Faster for updating BVH tree when doing modifications in viewport,
- * but slower for rendering.
- */
- BVH_DYNAMIC = 0,
- /* BVH tree is calculated for specific scene, updates in geometry
- * requires full tree rebuild.
- *
- * Slower to update BVH tree when modifying objects in viewport, also
- * slower to build final BVH tree but gives best possible render speed.
- */
- BVH_STATIC = 1,
-
- BVH_NUM_TYPES,
- };
-
- ShadingSystem shadingsystem;
-
- /* Requested BVH layout.
- *
- * If it's not supported by the device, the widest one from supported ones
- * will be used, but BVH wider than this one will never be used.
- */
- BVHLayout bvh_layout;
-
- BVHType bvh_type;
- bool use_bvh_spatial_split;
- bool use_bvh_unaligned_nodes;
- int num_bvh_time_steps;
- bool persistent_data;
- int texture_limit;
-
- SceneParams()
- {
- shadingsystem = SHADINGSYSTEM_SVM;
- bvh_layout = BVH_LAYOUT_BVH2;
- bvh_type = BVH_DYNAMIC;
- use_bvh_spatial_split = false;
- use_bvh_unaligned_nodes = true;
- num_bvh_time_steps = 0;
- persistent_data = false;
- texture_limit = 0;
- }
-
- bool modified(const SceneParams& params)
- { return !(shadingsystem == params.shadingsystem
- && bvh_layout == params.bvh_layout
- && bvh_type == params.bvh_type
- && use_bvh_spatial_split == params.use_bvh_spatial_split
- && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes
- && num_bvh_time_steps == params.num_bvh_time_steps
- && persistent_data == params.persistent_data
- && texture_limit == params.texture_limit); }
+ public:
+ /* Type of BVH, in terms whether it is supported dynamic updates of meshes
+ * or whether modifying geometry requires full BVH rebuild.
+ */
+ enum BVHType {
+ /* BVH supports dynamic updates of geometry.
+ *
+ * Faster for updating BVH tree when doing modifications in viewport,
+ * but slower for rendering.
+ */
+ BVH_DYNAMIC = 0,
+ /* BVH tree is calculated for specific scene, updates in geometry
+ * requires full tree rebuild.
+ *
+ * Slower to update BVH tree when modifying objects in viewport, also
+ * slower to build final BVH tree but gives best possible render speed.
+ */
+ BVH_STATIC = 1,
+
+ BVH_NUM_TYPES,
+ };
+
+ ShadingSystem shadingsystem;
+
+ /* Requested BVH layout.
+ *
+ * If it's not supported by the device, the widest one from supported ones
+ * will be used, but BVH wider than this one will never be used.
+ */
+ BVHLayout bvh_layout;
+
+ BVHType bvh_type;
+ bool use_bvh_spatial_split;
+ bool use_bvh_unaligned_nodes;
+ int num_bvh_time_steps;
+ bool persistent_data;
+ int texture_limit;
+
+ SceneParams()
+ {
+ shadingsystem = SHADINGSYSTEM_SVM;
+ bvh_layout = BVH_LAYOUT_BVH2;
+ bvh_type = BVH_DYNAMIC;
+ use_bvh_spatial_split = false;
+ use_bvh_unaligned_nodes = true;
+ num_bvh_time_steps = 0;
+ persistent_data = false;
+ texture_limit = 0;
+ }
+
+ bool modified(const SceneParams &params)
+ {
+ return !(shadingsystem == params.shadingsystem && bvh_layout == params.bvh_layout &&
+ bvh_type == params.bvh_type &&
+ use_bvh_spatial_split == params.use_bvh_spatial_split &&
+ use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes &&
+ num_bvh_time_steps == params.num_bvh_time_steps &&
+ persistent_data == params.persistent_data && texture_limit == params.texture_limit);
+ }
};
/* Scene */
class Scene {
-public:
- /* Optional name. Is used for logging and reporting. */
- string name;
-
- /* data */
- Camera *camera;
- Camera *dicing_camera;
- LookupTables *lookup_tables;
- Film *film;
- Background *background;
- Integrator *integrator;
-
- /* data lists */
- vector<Object*> objects;
- vector<Mesh*> meshes;
- vector<Shader*> shaders;
- vector<Light*> lights;
- vector<ParticleSystem*> particle_systems;
-
- /* data managers */
- ImageManager *image_manager;
- LightManager *light_manager;
- ShaderManager *shader_manager;
- MeshManager *mesh_manager;
- ObjectManager *object_manager;
- ParticleSystemManager *particle_system_manager;
- CurveSystemManager *curve_system_manager;
- BakeManager *bake_manager;
-
- /* default shaders */
- Shader *default_surface;
- Shader *default_light;
- Shader *default_background;
- Shader *default_empty;
-
- /* device */
- Device *device;
- DeviceScene dscene;
-
- /* parameters */
- SceneParams params;
-
- /* mutex must be locked manually by callers */
- thread_mutex mutex;
-
- Scene(const SceneParams& params, Device *device);
- ~Scene();
-
- void device_update(Device *device, Progress& progress);
-
- bool need_global_attribute(AttributeStandard std);
- void need_global_attributes(AttributeRequestSet& attributes);
-
- enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
- MotionType need_motion();
- float motion_shutter_time();
-
- bool need_update();
- bool need_reset();
-
- void reset();
- void device_free();
-
- void collect_statistics(RenderStats *stats);
-
-protected:
- /* Check if some heavy data worth logging was updated.
- * Mainly used to suppress extra annoying logging.
- */
- bool need_data_update();
-
- void free_memory(bool final);
+ public:
+ /* Optional name. Is used for logging and reporting. */
+ string name;
+
+ /* data */
+ Camera *camera;
+ Camera *dicing_camera;
+ LookupTables *lookup_tables;
+ Film *film;
+ Background *background;
+ Integrator *integrator;
+
+ /* data lists */
+ vector<Object *> objects;
+ vector<Mesh *> meshes;
+ vector<Shader *> shaders;
+ vector<Light *> lights;
+ vector<ParticleSystem *> particle_systems;
+
+ /* data managers */
+ ImageManager *image_manager;
+ LightManager *light_manager;
+ ShaderManager *shader_manager;
+ MeshManager *mesh_manager;
+ ObjectManager *object_manager;
+ ParticleSystemManager *particle_system_manager;
+ CurveSystemManager *curve_system_manager;
+ BakeManager *bake_manager;
+
+ /* default shaders */
+ Shader *default_surface;
+ Shader *default_light;
+ Shader *default_background;
+ Shader *default_empty;
+
+ /* device */
+ Device *device;
+ DeviceScene dscene;
+
+ /* parameters */
+ SceneParams params;
+
+ /* mutex must be locked manually by callers */
+ thread_mutex mutex;
+
+ Scene(const SceneParams &params, Device *device);
+ ~Scene();
+
+ void device_update(Device *device, Progress &progress);
+
+ bool need_global_attribute(AttributeStandard std);
+ void need_global_attributes(AttributeRequestSet &attributes);
+
+ enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
+ MotionType need_motion();
+ float motion_shutter_time();
+
+ bool need_update();
+ bool need_reset();
+
+ void reset();
+ void device_free();
+
+ void collect_statistics(RenderStats *stats);
+
+ protected:
+ /* Check if some heavy data worth logging was updated.
+ * Mainly used to suppress extra annoying logging.
+ */
+ bool need_data_update();
+
+ void free_memory(bool final);
};
CCL_NAMESPACE_END
-#endif /* __SCENE_H__ */
+#endif /* __SCENE_H__ */
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index e88d960d9d2..29eb779a7d6 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -43,1121 +43,1122 @@ CCL_NAMESPACE_BEGIN
* progressive refine and viewport rendering does requires tiles to
* always be allocated for the same device
*/
-Session::Session(const SessionParams& params_)
-: params(params_),
- tile_manager(params.progressive, params.samples, params.tile_size, params.start_resolution,
- params.background == false || params.progressive_refine, params.background, params.tile_order,
- max(params.device.multi_devices.size(), 1), params.pixel_size),
- stats(),
- profiler()
+Session::Session(const SessionParams &params_)
+ : params(params_),
+ tile_manager(params.progressive,
+ params.samples,
+ params.tile_size,
+ params.start_resolution,
+ params.background == false || params.progressive_refine,
+ params.background,
+ params.tile_order,
+ max(params.device.multi_devices.size(), 1),
+ params.pixel_size),
+ stats(),
+ profiler()
{
- device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
+ device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
- TaskScheduler::init(params.threads);
+ TaskScheduler::init(params.threads);
- device = Device::create(params.device, stats, profiler, params.background);
+ device = Device::create(params.device, stats, profiler, params.background);
- if(params.background && !params.write_render_cb) {
- buffers = NULL;
- display = NULL;
- }
- else {
- buffers = new RenderBuffers(device);
- display = new DisplayBuffer(device, params.display_buffer_linear);
- }
+ if (params.background && !params.write_render_cb) {
+ buffers = NULL;
+ display = NULL;
+ }
+ else {
+ buffers = new RenderBuffers(device);
+ display = new DisplayBuffer(device, params.display_buffer_linear);
+ }
- session_thread = NULL;
- scene = NULL;
+ session_thread = NULL;
+ scene = NULL;
- reset_time = 0.0;
- last_update_time = 0.0;
+ reset_time = 0.0;
+ last_update_time = 0.0;
- delayed_reset.do_reset = false;
- delayed_reset.samples = 0;
+ delayed_reset.do_reset = false;
+ delayed_reset.samples = 0;
- display_outdated = false;
- gpu_draw_ready = false;
- gpu_need_tonemap = false;
- pause = false;
- kernels_loaded = false;
+ display_outdated = false;
+ gpu_draw_ready = false;
+ gpu_need_tonemap = false;
+ pause = false;
+ kernels_loaded = false;
- /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
- max_closure_global = 1;
+ /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */
+ max_closure_global = 1;
}
Session::~Session()
{
- if(session_thread) {
- /* wait for session thread to end */
- progress.set_cancel("Exiting");
+ if (session_thread) {
+ /* wait for session thread to end */
+ progress.set_cancel("Exiting");
- gpu_need_tonemap = false;
- gpu_need_tonemap_cond.notify_all();
+ gpu_need_tonemap = false;
+ gpu_need_tonemap_cond.notify_all();
- {
- thread_scoped_lock pause_lock(pause_mutex);
- pause = false;
- }
- pause_cond.notify_all();
+ {
+ thread_scoped_lock pause_lock(pause_mutex);
+ pause = false;
+ }
+ pause_cond.notify_all();
- wait();
- }
+ wait();
+ }
- if(params.write_render_cb) {
- /* tonemap and write out image if requested */
- delete display;
+ if (params.write_render_cb) {
+ /* tonemap and write out image if requested */
+ delete display;
- display = new DisplayBuffer(device, false);
- display->reset(buffers->params);
- tonemap(params.samples);
+ display = new DisplayBuffer(device, false);
+ display->reset(buffers->params);
+ tonemap(params.samples);
- int w = display->draw_width;
- int h = display->draw_height;
- uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h);
- params.write_render_cb((uchar*)pixels, w, h, 4);
- }
+ int w = display->draw_width;
+ int h = display->draw_height;
+ uchar4 *pixels = display->rgba_byte.copy_from_device(0, w, h);
+ params.write_render_cb((uchar *)pixels, w, h, 4);
+ }
- /* clean up */
- tile_manager.device_free();
+ /* clean up */
+ tile_manager.device_free();
- delete buffers;
- delete display;
- delete scene;
- delete device;
+ delete buffers;
+ delete display;
+ delete scene;
+ delete device;
- TaskScheduler::exit();
+ TaskScheduler::exit();
}
void Session::start()
{
- if (!session_thread) {
- session_thread = new thread(function_bind(&Session::run, this));
- }
+ if (!session_thread) {
+ session_thread = new thread(function_bind(&Session::run, this));
+ }
}
bool Session::ready_to_reset()
{
- double dt = time_dt() - reset_time;
+ double dt = time_dt() - reset_time;
- if(!display_outdated)
- return (dt > params.reset_timeout);
- else
- return (dt > params.cancel_timeout);
+ if (!display_outdated)
+ return (dt > params.reset_timeout);
+ else
+ return (dt > params.cancel_timeout);
}
/* GPU Session */
-void Session::reset_gpu(BufferParams& buffer_params, int samples)
+void Session::reset_gpu(BufferParams &buffer_params, int samples)
{
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock pause_lock(pause_mutex);
- /* block for buffer access and reset immediately. we can't do this
- * in the thread, because we need to allocate an OpenGL buffer, and
- * that only works in the main thread */
- thread_scoped_lock display_lock(display_mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
+ /* block for buffer access and reset immediately. we can't do this
+ * in the thread, because we need to allocate an OpenGL buffer, and
+ * that only works in the main thread */
+ thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
- display_outdated = true;
- reset_time = time_dt();
+ display_outdated = true;
+ reset_time = time_dt();
- reset_(buffer_params, samples);
+ reset_(buffer_params, samples);
- gpu_need_tonemap = false;
- gpu_need_tonemap_cond.notify_all();
+ gpu_need_tonemap = false;
+ gpu_need_tonemap_cond.notify_all();
- pause_cond.notify_all();
+ pause_cond.notify_all();
}
-bool Session::draw_gpu(BufferParams& buffer_params, DeviceDrawParams& draw_params)
+bool Session::draw_gpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- /* block for buffer access */
- thread_scoped_lock display_lock(display_mutex);
-
- /* first check we already rendered something */
- if(gpu_draw_ready) {
- /* then verify the buffers have the expected size, so we don't
- * draw previous results in a resized window */
- if(!buffer_params.modified(display->params)) {
- /* for CUDA we need to do tonemapping still, since we can
- * only access GL buffers from the main thread */
- if(gpu_need_tonemap) {
- thread_scoped_lock buffers_lock(buffers_mutex);
- tonemap(tile_manager.state.sample);
- gpu_need_tonemap = false;
- gpu_need_tonemap_cond.notify_all();
- }
-
- display->draw(device, draw_params);
-
- if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
- return false;
-
- return true;
- }
- }
-
- return false;
+ /* block for buffer access */
+ thread_scoped_lock display_lock(display_mutex);
+
+ /* first check we already rendered something */
+ if (gpu_draw_ready) {
+ /* then verify the buffers have the expected size, so we don't
+ * draw previous results in a resized window */
+ if (!buffer_params.modified(display->params)) {
+ /* for CUDA we need to do tonemapping still, since we can
+ * only access GL buffers from the main thread */
+ if (gpu_need_tonemap) {
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ tonemap(tile_manager.state.sample);
+ gpu_need_tonemap = false;
+ gpu_need_tonemap_cond.notify_all();
+ }
+
+ display->draw(device, draw_params);
+
+ if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
+ return false;
+
+ return true;
+ }
+ }
+
+ return false;
}
void Session::run_gpu()
{
- bool tiles_written = false;
-
- reset_time = time_dt();
- last_update_time = time_dt();
-
- progress.set_render_start_time();
-
- while(!progress.get_cancel()) {
- /* advance to next tile */
- bool no_tiles = !tile_manager.next();
-
- DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
- if (no_tiles) {
- kernel_state = device->get_active_kernel_switch_state();
- }
-
- if(params.background) {
- /* if no work left and in background mode, we can stop immediately */
- if(no_tiles) {
- progress.set_status("Finished");
- break;
- }
- }
-
- /* Don't go in pause mode when image was rendered with preview kernels
- * When feature kernels become available the session will be resetted. */
- else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- time_sleep(0.1);
- }
- else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
- reset_gpu(tile_manager.params, params.samples);
- }
-
- else {
- /* if in interactive mode, and we are either paused or done for now,
- * wait for pause condition notify to wake up again */
- thread_scoped_lock pause_lock(pause_mutex);
-
- if(!pause && !tile_manager.done()) {
- /* reset could have happened after no_tiles was set, before this lock.
- * in this case we shall not wait for pause condition
- */
- }
- else if(pause || no_tiles) {
- update_status_time(pause, no_tiles);
-
- while(1) {
- scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if(pause) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause, no_tiles);
- progress.set_update();
-
- if(!pause)
- break;
- }
- }
-
- if(progress.get_cancel())
- break;
- }
-
- if(!no_tiles) {
- /* update scene */
- scoped_timer update_timer;
- if(update_scene()) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- if(progress.get_cancel())
- break;
- }
-
- if(!no_tiles) {
- /* buffers mutex is locked entirely while rendering each
- * sample, and released/reacquired on each iteration to allow
- * reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex);
-
- /* update status and timing */
- update_status_time();
-
- /* render */
- render();
-
- device->task_wait();
-
- if(!device->error_message().empty())
- progress.set_cancel(device->error_message());
-
- /* update status and timing */
- update_status_time();
-
- gpu_need_tonemap = true;
- gpu_draw_ready = true;
- progress.set_update();
-
- /* wait for tonemap */
- if(!params.background) {
- while(gpu_need_tonemap) {
- if(progress.get_cancel())
- break;
-
- gpu_need_tonemap_cond.wait(buffers_lock);
- }
- }
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- tiles_written = update_progressive_refine(progress.get_cancel());
-
- if(progress.get_cancel())
- break;
- }
- }
-
- if(!tiles_written)
- update_progressive_refine(true);
+ bool tiles_written = false;
+
+ reset_time = time_dt();
+ last_update_time = time_dt();
+
+ progress.set_render_start_time();
+
+ while (!progress.get_cancel()) {
+ /* advance to next tile */
+ bool no_tiles = !tile_manager.next();
+
+ DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
+ if (no_tiles) {
+ kernel_state = device->get_active_kernel_switch_state();
+ }
+
+ if (params.background) {
+ /* if no work left and in background mode, we can stop immediately */
+ if (no_tiles) {
+ progress.set_status("Finished");
+ break;
+ }
+ }
+
+ /* Don't go in pause mode when image was rendered with preview kernels
+ * When feature kernels become available the session will be resetted. */
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
+ time_sleep(0.1);
+ }
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
+ reset_gpu(tile_manager.params, params.samples);
+ }
+
+ else {
+ /* if in interactive mode, and we are either paused or done for now,
+ * wait for pause condition notify to wake up again */
+ thread_scoped_lock pause_lock(pause_mutex);
+
+ if (!pause && !tile_manager.done()) {
+ /* reset could have happened after no_tiles was set, before this lock.
+ * in this case we shall not wait for pause condition
+ */
+ }
+ else if (pause || no_tiles) {
+ update_status_time(pause, no_tiles);
+
+ while (1) {
+ scoped_timer pause_timer;
+ pause_cond.wait(pause_lock);
+ if (pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
+
+ update_status_time(pause, no_tiles);
+ progress.set_update();
+
+ if (!pause)
+ break;
+ }
+ }
+
+ if (progress.get_cancel())
+ break;
+ }
+
+ if (!no_tiles) {
+ /* update scene */
+ scoped_timer update_timer;
+ if (update_scene()) {
+ profiler.reset(scene->shaders.size(), scene->objects.size());
+ }
+ progress.add_skip_time(update_timer, params.background);
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ if (progress.get_cancel())
+ break;
+ }
+
+ if (!no_tiles) {
+ /* buffers mutex is locked entirely while rendering each
+ * sample, and released/reacquired on each iteration to allow
+ * reset and draw in between */
+ thread_scoped_lock buffers_lock(buffers_mutex);
+
+ /* update status and timing */
+ update_status_time();
+
+ /* render */
+ render();
+
+ device->task_wait();
+
+ if (!device->error_message().empty())
+ progress.set_cancel(device->error_message());
+
+ /* update status and timing */
+ update_status_time();
+
+ gpu_need_tonemap = true;
+ gpu_draw_ready = true;
+ progress.set_update();
+
+ /* wait for tonemap */
+ if (!params.background) {
+ while (gpu_need_tonemap) {
+ if (progress.get_cancel())
+ break;
+
+ gpu_need_tonemap_cond.wait(buffers_lock);
+ }
+ }
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ tiles_written = update_progressive_refine(progress.get_cancel());
+
+ if (progress.get_cancel())
+ break;
+ }
+ }
+
+ if (!tiles_written)
+ update_progressive_refine(true);
}
/* CPU Session */
-void Session::reset_cpu(BufferParams& buffer_params, int samples)
+void Session::reset_cpu(BufferParams &buffer_params, int samples)
{
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock pause_lock(pause_mutex);
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock pause_lock(pause_mutex);
- display_outdated = true;
- reset_time = time_dt();
+ display_outdated = true;
+ reset_time = time_dt();
- delayed_reset.params = buffer_params;
- delayed_reset.samples = samples;
- delayed_reset.do_reset = true;
- device->task_cancel();
+ delayed_reset.params = buffer_params;
+ delayed_reset.samples = samples;
+ delayed_reset.do_reset = true;
+ device->task_cancel();
- pause_cond.notify_all();
+ pause_cond.notify_all();
}
-bool Session::draw_cpu(BufferParams& buffer_params, DeviceDrawParams& draw_params)
+bool Session::draw_cpu(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- thread_scoped_lock display_lock(display_mutex);
+ thread_scoped_lock display_lock(display_mutex);
- /* first check we already rendered something */
- if(display->draw_ready()) {
- /* then verify the buffers have the expected size, so we don't
- * draw previous results in a resized window */
- if(!buffer_params.modified(display->params)) {
- display->draw(device, draw_params);
+ /* first check we already rendered something */
+ if (display->draw_ready()) {
+ /* then verify the buffers have the expected size, so we don't
+ * draw previous results in a resized window */
+ if (!buffer_params.modified(display->params)) {
+ display->draw(device, draw_params);
- if(display_outdated && (time_dt() - reset_time) > params.text_timeout)
- return false;
+ if (display_outdated && (time_dt() - reset_time) > params.text_timeout)
+ return false;
- return true;
- }
- }
+ return true;
+ }
+ }
- return false;
+ return false;
}
-bool Session::acquire_tile(Device *tile_device, RenderTile& rtile)
+bool Session::acquire_tile(Device *tile_device, RenderTile &rtile)
{
- if(progress.get_cancel()) {
- if(params.progressive_refine == false) {
- /* for progressive refine current sample should be finished for all tiles */
- return false;
- }
- }
-
- thread_scoped_lock tile_lock(tile_mutex);
-
- /* get next tile from manager */
- Tile *tile;
- int device_num = device->device_number(tile_device);
-
- if(!tile_manager.next_tile(tile, device_num))
- return false;
-
- /* fill render tile */
- rtile.x = tile_manager.state.buffer.full_x + tile->x;
- rtile.y = tile_manager.state.buffer.full_y + tile->y;
- rtile.w = tile->w;
- rtile.h = tile->h;
- rtile.start_sample = tile_manager.state.sample;
- rtile.num_samples = tile_manager.state.num_samples;
- rtile.resolution = tile_manager.state.resolution_divider;
- rtile.tile_index = tile->index;
- rtile.task = (tile->state == Tile::DENOISE)? RenderTile::DENOISE: RenderTile::PATH_TRACE;
-
- tile_lock.unlock();
-
- /* in case of a permanent buffer, return it, otherwise we will allocate
- * a new temporary buffer */
- if(buffers) {
- tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
-
- rtile.buffer = buffers->buffer.device_pointer;
- rtile.buffers = buffers;
-
- device->map_tile(tile_device, rtile);
-
- return true;
- }
-
- if(tile->buffers == NULL) {
- /* fill buffer parameters */
- BufferParams buffer_params = tile_manager.params;
- buffer_params.full_x = rtile.x;
- buffer_params.full_y = rtile.y;
- buffer_params.width = rtile.w;
- buffer_params.height = rtile.h;
-
- /* allocate buffers */
- tile->buffers = new RenderBuffers(tile_device);
- tile->buffers->reset(buffer_params);
- }
-
- tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
-
- rtile.buffer = tile->buffers->buffer.device_pointer;
- rtile.buffers = tile->buffers;
- rtile.sample = tile_manager.state.sample;
-
- /* this will tag tile as IN PROGRESS in blender-side render pipeline,
- * which is needed to highlight currently rendering tile before first
- * sample was processed for it
- */
- update_tile_sample(rtile);
-
- return true;
+ if (progress.get_cancel()) {
+ if (params.progressive_refine == false) {
+ /* for progressive refine current sample should be finished for all tiles */
+ return false;
+ }
+ }
+
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ /* get next tile from manager */
+ Tile *tile;
+ int device_num = device->device_number(tile_device);
+
+ if (!tile_manager.next_tile(tile, device_num))
+ return false;
+
+ /* fill render tile */
+ rtile.x = tile_manager.state.buffer.full_x + tile->x;
+ rtile.y = tile_manager.state.buffer.full_y + tile->y;
+ rtile.w = tile->w;
+ rtile.h = tile->h;
+ rtile.start_sample = tile_manager.state.sample;
+ rtile.num_samples = tile_manager.state.num_samples;
+ rtile.resolution = tile_manager.state.resolution_divider;
+ rtile.tile_index = tile->index;
+ rtile.task = (tile->state == Tile::DENOISE) ? RenderTile::DENOISE : RenderTile::PATH_TRACE;
+
+ tile_lock.unlock();
+
+ /* in case of a permanent buffer, return it, otherwise we will allocate
+ * a new temporary buffer */
+ if (buffers) {
+ tile_manager.state.buffer.get_offset_stride(rtile.offset, rtile.stride);
+
+ rtile.buffer = buffers->buffer.device_pointer;
+ rtile.buffers = buffers;
+
+ device->map_tile(tile_device, rtile);
+
+ return true;
+ }
+
+ if (tile->buffers == NULL) {
+ /* fill buffer parameters */
+ BufferParams buffer_params = tile_manager.params;
+ buffer_params.full_x = rtile.x;
+ buffer_params.full_y = rtile.y;
+ buffer_params.width = rtile.w;
+ buffer_params.height = rtile.h;
+
+ /* allocate buffers */
+ tile->buffers = new RenderBuffers(tile_device);
+ tile->buffers->reset(buffer_params);
+ }
+
+ tile->buffers->params.get_offset_stride(rtile.offset, rtile.stride);
+
+ rtile.buffer = tile->buffers->buffer.device_pointer;
+ rtile.buffers = tile->buffers;
+ rtile.sample = tile_manager.state.sample;
+
+ /* this will tag tile as IN PROGRESS in blender-side render pipeline,
+ * which is needed to highlight currently rendering tile before first
+ * sample was processed for it
+ */
+ update_tile_sample(rtile);
+
+ return true;
}
-void Session::update_tile_sample(RenderTile& rtile)
+void Session::update_tile_sample(RenderTile &rtile)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex);
- if(update_render_tile_cb) {
- if(params.progressive_refine == false) {
- /* todo: optimize this by making it thread safe and removing lock */
+ if (update_render_tile_cb) {
+ if (params.progressive_refine == false) {
+ /* todo: optimize this by making it thread safe and removing lock */
- update_render_tile_cb(rtile, true);
- }
- }
+ update_render_tile_cb(rtile, true);
+ }
+ }
- update_status_time();
+ update_status_time();
}
-void Session::release_tile(RenderTile& rtile)
+void Session::release_tile(RenderTile &rtile)
{
- thread_scoped_lock tile_lock(tile_mutex);
+ thread_scoped_lock tile_lock(tile_mutex);
- progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
+ progress.add_finished_tile(rtile.task == RenderTile::DENOISE);
- bool delete_tile;
+ bool delete_tile;
- if(tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
- if(write_render_tile_cb && params.progressive_refine == false) {
- write_render_tile_cb(rtile);
- }
+ if (tile_manager.finish_tile(rtile.tile_index, delete_tile)) {
+ if (write_render_tile_cb && params.progressive_refine == false) {
+ write_render_tile_cb(rtile);
+ }
- if(delete_tile) {
- delete rtile.buffers;
- tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
- }
- }
- else {
- if(update_render_tile_cb && params.progressive_refine == false) {
- update_render_tile_cb(rtile, false);
- }
- }
+ if (delete_tile) {
+ delete rtile.buffers;
+ tile_manager.state.tiles[rtile.tile_index].buffers = NULL;
+ }
+ }
+ else {
+ if (update_render_tile_cb && params.progressive_refine == false) {
+ update_render_tile_cb(rtile, false);
+ }
+ }
- update_status_time();
+ update_status_time();
}
void Session::map_neighbor_tiles(RenderTile *tiles, Device *tile_device)
{
- thread_scoped_lock tile_lock(tile_mutex);
-
- int center_idx = tiles[4].tile_index;
- assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
- BufferParams buffer_params = tile_manager.params;
- int4 image_region = make_int4(buffer_params.full_x, buffer_params.full_y,
- buffer_params.full_x + buffer_params.width, buffer_params.full_y + buffer_params.height);
-
- for(int dy = -1, i = 0; dy <= 1; dy++) {
- for(int dx = -1; dx <= 1; dx++, i++) {
- int px = tiles[4].x + dx*params.tile_size.x;
- int py = tiles[4].y + dy*params.tile_size.y;
- if(px >= image_region.x && py >= image_region.y &&
- px < image_region.z && py < image_region.w) {
- int tile_index = center_idx + dy*tile_manager.state.tile_stride + dx;
- Tile *tile = &tile_manager.state.tiles[tile_index];
- assert(tile->buffers);
-
- tiles[i].buffer = tile->buffers->buffer.device_pointer;
- tiles[i].x = tile_manager.state.buffer.full_x + tile->x;
- tiles[i].y = tile_manager.state.buffer.full_y + tile->y;
- tiles[i].w = tile->w;
- tiles[i].h = tile->h;
- tiles[i].buffers = tile->buffers;
-
- tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride);
- }
- else {
- tiles[i].buffer = (device_ptr)NULL;
- tiles[i].buffers = NULL;
- tiles[i].x = clamp(px, image_region.x, image_region.z);
- tiles[i].y = clamp(py, image_region.y, image_region.w);
- tiles[i].w = tiles[i].h = 0;
- }
- }
- }
-
- assert(tiles[4].buffers);
- device->map_neighbor_tiles(tile_device, tiles);
-
- /* The denoised result is written back to the original tile. */
- tiles[9] = tiles[4];
+ thread_scoped_lock tile_lock(tile_mutex);
+
+ int center_idx = tiles[4].tile_index;
+ assert(tile_manager.state.tiles[center_idx].state == Tile::DENOISE);
+ BufferParams buffer_params = tile_manager.params;
+ int4 image_region = make_int4(buffer_params.full_x,
+ buffer_params.full_y,
+ buffer_params.full_x + buffer_params.width,
+ buffer_params.full_y + buffer_params.height);
+
+ for (int dy = -1, i = 0; dy <= 1; dy++) {
+ for (int dx = -1; dx <= 1; dx++, i++) {
+ int px = tiles[4].x + dx * params.tile_size.x;
+ int py = tiles[4].y + dy * params.tile_size.y;
+ if (px >= image_region.x && py >= image_region.y && px < image_region.z &&
+ py < image_region.w) {
+ int tile_index = center_idx + dy * tile_manager.state.tile_stride + dx;
+ Tile *tile = &tile_manager.state.tiles[tile_index];
+ assert(tile->buffers);
+
+ tiles[i].buffer = tile->buffers->buffer.device_pointer;
+ tiles[i].x = tile_manager.state.buffer.full_x + tile->x;
+ tiles[i].y = tile_manager.state.buffer.full_y + tile->y;
+ tiles[i].w = tile->w;
+ tiles[i].h = tile->h;
+ tiles[i].buffers = tile->buffers;
+
+ tile->buffers->params.get_offset_stride(tiles[i].offset, tiles[i].stride);
+ }
+ else {
+ tiles[i].buffer = (device_ptr)NULL;
+ tiles[i].buffers = NULL;
+ tiles[i].x = clamp(px, image_region.x, image_region.z);
+ tiles[i].y = clamp(py, image_region.y, image_region.w);
+ tiles[i].w = tiles[i].h = 0;
+ }
+ }
+ }
+
+ assert(tiles[4].buffers);
+ device->map_neighbor_tiles(tile_device, tiles);
+
+ /* The denoised result is written back to the original tile. */
+ tiles[9] = tiles[4];
}
void Session::unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device)
{
- thread_scoped_lock tile_lock(tile_mutex);
- device->unmap_neighbor_tiles(tile_device, tiles);
+ thread_scoped_lock tile_lock(tile_mutex);
+ device->unmap_neighbor_tiles(tile_device, tiles);
}
void Session::run_cpu()
{
- bool tiles_written = false;
-
- last_update_time = time_dt();
-
- {
- /* reset once to start */
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- reset_(delayed_reset.params, delayed_reset.samples);
- delayed_reset.do_reset = false;
- }
-
- while(!progress.get_cancel()) {
- /* advance to next tile */
- bool no_tiles = !tile_manager.next();
- bool need_tonemap = false;
-
- DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
- if (no_tiles) {
- kernel_state = device->get_active_kernel_switch_state();
- }
-
- if(params.background) {
- /* if no work left and in background mode, we can stop immediately */
- if(no_tiles) {
- progress.set_status("Finished");
- break;
- }
- }
-
- /* Don't go in pause mode when preview kernels are used
- * When feature kernels become available the session will be resetted. */
- else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- time_sleep(0.1);
- }
- else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
- reset_cpu(tile_manager.params, params.samples);
- }
-
- else {
- /* if in interactive mode, and we are either paused or done for now,
- * wait for pause condition notify to wake up again */
- thread_scoped_lock pause_lock(pause_mutex);
-
- if(!pause && delayed_reset.do_reset) {
- /* reset once to start */
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- reset_(delayed_reset.params, delayed_reset.samples);
- delayed_reset.do_reset = false;
- }
- else if(pause || no_tiles) {
- update_status_time(pause, no_tiles);
-
- while(1) {
- scoped_timer pause_timer;
- pause_cond.wait(pause_lock);
- if(pause) {
- progress.add_skip_time(pause_timer, params.background);
- }
-
- update_status_time(pause, no_tiles);
- progress.set_update();
-
- if(!pause)
- break;
- }
- }
-
- if(progress.get_cancel())
- break;
- }
-
- if(!no_tiles) {
- /* buffers mutex is locked entirely while rendering each
- * sample, and released/reacquired on each iteration to allow
- * reset and draw in between */
- thread_scoped_lock buffers_lock(buffers_mutex);
-
- /* update scene */
- scoped_timer update_timer;
- if(update_scene()) {
- profiler.reset(scene->shaders.size(), scene->objects.size());
- }
- progress.add_skip_time(update_timer, params.background);
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- if(progress.get_cancel())
- break;
-
- /* update status and timing */
- update_status_time();
-
- /* render */
- render();
-
- /* update status and timing */
- update_status_time();
-
- if(!params.background)
- need_tonemap = true;
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
- }
-
- device->task_wait();
-
- {
- thread_scoped_lock reset_lock(delayed_reset.mutex);
- thread_scoped_lock buffers_lock(buffers_mutex);
- thread_scoped_lock display_lock(display_mutex);
-
- if(delayed_reset.do_reset) {
- /* reset rendering if request from main thread */
- delayed_reset.do_reset = false;
- reset_(delayed_reset.params, delayed_reset.samples);
- }
- else if(need_tonemap) {
- /* tonemap only if we do not reset, we don't we don't
- * want to show the result of an incomplete sample */
- tonemap(tile_manager.state.sample);
- }
-
- if(!device->error_message().empty())
- progress.set_error(device->error_message());
-
- tiles_written = update_progressive_refine(progress.get_cancel());
- }
-
- progress.set_update();
- }
-
- if(!tiles_written)
- update_progressive_refine(true);
+ bool tiles_written = false;
+
+ last_update_time = time_dt();
+
+ {
+ /* reset once to start */
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset.do_reset = false;
+ }
+
+ while (!progress.get_cancel()) {
+ /* advance to next tile */
+ bool no_tiles = !tile_manager.next();
+ bool need_tonemap = false;
+
+ DeviceKernelStatus kernel_state = DEVICE_KERNEL_UNKNOWN;
+ if (no_tiles) {
+ kernel_state = device->get_active_kernel_switch_state();
+ }
+
+ if (params.background) {
+ /* if no work left and in background mode, we can stop immediately */
+ if (no_tiles) {
+ progress.set_status("Finished");
+ break;
+ }
+ }
+
+ /* Don't go in pause mode when preview kernels are used
+ * When feature kernels become available the session will be resetted. */
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
+ time_sleep(0.1);
+ }
+ else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
+ reset_cpu(tile_manager.params, params.samples);
+ }
+
+ else {
+ /* if in interactive mode, and we are either paused or done for now,
+ * wait for pause condition notify to wake up again */
+ thread_scoped_lock pause_lock(pause_mutex);
+
+ if (!pause && delayed_reset.do_reset) {
+ /* reset once to start */
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ reset_(delayed_reset.params, delayed_reset.samples);
+ delayed_reset.do_reset = false;
+ }
+ else if (pause || no_tiles) {
+ update_status_time(pause, no_tiles);
+
+ while (1) {
+ scoped_timer pause_timer;
+ pause_cond.wait(pause_lock);
+ if (pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
+
+ update_status_time(pause, no_tiles);
+ progress.set_update();
+
+ if (!pause)
+ break;
+ }
+ }
+
+ if (progress.get_cancel())
+ break;
+ }
+
+ if (!no_tiles) {
+ /* buffers mutex is locked entirely while rendering each
+ * sample, and released/reacquired on each iteration to allow
+ * reset and draw in between */
+ thread_scoped_lock buffers_lock(buffers_mutex);
+
+ /* update scene */
+ scoped_timer update_timer;
+ if (update_scene()) {
+ profiler.reset(scene->shaders.size(), scene->objects.size());
+ }
+ progress.add_skip_time(update_timer, params.background);
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ if (progress.get_cancel())
+ break;
+
+ /* update status and timing */
+ update_status_time();
+
+ /* render */
+ render();
+
+ /* update status and timing */
+ update_status_time();
+
+ if (!params.background)
+ need_tonemap = true;
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+ }
+
+ device->task_wait();
+
+ {
+ thread_scoped_lock reset_lock(delayed_reset.mutex);
+ thread_scoped_lock buffers_lock(buffers_mutex);
+ thread_scoped_lock display_lock(display_mutex);
+
+ if (delayed_reset.do_reset) {
+ /* reset rendering if request from main thread */
+ delayed_reset.do_reset = false;
+ reset_(delayed_reset.params, delayed_reset.samples);
+ }
+ else if (need_tonemap) {
+ /* tonemap only if we do not reset, we don't we don't
+ * want to show the result of an incomplete sample */
+ tonemap(tile_manager.state.sample);
+ }
+
+ if (!device->error_message().empty())
+ progress.set_error(device->error_message());
+
+ tiles_written = update_progressive_refine(progress.get_cancel());
+ }
+
+ progress.set_update();
+ }
+
+ if (!tiles_written)
+ update_progressive_refine(true);
}
DeviceRequestedFeatures Session::get_requested_device_features()
{
- /* TODO(sergey): Consider moving this to the Scene level. */
- DeviceRequestedFeatures requested_features;
- requested_features.experimental = params.experimental;
-
- scene->shader_manager->get_requested_features(
- scene,
- &requested_features);
-
- /* This features are not being tweaked as often as shaders,
- * so could be done selective magic for the viewport as well.
- */
- bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR;
- requested_features.use_hair = false;
- requested_features.use_object_motion = false;
- requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
- foreach(Object *object, scene->objects) {
- Mesh *mesh = object->mesh;
- if(mesh->num_curves()) {
- requested_features.use_hair = true;
- }
- if (use_motion) {
- requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
- requested_features.use_camera_motion |= mesh->use_motion_blur;
- }
+ /* TODO(sergey): Consider moving this to the Scene level. */
+ DeviceRequestedFeatures requested_features;
+ requested_features.experimental = params.experimental;
+
+ scene->shader_manager->get_requested_features(scene, &requested_features);
+
+ /* This features are not being tweaked as often as shaders,
+ * so could be done selective magic for the viewport as well.
+ */
+ bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR;
+ requested_features.use_hair = false;
+ requested_features.use_object_motion = false;
+ requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
+ foreach (Object *object, scene->objects) {
+ Mesh *mesh = object->mesh;
+ if (mesh->num_curves()) {
+ requested_features.use_hair = true;
+ }
+ if (use_motion) {
+ requested_features.use_object_motion |= object->use_motion() | mesh->use_motion_blur;
+ requested_features.use_camera_motion |= mesh->use_motion_blur;
+ }
#ifdef WITH_OPENSUBDIV
- if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
- requested_features.use_patch_evaluation = true;
- }
+ if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) {
+ requested_features.use_patch_evaluation = true;
+ }
#endif
- if(object->is_shadow_catcher) {
- requested_features.use_shadow_tricks = true;
- }
- requested_features.use_true_displacement |= mesh->has_true_displacement();
- }
-
- requested_features.use_background_light = scene->light_manager->has_background_light(scene);
-
- BakeManager *bake_manager = scene->bake_manager;
- requested_features.use_baking = bake_manager->get_baking();
- requested_features.use_integrator_branched = (scene->integrator->method == Integrator::BRANCHED_PATH);
- if(params.run_denoising) {
- requested_features.use_denoising = true;
- requested_features.use_shadow_tricks = true;
- }
-
- return requested_features;
+ if (object->is_shadow_catcher) {
+ requested_features.use_shadow_tricks = true;
+ }
+ requested_features.use_true_displacement |= mesh->has_true_displacement();
+ }
+
+ requested_features.use_background_light = scene->light_manager->has_background_light(scene);
+
+ BakeManager *bake_manager = scene->bake_manager;
+ requested_features.use_baking = bake_manager->get_baking();
+ requested_features.use_integrator_branched = (scene->integrator->method ==
+ Integrator::BRANCHED_PATH);
+ if (params.run_denoising) {
+ requested_features.use_denoising = true;
+ requested_features.use_shadow_tricks = true;
+ }
+
+ return requested_features;
}
bool Session::load_kernels(bool lock_scene)
{
- thread_scoped_lock scene_lock;
- if(lock_scene) {
- scene_lock = thread_scoped_lock(scene->mutex);
- }
-
- DeviceRequestedFeatures requested_features = get_requested_device_features();
-
- if(!kernels_loaded || loaded_kernel_features.modified(requested_features)) {
- progress.set_status("Loading render kernels (may take a few minutes the first time)");
-
- scoped_timer timer;
-
- VLOG(2) << "Requested features:\n" << requested_features;
- if(!device->load_kernels(requested_features)) {
- string message = device->error_message();
- if(message.empty())
- message = "Failed loading render kernel, see console for errors";
-
- progress.set_error(message);
- progress.set_status("Error", message);
- progress.set_update();
- return false;
- }
-
- progress.add_skip_time(timer, false);
- VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
-
- kernels_loaded = true;
- loaded_kernel_features = requested_features;
- return true;
- }
- return false;
+ thread_scoped_lock scene_lock;
+ if (lock_scene) {
+ scene_lock = thread_scoped_lock(scene->mutex);
+ }
+
+ DeviceRequestedFeatures requested_features = get_requested_device_features();
+
+ if (!kernels_loaded || loaded_kernel_features.modified(requested_features)) {
+ progress.set_status("Loading render kernels (may take a few minutes the first time)");
+
+ scoped_timer timer;
+
+ VLOG(2) << "Requested features:\n" << requested_features;
+ if (!device->load_kernels(requested_features)) {
+ string message = device->error_message();
+ if (message.empty())
+ message = "Failed loading render kernel, see console for errors";
+
+ progress.set_error(message);
+ progress.set_status("Error", message);
+ progress.set_update();
+ return false;
+ }
+
+ progress.add_skip_time(timer, false);
+ VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
+
+ kernels_loaded = true;
+ loaded_kernel_features = requested_features;
+ return true;
+ }
+ return false;
}
void Session::run()
{
- if(params.use_profiling && (params.device.type == DEVICE_CPU)) {
- profiler.start();
- }
-
- /* session thread loop */
- progress.set_status("Waiting for render to start");
-
- /* run */
- if(!progress.get_cancel()) {
- /* reset number of rendered samples */
- progress.reset_sample();
-
- if(device_use_gl)
- run_gpu();
- else
- run_cpu();
- }
-
- profiler.stop();
-
- /* progress update */
- if(progress.get_cancel())
- progress.set_status("Cancel", progress.get_cancel_message());
- else
- progress.set_update();
+ if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
+ profiler.start();
+ }
+
+ /* session thread loop */
+ progress.set_status("Waiting for render to start");
+
+ /* run */
+ if (!progress.get_cancel()) {
+ /* reset number of rendered samples */
+ progress.reset_sample();
+
+ if (device_use_gl)
+ run_gpu();
+ else
+ run_cpu();
+ }
+
+ profiler.stop();
+
+ /* progress update */
+ if (progress.get_cancel())
+ progress.set_status("Cancel", progress.get_cancel_message());
+ else
+ progress.set_update();
}
-bool Session::draw(BufferParams& buffer_params, DeviceDrawParams &draw_params)
+bool Session::draw(BufferParams &buffer_params, DeviceDrawParams &draw_params)
{
- if(device_use_gl)
- return draw_gpu(buffer_params, draw_params);
- else
- return draw_cpu(buffer_params, draw_params);
+ if (device_use_gl)
+ return draw_gpu(buffer_params, draw_params);
+ else
+ return draw_cpu(buffer_params, draw_params);
}
-void Session::reset_(BufferParams& buffer_params, int samples)
+void Session::reset_(BufferParams &buffer_params, int samples)
{
- if(buffers && buffer_params.modified(tile_manager.params)) {
- gpu_draw_ready = false;
- buffers->reset(buffer_params);
- if(display) {
- display->reset(buffer_params);
- }
- }
-
- tile_manager.reset(buffer_params, samples);
- progress.reset_sample();
-
- bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
- progress.set_total_pixel_samples(show_progress? tile_manager.state.total_pixel_samples : 0);
-
- if(!params.background)
- progress.set_start_time();
- progress.set_render_start_time();
+ if (buffers && buffer_params.modified(tile_manager.params)) {
+ gpu_draw_ready = false;
+ buffers->reset(buffer_params);
+ if (display) {
+ display->reset(buffer_params);
+ }
+ }
+
+ tile_manager.reset(buffer_params, samples);
+ progress.reset_sample();
+
+ bool show_progress = params.background || tile_manager.get_num_effective_samples() != INT_MAX;
+ progress.set_total_pixel_samples(show_progress ? tile_manager.state.total_pixel_samples : 0);
+
+ if (!params.background)
+ progress.set_start_time();
+ progress.set_render_start_time();
}
-void Session::reset(BufferParams& buffer_params, int samples)
+void Session::reset(BufferParams &buffer_params, int samples)
{
- if(device_use_gl)
- reset_gpu(buffer_params, samples);
- else
- reset_cpu(buffer_params, samples);
+ if (device_use_gl)
+ reset_gpu(buffer_params, samples);
+ else
+ reset_cpu(buffer_params, samples);
}
void Session::set_samples(int samples)
{
- if(samples != params.samples) {
- params.samples = samples;
- tile_manager.set_samples(samples);
-
- {
- thread_scoped_lock pause_lock(pause_mutex);
- }
- pause_cond.notify_all();
- }
+ if (samples != params.samples) {
+ params.samples = samples;
+ tile_manager.set_samples(samples);
+
+ {
+ thread_scoped_lock pause_lock(pause_mutex);
+ }
+ pause_cond.notify_all();
+ }
}
void Session::set_pause(bool pause_)
{
- bool notify = false;
+ bool notify = false;
- {
- thread_scoped_lock pause_lock(pause_mutex);
+ {
+ thread_scoped_lock pause_lock(pause_mutex);
- if(pause != pause_) {
- pause = pause_;
- notify = true;
- }
- }
+ if (pause != pause_) {
+ pause = pause_;
+ notify = true;
+ }
+ }
- if(notify)
- pause_cond.notify_all();
+ if (notify)
+ pause_cond.notify_all();
}
void Session::wait()
{
- if (session_thread) {
- session_thread->join();
- delete session_thread;
- }
+ if (session_thread) {
+ session_thread->join();
+ delete session_thread;
+ }
- session_thread = NULL;
+ session_thread = NULL;
}
bool Session::update_scene()
{
- thread_scoped_lock scene_lock(scene->mutex);
-
- /* update camera if dimensions changed for progressive render. the camera
- * knows nothing about progressive or cropped rendering, it just gets the
- * image dimensions passed in */
- Camera *cam = scene->camera;
- int width = tile_manager.state.buffer.full_width;
- int height = tile_manager.state.buffer.full_height;
- int resolution = tile_manager.state.resolution_divider;
-
- if(width != cam->width || height != cam->height) {
- cam->width = width;
- cam->height = height;
- cam->resolution = resolution;
- cam->tag_update();
- }
-
- /* number of samples is needed by multi jittered
- * sampling pattern and by baking */
- Integrator *integrator = scene->integrator;
- BakeManager *bake_manager = scene->bake_manager;
-
- if(integrator->sampling_pattern == SAMPLING_PATTERN_CMJ ||
- bake_manager->get_baking())
- {
- int aa_samples = tile_manager.num_samples;
-
- if(aa_samples != integrator->aa_samples) {
- integrator->aa_samples = aa_samples;
- integrator->tag_update(scene);
- }
- }
-
- /* update scene */
- if(scene->need_update()) {
- bool new_kernels_needed = load_kernels(false);
-
- /* Update max_closures. */
- KernelIntegrator *kintegrator = &scene->dscene.data.integrator;
- if(params.background) {
- kintegrator->max_closures = get_max_closure_count();
- }
- else {
- /* Currently viewport render is faster with higher max_closures, needs investigating. */
- kintegrator->max_closures = MAX_CLOSURE;
- }
-
- progress.set_status("Updating Scene");
- MEM_GUARDED_CALL(&progress, scene->device_update, device, progress);
-
- DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
- bool kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
- kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
- if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
- progress.set_kernel_status("Compiling render kernels");
- }
- if (new_kernels_needed || kernel_switch_needed) {
- progress.set_kernel_status("Compiling render kernels");
- device->wait_for_availability(loaded_kernel_features);
- progress.set_kernel_status("");
- }
-
- if (kernel_switch_needed) {
- reset(tile_manager.params, params.samples);
- }
- return true;
- }
- return false;
+ thread_scoped_lock scene_lock(scene->mutex);
+
+ /* update camera if dimensions changed for progressive render. the camera
+ * knows nothing about progressive or cropped rendering, it just gets the
+ * image dimensions passed in */
+ Camera *cam = scene->camera;
+ int width = tile_manager.state.buffer.full_width;
+ int height = tile_manager.state.buffer.full_height;
+ int resolution = tile_manager.state.resolution_divider;
+
+ if (width != cam->width || height != cam->height) {
+ cam->width = width;
+ cam->height = height;
+ cam->resolution = resolution;
+ cam->tag_update();
+ }
+
+ /* number of samples is needed by multi jittered
+ * sampling pattern and by baking */
+ Integrator *integrator = scene->integrator;
+ BakeManager *bake_manager = scene->bake_manager;
+
+ if (integrator->sampling_pattern == SAMPLING_PATTERN_CMJ || bake_manager->get_baking()) {
+ int aa_samples = tile_manager.num_samples;
+
+ if (aa_samples != integrator->aa_samples) {
+ integrator->aa_samples = aa_samples;
+ integrator->tag_update(scene);
+ }
+ }
+
+ /* update scene */
+ if (scene->need_update()) {
+ bool new_kernels_needed = load_kernels(false);
+
+ /* Update max_closures. */
+ KernelIntegrator *kintegrator = &scene->dscene.data.integrator;
+ if (params.background) {
+ kintegrator->max_closures = get_max_closure_count();
+ }
+ else {
+ /* Currently viewport render is faster with higher max_closures, needs investigating. */
+ kintegrator->max_closures = MAX_CLOSURE;
+ }
+
+ progress.set_status("Updating Scene");
+ MEM_GUARDED_CALL(&progress, scene->device_update, device, progress);
+
+ DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
+ bool kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
+ kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
+ if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
+ progress.set_kernel_status("Compiling render kernels");
+ }
+ if (new_kernels_needed || kernel_switch_needed) {
+ progress.set_kernel_status("Compiling render kernels");
+ device->wait_for_availability(loaded_kernel_features);
+ progress.set_kernel_status("");
+ }
+
+ if (kernel_switch_needed) {
+ reset(tile_manager.params, params.samples);
+ }
+ return true;
+ }
+ return false;
}
void Session::update_status_time(bool show_pause, bool show_done)
{
- int progressive_sample = tile_manager.state.sample;
- int num_samples = tile_manager.get_num_effective_samples();
-
- int tile = progress.get_rendered_tiles();
- int num_tiles = tile_manager.state.num_tiles;
-
- /* update status */
- string status, substatus;
-
- if(!params.progressive) {
- const bool is_cpu = params.device.type == DEVICE_CPU;
- const bool rendering_finished = (tile == num_tiles);
- const bool is_last_tile = (tile + 1) == num_tiles;
-
- substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles);
-
- if(!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) {
- /* Some devices automatically support showing the sample number:
- * - CUDADevice
- * - OpenCLDevice when using the megakernel (the split kernel renders multiple
- * samples at the same time, so the current sample isn't really defined)
- * - CPUDevice when using one thread
- * For these devices, the current sample is always shown.
- *
- * The other option is when the last tile is currently being rendered by the CPU.
- */
- substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
- }
- if(params.full_denoising) {
- substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
- }
- else if(params.run_denoising) {
- substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles());
- }
- }
- else if(tile_manager.num_samples == INT_MAX)
- substatus = string_printf("Path Tracing Sample %d", progressive_sample+1);
- else
- substatus = string_printf("Path Tracing Sample %d/%d",
- progressive_sample+1,
- num_samples);
-
- if(show_pause) {
- status = "Rendering Paused";
- }
- else if(show_done) {
- status = "Rendering Done";
- progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
- }
- else {
- status = substatus;
- substatus.clear();
- }
-
- progress.set_status(status, substatus);
+ int progressive_sample = tile_manager.state.sample;
+ int num_samples = tile_manager.get_num_effective_samples();
+
+ int tile = progress.get_rendered_tiles();
+ int num_tiles = tile_manager.state.num_tiles;
+
+ /* update status */
+ string status, substatus;
+
+ if (!params.progressive) {
+ const bool is_cpu = params.device.type == DEVICE_CPU;
+ const bool rendering_finished = (tile == num_tiles);
+ const bool is_last_tile = (tile + 1) == num_tiles;
+
+ substatus = string_printf("Rendered %d/%d Tiles", tile, num_tiles);
+
+ if (!rendering_finished && (device->show_samples() || (is_cpu && is_last_tile))) {
+ /* Some devices automatically support showing the sample number:
+ * - CUDADevice
+ * - OpenCLDevice when using the megakernel (the split kernel renders multiple
+ * samples at the same time, so the current sample isn't really defined)
+ * - CPUDevice when using one thread
+ * For these devices, the current sample is always shown.
+ *
+ * The other option is when the last tile is currently being rendered by the CPU.
+ */
+ substatus += string_printf(", Sample %d/%d", progress.get_current_sample(), num_samples);
+ }
+ if (params.full_denoising) {
+ substatus += string_printf(", Denoised %d tiles", progress.get_denoised_tiles());
+ }
+ else if (params.run_denoising) {
+ substatus += string_printf(", Prefiltered %d tiles", progress.get_denoised_tiles());
+ }
+ }
+ else if (tile_manager.num_samples == INT_MAX)
+ substatus = string_printf("Path Tracing Sample %d", progressive_sample + 1);
+ else
+ substatus = string_printf("Path Tracing Sample %d/%d", progressive_sample + 1, num_samples);
+
+ if (show_pause) {
+ status = "Rendering Paused";
+ }
+ else if (show_done) {
+ status = "Rendering Done";
+ progress.set_end_time(); /* Save end time so that further calls to get_time are accurate. */
+ }
+ else {
+ status = substatus;
+ substatus.clear();
+ }
+
+ progress.set_status(status, substatus);
}
void Session::render()
{
- /* Clear buffers. */
- if(buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
- buffers->zero();
- }
-
- /* Add path trace task. */
- DeviceTask task(DeviceTask::RENDER);
-
- task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
- task.release_tile = function_bind(&Session::release_tile, this, _1);
- task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
- task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
- task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
- task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
- task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
- task.need_finish_queue = params.progressive_refine;
- task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
- task.requested_tile_size = params.tile_size;
- task.passes_size = tile_manager.params.get_passes_size();
-
- if(params.run_denoising) {
- task.denoising = params.denoising;
-
- assert(!scene->film->need_update);
- task.pass_stride = scene->film->pass_stride;
- task.target_pass_stride = task.pass_stride;
- task.pass_denoising_data = scene->film->denoising_data_offset;
- task.pass_denoising_clean = scene->film->denoising_clean_offset;
-
- task.denoising_from_render = true;
- task.denoising_do_filter = params.full_denoising;
- task.denoising_write_passes = params.write_denoising_passes;
- }
-
- device->task_add(task);
+ /* Clear buffers. */
+ if (buffers && tile_manager.state.sample == tile_manager.range_start_sample) {
+ buffers->zero();
+ }
+
+ /* Add path trace task. */
+ DeviceTask task(DeviceTask::RENDER);
+
+ task.acquire_tile = function_bind(&Session::acquire_tile, this, _1, _2);
+ task.release_tile = function_bind(&Session::release_tile, this, _1);
+ task.map_neighbor_tiles = function_bind(&Session::map_neighbor_tiles, this, _1, _2);
+ task.unmap_neighbor_tiles = function_bind(&Session::unmap_neighbor_tiles, this, _1, _2);
+ task.get_cancel = function_bind(&Progress::get_cancel, &this->progress);
+ task.update_tile_sample = function_bind(&Session::update_tile_sample, this, _1);
+ task.update_progress_sample = function_bind(&Progress::add_samples, &this->progress, _1, _2);
+ task.need_finish_queue = params.progressive_refine;
+ task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
+ task.requested_tile_size = params.tile_size;
+ task.passes_size = tile_manager.params.get_passes_size();
+
+ if (params.run_denoising) {
+ task.denoising = params.denoising;
+
+ assert(!scene->film->need_update);
+ task.pass_stride = scene->film->pass_stride;
+ task.target_pass_stride = task.pass_stride;
+ task.pass_denoising_data = scene->film->denoising_data_offset;
+ task.pass_denoising_clean = scene->film->denoising_clean_offset;
+
+ task.denoising_from_render = true;
+ task.denoising_do_filter = params.full_denoising;
+ task.denoising_write_passes = params.write_denoising_passes;
+ }
+
+ device->task_add(task);
}
void Session::tonemap(int sample)
{
- /* add tonemap task */
- DeviceTask task(DeviceTask::FILM_CONVERT);
-
- task.x = tile_manager.state.buffer.full_x;
- task.y = tile_manager.state.buffer.full_y;
- task.w = tile_manager.state.buffer.width;
- task.h = tile_manager.state.buffer.height;
- task.rgba_byte = display->rgba_byte.device_pointer;
- task.rgba_half = display->rgba_half.device_pointer;
- task.buffer = buffers->buffer.device_pointer;
- task.sample = sample;
- tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
-
- if(task.w > 0 && task.h > 0) {
- device->task_add(task);
- device->task_wait();
-
- /* set display to new size */
- display->draw_set(task.w, task.h);
- }
-
- display_outdated = false;
+ /* add tonemap task */
+ DeviceTask task(DeviceTask::FILM_CONVERT);
+
+ task.x = tile_manager.state.buffer.full_x;
+ task.y = tile_manager.state.buffer.full_y;
+ task.w = tile_manager.state.buffer.width;
+ task.h = tile_manager.state.buffer.height;
+ task.rgba_byte = display->rgba_byte.device_pointer;
+ task.rgba_half = display->rgba_half.device_pointer;
+ task.buffer = buffers->buffer.device_pointer;
+ task.sample = sample;
+ tile_manager.state.buffer.get_offset_stride(task.offset, task.stride);
+
+ if (task.w > 0 && task.h > 0) {
+ device->task_add(task);
+ device->task_wait();
+
+ /* set display to new size */
+ display->draw_set(task.w, task.h);
+ }
+
+ display_outdated = false;
}
bool Session::update_progressive_refine(bool cancel)
{
- int sample = tile_manager.state.sample + 1;
- bool write = sample == tile_manager.num_samples || cancel;
-
- double current_time = time_dt();
-
- if(current_time - last_update_time < params.progressive_update_timeout) {
- /* if last sample was processed, we need to write buffers anyway */
- if(!write && sample != 1)
- return false;
- }
-
- if(params.progressive_refine) {
- foreach(Tile& tile, tile_manager.state.tiles) {
- if(!tile.buffers) {
- continue;
- }
-
- RenderTile rtile;
- rtile.x = tile_manager.state.buffer.full_x + tile.x;
- rtile.y = tile_manager.state.buffer.full_y + tile.y;
- rtile.w = tile.w;
- rtile.h = tile.h;
- rtile.sample = sample;
- rtile.buffers = tile.buffers;
-
- if(write) {
- if(write_render_tile_cb)
- write_render_tile_cb(rtile);
- }
- else {
- if(update_render_tile_cb)
- update_render_tile_cb(rtile, true);
- }
- }
- }
-
- last_update_time = current_time;
-
- return write;
+ int sample = tile_manager.state.sample + 1;
+ bool write = sample == tile_manager.num_samples || cancel;
+
+ double current_time = time_dt();
+
+ if (current_time - last_update_time < params.progressive_update_timeout) {
+ /* if last sample was processed, we need to write buffers anyway */
+ if (!write && sample != 1)
+ return false;
+ }
+
+ if (params.progressive_refine) {
+ foreach (Tile &tile, tile_manager.state.tiles) {
+ if (!tile.buffers) {
+ continue;
+ }
+
+ RenderTile rtile;
+ rtile.x = tile_manager.state.buffer.full_x + tile.x;
+ rtile.y = tile_manager.state.buffer.full_y + tile.y;
+ rtile.w = tile.w;
+ rtile.h = tile.h;
+ rtile.sample = sample;
+ rtile.buffers = tile.buffers;
+
+ if (write) {
+ if (write_render_tile_cb)
+ write_render_tile_cb(rtile);
+ }
+ else {
+ if (update_render_tile_cb)
+ update_render_tile_cb(rtile, true);
+ }
+ }
+ }
+
+ last_update_time = current_time;
+
+ return write;
}
void Session::device_free()
{
- scene->device_free();
+ scene->device_free();
- tile_manager.device_free();
+ tile_manager.device_free();
- /* used from background render only, so no need to
- * re-create render/display buffers here
- */
+ /* used from background render only, so no need to
+ * re-create render/display buffers here
+ */
}
void Session::collect_statistics(RenderStats *render_stats)
{
- scene->collect_statistics(render_stats);
- if(params.use_profiling && (params.device.type == DEVICE_CPU)) {
- render_stats->collect_profiling(scene, profiler);
- }
+ scene->collect_statistics(render_stats);
+ if (params.use_profiling && (params.device.type == DEVICE_CPU)) {
+ render_stats->collect_profiling(scene, profiler);
+ }
}
int Session::get_max_closure_count()
{
- if (scene->shader_manager->use_osl()) {
- /* OSL always needs the maximum as we can't predict the
- * number of closures a shader might generate. */
- return MAX_CLOSURE;
- }
-
- int max_closures = 0;
- for(int i = 0; i < scene->shaders.size(); i++) {
- int num_closures = scene->shaders[i]->graph->get_num_closures();
- max_closures = max(max_closures, num_closures);
- }
- max_closure_global = max(max_closure_global, max_closures);
-
- if (max_closure_global > MAX_CLOSURE) {
- /* This is usually harmless as more complex shader tend to get many
- * closures discarded due to mixing or low weights. We need to limit
- * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
- * avoids excessive memory usage for split kernels. */
- VLOG(2) << "Maximum number of closures exceeded: "
- << max_closure_global
- << " > "
- << MAX_CLOSURE;
-
- max_closure_global = MAX_CLOSURE;
- }
-
- return max_closure_global;
+ if (scene->shader_manager->use_osl()) {
+ /* OSL always needs the maximum as we can't predict the
+ * number of closures a shader might generate. */
+ return MAX_CLOSURE;
+ }
+
+ int max_closures = 0;
+ for (int i = 0; i < scene->shaders.size(); i++) {
+ int num_closures = scene->shaders[i]->graph->get_num_closures();
+ max_closures = max(max_closures, num_closures);
+ }
+ max_closure_global = max(max_closure_global, max_closures);
+
+ if (max_closure_global > MAX_CLOSURE) {
+ /* This is usually harmless as more complex shader tend to get many
+ * closures discarded due to mixing or low weights. We need to limit
+ * to MAX_CLOSURE as this is hardcoded in CPU/mega kernels, and it
+ * avoids excessive memory usage for split kernels. */
+ VLOG(2) << "Maximum number of closures exceeded: " << max_closure_global << " > "
+ << MAX_CLOSURE;
+
+ max_closure_global = MAX_CLOSURE;
+ }
+
+ return max_closure_global;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 404b7b7a945..60d8f7a8b14 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -42,91 +42,83 @@ class Scene;
/* Session Parameters */
class SessionParams {
-public:
- DeviceInfo device;
- bool background;
- bool progressive_refine;
-
- bool progressive;
- bool experimental;
- int samples;
- int2 tile_size;
- TileOrder tile_order;
- int start_resolution;
- int pixel_size;
- int threads;
-
- bool use_profiling;
-
- bool display_buffer_linear;
-
- bool run_denoising;
- bool write_denoising_passes;
- bool full_denoising;
- DenoiseParams denoising;
-
- double cancel_timeout;
- double reset_timeout;
- double text_timeout;
- double progressive_update_timeout;
-
- ShadingSystem shadingsystem;
-
- function<bool(const uchar *pixels,
- int width,
- int height,
- int channels)> write_render_cb;
-
- SessionParams()
- {
- background = false;
- progressive_refine = false;
-
- progressive = false;
- experimental = false;
- samples = 1024;
- tile_size = make_int2(64, 64);
- start_resolution = INT_MAX;
- pixel_size = 1;
- threads = 0;
-
- use_profiling = false;
-
- run_denoising = false;
- write_denoising_passes = false;
- full_denoising = false;
-
- display_buffer_linear = false;
-
- cancel_timeout = 0.1;
- reset_timeout = 0.1;
- text_timeout = 1.0;
- progressive_update_timeout = 1.0;
-
- shadingsystem = SHADINGSYSTEM_SVM;
- tile_order = TILE_CENTER;
- }
-
- bool modified(const SessionParams& params)
- { return !(device == params.device
- && background == params.background
- && progressive_refine == params.progressive_refine
- /* && samples == params.samples */
- && progressive == params.progressive
- && experimental == params.experimental
- && tile_size == params.tile_size
- && start_resolution == params.start_resolution
- && pixel_size == params.pixel_size
- && threads == params.threads
- && use_profiling == params.use_profiling
- && display_buffer_linear == params.display_buffer_linear
- && cancel_timeout == params.cancel_timeout
- && reset_timeout == params.reset_timeout
- && text_timeout == params.text_timeout
- && progressive_update_timeout == params.progressive_update_timeout
- && tile_order == params.tile_order
- && shadingsystem == params.shadingsystem); }
-
+ public:
+ DeviceInfo device;
+ bool background;
+ bool progressive_refine;
+
+ bool progressive;
+ bool experimental;
+ int samples;
+ int2 tile_size;
+ TileOrder tile_order;
+ int start_resolution;
+ int pixel_size;
+ int threads;
+
+ bool use_profiling;
+
+ bool display_buffer_linear;
+
+ bool run_denoising;
+ bool write_denoising_passes;
+ bool full_denoising;
+ DenoiseParams denoising;
+
+ double cancel_timeout;
+ double reset_timeout;
+ double text_timeout;
+ double progressive_update_timeout;
+
+ ShadingSystem shadingsystem;
+
+ function<bool(const uchar *pixels, int width, int height, int channels)> write_render_cb;
+
+ SessionParams()
+ {
+ background = false;
+ progressive_refine = false;
+
+ progressive = false;
+ experimental = false;
+ samples = 1024;
+ tile_size = make_int2(64, 64);
+ start_resolution = INT_MAX;
+ pixel_size = 1;
+ threads = 0;
+
+ use_profiling = false;
+
+ run_denoising = false;
+ write_denoising_passes = false;
+ full_denoising = false;
+
+ display_buffer_linear = false;
+
+ cancel_timeout = 0.1;
+ reset_timeout = 0.1;
+ text_timeout = 1.0;
+ progressive_update_timeout = 1.0;
+
+ shadingsystem = SHADINGSYSTEM_SVM;
+ tile_order = TILE_CENTER;
+ }
+
+ bool modified(const SessionParams &params)
+ {
+ return !(device == params.device && background == params.background &&
+ progressive_refine == params.progressive_refine
+ /* && samples == params.samples */
+ && progressive == params.progressive && experimental == params.experimental &&
+ tile_size == params.tile_size && start_resolution == params.start_resolution &&
+ pixel_size == params.pixel_size && threads == params.threads &&
+ use_profiling == params.use_profiling &&
+ display_buffer_linear == params.display_buffer_linear &&
+ cancel_timeout == params.cancel_timeout && reset_timeout == params.reset_timeout &&
+ text_timeout == params.text_timeout &&
+ progressive_update_timeout == params.progressive_update_timeout &&
+ tile_order == params.tile_order && shadingsystem == params.shadingsystem);
+ }
};
/* Session
@@ -135,111 +127,111 @@ public:
* control loop and dispatching tasks. */
class Session {
-public:
- Device *device;
- Scene *scene;
- RenderBuffers *buffers;
- DisplayBuffer *display;
- Progress progress;
- SessionParams params;
- TileManager tile_manager;
- Stats stats;
- Profiler profiler;
+ public:
+ Device *device;
+ Scene *scene;
+ RenderBuffers *buffers;
+ DisplayBuffer *display;
+ Progress progress;
+ SessionParams params;
+ TileManager tile_manager;
+ Stats stats;
+ Profiler profiler;
- function<void(RenderTile&)> write_render_tile_cb;
- function<void(RenderTile&, bool)> update_render_tile_cb;
+ function<void(RenderTile &)> write_render_tile_cb;
+ function<void(RenderTile &, bool)> update_render_tile_cb;
- explicit Session(const SessionParams& params);
- ~Session();
+ explicit Session(const SessionParams &params);
+ ~Session();
- void start();
- bool draw(BufferParams& params, DeviceDrawParams& draw_params);
- void wait();
+ void start();
+ bool draw(BufferParams &params, DeviceDrawParams &draw_params);
+ void wait();
- bool ready_to_reset();
- void reset(BufferParams& params, int samples);
- void set_samples(int samples);
- void set_pause(bool pause);
+ bool ready_to_reset();
+ void reset(BufferParams &params, int samples);
+ void set_samples(int samples);
+ void set_pause(bool pause);
- bool update_scene();
- bool load_kernels(bool lock_scene=true);
+ bool update_scene();
+ bool load_kernels(bool lock_scene = true);
- void device_free();
+ void device_free();
- /* Returns the rendering progress or 0 if no progress can be determined
- * (for example, when rendering with unlimited samples). */
- float get_progress();
+ /* Returns the rendering progress or 0 if no progress can be determined
+ * (for example, when rendering with unlimited samples). */
+ float get_progress();
- void collect_statistics(RenderStats *stats);
+ void collect_statistics(RenderStats *stats);
-protected:
- struct DelayedReset {
- thread_mutex mutex;
- bool do_reset;
- BufferParams params;
- int samples;
- } delayed_reset;
+ protected:
+ struct DelayedReset {
+ thread_mutex mutex;
+ bool do_reset;
+ BufferParams params;
+ int samples;
+ } delayed_reset;
- void run();
+ void run();
- void update_status_time(bool show_pause = false, bool show_done = false);
+ void update_status_time(bool show_pause = false, bool show_done = false);
- void tonemap(int sample);
- void render();
- void reset_(BufferParams& params, int samples);
+ void tonemap(int sample);
+ void render();
+ void reset_(BufferParams &params, int samples);
- void run_cpu();
- bool draw_cpu(BufferParams& params, DeviceDrawParams& draw_params);
- void reset_cpu(BufferParams& params, int samples);
+ void run_cpu();
+ bool draw_cpu(BufferParams &params, DeviceDrawParams &draw_params);
+ void reset_cpu(BufferParams &params, int samples);
- void run_gpu();
- bool draw_gpu(BufferParams& params, DeviceDrawParams& draw_params);
- void reset_gpu(BufferParams& params, int samples);
+ void run_gpu();
+ bool draw_gpu(BufferParams &params, DeviceDrawParams &draw_params);
+ void reset_gpu(BufferParams &params, int samples);
- bool acquire_tile(Device *tile_device, RenderTile& tile);
- void update_tile_sample(RenderTile& tile);
- void release_tile(RenderTile& tile);
+ bool acquire_tile(Device *tile_device, RenderTile &tile);
+ void update_tile_sample(RenderTile &tile);
+ void release_tile(RenderTile &tile);
- void map_neighbor_tiles(RenderTile *tiles, Device *tile_device);
- void unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device);
+ void map_neighbor_tiles(RenderTile *tiles, Device *tile_device);
+ void unmap_neighbor_tiles(RenderTile *tiles, Device *tile_device);
- bool device_use_gl;
+ bool device_use_gl;
- thread *session_thread;
+ thread *session_thread;
- volatile bool display_outdated;
+ volatile bool display_outdated;
- volatile bool gpu_draw_ready;
- volatile bool gpu_need_tonemap;
- thread_condition_variable gpu_need_tonemap_cond;
+ volatile bool gpu_draw_ready;
+ volatile bool gpu_need_tonemap;
+ thread_condition_variable gpu_need_tonemap_cond;
- bool pause;
- thread_condition_variable pause_cond;
- thread_mutex pause_mutex;
- thread_mutex tile_mutex;
- thread_mutex buffers_mutex;
- thread_mutex display_mutex;
+ bool pause;
+ thread_condition_variable pause_cond;
+ thread_mutex pause_mutex;
+ thread_mutex tile_mutex;
+ thread_mutex buffers_mutex;
+ thread_mutex display_mutex;
- bool kernels_loaded;
- DeviceRequestedFeatures loaded_kernel_features;
+ bool kernels_loaded;
+ DeviceRequestedFeatures loaded_kernel_features;
- double reset_time;
+ double reset_time;
- /* progressive refine */
- double last_update_time;
- bool update_progressive_refine(bool cancel);
+ /* progressive refine */
+ double last_update_time;
+ bool update_progressive_refine(bool cancel);
- DeviceRequestedFeatures get_requested_device_features();
+ DeviceRequestedFeatures get_requested_device_features();
- /* ** Split kernel routines ** */
+ /* ** Split kernel routines ** */
- /* Maximumnumber of closure during session lifetime. */
- int max_closure_global;
+ /* Maximumnumber of closure during session lifetime. */
+ int max_closure_global;
- /* Get maximum number of closures to be used in kernel. */
- int get_max_closure_count();
+ /* Get maximum number of closures to be used in kernel. */
+ int get_max_closure_count();
};
CCL_NAMESPACE_END
-#endif /* __SESSION_H__ */
+#endif /* __SESSION_H__ */
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 3c94f2dfb59..ac3303cbfeb 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -48,16 +48,15 @@ bool ShaderManager::beckmann_table_ready = false;
/* 2D slope distribution (alpha = 1.0) */
static float beckmann_table_P22(const float slope_x, const float slope_y)
{
- return expf(-(slope_x*slope_x + slope_y*slope_y));
+ return expf(-(slope_x * slope_x + slope_y * slope_y));
}
/* maximal slope amplitude (range that contains 99.99% of the distribution) */
static float beckmann_table_slope_max()
{
- return 6.0;
+ return 6.0;
}
-
/* MSVC 2015 needs this ugly hack to prevent a codegen bug on x86
* see T50176 for details
*/
@@ -74,327 +73,331 @@ static float beckmann_table_slope_max()
*/
static void beckmann_table_rows(float *table, int row_from, int row_to)
{
- /* allocate temporary data */
- const int DATA_TMP_SIZE = 512;
- vector<double> slope_x(DATA_TMP_SIZE);
- vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
-
- /* loop over incident directions */
- for(int index_theta = row_from; index_theta < row_to; index_theta++) {
- /* incident vector */
- const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
- const float sin_theta = safe_sqrtf(1.0f - cos_theta*cos_theta);
-
- /* for a given incident vector
- * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- slope_x[0] = (double)-beckmann_table_slope_max();
- CDF_P22_omega_i[0] = 0;
-
- for(MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
- /* slope_x */
- slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * index_slope_x/(DATA_TMP_SIZE - 1.0f));
-
- /* dot product with incident vector */
- float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x]*sin_theta + cos_theta);
- /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- float P22_omega_i = 0.0f;
-
- for(int j = 0; j < 100; ++j) {
- float slope_y = -beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * j * (1.0f/99.0f);
- P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
- }
-
- /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
- CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
- }
-
- /* renormalize CDF_P22_omega_i */
- for(int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
- CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
-
- /* loop over random number U1 */
- int index_slope_x = 0;
-
- for(int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
- const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
-
- /* inverse CDF_P22_omega_i, solve Eq.(11) */
- while(CDF_P22_omega_i[index_slope_x] <= U)
- ++index_slope_x;
-
- const double interp =
- (CDF_P22_omega_i[index_slope_x] - U) /
- (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
-
- /* store value */
- table[index_U + index_theta*BECKMANN_TABLE_SIZE] = (float)(
- interp * slope_x[index_slope_x - 1] +
- (1.0 - interp) * slope_x[index_slope_x]);
- }
- }
+ /* allocate temporary data */
+ const int DATA_TMP_SIZE = 512;
+ vector<double> slope_x(DATA_TMP_SIZE);
+ vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
+
+ /* loop over incident directions */
+ for (int index_theta = row_from; index_theta < row_to; index_theta++) {
+ /* incident vector */
+ const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
+ const float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+
+ /* for a given incident vector
+ * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ slope_x[0] = (double)-beckmann_table_slope_max();
+ CDF_P22_omega_i[0] = 0;
+
+ for (MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
+ /* slope_x */
+ slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() +
+ 2.0f * beckmann_table_slope_max() * index_slope_x /
+ (DATA_TMP_SIZE - 1.0f));
+
+ /* dot product with incident vector */
+ float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x] * sin_theta + cos_theta);
+ /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ float P22_omega_i = 0.0f;
+
+ for (int j = 0; j < 100; ++j) {
+ float slope_y = -beckmann_table_slope_max() +
+ 2.0f * beckmann_table_slope_max() * j * (1.0f / 99.0f);
+ P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
+ }
+
+ /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+ CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
+ }
+
+ /* renormalize CDF_P22_omega_i */
+ for (int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
+ CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
+
+ /* loop over random number U1 */
+ int index_slope_x = 0;
+
+ for (int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
+ const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
+
+ /* inverse CDF_P22_omega_i, solve Eq.(11) */
+ while (CDF_P22_omega_i[index_slope_x] <= U)
+ ++index_slope_x;
+
+ const double interp = (CDF_P22_omega_i[index_slope_x] - U) /
+ (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
+
+ /* store value */
+ table[index_U + index_theta * BECKMANN_TABLE_SIZE] =
+ (float)(interp * slope_x[index_slope_x - 1] + (1.0 - interp) * slope_x[index_slope_x]);
+ }
+ }
}
#undef MSVC_VOLATILE
-static void beckmann_table_build(vector<float>& table)
+static void beckmann_table_build(vector<float> &table)
{
- table.resize(BECKMANN_TABLE_SIZE*BECKMANN_TABLE_SIZE);
+ table.resize(BECKMANN_TABLE_SIZE * BECKMANN_TABLE_SIZE);
- /* multithreaded build */
- TaskPool pool;
+ /* multithreaded build */
+ TaskPool pool;
- for(int i = 0; i < BECKMANN_TABLE_SIZE; i+=8)
- pool.push(function_bind(&beckmann_table_rows, &table[0], i, i+8));
+ for (int i = 0; i < BECKMANN_TABLE_SIZE; i += 8)
+ pool.push(function_bind(&beckmann_table_rows, &table[0], i, i + 8));
- pool.wait_work();
+ pool.wait_work();
}
/* Shader */
NODE_DEFINE(Shader)
{
- NodeType* type = NodeType::add("shader", create);
-
- SOCKET_BOOLEAN(use_mis, "Use MIS", true);
- SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
- SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
-
- static NodeEnum volume_sampling_method_enum;
- volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
- volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
- volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
- SOCKET_ENUM(volume_sampling_method, "Volume Sampling Method", volume_sampling_method_enum, VOLUME_SAMPLING_DISTANCE);
-
- static NodeEnum volume_interpolation_method_enum;
- volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
- volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
- SOCKET_ENUM(volume_interpolation_method, "Volume Interpolation Method", volume_interpolation_method_enum, VOLUME_INTERPOLATION_LINEAR);
-
- static NodeEnum displacement_method_enum;
- displacement_method_enum.insert("bump", DISPLACE_BUMP);
- displacement_method_enum.insert("true", DISPLACE_TRUE);
- displacement_method_enum.insert("both", DISPLACE_BOTH);
- SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
-
- return type;
+ NodeType *type = NodeType::add("shader", create);
+
+ SOCKET_BOOLEAN(use_mis, "Use MIS", true);
+ SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
+ SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
+
+ static NodeEnum volume_sampling_method_enum;
+ volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
+ volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
+ volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
+ SOCKET_ENUM(volume_sampling_method,
+ "Volume Sampling Method",
+ volume_sampling_method_enum,
+ VOLUME_SAMPLING_DISTANCE);
+
+ static NodeEnum volume_interpolation_method_enum;
+ volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
+ volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
+ SOCKET_ENUM(volume_interpolation_method,
+ "Volume Interpolation Method",
+ volume_interpolation_method_enum,
+ VOLUME_INTERPOLATION_LINEAR);
+
+ static NodeEnum displacement_method_enum;
+ displacement_method_enum.insert("bump", DISPLACE_BUMP);
+ displacement_method_enum.insert("true", DISPLACE_TRUE);
+ displacement_method_enum.insert("both", DISPLACE_BOTH);
+ SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
+
+ return type;
}
-Shader::Shader()
-: Node(node_type)
+Shader::Shader() : Node(node_type)
{
- pass_id = 0;
-
- graph = NULL;
-
- has_surface = false;
- has_surface_transparent = false;
- has_surface_emission = false;
- has_surface_bssrdf = false;
- has_volume = false;
- has_displacement = false;
- has_bump = false;
- has_bssrdf_bump = false;
- has_surface_spatial_varying = false;
- has_volume_spatial_varying = false;
- has_object_dependency = false;
- has_attribute_dependency = false;
- has_integrator_dependency = false;
- has_volume_connected = false;
-
- displacement_method = DISPLACE_BUMP;
-
- id = -1;
- used = false;
-
- need_update = true;
- need_update_mesh = true;
- need_sync_object = false;
+ pass_id = 0;
+
+ graph = NULL;
+
+ has_surface = false;
+ has_surface_transparent = false;
+ has_surface_emission = false;
+ has_surface_bssrdf = false;
+ has_volume = false;
+ has_displacement = false;
+ has_bump = false;
+ has_bssrdf_bump = false;
+ has_surface_spatial_varying = false;
+ has_volume_spatial_varying = false;
+ has_object_dependency = false;
+ has_attribute_dependency = false;
+ has_integrator_dependency = false;
+ has_volume_connected = false;
+
+ displacement_method = DISPLACE_BUMP;
+
+ id = -1;
+ used = false;
+
+ need_update = true;
+ need_update_mesh = true;
+ need_sync_object = false;
}
Shader::~Shader()
{
- delete graph;
+ delete graph;
}
bool Shader::is_constant_emission(float3 *emission)
{
- ShaderInput *surf = graph->output()->input("Surface");
+ ShaderInput *surf = graph->output()->input("Surface");
- if(surf->link == NULL) {
- return false;
- }
+ if (surf->link == NULL) {
+ return false;
+ }
- if(surf->link->parent->type == EmissionNode::node_type) {
- EmissionNode *node = (EmissionNode*) surf->link->parent;
+ if (surf->link->parent->type == EmissionNode::node_type) {
+ EmissionNode *node = (EmissionNode *)surf->link->parent;
- assert(node->input("Color"));
- assert(node->input("Strength"));
+ assert(node->input("Color"));
+ assert(node->input("Strength"));
- if(node->input("Color")->link || node->input("Strength")->link) {
- return false;
- }
+ if (node->input("Color")->link || node->input("Strength")->link) {
+ return false;
+ }
- *emission = node->color*node->strength;
- }
- else if(surf->link->parent->type == BackgroundNode::node_type) {
- BackgroundNode *node = (BackgroundNode*) surf->link->parent;
+ *emission = node->color * node->strength;
+ }
+ else if (surf->link->parent->type == BackgroundNode::node_type) {
+ BackgroundNode *node = (BackgroundNode *)surf->link->parent;
- assert(node->input("Color"));
- assert(node->input("Strength"));
+ assert(node->input("Color"));
+ assert(node->input("Strength"));
- if(node->input("Color")->link || node->input("Strength")->link) {
- return false;
- }
+ if (node->input("Color")->link || node->input("Strength")->link) {
+ return false;
+ }
- *emission = node->color*node->strength;
- }
- else {
- return false;
- }
+ *emission = node->color * node->strength;
+ }
+ else {
+ return false;
+ }
- return true;
+ return true;
}
void Shader::set_graph(ShaderGraph *graph_)
{
- /* 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_proxy_nodes();
-
- if(displacement_method != DISPLACE_BUMP) {
- graph_->compute_displacement_hash();
- }
- }
-
- /* update geometry if displacement changed */
- if(displacement_method != DISPLACE_BUMP) {
- const char *old_hash = (graph)? graph->displacement_hash.c_str() : "";
- const char *new_hash = (graph_)? graph_->displacement_hash.c_str() : "";
-
- if(strcmp(old_hash, new_hash) != 0) {
- need_update_mesh = true;
- }
- }
-
- /* assign graph */
- delete graph;
- graph = graph_;
-
- /* Store info here before graph optimization to make sure that
- * nodes that get optimized away still count. */
- has_volume_connected = (graph->output()->input("Volume")->link != NULL);
+ /* 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_proxy_nodes();
+
+ if (displacement_method != DISPLACE_BUMP) {
+ graph_->compute_displacement_hash();
+ }
+ }
+
+ /* update geometry if displacement changed */
+ if (displacement_method != DISPLACE_BUMP) {
+ const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
+ const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
+
+ if (strcmp(old_hash, new_hash) != 0) {
+ need_update_mesh = true;
+ }
+ }
+
+ /* assign graph */
+ delete graph;
+ graph = graph_;
+
+ /* Store info here before graph optimization to make sure that
+ * nodes that get optimized away still count. */
+ has_volume_connected = (graph->output()->input("Volume")->link != 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. */
- if(use_mis && has_surface_emission)
- scene->light_manager->need_update = true;
-
- /* Special handle of background MIS light for now: for some reason it
- * has use_mis set to false. We are quite close to release now, so
- * better to be safe.
- */
- if(this == scene->default_background &&
- scene->light_manager->has_background_light(scene))
- {
- scene->light_manager->need_update = true;
- }
-
- /* quick detection of which kind of shaders we have to avoid loading
- * e.g. surface attributes when there is only a volume shader. this could
- * be more fine grained but it's better than nothing */
- OutputNode *output = graph->output();
- bool prev_has_volume = has_volume;
- has_surface = has_surface || output->input("Surface")->link;
- has_volume = has_volume || output->input("Volume")->link;
- has_displacement = has_displacement || output->input("Displacement")->link;
-
- /* get requested attributes. this could be optimized by pruning unused
- * 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 */
-
- AttributeRequestSet prev_attributes = attributes;
-
- attributes.clear();
- foreach(ShaderNode *node, graph->nodes)
- node->attributes(this, &attributes);
-
- if(has_displacement && displacement_method == DISPLACE_BOTH) {
- attributes.add(ATTR_STD_POSITION_UNDISPLACED);
- }
-
- /* compare if the attributes changed, mesh manager will check
- * need_update_mesh, update the relevant meshes and clear it. */
- if(attributes.modified(prev_attributes)) {
- need_update_mesh = true;
- scene->mesh_manager->need_update = true;
- }
-
- if(has_volume != prev_has_volume) {
- scene->mesh_manager->need_flags_update = true;
- scene->object_manager->need_flags_update = true;
- }
+ /* 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. */
+ if (use_mis && has_surface_emission)
+ scene->light_manager->need_update = true;
+
+ /* Special handle of background MIS light for now: for some reason it
+ * has use_mis set to false. We are quite close to release now, so
+ * better to be safe.
+ */
+ if (this == scene->default_background && scene->light_manager->has_background_light(scene)) {
+ scene->light_manager->need_update = true;
+ }
+
+ /* quick detection of which kind of shaders we have to avoid loading
+ * e.g. surface attributes when there is only a volume shader. this could
+ * be more fine grained but it's better than nothing */
+ OutputNode *output = graph->output();
+ bool prev_has_volume = has_volume;
+ has_surface = has_surface || output->input("Surface")->link;
+ has_volume = has_volume || output->input("Volume")->link;
+ has_displacement = has_displacement || output->input("Displacement")->link;
+
+ /* get requested attributes. this could be optimized by pruning unused
+ * 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 */
+
+ AttributeRequestSet prev_attributes = attributes;
+
+ attributes.clear();
+ foreach (ShaderNode *node, graph->nodes)
+ node->attributes(this, &attributes);
+
+ if (has_displacement && displacement_method == DISPLACE_BOTH) {
+ attributes.add(ATTR_STD_POSITION_UNDISPLACED);
+ }
+
+ /* compare if the attributes changed, mesh manager will check
+ * need_update_mesh, update the relevant meshes and clear it. */
+ if (attributes.modified(prev_attributes)) {
+ need_update_mesh = true;
+ scene->mesh_manager->need_update = true;
+ }
+
+ if (has_volume != prev_has_volume) {
+ scene->mesh_manager->need_flags_update = true;
+ scene->object_manager->need_flags_update = true;
+ }
}
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;
- }
+ /* 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;
+ }
}
/* Shader Manager */
ShaderManager::ShaderManager()
{
- need_update = true;
- beckmann_table_offset = TABLE_OFFSET_INVALID;
+ need_update = true;
+ beckmann_table_offset = TABLE_OFFSET_INVALID;
- xyz_to_r = make_float3( 3.2404542f, -1.5371385f, -0.4985314f);
- xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
- xyz_to_b = make_float3( 0.0556434f, -0.2040259f, 1.0572252f);
- rgb_to_y = make_float3( 0.2126729f, 0.7151522f, 0.0721750f);
+ xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
+ xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
+ xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
+ rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
#ifdef WITH_OCIO
- OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
- if(config) {
- if(config->hasRole("XYZ") && config->hasRole("scene_linear")) {
- OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
- OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
- if(to_rgb_processor && to_xyz_processor) {
- float r[] = {1.0f, 0.0f, 0.0f};
- float g[] = {0.0f, 1.0f, 0.0f};
- float b[] = {0.0f, 0.0f, 1.0f};
- to_xyz_processor->applyRGB(r);
- to_xyz_processor->applyRGB(g);
- to_xyz_processor->applyRGB(b);
- rgb_to_y = make_float3(r[1], g[1], b[1]);
-
- float x[] = {1.0f, 0.0f, 0.0f};
- float y[] = {0.0f, 1.0f, 0.0f};
- float z[] = {0.0f, 0.0f, 1.0f};
- to_rgb_processor->applyRGB(x);
- to_rgb_processor->applyRGB(y);
- to_rgb_processor->applyRGB(z);
- xyz_to_r = make_float3(x[0], y[0], z[0]);
- xyz_to_g = make_float3(x[1], y[1], z[1]);
- xyz_to_b = make_float3(x[2], y[2], z[2]);
- }
- }
- }
+ OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+ if (config) {
+ if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
+ OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
+ OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
+ if (to_rgb_processor && to_xyz_processor) {
+ float r[] = {1.0f, 0.0f, 0.0f};
+ float g[] = {0.0f, 1.0f, 0.0f};
+ float b[] = {0.0f, 0.0f, 1.0f};
+ to_xyz_processor->applyRGB(r);
+ to_xyz_processor->applyRGB(g);
+ to_xyz_processor->applyRGB(b);
+ rgb_to_y = make_float3(r[1], g[1], b[1]);
+
+ float x[] = {1.0f, 0.0f, 0.0f};
+ float y[] = {0.0f, 1.0f, 0.0f};
+ float z[] = {0.0f, 0.0f, 1.0f};
+ to_rgb_processor->applyRGB(x);
+ to_rgb_processor->applyRGB(y);
+ to_rgb_processor->applyRGB(z);
+ xyz_to_r = make_float3(x[0], y[0], z[0]);
+ xyz_to_g = make_float3(x[1], y[1], z[1]);
+ xyz_to_b = make_float3(x[2], y[2], z[2]);
+ }
+ }
+ }
#endif
}
@@ -404,337 +407,337 @@ ShaderManager::~ShaderManager()
ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
{
- ShaderManager *manager;
+ ShaderManager *manager;
- (void) shadingsystem; /* Ignored when built without OSL. */
+ (void)shadingsystem; /* Ignored when built without OSL. */
#ifdef WITH_OSL
- if(shadingsystem == SHADINGSYSTEM_OSL) {
- manager = new OSLShaderManager();
- }
- else
+ if (shadingsystem == SHADINGSYSTEM_OSL) {
+ manager = new OSLShaderManager();
+ }
+ else
#endif
- {
- manager = new SVMShaderManager();
- }
+ {
+ manager = new SVMShaderManager();
+ }
- add_default(scene);
+ add_default(scene);
- return manager;
+ return manager;
}
uint ShaderManager::get_attribute_id(ustring name)
{
- thread_scoped_spin_lock lock(attribute_lock_);
+ thread_scoped_spin_lock lock(attribute_lock_);
- /* get a unique id for each name, for SVM attribute lookup */
- AttributeIDMap::iterator it = unique_attribute_id.find(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;
+ if (it != unique_attribute_id.end())
+ return it->second;
- uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
- unique_attribute_id[name] = id;
- return id;
+ uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
+ unique_attribute_id[name] = id;
+ return id;
}
uint ShaderManager::get_attribute_id(AttributeStandard std)
{
- return (uint)std;
+ return (uint)std;
}
int ShaderManager::get_shader_id(Shader *shader, bool smooth)
{
- /* get a shader id to pass to the kernel */
- int id = shader->id;
+ /* get a shader id to pass to the kernel */
+ int id = shader->id;
- /* smooth flag */
- if(smooth)
- id |= SHADER_SMOOTH_NORMAL;
+ /* smooth flag */
+ if (smooth)
+ id |= SHADER_SMOOTH_NORMAL;
- /* default flags */
- id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
+ /* default flags */
+ id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT;
- return id;
+ return id;
}
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 */
- uint id = 0;
- foreach(Shader *shader, scene->shaders) {
- shader->used = false;
- shader->id = id++;
- }
-
- scene->default_surface->used = true;
- scene->default_light->used = true;
- scene->default_background->used = true;
- scene->default_empty->used = true;
-
- if(scene->background->shader)
- scene->background->shader->used = true;
-
- foreach(Mesh *mesh, scene->meshes)
- foreach(Shader *shader, mesh->used_shaders)
- shader->used = true;
-
- foreach(Light *light, scene->lights)
- if(light->shader)
- light->shader->used = true;
+ /* figure out which shaders are in use, so SVM/OSL can skip compiling them
+ * for speed and avoid loading image textures into memory */
+ uint id = 0;
+ foreach (Shader *shader, scene->shaders) {
+ shader->used = false;
+ shader->id = id++;
+ }
+
+ scene->default_surface->used = true;
+ scene->default_light->used = true;
+ scene->default_background->used = true;
+ scene->default_empty->used = true;
+
+ if (scene->background->shader)
+ scene->background->shader->used = true;
+
+ foreach (Mesh *mesh, scene->meshes)
+ foreach (Shader *shader, mesh->used_shaders)
+ shader->used = true;
+
+ foreach (Light *light, scene->lights)
+ if (light->shader)
+ light->shader->used = true;
}
void ShaderManager::device_update_common(Device *device,
DeviceScene *dscene,
Scene *scene,
- Progress& /*progress*/)
+ Progress & /*progress*/)
{
- dscene->shaders.free();
-
- if(scene->shaders.size() == 0)
- return;
-
- KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
- bool has_volumes = false;
- bool has_transparent_shadow = false;
-
- foreach(Shader *shader, scene->shaders) {
- uint flag = 0;
-
- if(shader->use_mis)
- flag |= SD_USE_MIS;
- if(shader->has_surface_transparent && shader->use_transparent_shadow)
- flag |= SD_HAS_TRANSPARENT_SHADOW;
- if(shader->has_volume) {
- flag |= SD_HAS_VOLUME;
- has_volumes = true;
-
- /* todo: this could check more fine grained, to skip useless volumes
- * enclosed inside an opaque bsdf.
- */
- flag |= SD_HAS_TRANSPARENT_SHADOW;
- }
- /* in this case we can assume transparent surface */
- if(shader->has_volume_connected && !shader->has_surface)
- flag |= SD_HAS_ONLY_VOLUME;
- if(shader->heterogeneous_volume && shader->has_volume_spatial_varying)
- flag |= SD_HETEROGENEOUS_VOLUME;
- if(shader->has_attribute_dependency)
- flag |= SD_NEED_ATTRIBUTES;
- if(shader->has_bssrdf_bump)
- flag |= SD_HAS_BSSRDF_BUMP;
- if(device->info.has_volume_decoupled) {
- if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
- flag |= SD_VOLUME_EQUIANGULAR;
- if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
- flag |= SD_VOLUME_MIS;
- }
- if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
- flag |= SD_VOLUME_CUBIC;
- if(shader->has_bump)
- flag |= SD_HAS_BUMP;
- if(shader->displacement_method != DISPLACE_BUMP)
- flag |= SD_HAS_DISPLACEMENT;
-
- /* constant emission check */
- float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
- if(shader->is_constant_emission(&constant_emission))
- flag |= SD_HAS_CONSTANT_EMISSION;
-
- uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
-
- /* regular shader */
- kshader->flags = flag;
- kshader->pass_id = shader->pass_id;
- kshader->constant_emission[0] = constant_emission.x;
- kshader->constant_emission[1] = constant_emission.y;
- kshader->constant_emission[2] = constant_emission.z;
- kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
- kshader++;
-
- has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
- }
-
- dscene->shaders.copy_to_device();
-
- /* lookup tables */
- KernelTables *ktables = &dscene->data.tables;
-
- /* beckmann lookup table */
- if(beckmann_table_offset == TABLE_OFFSET_INVALID) {
- if(!beckmann_table_ready) {
- thread_scoped_lock lock(lookup_table_mutex);
- if(!beckmann_table_ready) {
- beckmann_table_build(beckmann_table);
- beckmann_table_ready = true;
- }
- }
- beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
- }
- ktables->beckmann_offset = (int)beckmann_table_offset;
-
- /* integrator */
- KernelIntegrator *kintegrator = &dscene->data.integrator;
- kintegrator->use_volumes = has_volumes;
- /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
- kintegrator->transparent_shadows = has_transparent_shadow;
-
- /* film */
- KernelFilm *kfilm = &dscene->data.film;
- /* color space, needs to be here because e.g. displacement shaders could depend on it */
- kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
- kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
- kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
- kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
+ dscene->shaders.free();
+
+ if (scene->shaders.size() == 0)
+ return;
+
+ KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
+ bool has_volumes = false;
+ bool has_transparent_shadow = false;
+
+ foreach (Shader *shader, scene->shaders) {
+ uint flag = 0;
+
+ if (shader->use_mis)
+ flag |= SD_USE_MIS;
+ if (shader->has_surface_transparent && shader->use_transparent_shadow)
+ flag |= SD_HAS_TRANSPARENT_SHADOW;
+ if (shader->has_volume) {
+ flag |= SD_HAS_VOLUME;
+ has_volumes = true;
+
+ /* todo: this could check more fine grained, to skip useless volumes
+ * enclosed inside an opaque bsdf.
+ */
+ flag |= SD_HAS_TRANSPARENT_SHADOW;
+ }
+ /* in this case we can assume transparent surface */
+ if (shader->has_volume_connected && !shader->has_surface)
+ flag |= SD_HAS_ONLY_VOLUME;
+ if (shader->heterogeneous_volume && shader->has_volume_spatial_varying)
+ flag |= SD_HETEROGENEOUS_VOLUME;
+ if (shader->has_attribute_dependency)
+ flag |= SD_NEED_ATTRIBUTES;
+ if (shader->has_bssrdf_bump)
+ flag |= SD_HAS_BSSRDF_BUMP;
+ if (device->info.has_volume_decoupled) {
+ if (shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
+ flag |= SD_VOLUME_EQUIANGULAR;
+ if (shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
+ flag |= SD_VOLUME_MIS;
+ }
+ if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
+ flag |= SD_VOLUME_CUBIC;
+ if (shader->has_bump)
+ flag |= SD_HAS_BUMP;
+ if (shader->displacement_method != DISPLACE_BUMP)
+ flag |= SD_HAS_DISPLACEMENT;
+
+ /* constant emission check */
+ float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
+ if (shader->is_constant_emission(&constant_emission))
+ flag |= SD_HAS_CONSTANT_EMISSION;
+
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+
+ /* regular shader */
+ kshader->flags = flag;
+ kshader->pass_id = shader->pass_id;
+ kshader->constant_emission[0] = constant_emission.x;
+ kshader->constant_emission[1] = constant_emission.y;
+ kshader->constant_emission[2] = constant_emission.z;
+ kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
+ kshader++;
+
+ has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
+ }
+
+ dscene->shaders.copy_to_device();
+
+ /* lookup tables */
+ KernelTables *ktables = &dscene->data.tables;
+
+ /* beckmann lookup table */
+ if (beckmann_table_offset == TABLE_OFFSET_INVALID) {
+ if (!beckmann_table_ready) {
+ thread_scoped_lock lock(lookup_table_mutex);
+ if (!beckmann_table_ready) {
+ beckmann_table_build(beckmann_table);
+ beckmann_table_ready = true;
+ }
+ }
+ beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
+ }
+ ktables->beckmann_offset = (int)beckmann_table_offset;
+
+ /* integrator */
+ KernelIntegrator *kintegrator = &dscene->data.integrator;
+ kintegrator->use_volumes = has_volumes;
+ /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
+ kintegrator->transparent_shadows = has_transparent_shadow;
+
+ /* film */
+ KernelFilm *kfilm = &dscene->data.film;
+ /* color space, needs to be here because e.g. displacement shaders could depend on it */
+ kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
+ kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
+ kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
+ kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
}
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
{
- scene->lookup_tables->remove_table(&beckmann_table_offset);
+ scene->lookup_tables->remove_table(&beckmann_table_offset);
- dscene->shaders.free();
+ dscene->shaders.free();
}
void ShaderManager::add_default(Scene *scene)
{
- /* default surface */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
- diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
- graph->add(diffuse);
-
- graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
-
- Shader *shader = new Shader();
- shader->name = "default_surface";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_surface = shader;
- }
-
- /* default light */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- EmissionNode *emission = new EmissionNode();
- emission->color = make_float3(0.8f, 0.8f, 0.8f);
- emission->strength = 0.0f;
- graph->add(emission);
-
- graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
-
- Shader *shader = new Shader();
- shader->name = "default_light";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_light = shader;
- }
-
- /* default background */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- Shader *shader = new Shader();
- shader->name = "default_background";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_background = shader;
- }
-
- /* default empty */
- {
- ShaderGraph *graph = new ShaderGraph();
-
- Shader *shader = new Shader();
- shader->name = "default_empty";
- shader->graph = graph;
- scene->shaders.push_back(shader);
- scene->default_empty = shader;
- }
+ /* default surface */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
+ graph->add(diffuse);
+
+ graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
+
+ Shader *shader = new Shader();
+ shader->name = "default_surface";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_surface = shader;
+ }
+
+ /* default light */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ EmissionNode *emission = new EmissionNode();
+ emission->color = make_float3(0.8f, 0.8f, 0.8f);
+ emission->strength = 0.0f;
+ graph->add(emission);
+
+ graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
+
+ Shader *shader = new Shader();
+ shader->name = "default_light";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_light = shader;
+ }
+
+ /* default background */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ Shader *shader = new Shader();
+ shader->name = "default_background";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_background = shader;
+ }
+
+ /* default empty */
+ {
+ ShaderGraph *graph = new ShaderGraph();
+
+ Shader *shader = new Shader();
+ shader->name = "default_empty";
+ shader->graph = graph;
+ scene->shaders.push_back(shader);
+ scene->default_empty = shader;
+ }
}
void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
DeviceRequestedFeatures *requested_features)
{
- foreach(ShaderNode *node, graph->nodes) {
- requested_features->max_nodes_group = max(requested_features->max_nodes_group,
- node->get_group());
- requested_features->nodes_features |= node->get_feature();
- if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
- BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode*>(node);
- if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
- requested_features->nodes_features |= NODE_FEATURE_VOLUME;
- }
- else if(CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
- requested_features->use_principled = true;
- }
- }
- if(node->has_surface_bssrdf()) {
- requested_features->use_subsurface = true;
- }
- if(node->has_surface_transparent()) {
- requested_features->use_transparent = true;
- }
- if(node->has_raytrace()) {
- requested_features->use_shader_raytrace = true;
- }
- }
+ foreach (ShaderNode *node, graph->nodes) {
+ requested_features->max_nodes_group = max(requested_features->max_nodes_group,
+ node->get_group());
+ requested_features->nodes_features |= node->get_feature();
+ if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+ BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
+ if (CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+ requested_features->nodes_features |= NODE_FEATURE_VOLUME;
+ }
+ else if (CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
+ requested_features->use_principled = true;
+ }
+ }
+ if (node->has_surface_bssrdf()) {
+ requested_features->use_subsurface = true;
+ }
+ if (node->has_surface_transparent()) {
+ requested_features->use_transparent = true;
+ }
+ if (node->has_raytrace()) {
+ requested_features->use_shader_raytrace = true;
+ }
+ }
}
void ShaderManager::get_requested_features(Scene *scene,
DeviceRequestedFeatures *requested_features)
{
- requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
- requested_features->nodes_features = 0;
- for(int i = 0; i < scene->shaders.size(); i++) {
- Shader *shader = scene->shaders[i];
- /* Gather requested features from all the nodes from the graph nodes. */
- get_requested_graph_features(shader->graph, requested_features);
- ShaderNode *output_node = shader->graph->output();
- if(output_node->input("Displacement")->link != NULL) {
- requested_features->nodes_features |= NODE_FEATURE_BUMP;
- if(shader->displacement_method == DISPLACE_BOTH) {
- requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
- }
- }
- /* On top of volume nodes, also check if we need volume sampling because
- * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
- if(shader->has_volume)
- requested_features->use_volume |= true;
- }
+ requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
+ requested_features->nodes_features = 0;
+ for (int i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ /* Gather requested features from all the nodes from the graph nodes. */
+ get_requested_graph_features(shader->graph, requested_features);
+ ShaderNode *output_node = shader->graph->output();
+ if (output_node->input("Displacement")->link != NULL) {
+ requested_features->nodes_features |= NODE_FEATURE_BUMP;
+ if (shader->displacement_method == DISPLACE_BOTH) {
+ requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
+ }
+ }
+ /* On top of volume nodes, also check if we need volume sampling because
+ * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
+ if (shader->has_volume)
+ requested_features->use_volume |= true;
+ }
}
void ShaderManager::free_memory()
{
- beckmann_table.free_memory();
+ beckmann_table.free_memory();
#ifdef WITH_OSL
- OSLShaderManager::free_memory();
+ OSLShaderManager::free_memory();
#endif
}
float ShaderManager::linear_rgb_to_gray(float3 c)
{
- return dot(c, rgb_to_y);
+ return dot(c, rgb_to_y);
}
string ShaderManager::get_cryptomatte_materials(Scene *scene)
{
- string manifest = "{";
- unordered_set<ustring, ustringHash> materials;
- foreach(Shader *shader, scene->shaders) {
- if(materials.count(shader->name)) {
- continue;
- }
- materials.insert(shader->name);
- uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
- manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
- }
- manifest[manifest.size()-1] = '}';
- return manifest;
+ string manifest = "{";
+ unordered_set<ustring, ustringHash> materials;
+ foreach (Shader *shader, scene->shaders) {
+ if (materials.count(shader->name)) {
+ continue;
+ }
+ materials.insert(shader->name);
+ uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+ manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
+ }
+ manifest[manifest.size() - 1] = '}';
+ return manifest;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 05772b9a9cd..600b0cc59d4 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -45,33 +45,30 @@ class Scene;
class ShaderGraph;
struct float3;
-enum ShadingSystem {
- SHADINGSYSTEM_OSL,
- SHADINGSYSTEM_SVM
-};
+enum ShadingSystem { SHADINGSYSTEM_OSL, SHADINGSYSTEM_SVM };
/* Keep those in sync with the python-defined enum. */
enum VolumeSampling {
- VOLUME_SAMPLING_DISTANCE = 0,
- VOLUME_SAMPLING_EQUIANGULAR = 1,
- VOLUME_SAMPLING_MULTIPLE_IMPORTANCE = 2,
+ VOLUME_SAMPLING_DISTANCE = 0,
+ VOLUME_SAMPLING_EQUIANGULAR = 1,
+ VOLUME_SAMPLING_MULTIPLE_IMPORTANCE = 2,
- VOLUME_NUM_SAMPLING,
+ VOLUME_NUM_SAMPLING,
};
enum VolumeInterpolation {
- VOLUME_INTERPOLATION_LINEAR = 0,
- VOLUME_INTERPOLATION_CUBIC = 1,
+ VOLUME_INTERPOLATION_LINEAR = 0,
+ VOLUME_INTERPOLATION_CUBIC = 1,
- VOLUME_NUM_INTERPOLATION,
+ VOLUME_NUM_INTERPOLATION,
};
enum DisplacementMethod {
- DISPLACE_BUMP = 0,
- DISPLACE_TRUE = 1,
- DISPLACE_BOTH = 2,
+ DISPLACE_BUMP = 0,
+ DISPLACE_TRUE = 1,
+ DISPLACE_BOTH = 2,
- DISPLACE_NUM_METHODS,
+ DISPLACE_NUM_METHODS,
};
/* Shader describing the appearance of a Mesh, Light or Background.
@@ -81,78 +78,78 @@ enum DisplacementMethod {
* separately. */
class Shader : public Node {
-public:
- NODE_DECLARE
-
- int pass_id;
-
- /* shader graph */
- ShaderGraph *graph;
-
- /* sampling */
- bool use_mis;
- bool use_transparent_shadow;
- bool heterogeneous_volume;
- VolumeSampling volume_sampling_method;
- int volume_interpolation_method;
-
- /* synchronization */
- bool need_update;
- bool need_update_mesh;
- bool need_sync_object;
-
- /* If the shader has only volume components, the surface is assumed to
- * be transparent.
- * However, graph optimization might remove the volume subgraph, but
- * since the user connected something to the volume output the surface
- * should still be transparent.
- * Therefore, has_volume_connected stores whether some volume subtree
- * was connected before optimization. */
- bool has_volume_connected;
-
- /* information about shader after compiling */
- bool has_surface;
- bool has_surface_emission;
- bool has_surface_transparent;
- bool has_volume;
- bool has_displacement;
- bool has_surface_bssrdf;
- bool has_bump;
- bool has_bssrdf_bump;
- bool has_surface_spatial_varying;
- bool has_volume_spatial_varying;
- bool has_object_dependency;
- bool has_attribute_dependency;
- bool has_integrator_dependency;
-
- /* displacement */
- DisplacementMethod displacement_method;
-
- /* requested mesh attributes */
- AttributeRequestSet attributes;
-
- /* determined before compiling */
- uint id;
- bool used;
+ public:
+ NODE_DECLARE
+
+ int pass_id;
+
+ /* shader graph */
+ ShaderGraph *graph;
+
+ /* sampling */
+ bool use_mis;
+ bool use_transparent_shadow;
+ bool heterogeneous_volume;
+ VolumeSampling volume_sampling_method;
+ int volume_interpolation_method;
+
+ /* synchronization */
+ bool need_update;
+ bool need_update_mesh;
+ bool need_sync_object;
+
+ /* If the shader has only volume components, the surface is assumed to
+ * be transparent.
+ * However, graph optimization might remove the volume subgraph, but
+ * since the user connected something to the volume output the surface
+ * should still be transparent.
+ * Therefore, has_volume_connected stores whether some volume subtree
+ * was connected before optimization. */
+ bool has_volume_connected;
+
+ /* information about shader after compiling */
+ bool has_surface;
+ bool has_surface_emission;
+ bool has_surface_transparent;
+ bool has_volume;
+ bool has_displacement;
+ bool has_surface_bssrdf;
+ bool has_bump;
+ bool has_bssrdf_bump;
+ bool has_surface_spatial_varying;
+ bool has_volume_spatial_varying;
+ bool has_object_dependency;
+ bool has_attribute_dependency;
+ bool has_integrator_dependency;
+
+ /* displacement */
+ DisplacementMethod displacement_method;
+
+ /* requested mesh attributes */
+ AttributeRequestSet attributes;
+
+ /* determined before compiling */
+ uint id;
+ bool used;
#ifdef WITH_OSL
- /* osl shading state references */
- OSL::ShaderGroupRef osl_surface_ref;
- OSL::ShaderGroupRef osl_surface_bump_ref;
- OSL::ShaderGroupRef osl_volume_ref;
- OSL::ShaderGroupRef osl_displacement_ref;
+ /* osl shading state references */
+ OSL::ShaderGroupRef osl_surface_ref;
+ OSL::ShaderGroupRef osl_surface_bump_ref;
+ OSL::ShaderGroupRef osl_volume_ref;
+ OSL::ShaderGroupRef osl_displacement_ref;
#endif
- Shader();
- ~Shader();
+ Shader();
+ ~Shader();
- /* Checks whether the shader consists of just a emission node with fixed inputs that's connected directly to the output.
- * If yes, it sets the content of emission to the constant value (color * strength), which is then used for speeding up light evaluation. */
- bool is_constant_emission(float3* emission);
+ /* Checks whether the shader consists of just a emission node with fixed inputs that's connected directly to the output.
+ * If yes, it sets the content of emission to the constant value (color * strength), which is then used for speeding up light evaluation. */
+ bool is_constant_emission(float3 *emission);
- void set_graph(ShaderGraph *graph);
- void tag_update(Scene *scene);
- void tag_used(Scene *scene);
+ void set_graph(ShaderGraph *graph);
+ void tag_update(Scene *scene);
+ void tag_used(Scene *scene);
};
/* Shader Manager virtual base class
@@ -161,68 +158,73 @@ public:
* shader compiling and device updating. */
class ShaderManager {
-public:
- bool need_update;
+ public:
+ bool need_update;
- static ShaderManager *create(Scene *scene, int shadingsystem);
- virtual ~ShaderManager();
+ static ShaderManager *create(Scene *scene, int shadingsystem);
+ virtual ~ShaderManager();
- virtual void reset(Scene *scene) = 0;
+ virtual void reset(Scene *scene) = 0;
- virtual bool use_osl() { return false; }
+ virtual bool use_osl()
+ {
+ return false;
+ }
- /* device update */
- virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0;
- virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0;
+ /* device update */
+ virtual void device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress) = 0;
+ virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0;
- void device_update_shaders_used(Scene *scene);
- void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free_common(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update_shaders_used(Scene *scene);
+ void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free_common(Device *device, DeviceScene *dscene, Scene *scene);
- /* get globally unique id for a type of attribute */
- uint get_attribute_id(ustring name);
- uint get_attribute_id(AttributeStandard std);
+ /* get globally unique id for a type of attribute */
+ uint get_attribute_id(ustring name);
+ uint get_attribute_id(AttributeStandard std);
- /* get shader id for mesh faces */
- int get_shader_id(Shader *shader, bool smooth = false);
+ /* get shader id for mesh faces */
+ int get_shader_id(Shader *shader, bool smooth = false);
- /* add default shaders to scene, to use as default for things that don't
- * have any shader assigned explicitly */
- static void add_default(Scene *scene);
+ /* add default shaders to scene, to use as default for things that don't
+ * have any shader assigned explicitly */
+ static void add_default(Scene *scene);
- /* Selective nodes compilation. */
- void get_requested_features(Scene *scene,
- DeviceRequestedFeatures *requested_features);
+ /* Selective nodes compilation. */
+ void get_requested_features(Scene *scene, DeviceRequestedFeatures *requested_features);
- static void free_memory();
+ static void free_memory();
- float linear_rgb_to_gray(float3 c);
+ float linear_rgb_to_gray(float3 c);
- string get_cryptomatte_materials(Scene *scene);
+ string get_cryptomatte_materials(Scene *scene);
-protected:
- ShaderManager();
+ protected:
+ ShaderManager();
- typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
- AttributeIDMap unique_attribute_id;
+ typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap;
+ AttributeIDMap unique_attribute_id;
- static thread_mutex lookup_table_mutex;
- static vector<float> beckmann_table;
- static bool beckmann_table_ready;
+ static thread_mutex lookup_table_mutex;
+ static vector<float> beckmann_table;
+ static bool beckmann_table_ready;
- size_t beckmann_table_offset;
+ size_t beckmann_table_offset;
- void get_requested_graph_features(ShaderGraph *graph,
- DeviceRequestedFeatures *requested_features);
+ void get_requested_graph_features(ShaderGraph *graph,
+ DeviceRequestedFeatures *requested_features);
- thread_spin_lock attribute_lock_;
+ thread_spin_lock attribute_lock_;
- float3 xyz_to_r;
- float3 xyz_to_g;
- float3 xyz_to_b;
- float3 rgb_to_y;
+ float3 xyz_to_r;
+ float3 xyz_to_g;
+ float3 xyz_to_b;
+ float3 rgb_to_y;
};
CCL_NAMESPACE_END
-#endif /* __SHADER_H__ */
+#endif /* __SHADER_H__ */
diff --git a/intern/cycles/render/sobol.h b/intern/cycles/render/sobol.h
index ce7a28587f2..d38857d2b35 100644
--- a/intern/cycles/render/sobol.h
+++ b/intern/cycles/render/sobol.h
@@ -28,4 +28,4 @@ void sobol_generate_direction_vectors(uint vectors[][SOBOL_BITS], int dimensions
CCL_NAMESPACE_END
-#endif /* __SOBOL_H__ */
+#endif /* __SOBOL_H__ */
diff --git a/intern/cycles/render/stats.cpp b/intern/cycles/render/stats.cpp
index 4245745944d..0937b95a891 100644
--- a/intern/cycles/render/stats.cpp
+++ b/intern/cycles/render/stats.cpp
@@ -28,284 +28,293 @@ static int kIndentNumSpaces = 2;
namespace {
-bool namedSizeEntryComparator(const NamedSizeEntry& a, const NamedSizeEntry& b)
+bool namedSizeEntryComparator(const NamedSizeEntry &a, const NamedSizeEntry &b)
{
- /* We sort in descending order. */
- return a.size > b.size;
+ /* We sort in descending order. */
+ return a.size > b.size;
}
-bool namedTimeSampleEntryComparator(const NamedNestedSampleStats& a, const NamedNestedSampleStats& b)
+bool namedTimeSampleEntryComparator(const NamedNestedSampleStats &a,
+ const NamedNestedSampleStats &b)
{
- return a.sum_samples > b.sum_samples;
+ return a.sum_samples > b.sum_samples;
}
-bool namedSampleCountPairComparator(const NamedSampleCountPair& a, const NamedSampleCountPair& b)
+bool namedSampleCountPairComparator(const NamedSampleCountPair &a, const NamedSampleCountPair &b)
{
- return a.samples > b.samples;
+ return a.samples > b.samples;
}
} // namespace
-NamedSizeEntry::NamedSizeEntry()
- : name(""),
- size(0) {
+NamedSizeEntry::NamedSizeEntry() : name(""), size(0)
+{
}
-NamedSizeEntry::NamedSizeEntry(const string& name, size_t size)
- : name(name),
- size(size) {
+NamedSizeEntry::NamedSizeEntry(const string &name, size_t size) : name(name), size(size)
+{
}
/* Named size statistics. */
-NamedSizeStats::NamedSizeStats()
- : total_size(0) {
+NamedSizeStats::NamedSizeStats() : total_size(0)
+{
}
-void NamedSizeStats::add_entry(const NamedSizeEntry& entry) {
- total_size += entry.size;
- entries.push_back(entry);
+void NamedSizeStats::add_entry(const NamedSizeEntry &entry)
+{
+ total_size += entry.size;
+ entries.push_back(entry);
}
string NamedSizeStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
- const string double_indent = indent + indent;
- string result = "";
- result += string_printf("%sTotal memory: %s (%s)\n",
- indent.c_str(),
- string_human_readable_size(total_size).c_str(),
- string_human_readable_number(total_size).c_str());
- sort(entries.begin(), entries.end(), namedSizeEntryComparator);
- foreach(const NamedSizeEntry& entry, entries) {
- result += string_printf(
- "%s%-32s %s (%s)\n",
- double_indent.c_str(),
- entry.name.c_str(),
- string_human_readable_size(entry.size).c_str(),
- string_human_readable_number(entry.size).c_str());
- }
- return result;
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ const string double_indent = indent + indent;
+ string result = "";
+ result += string_printf("%sTotal memory: %s (%s)\n",
+ indent.c_str(),
+ string_human_readable_size(total_size).c_str(),
+ string_human_readable_number(total_size).c_str());
+ sort(entries.begin(), entries.end(), namedSizeEntryComparator);
+ foreach (const NamedSizeEntry &entry, entries) {
+ result += string_printf("%s%-32s %s (%s)\n",
+ double_indent.c_str(),
+ entry.name.c_str(),
+ string_human_readable_size(entry.size).c_str(),
+ string_human_readable_number(entry.size).c_str());
+ }
+ return result;
}
/* Named time sample statistics. */
-NamedNestedSampleStats::NamedNestedSampleStats()
- : name(""), self_samples(0), sum_samples(0)
-{}
+NamedNestedSampleStats::NamedNestedSampleStats() : name(""), self_samples(0), sum_samples(0)
+{
+}
-NamedNestedSampleStats::NamedNestedSampleStats(const string& name, uint64_t samples)
- : name(name), self_samples(samples), sum_samples(samples)
-{}
+NamedNestedSampleStats::NamedNestedSampleStats(const string &name, uint64_t samples)
+ : name(name), self_samples(samples), sum_samples(samples)
+{
+}
-NamedNestedSampleStats& NamedNestedSampleStats::add_entry(const string& name_, uint64_t samples_)
+NamedNestedSampleStats &NamedNestedSampleStats::add_entry(const string &name_, uint64_t samples_)
{
- entries.push_back(NamedNestedSampleStats(name_, samples_));
- return entries[entries.size()-1];
+ entries.push_back(NamedNestedSampleStats(name_, samples_));
+ return entries[entries.size() - 1];
}
void NamedNestedSampleStats::update_sum()
{
- sum_samples = self_samples;
- foreach(NamedNestedSampleStats& entry, entries) {
- entry.update_sum();
- sum_samples += entry.sum_samples;
- }
+ sum_samples = self_samples;
+ foreach (NamedNestedSampleStats &entry, entries) {
+ entry.update_sum();
+ sum_samples += entry.sum_samples;
+ }
}
string NamedNestedSampleStats::full_report(int indent_level, uint64_t total_samples)
{
- update_sum();
-
- if(total_samples == 0) {
- total_samples = sum_samples;
- }
-
- const string indent(indent_level * kIndentNumSpaces, ' ');
-
- const double sum_percent = 100*((double) sum_samples) / total_samples;
- const double sum_seconds = sum_samples * 0.001;
- const double self_percent = 100*((double) self_samples) / total_samples;
- const double self_seconds = self_samples * 0.001;
- string info = string_printf("%-32s: Total %3.2f%% (%.2fs), Self %3.2f%% (%.2fs)\n",
- name.c_str(),
- sum_percent,
- sum_seconds,
- self_percent,
- self_seconds);
- string result = indent + info;
-
- sort(entries.begin(), entries.end(), namedTimeSampleEntryComparator);
- foreach(NamedNestedSampleStats& entry, entries) {
- result += entry.full_report(indent_level + 1, total_samples);
- }
- return result;
+ update_sum();
+
+ if (total_samples == 0) {
+ total_samples = sum_samples;
+ }
+
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+
+ const double sum_percent = 100 * ((double)sum_samples) / total_samples;
+ const double sum_seconds = sum_samples * 0.001;
+ const double self_percent = 100 * ((double)self_samples) / total_samples;
+ const double self_seconds = self_samples * 0.001;
+ string info = string_printf("%-32s: Total %3.2f%% (%.2fs), Self %3.2f%% (%.2fs)\n",
+ name.c_str(),
+ sum_percent,
+ sum_seconds,
+ self_percent,
+ self_seconds);
+ string result = indent + info;
+
+ sort(entries.begin(), entries.end(), namedTimeSampleEntryComparator);
+ foreach (NamedNestedSampleStats &entry, entries) {
+ result += entry.full_report(indent_level + 1, total_samples);
+ }
+ return result;
}
/* Named sample count pairs. */
-NamedSampleCountPair::NamedSampleCountPair(const ustring& name, uint64_t samples, uint64_t hits)
- : name(name), samples(samples), hits(hits)
-{}
+NamedSampleCountPair::NamedSampleCountPair(const ustring &name, uint64_t samples, uint64_t hits)
+ : name(name), samples(samples), hits(hits)
+{
+}
NamedSampleCountStats::NamedSampleCountStats()
-{}
+{
+}
-void NamedSampleCountStats::add(const ustring& name, uint64_t samples, uint64_t hits)
+void NamedSampleCountStats::add(const ustring &name, uint64_t samples, uint64_t hits)
{
- entry_map::iterator entry = entries.find(name);
- if(entry != entries.end()) {
- entry->second.samples += samples;
- entry->second.hits += hits;
- return;
- }
- entries.emplace(name, NamedSampleCountPair(name, samples, hits));
+ entry_map::iterator entry = entries.find(name);
+ if (entry != entries.end()) {
+ entry->second.samples += samples;
+ entry->second.hits += hits;
+ return;
+ }
+ entries.emplace(name, NamedSampleCountPair(name, samples, hits));
}
string NamedSampleCountStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
+ const string indent(indent_level * kIndentNumSpaces, ' ');
- vector<NamedSampleCountPair> sorted_entries;
- sorted_entries.reserve(entries.size());
+ vector<NamedSampleCountPair> sorted_entries;
+ sorted_entries.reserve(entries.size());
- uint64_t total_hits = 0, total_samples = 0;
- foreach(entry_map::const_reference entry, entries) {
- const NamedSampleCountPair &pair = entry.second;
+ uint64_t total_hits = 0, total_samples = 0;
+ foreach (entry_map::const_reference entry, entries) {
+ const NamedSampleCountPair &pair = entry.second;
- total_hits += pair.hits;
- total_samples += pair.samples;
+ total_hits += pair.hits;
+ total_samples += pair.samples;
- sorted_entries.push_back(pair);
- }
- const double avg_samples_per_hit = ((double) total_samples) / total_hits;
+ sorted_entries.push_back(pair);
+ }
+ const double avg_samples_per_hit = ((double)total_samples) / total_hits;
- sort(sorted_entries.begin(), sorted_entries.end(), namedSampleCountPairComparator);
+ sort(sorted_entries.begin(), sorted_entries.end(), namedSampleCountPairComparator);
- string result = "";
- foreach(const NamedSampleCountPair& entry, sorted_entries) {
- const double seconds = entry.samples * 0.001;
- const double relative = ((double) entry.samples) / (entry.hits * avg_samples_per_hit);
+ string result = "";
+ foreach (const NamedSampleCountPair &entry, sorted_entries) {
+ const double seconds = entry.samples * 0.001;
+ const double relative = ((double)entry.samples) / (entry.hits * avg_samples_per_hit);
- result += indent + string_printf("%-32s: %.2fs (Relative cost: %.2f)\n",
- entry.name.c_str(),
- seconds,
- relative);
- }
- return result;
+ result += indent +
+ string_printf(
+ "%-32s: %.2fs (Relative cost: %.2f)\n", entry.name.c_str(), seconds, relative);
+ }
+ return result;
}
/* Mesh statistics. */
-MeshStats::MeshStats() {
+MeshStats::MeshStats()
+{
}
string MeshStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
- string result = "";
- result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1);
- return result;
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ string result = "";
+ result += indent + "Geometry:\n" + geometry.full_report(indent_level + 1);
+ return result;
}
/* Image statistics. */
-ImageStats::ImageStats() {
+ImageStats::ImageStats()
+{
}
string ImageStats::full_report(int indent_level)
{
- const string indent(indent_level * kIndentNumSpaces, ' ');
- string result = "";
- result += indent + "Textures:\n" + textures.full_report(indent_level + 1);
- return result;
+ const string indent(indent_level * kIndentNumSpaces, ' ');
+ string result = "";
+ result += indent + "Textures:\n" + textures.full_report(indent_level + 1);
+ return result;
}
/* Overall statistics. */
-RenderStats::RenderStats() {
- has_profiling = false;
+RenderStats::RenderStats()
+{
+ has_profiling = false;
}
-void RenderStats::collect_profiling(Scene *scene, Profiler& prof)
+void RenderStats::collect_profiling(Scene *scene, Profiler &prof)
{
- has_profiling = true;
-
- kernel = NamedNestedSampleStats("Total render time", prof.get_event(PROFILING_UNKNOWN));
-
- kernel.add_entry("Ray setup", prof.get_event(PROFILING_RAY_SETUP));
- kernel.add_entry("Result writing", prof.get_event(PROFILING_WRITE_RESULT));
-
- NamedNestedSampleStats &integrator = kernel.add_entry("Path integration", prof.get_event(PROFILING_PATH_INTEGRATE));
- integrator.add_entry("Scene intersection", prof.get_event(PROFILING_SCENE_INTERSECT));
- integrator.add_entry("Indirect emission", prof.get_event(PROFILING_INDIRECT_EMISSION));
- integrator.add_entry("Volumes", prof.get_event(PROFILING_VOLUME));
-
- NamedNestedSampleStats &shading = integrator.add_entry("Shading", 0);
- shading.add_entry("Shader Setup", prof.get_event(PROFILING_SHADER_SETUP));
- shading.add_entry("Shader Eval", prof.get_event(PROFILING_SHADER_EVAL));
- shading.add_entry("Shader Apply", prof.get_event(PROFILING_SHADER_APPLY));
- shading.add_entry("Ambient Occlusion", prof.get_event(PROFILING_AO));
- shading.add_entry("Subsurface", prof.get_event(PROFILING_SUBSURFACE));
-
- integrator.add_entry("Connect Light", prof.get_event(PROFILING_CONNECT_LIGHT));
- integrator.add_entry("Surface Bounce", prof.get_event(PROFILING_SURFACE_BOUNCE));
-
- NamedNestedSampleStats &intersection = kernel.add_entry("Intersection", 0);
- intersection.add_entry("Full Intersection", prof.get_event(PROFILING_INTERSECT));
- intersection.add_entry("Local Intersection", prof.get_event(PROFILING_INTERSECT_LOCAL));
- intersection.add_entry("Shadow All Intersection", prof.get_event(PROFILING_INTERSECT_SHADOW_ALL));
- intersection.add_entry("Volume Intersection", prof.get_event(PROFILING_INTERSECT_VOLUME));
- intersection.add_entry("Volume All Intersection", prof.get_event(PROFILING_INTERSECT_VOLUME_ALL));
-
- NamedNestedSampleStats &closure = kernel.add_entry("Closures", 0);
- closure.add_entry("Surface Closure Evaluation", prof.get_event(PROFILING_CLOSURE_EVAL));
- closure.add_entry("Surface Closure Sampling", prof.get_event(PROFILING_CLOSURE_SAMPLE));
- closure.add_entry("Volume Closure Evaluation", prof.get_event(PROFILING_CLOSURE_VOLUME_EVAL));
- closure.add_entry("Volume Closure Sampling", prof.get_event(PROFILING_CLOSURE_VOLUME_SAMPLE));
-
- NamedNestedSampleStats &denoising = kernel.add_entry("Denoising", prof.get_event(PROFILING_DENOISING));
- denoising.add_entry("Construct Transform", prof.get_event(PROFILING_DENOISING_CONSTRUCT_TRANSFORM));
- denoising.add_entry("Reconstruct", prof.get_event(PROFILING_DENOISING_RECONSTRUCT));
-
- NamedNestedSampleStats &prefilter = denoising.add_entry("Prefiltering", 0);
- prefilter.add_entry("Divide Shadow", prof.get_event(PROFILING_DENOISING_DIVIDE_SHADOW));
- prefilter.add_entry("Non-Local means", prof.get_event(PROFILING_DENOISING_NON_LOCAL_MEANS));
- prefilter.add_entry("Get Feature", prof.get_event(PROFILING_DENOISING_GET_FEATURE));
- prefilter.add_entry("Detect Outliers", prof.get_event(PROFILING_DENOISING_DETECT_OUTLIERS));
- prefilter.add_entry("Combine Halves", prof.get_event(PROFILING_DENOISING_COMBINE_HALVES));
-
- shaders.entries.clear();
- foreach(Shader *shader, scene->shaders) {
- uint64_t samples, hits;
- if(prof.get_shader(shader->id, samples, hits)) {
- shaders.add(shader->name, samples, hits);
- }
- }
-
- objects.entries.clear();
- foreach(Object *object, scene->objects) {
- uint64_t samples, hits;
- if(prof.get_object(object->get_device_index(), samples, hits)) {
- objects.add(object->name, samples, hits);
- }
- }
+ has_profiling = true;
+
+ kernel = NamedNestedSampleStats("Total render time", prof.get_event(PROFILING_UNKNOWN));
+
+ kernel.add_entry("Ray setup", prof.get_event(PROFILING_RAY_SETUP));
+ kernel.add_entry("Result writing", prof.get_event(PROFILING_WRITE_RESULT));
+
+ NamedNestedSampleStats &integrator = kernel.add_entry("Path integration",
+ prof.get_event(PROFILING_PATH_INTEGRATE));
+ integrator.add_entry("Scene intersection", prof.get_event(PROFILING_SCENE_INTERSECT));
+ integrator.add_entry("Indirect emission", prof.get_event(PROFILING_INDIRECT_EMISSION));
+ integrator.add_entry("Volumes", prof.get_event(PROFILING_VOLUME));
+
+ NamedNestedSampleStats &shading = integrator.add_entry("Shading", 0);
+ shading.add_entry("Shader Setup", prof.get_event(PROFILING_SHADER_SETUP));
+ shading.add_entry("Shader Eval", prof.get_event(PROFILING_SHADER_EVAL));
+ shading.add_entry("Shader Apply", prof.get_event(PROFILING_SHADER_APPLY));
+ shading.add_entry("Ambient Occlusion", prof.get_event(PROFILING_AO));
+ shading.add_entry("Subsurface", prof.get_event(PROFILING_SUBSURFACE));
+
+ integrator.add_entry("Connect Light", prof.get_event(PROFILING_CONNECT_LIGHT));
+ integrator.add_entry("Surface Bounce", prof.get_event(PROFILING_SURFACE_BOUNCE));
+
+ NamedNestedSampleStats &intersection = kernel.add_entry("Intersection", 0);
+ intersection.add_entry("Full Intersection", prof.get_event(PROFILING_INTERSECT));
+ intersection.add_entry("Local Intersection", prof.get_event(PROFILING_INTERSECT_LOCAL));
+ intersection.add_entry("Shadow All Intersection",
+ prof.get_event(PROFILING_INTERSECT_SHADOW_ALL));
+ intersection.add_entry("Volume Intersection", prof.get_event(PROFILING_INTERSECT_VOLUME));
+ intersection.add_entry("Volume All Intersection",
+ prof.get_event(PROFILING_INTERSECT_VOLUME_ALL));
+
+ NamedNestedSampleStats &closure = kernel.add_entry("Closures", 0);
+ closure.add_entry("Surface Closure Evaluation", prof.get_event(PROFILING_CLOSURE_EVAL));
+ closure.add_entry("Surface Closure Sampling", prof.get_event(PROFILING_CLOSURE_SAMPLE));
+ closure.add_entry("Volume Closure Evaluation", prof.get_event(PROFILING_CLOSURE_VOLUME_EVAL));
+ closure.add_entry("Volume Closure Sampling", prof.get_event(PROFILING_CLOSURE_VOLUME_SAMPLE));
+
+ NamedNestedSampleStats &denoising = kernel.add_entry("Denoising",
+ prof.get_event(PROFILING_DENOISING));
+ denoising.add_entry("Construct Transform",
+ prof.get_event(PROFILING_DENOISING_CONSTRUCT_TRANSFORM));
+ denoising.add_entry("Reconstruct", prof.get_event(PROFILING_DENOISING_RECONSTRUCT));
+
+ NamedNestedSampleStats &prefilter = denoising.add_entry("Prefiltering", 0);
+ prefilter.add_entry("Divide Shadow", prof.get_event(PROFILING_DENOISING_DIVIDE_SHADOW));
+ prefilter.add_entry("Non-Local means", prof.get_event(PROFILING_DENOISING_NON_LOCAL_MEANS));
+ prefilter.add_entry("Get Feature", prof.get_event(PROFILING_DENOISING_GET_FEATURE));
+ prefilter.add_entry("Detect Outliers", prof.get_event(PROFILING_DENOISING_DETECT_OUTLIERS));
+ prefilter.add_entry("Combine Halves", prof.get_event(PROFILING_DENOISING_COMBINE_HALVES));
+
+ shaders.entries.clear();
+ foreach (Shader *shader, scene->shaders) {
+ uint64_t samples, hits;
+ if (prof.get_shader(shader->id, samples, hits)) {
+ shaders.add(shader->name, samples, hits);
+ }
+ }
+
+ objects.entries.clear();
+ foreach (Object *object, scene->objects) {
+ uint64_t samples, hits;
+ if (prof.get_object(object->get_device_index(), samples, hits)) {
+ objects.add(object->name, samples, hits);
+ }
+ }
}
string RenderStats::full_report()
{
- string result = "";
- result += "Mesh statistics:\n" + mesh.full_report(1);
- result += "Image statistics:\n" + image.full_report(1);
- if(has_profiling) {
- result += "Kernel statistics:\n" + kernel.full_report(1);
- result += "Shader statistics:\n" + shaders.full_report(1);
- result += "Object statistics:\n" + objects.full_report(1);
- }
- else {
- result += "Profiling information not available (only works with CPU rendering)";
- }
- return result;
+ string result = "";
+ result += "Mesh statistics:\n" + mesh.full_report(1);
+ result += "Image statistics:\n" + image.full_report(1);
+ if (has_profiling) {
+ result += "Kernel statistics:\n" + kernel.full_report(1);
+ result += "Shader statistics:\n" + shaders.full_report(1);
+ result += "Object statistics:\n" + objects.full_report(1);
+ }
+ else {
+ result += "Profiling information not available (only works with CPU rendering)";
+ }
+ return result;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/stats.h b/intern/cycles/render/stats.h
index 33fe1f4b185..f1bf1903483 100644
--- a/intern/cycles/render/stats.h
+++ b/intern/cycles/render/stats.h
@@ -33,12 +33,12 @@ CCL_NAMESPACE_BEGIN
* avoiding duplicating code for things like sorting.
*/
class NamedSizeEntry {
-public:
- NamedSizeEntry();
- NamedSizeEntry(const string& name, size_t size);
+ public:
+ NamedSizeEntry();
+ NamedSizeEntry(const string &name, size_t size);
- string name;
- size_t size;
+ string name;
+ size_t size;
};
/* Container of named size entries. Used, for example, to store per-mesh memory
@@ -46,115 +46,115 @@ public:
* container.
*/
class NamedSizeStats {
-public:
- NamedSizeStats();
+ public:
+ NamedSizeStats();
- /* Add entry to the statistics. */
- void add_entry(const NamedSizeEntry& entry);
+ /* Add entry to the statistics. */
+ void add_entry(const NamedSizeEntry &entry);
- /* Generate full human-readable report. */
- string full_report(int indent_level = 0);
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
- /* Total size of all entries. */
- size_t total_size;
+ /* Total size of all entries. */
+ size_t total_size;
- /* NOTE: Is fine to read directly, but for adding use add_entry(), which
- * makes sure all accumulating values are properly updated.
- */
- vector<NamedSizeEntry> entries;
+ /* NOTE: Is fine to read directly, but for adding use add_entry(), which
+ * makes sure all accumulating values are properly updated.
+ */
+ vector<NamedSizeEntry> entries;
};
class NamedNestedSampleStats {
-public:
- NamedNestedSampleStats();
- NamedNestedSampleStats(const string& name, uint64_t samples);
+ public:
+ NamedNestedSampleStats();
+ NamedNestedSampleStats(const string &name, uint64_t samples);
- NamedNestedSampleStats& add_entry(const string& name, uint64_t samples);
+ NamedNestedSampleStats &add_entry(const string &name, uint64_t samples);
- /* Updates sum_samples recursively. */
- void update_sum();
+ /* Updates sum_samples recursively. */
+ void update_sum();
- string full_report(int indent_level = 0, uint64_t total_samples = 0);
+ string full_report(int indent_level = 0, uint64_t total_samples = 0);
- string name;
+ string name;
- /* self_samples contains only the samples that this specific event got,
- * while sum_samples also includes the samples of all sub-entries. */
- uint64_t self_samples, sum_samples;
+ /* self_samples contains only the samples that this specific event got,
+ * while sum_samples also includes the samples of all sub-entries. */
+ uint64_t self_samples, sum_samples;
- vector<NamedNestedSampleStats> entries;
+ vector<NamedNestedSampleStats> entries;
};
/* Named entry containing both a time-sample count for objects of a type and a
* total count of processed items.
* This allows to estimate the time spent per item. */
class NamedSampleCountPair {
-public:
- NamedSampleCountPair(const ustring& name, uint64_t samples, uint64_t hits);
+ public:
+ NamedSampleCountPair(const ustring &name, uint64_t samples, uint64_t hits);
- ustring name;
- uint64_t samples;
- uint64_t hits;
+ ustring name;
+ uint64_t samples;
+ uint64_t hits;
};
/* Contains statistics about pairs of samples and counts as described above. */
class NamedSampleCountStats {
-public:
- NamedSampleCountStats();
+ public:
+ NamedSampleCountStats();
- string full_report(int indent_level = 0);
- void add(const ustring& name, uint64_t samples, uint64_t hits);
+ string full_report(int indent_level = 0);
+ void add(const ustring &name, uint64_t samples, uint64_t hits);
- typedef unordered_map<ustring, NamedSampleCountPair, ustringHash> entry_map;
- entry_map entries;
+ typedef unordered_map<ustring, NamedSampleCountPair, ustringHash> entry_map;
+ entry_map entries;
};
/* Statistics about mesh in the render database. */
class MeshStats {
-public:
- MeshStats();
+ public:
+ MeshStats();
- /* Generate full human-readable report. */
- string full_report(int indent_level = 0);
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
- /* Input geometry statistics, this is what is coming as an input to render
- * from. say, Blender. This does not include runtime or engine specific
- * memory like BVH.
- */
- NamedSizeStats geometry;
+ /* Input geometry statistics, this is what is coming as an input to render
+ * from. say, Blender. This does not include runtime or engine specific
+ * memory like BVH.
+ */
+ NamedSizeStats geometry;
};
/* Statistics about images held in memory. */
class ImageStats {
-public:
- ImageStats();
+ public:
+ ImageStats();
- /* Generate full human-readable report. */
- string full_report(int indent_level = 0);
+ /* Generate full human-readable report. */
+ string full_report(int indent_level = 0);
- NamedSizeStats textures;
+ NamedSizeStats textures;
};
/* Render process statistics. */
class RenderStats {
-public:
- RenderStats();
+ public:
+ RenderStats();
- /* Return full report as string. */
- string full_report();
+ /* Return full report as string. */
+ string full_report();
- /* Collect kernel sampling information from Stats. */
- void collect_profiling(Scene *scene, Profiler& prof);
+ /* Collect kernel sampling information from Stats. */
+ void collect_profiling(Scene *scene, Profiler &prof);
- bool has_profiling;
+ bool has_profiling;
- MeshStats mesh;
- ImageStats image;
- NamedNestedSampleStats kernel;
- NamedSampleCountStats shaders;
- NamedSampleCountStats objects;
+ MeshStats mesh;
+ ImageStats image;
+ NamedNestedSampleStats kernel;
+ NamedSampleCountStats shaders;
+ NamedSampleCountStats objects;
};
CCL_NAMESPACE_END
-#endif /* __RENDER_STATS_H__ */
+#endif /* __RENDER_STATS_H__ */
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 360b2b461cf..d8e3e24f39e 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -49,107 +49,106 @@ void SVMShaderManager::device_update_shader(Scene *scene,
Progress *progress,
array<int4> *global_svm_nodes)
{
- if(progress->get_cancel()) {
- return;
- }
- assert(shader->graph);
+ if (progress->get_cancel()) {
+ return;
+ }
+ assert(shader->graph);
- array<int4> svm_nodes;
- svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
+ array<int4> svm_nodes;
+ svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
- SVMCompiler::Summary summary;
- SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager);
- compiler.background = (shader == scene->default_background);
- compiler.compile(scene, shader, svm_nodes, 0, &summary);
+ SVMCompiler::Summary summary;
+ SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager);
+ compiler.background = (shader == scene->default_background);
+ compiler.compile(scene, shader, svm_nodes, 0, &summary);
- VLOG(2) << "Compilation summary:\n"
- << "Shader name: " << shader->name << "\n"
- << summary.full_report();
+ VLOG(2) << "Compilation summary:\n"
+ << "Shader name: " << shader->name << "\n"
+ << summary.full_report();
- nodes_lock_.lock();
- if(shader->use_mis && shader->has_surface_emission) {
- scene->light_manager->need_update = true;
- }
+ nodes_lock_.lock();
+ if (shader->use_mis && shader->has_surface_emission) {
+ scene->light_manager->need_update = true;
+ }
- /* The copy needs to be done inside the lock, if another thread resizes the array
- * while memcpy is running, it'll be copying into possibly invalid/freed ram.
- */
- size_t global_nodes_size = global_svm_nodes->size();
- global_svm_nodes->resize(global_nodes_size + svm_nodes.size());
+ /* The copy needs to be done inside the lock, if another thread resizes the array
+ * while memcpy is running, it'll be copying into possibly invalid/freed ram.
+ */
+ size_t global_nodes_size = global_svm_nodes->size();
+ global_svm_nodes->resize(global_nodes_size + svm_nodes.size());
- /* Offset local SVM nodes to a global address space. */
- int4& jump_node = (*global_svm_nodes)[shader->id];
- jump_node.y = svm_nodes[0].y + global_nodes_size - 1;
- jump_node.z = svm_nodes[0].z + global_nodes_size - 1;
- jump_node.w = svm_nodes[0].w + global_nodes_size - 1;
- /* Copy new nodes to global storage. */
- memcpy(&(*global_svm_nodes)[global_nodes_size],
- &svm_nodes[1],
- sizeof(int4) * (svm_nodes.size() - 1));
- nodes_lock_.unlock();
+ /* Offset local SVM nodes to a global address space. */
+ int4 &jump_node = (*global_svm_nodes)[shader->id];
+ jump_node.y = svm_nodes[0].y + global_nodes_size - 1;
+ jump_node.z = svm_nodes[0].z + global_nodes_size - 1;
+ jump_node.w = svm_nodes[0].w + global_nodes_size - 1;
+ /* Copy new nodes to global storage. */
+ memcpy(&(*global_svm_nodes)[global_nodes_size],
+ &svm_nodes[1],
+ sizeof(int4) * (svm_nodes.size() - 1));
+ nodes_lock_.unlock();
}
-void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void SVMShaderManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress &progress)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
+ VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
- double start_time = time_dt();
+ double start_time = time_dt();
- /* test if we need to update */
- device_free(device, dscene, scene);
+ /* test if we need to update */
+ device_free(device, dscene, scene);
- /* determine which shaders are in use */
- device_update_shaders_used(scene);
+ /* determine which shaders are in use */
+ device_update_shaders_used(scene);
- /* svm_nodes */
- array<int4> svm_nodes;
- size_t i;
+ /* svm_nodes */
+ array<int4> svm_nodes;
+ size_t i;
- for(i = 0; i < scene->shaders.size(); i++) {
- svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
- }
+ for (i = 0; i < scene->shaders.size(); i++) {
+ svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
+ }
- TaskPool task_pool;
- foreach(Shader *shader, scene->shaders) {
- task_pool.push(function_bind(&SVMShaderManager::device_update_shader,
- this,
- scene,
- shader,
- &progress,
- &svm_nodes),
- false);
- }
- task_pool.wait_work();
+ TaskPool task_pool;
+ foreach (Shader *shader, scene->shaders) {
+ task_pool.push(
+ function_bind(
+ &SVMShaderManager::device_update_shader, this, scene, shader, &progress, &svm_nodes),
+ false);
+ }
+ task_pool.wait_work();
- if(progress.get_cancel()) {
- return;
- }
+ if (progress.get_cancel()) {
+ return;
+ }
- dscene->svm_nodes.steal_data(svm_nodes);
- dscene->svm_nodes.copy_to_device();
+ dscene->svm_nodes.steal_data(svm_nodes);
+ dscene->svm_nodes.copy_to_device();
- for(i = 0; i < scene->shaders.size(); i++) {
- Shader *shader = scene->shaders[i];
- shader->need_update = false;
- }
+ for (i = 0; i < scene->shaders.size(); i++) {
+ Shader *shader = scene->shaders[i];
+ shader->need_update = false;
+ }
- device_update_common(device, dscene, scene, progress);
+ device_update_common(device, dscene, scene, progress);
- need_update = false;
+ need_update = false;
- VLOG(1) << "Shader manager updated "
- << scene->shaders.size() << " shaders in "
- << time_dt() - start_time << " seconds.";
+ VLOG(1) << "Shader manager updated " << scene->shaders.size() << " shaders in "
+ << time_dt() - start_time << " seconds.";
}
void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
{
- device_free_common(device, dscene, scene);
+ device_free_common(device, dscene, scene);
- dscene->svm_nodes.free();
+ dscene->svm_nodes.free();
}
/* Graph Compiler */
@@ -158,772 +157,751 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_,
ImageManager *image_manager_,
LightManager *light_manager_)
{
- shader_manager = shader_manager_;
- image_manager = image_manager_;
- light_manager = light_manager_;
- max_stack_use = 0;
- current_type = SHADER_TYPE_SURFACE;
- current_shader = NULL;
- current_graph = NULL;
- background = false;
- mix_weight_offset = SVM_STACK_INVALID;
- compile_failed = false;
+ shader_manager = shader_manager_;
+ image_manager = image_manager_;
+ light_manager = light_manager_;
+ max_stack_use = 0;
+ current_type = SHADER_TYPE_SURFACE;
+ current_shader = NULL;
+ current_graph = NULL;
+ background = false;
+ mix_weight_offset = SVM_STACK_INVALID;
+ compile_failed = false;
}
int SVMCompiler::stack_size(SocketType::Type type)
{
- int size = 0;
-
- switch(type) {
- case SocketType::FLOAT:
- case SocketType::INT:
- size = 1;
- break;
- case SocketType::COLOR:
- case SocketType::VECTOR:
- case SocketType::NORMAL:
- case SocketType::POINT:
- size = 3;
- break;
- case SocketType::CLOSURE:
- size = 0;
- break;
- default:
- assert(0);
- break;
- }
-
- return size;
+ int size = 0;
+
+ switch (type) {
+ case SocketType::FLOAT:
+ case SocketType::INT:
+ size = 1;
+ break;
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::NORMAL:
+ case SocketType::POINT:
+ size = 3;
+ break;
+ case SocketType::CLOSURE:
+ size = 0;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return size;
}
int SVMCompiler::stack_find_offset(int size)
{
- int offset = -1;
+ int offset = -1;
- /* find free space in stack & mark as used */
- for(int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
- if(active_stack.users[i]) num_unused = 0;
- else num_unused++;
+ /* find free space in stack & mark as used */
+ for (int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
+ if (active_stack.users[i])
+ num_unused = 0;
+ else
+ num_unused++;
- if(num_unused == size) {
- offset = i+1 - size;
- max_stack_use = max(i+1, max_stack_use);
+ if (num_unused == size) {
+ offset = i + 1 - size;
+ max_stack_use = max(i + 1, max_stack_use);
- while(i >= offset)
- active_stack.users[i--] = 1;
+ while (i >= offset)
+ active_stack.users[i--] = 1;
- return offset;
- }
- }
+ return offset;
+ }
+ }
- if(!compile_failed) {
- compile_failed = true;
- fprintf(stderr, "Cycles: out of SVM stack space, shader \"%s\" too big.\n", current_shader->name.c_str());
- }
+ if (!compile_failed) {
+ compile_failed = true;
+ fprintf(stderr,
+ "Cycles: out of SVM stack space, shader \"%s\" too big.\n",
+ current_shader->name.c_str());
+ }
- return 0;
+ return 0;
}
int SVMCompiler::stack_find_offset(SocketType::Type type)
{
- return stack_find_offset(stack_size(type));
+ return stack_find_offset(stack_size(type));
}
void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
{
- int size = stack_size(type);
+ int size = stack_size(type);
- for(int i = 0; i < size; i++)
- active_stack.users[offset + i]--;
+ for (int i = 0; i < size; i++)
+ active_stack.users[offset + i]--;
}
int SVMCompiler::stack_assign(ShaderInput *input)
{
- /* stack offset assign? */
- if(input->stack_offset == SVM_STACK_INVALID) {
- if(input->link) {
- /* linked to output -> use output offset */
- assert(input->link->stack_offset != SVM_STACK_INVALID);
- input->stack_offset = input->link->stack_offset;
- }
- else {
- Node *node = input->parent;
-
- /* not linked to output -> add nodes to load default value */
- input->stack_offset = stack_find_offset(input->type());
-
- if(input->type() == SocketType::FLOAT) {
- add_node(NODE_VALUE_F, __float_as_int(node->get_float(input->socket_type)), input->stack_offset);
- }
- else if(input->type() == SocketType::INT) {
- add_node(NODE_VALUE_F, node->get_int(input->socket_type), input->stack_offset);
- }
- else if(input->type() == SocketType::VECTOR ||
- input->type() == SocketType::NORMAL ||
- input->type() == SocketType::POINT ||
- input->type() == SocketType::COLOR)
- {
-
- add_node(NODE_VALUE_V, input->stack_offset);
- add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
- }
- else /* should not get called for closure */
- assert(0);
- }
- }
-
- return input->stack_offset;
+ /* stack offset assign? */
+ if (input->stack_offset == SVM_STACK_INVALID) {
+ if (input->link) {
+ /* linked to output -> use output offset */
+ assert(input->link->stack_offset != SVM_STACK_INVALID);
+ input->stack_offset = input->link->stack_offset;
+ }
+ else {
+ Node *node = input->parent;
+
+ /* not linked to output -> add nodes to load default value */
+ input->stack_offset = stack_find_offset(input->type());
+
+ if (input->type() == SocketType::FLOAT) {
+ add_node(NODE_VALUE_F,
+ __float_as_int(node->get_float(input->socket_type)),
+ input->stack_offset);
+ }
+ else if (input->type() == SocketType::INT) {
+ add_node(NODE_VALUE_F, node->get_int(input->socket_type), input->stack_offset);
+ }
+ else if (input->type() == SocketType::VECTOR || input->type() == SocketType::NORMAL ||
+ input->type() == SocketType::POINT || input->type() == SocketType::COLOR) {
+
+ add_node(NODE_VALUE_V, input->stack_offset);
+ add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
+ }
+ else /* should not get called for closure */
+ assert(0);
+ }
+ }
+
+ return input->stack_offset;
}
int SVMCompiler::stack_assign(ShaderOutput *output)
{
- /* if no stack offset assigned yet, find one */
- if(output->stack_offset == SVM_STACK_INVALID)
- output->stack_offset = stack_find_offset(output->type());
+ /* if no stack offset assigned yet, find one */
+ if (output->stack_offset == SVM_STACK_INVALID)
+ output->stack_offset = stack_find_offset(output->type());
- return output->stack_offset;
+ return output->stack_offset;
}
int SVMCompiler::stack_assign_if_linked(ShaderInput *input)
{
- if(input->link)
- return stack_assign(input);
+ if (input->link)
+ return stack_assign(input);
- return SVM_STACK_INVALID;
+ return SVM_STACK_INVALID;
}
int SVMCompiler::stack_assign_if_linked(ShaderOutput *output)
{
- if(!output->links.empty())
- return stack_assign(output);
+ if (!output->links.empty())
+ return stack_assign(output);
- return SVM_STACK_INVALID;
+ return SVM_STACK_INVALID;
}
void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
{
- if(output->stack_offset == SVM_STACK_INVALID) {
- assert(input->link);
- assert(stack_size(output->type()) == stack_size(input->link->type()));
+ if (output->stack_offset == SVM_STACK_INVALID) {
+ assert(input->link);
+ assert(stack_size(output->type()) == stack_size(input->link->type()));
- output->stack_offset = input->link->stack_offset;
+ output->stack_offset = input->link->stack_offset;
- int size = stack_size(output->type());
+ int size = stack_size(output->type());
- for(int i = 0; i < size; i++)
- active_stack.users[output->stack_offset + i]++;
- }
+ for (int i = 0; i < size; i++)
+ active_stack.users[output->stack_offset + i]++;
+ }
}
-void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet& done)
+void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet &done)
{
- /* optimization we should add:
- * find and lower user counts for outputs for which all inputs are done.
- * this is done before the node is compiled, under the assumption that the
- * node will first load all inputs from the stack and then writes its
- * outputs. this used to work, but was disabled because it gave trouble
- * with inputs getting stack positions assigned */
+ /* optimization we should add:
+ * find and lower user counts for outputs for which all inputs are done.
+ * this is done before the node is compiled, under the assumption that the
+ * node will first load all inputs from the stack and then writes its
+ * outputs. this used to work, but was disabled because it gave trouble
+ * with inputs getting stack positions assigned */
- foreach(ShaderInput *input, node->inputs) {
- ShaderOutput *output = input->link;
+ foreach (ShaderInput *input, node->inputs) {
+ ShaderOutput *output = input->link;
- if(output && output->stack_offset != SVM_STACK_INVALID) {
- bool all_done = true;
+ if (output && output->stack_offset != SVM_STACK_INVALID) {
+ bool all_done = true;
- /* optimization we should add: verify if in->parent is actually used */
- foreach(ShaderInput *in, output->links)
- if(in->parent != node && done.find(in->parent) == done.end())
- all_done = false;
+ /* optimization we should add: verify if in->parent is actually used */
+ foreach (ShaderInput *in, output->links)
+ if (in->parent != node && done.find(in->parent) == done.end())
+ all_done = false;
- if(all_done) {
- stack_clear_offset(output->type(), output->stack_offset);
- output->stack_offset = SVM_STACK_INVALID;
+ if (all_done) {
+ stack_clear_offset(output->type(), output->stack_offset);
+ output->stack_offset = SVM_STACK_INVALID;
- foreach(ShaderInput *in, output->links)
- in->stack_offset = SVM_STACK_INVALID;
- }
- }
- }
+ foreach (ShaderInput *in, output->links)
+ in->stack_offset = SVM_STACK_INVALID;
+ }
+ }
+ }
}
void SVMCompiler::stack_clear_temporary(ShaderNode *node)
{
- foreach(ShaderInput *input, node->inputs) {
- if(!input->link && input->stack_offset != SVM_STACK_INVALID) {
- stack_clear_offset(input->type(), input->stack_offset);
- input->stack_offset = SVM_STACK_INVALID;
- }
- }
+ foreach (ShaderInput *input, node->inputs) {
+ if (!input->link && input->stack_offset != SVM_STACK_INVALID) {
+ stack_clear_offset(input->type(), input->stack_offset);
+ input->stack_offset = SVM_STACK_INVALID;
+ }
+ }
}
uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w)
{
- assert(x <= 255);
- assert(y <= 255);
- assert(z <= 255);
- assert(w <= 255);
+ assert(x <= 255);
+ assert(y <= 255);
+ assert(z <= 255);
+ assert(w <= 255);
- return (x) | (y << 8) | (z << 16) | (w << 24);
+ return (x) | (y << 8) | (z << 16) | (w << 24);
}
void SVMCompiler::add_node(int a, int b, int c, int d)
{
- current_svm_nodes.push_back_slow(make_int4(a, b, c, d));
+ current_svm_nodes.push_back_slow(make_int4(a, b, c, d));
}
void SVMCompiler::add_node(ShaderNodeType type, int a, int b, int c)
{
- current_svm_nodes.push_back_slow(make_int4(type, a, b, c));
+ current_svm_nodes.push_back_slow(make_int4(type, a, b, c));
}
-void SVMCompiler::add_node(ShaderNodeType type, const float3& f)
+void SVMCompiler::add_node(ShaderNodeType type, const float3 &f)
{
- current_svm_nodes.push_back_slow(make_int4(type,
- __float_as_int(f.x),
- __float_as_int(f.y),
- __float_as_int(f.z)));
+ current_svm_nodes.push_back_slow(
+ make_int4(type, __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z)));
}
-void SVMCompiler::add_node(const float4& f)
+void SVMCompiler::add_node(const float4 &f)
{
- current_svm_nodes.push_back_slow(make_int4(
- __float_as_int(f.x),
- __float_as_int(f.y),
- __float_as_int(f.z),
- __float_as_int(f.w)));
+ current_svm_nodes.push_back_slow(make_int4(
+ __float_as_int(f.x), __float_as_int(f.y), __float_as_int(f.z), __float_as_int(f.w)));
}
uint SVMCompiler::attribute(ustring name)
{
- return shader_manager->get_attribute_id(name);
+ return shader_manager->get_attribute_id(name);
}
uint SVMCompiler::attribute(AttributeStandard std)
{
- return shader_manager->get_attribute_id(std);
+ return shader_manager->get_attribute_id(std);
}
uint SVMCompiler::attribute_standard(ustring name)
{
- AttributeStandard std = Attribute::name_standard(name.c_str());
- return (std)? attribute(std): attribute(name);
+ AttributeStandard std = Attribute::name_standard(name.c_str());
+ return (std) ? attribute(std) : attribute(name);
}
-void SVMCompiler::find_dependencies(ShaderNodeSet& dependencies,
- const ShaderNodeSet& done,
+void SVMCompiler::find_dependencies(ShaderNodeSet &dependencies,
+ const ShaderNodeSet &done,
ShaderInput *input,
ShaderNode *skip_node)
{
- ShaderNode *node = (input->link)? input->link->parent: NULL;
- if(node != NULL &&
- done.find(node) == done.end() &&
- node != skip_node &&
- dependencies.find(node) == dependencies.end())
- {
- foreach(ShaderInput *in, node->inputs) {
- find_dependencies(dependencies, done, in, skip_node);
- }
- dependencies.insert(node);
- }
-}
-
-void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet& done)
-{
- node->compile(*this);
- stack_clear_users(node, done);
- stack_clear_temporary(node);
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(node->has_spatial_varying())
- current_shader->has_surface_spatial_varying = true;
- }
- else if(current_type == SHADER_TYPE_VOLUME) {
- if(node->has_spatial_varying())
- current_shader->has_volume_spatial_varying = true;
- }
-
- if(node->has_object_dependency()) {
- current_shader->has_object_dependency = true;
- }
-
- if(node->has_attribute_dependency()) {
- current_shader->has_attribute_dependency = true;
- }
-
- if(node->has_integrator_dependency()) {
- current_shader->has_integrator_dependency = true;
- }
-}
-
-void SVMCompiler::generate_svm_nodes(const ShaderNodeSet& nodes,
- CompilerState *state)
-{
- ShaderNodeSet& done = state->nodes_done;
- vector<bool>& done_flag = state->nodes_done_flag;
-
- bool nodes_done;
- do {
- nodes_done = true;
-
- foreach(ShaderNode *node, nodes) {
- if(!done_flag[node->id]) {
- bool inputs_done = true;
-
- foreach(ShaderInput *input, node->inputs) {
- if(input->link && !done_flag[input->link->parent->id]) {
- inputs_done = false;
- }
- }
- if(inputs_done) {
- generate_node(node, done);
- done.insert(node);
- done_flag[node->id] = true;
- }
- else {
- nodes_done = false;
- }
- }
- }
- } while(!nodes_done);
-}
-
-void SVMCompiler::generate_closure_node(ShaderNode *node,
- CompilerState *state)
-{
- /* execute dependencies for closure */
- foreach(ShaderInput *in, node->inputs) {
- if(in->link != NULL) {
- ShaderNodeSet dependencies;
- find_dependencies(dependencies, state->nodes_done, in);
- generate_svm_nodes(dependencies, state);
- }
- }
-
- /* closure mix weight */
- const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
- ShaderInput *weight_in = node->input(weight_name);
-
- if(weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f))
- mix_weight_offset = stack_assign(weight_in);
- else
- mix_weight_offset = SVM_STACK_INVALID;
-
- /* compile closure itself */
- generate_node(node, state->nodes_done);
-
- mix_weight_offset = SVM_STACK_INVALID;
-
- if(current_type == SHADER_TYPE_SURFACE) {
- if(node->has_surface_emission())
- current_shader->has_surface_emission = true;
- if(node->has_surface_transparent())
- current_shader->has_surface_transparent = true;
- if(node->has_surface_bssrdf()) {
- current_shader->has_surface_bssrdf = true;
- if(node->has_bssrdf_bump())
- current_shader->has_bssrdf_bump = true;
- }
- if(node->has_bump()) {
- current_shader->has_bump = true;
- }
- }
+ ShaderNode *node = (input->link) ? input->link->parent : NULL;
+ if (node != NULL && done.find(node) == done.end() && node != skip_node &&
+ dependencies.find(node) == dependencies.end()) {
+ foreach (ShaderInput *in, node->inputs) {
+ find_dependencies(dependencies, done, in, skip_node);
+ }
+ dependencies.insert(node);
+ }
+}
+
+void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
+{
+ node->compile(*this);
+ stack_clear_users(node, done);
+ stack_clear_temporary(node);
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (node->has_spatial_varying())
+ current_shader->has_surface_spatial_varying = true;
+ }
+ else if (current_type == SHADER_TYPE_VOLUME) {
+ if (node->has_spatial_varying())
+ current_shader->has_volume_spatial_varying = true;
+ }
+
+ if (node->has_object_dependency()) {
+ current_shader->has_object_dependency = true;
+ }
+
+ if (node->has_attribute_dependency()) {
+ current_shader->has_attribute_dependency = true;
+ }
+
+ if (node->has_integrator_dependency()) {
+ current_shader->has_integrator_dependency = true;
+ }
+}
+
+void SVMCompiler::generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state)
+{
+ ShaderNodeSet &done = state->nodes_done;
+ vector<bool> &done_flag = state->nodes_done_flag;
+
+ bool nodes_done;
+ do {
+ nodes_done = true;
+
+ foreach (ShaderNode *node, nodes) {
+ if (!done_flag[node->id]) {
+ bool inputs_done = true;
+
+ foreach (ShaderInput *input, node->inputs) {
+ if (input->link && !done_flag[input->link->parent->id]) {
+ inputs_done = false;
+ }
+ }
+ if (inputs_done) {
+ generate_node(node, done);
+ done.insert(node);
+ done_flag[node->id] = true;
+ }
+ else {
+ nodes_done = false;
+ }
+ }
+ }
+ } while (!nodes_done);
+}
+
+void SVMCompiler::generate_closure_node(ShaderNode *node, CompilerState *state)
+{
+ /* execute dependencies for closure */
+ foreach (ShaderInput *in, node->inputs) {
+ if (in->link != NULL) {
+ ShaderNodeSet dependencies;
+ find_dependencies(dependencies, state->nodes_done, in);
+ generate_svm_nodes(dependencies, state);
+ }
+ }
+
+ /* closure mix weight */
+ const char *weight_name = (current_type == SHADER_TYPE_VOLUME) ? "VolumeMixWeight" :
+ "SurfaceMixWeight";
+ ShaderInput *weight_in = node->input(weight_name);
+
+ if (weight_in && (weight_in->link || node->get_float(weight_in->socket_type) != 1.0f))
+ mix_weight_offset = stack_assign(weight_in);
+ else
+ mix_weight_offset = SVM_STACK_INVALID;
+
+ /* compile closure itself */
+ generate_node(node, state->nodes_done);
+
+ mix_weight_offset = SVM_STACK_INVALID;
+
+ if (current_type == SHADER_TYPE_SURFACE) {
+ if (node->has_surface_emission())
+ current_shader->has_surface_emission = true;
+ if (node->has_surface_transparent())
+ current_shader->has_surface_transparent = true;
+ if (node->has_surface_bssrdf()) {
+ current_shader->has_surface_bssrdf = true;
+ if (node->has_bssrdf_bump())
+ current_shader->has_bssrdf_bump = true;
+ }
+ if (node->has_bump()) {
+ current_shader->has_bump = true;
+ }
+ }
}
void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
ShaderNode *node,
CompilerState *state,
- const ShaderNodeSet& shared)
-{
- if(shared.find(node) != shared.end()) {
- generate_multi_closure(root_node, node, state);
- }
- else {
- foreach(ShaderInput *in, node->inputs) {
- if(in->type() == SocketType::CLOSURE && in->link)
- generated_shared_closure_nodes(root_node,
- in->link->parent,
- state,
- shared);
- }
- }
+ const ShaderNodeSet &shared)
+{
+ if (shared.find(node) != shared.end()) {
+ generate_multi_closure(root_node, node, state);
+ }
+ else {
+ foreach (ShaderInput *in, node->inputs) {
+ if (in->type() == SocketType::CLOSURE && in->link)
+ generated_shared_closure_nodes(root_node, in->link->parent, state, shared);
+ }
+ }
}
void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
ShaderNode *node,
CompilerState *state)
{
- /* only generate once */
- if(state->closure_done.find(node) != state->closure_done.end())
- return;
-
- state->closure_done.insert(node);
-
- if(node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
- /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
- ShaderInput *cl1in = node->input("Closure1");
- ShaderInput *cl2in = node->input("Closure2");
- ShaderInput *facin = node->input("Fac");
-
- /* skip empty mix/add closure nodes */
- if(!cl1in->link && !cl2in->link)
- return;
-
- if(facin && facin->link) {
- /* mix closure: generate instructions to compute mix weight */
- ShaderNodeSet dependencies;
- find_dependencies(dependencies, state->nodes_done, facin);
- generate_svm_nodes(dependencies, state);
-
- /* execute shared dependencies. this is needed to allow skipping
- * of zero weight closures and their dependencies later, so we
- * ensure that they only skip dependencies that are unique to them */
- ShaderNodeSet cl1deps, cl2deps, shareddeps;
-
- find_dependencies(cl1deps, state->nodes_done, cl1in);
- find_dependencies(cl2deps, state->nodes_done, cl2in);
-
- ShaderNodeIDComparator node_id_comp;
- set_intersection(cl1deps.begin(), cl1deps.end(),
- cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()),
- node_id_comp);
-
- /* it's possible some nodes are not shared between this mix node
- * inputs, but still needed to be always executed, this mainly
- * happens when a node of current subbranch is used by a parent
- * node or so */
- if(root_node != node) {
- foreach(ShaderInput *in, root_node->inputs) {
- ShaderNodeSet rootdeps;
- find_dependencies(rootdeps, state->nodes_done, in, node);
- set_intersection(rootdeps.begin(), rootdeps.end(),
- cl1deps.begin(), cl1deps.end(),
- std::inserter(shareddeps, shareddeps.begin()),
- node_id_comp);
- set_intersection(rootdeps.begin(), rootdeps.end(),
- cl2deps.begin(), cl2deps.end(),
- std::inserter(shareddeps, shareddeps.begin()),
- node_id_comp);
- }
- }
-
- if(!shareddeps.empty()) {
- if(cl1in->link) {
- generated_shared_closure_nodes(root_node,
- cl1in->link->parent,
- state,
- shareddeps);
- }
- if(cl2in->link) {
- generated_shared_closure_nodes(root_node,
- cl2in->link->parent,
- state,
- shareddeps);
- }
-
- generate_svm_nodes(shareddeps, state);
- }
-
- /* generate instructions for input closure 1 */
- if(cl1in->link) {
- /* Add instruction to skip closure and its dependencies if mix
- * weight is zero.
- */
- current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE,
- 0,
- stack_assign(facin),
- 0));
- int node_jump_skip_index = current_svm_nodes.size() - 1;
-
- generate_multi_closure(root_node, cl1in->link->parent, state);
-
- /* Fill in jump instruction location to be after closure. */
- current_svm_nodes[node_jump_skip_index].y =
- current_svm_nodes.size() - node_jump_skip_index - 1;
- }
-
- /* generate instructions for input closure 2 */
- if(cl2in->link) {
- /* Add instruction to skip closure and its dependencies if mix
- * weight is zero.
- */
- current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO,
- 0,
- stack_assign(facin),
- 0));
- int node_jump_skip_index = current_svm_nodes.size() - 1;
-
- generate_multi_closure(root_node, cl2in->link->parent, state);
-
- /* Fill in jump instruction location to be after closure. */
- current_svm_nodes[node_jump_skip_index].y =
- current_svm_nodes.size() - node_jump_skip_index - 1;
- }
-
- /* unassign */
- facin->stack_offset = SVM_STACK_INVALID;
- }
- else {
- /* execute closures and their dependencies, no runtime checks
- * to skip closures here because was already optimized due to
- * fixed weight or add closure that always needs both */
- if(cl1in->link)
- generate_multi_closure(root_node, cl1in->link->parent, state);
- if(cl2in->link)
- generate_multi_closure(root_node, cl2in->link->parent, state);
- }
- }
- else {
- generate_closure_node(node, state);
- }
-
- state->nodes_done.insert(node);
- state->nodes_done_flag[node->id] = true;
+ /* only generate once */
+ if (state->closure_done.find(node) != state->closure_done.end())
+ return;
+
+ state->closure_done.insert(node);
+
+ if (node->special_type == SHADER_SPECIAL_TYPE_COMBINE_CLOSURE) {
+ /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
+ ShaderInput *cl1in = node->input("Closure1");
+ ShaderInput *cl2in = node->input("Closure2");
+ ShaderInput *facin = node->input("Fac");
+
+ /* skip empty mix/add closure nodes */
+ if (!cl1in->link && !cl2in->link)
+ return;
+
+ if (facin && facin->link) {
+ /* mix closure: generate instructions to compute mix weight */
+ ShaderNodeSet dependencies;
+ find_dependencies(dependencies, state->nodes_done, facin);
+ generate_svm_nodes(dependencies, state);
+
+ /* execute shared dependencies. this is needed to allow skipping
+ * of zero weight closures and their dependencies later, so we
+ * ensure that they only skip dependencies that are unique to them */
+ ShaderNodeSet cl1deps, cl2deps, shareddeps;
+
+ find_dependencies(cl1deps, state->nodes_done, cl1in);
+ find_dependencies(cl2deps, state->nodes_done, cl2in);
+
+ ShaderNodeIDComparator node_id_comp;
+ set_intersection(cl1deps.begin(),
+ cl1deps.end(),
+ cl2deps.begin(),
+ cl2deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
+
+ /* it's possible some nodes are not shared between this mix node
+ * inputs, but still needed to be always executed, this mainly
+ * happens when a node of current subbranch is used by a parent
+ * node or so */
+ if (root_node != node) {
+ foreach (ShaderInput *in, root_node->inputs) {
+ ShaderNodeSet rootdeps;
+ find_dependencies(rootdeps, state->nodes_done, in, node);
+ set_intersection(rootdeps.begin(),
+ rootdeps.end(),
+ cl1deps.begin(),
+ cl1deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
+ set_intersection(rootdeps.begin(),
+ rootdeps.end(),
+ cl2deps.begin(),
+ cl2deps.end(),
+ std::inserter(shareddeps, shareddeps.begin()),
+ node_id_comp);
+ }
+ }
+
+ if (!shareddeps.empty()) {
+ if (cl1in->link) {
+ generated_shared_closure_nodes(root_node, cl1in->link->parent, state, shareddeps);
+ }
+ if (cl2in->link) {
+ generated_shared_closure_nodes(root_node, cl2in->link->parent, state, shareddeps);
+ }
+
+ generate_svm_nodes(shareddeps, state);
+ }
+
+ /* generate instructions for input closure 1 */
+ if (cl1in->link) {
+ /* Add instruction to skip closure and its dependencies if mix
+ * weight is zero.
+ */
+ current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ONE, 0, stack_assign(facin), 0));
+ int node_jump_skip_index = current_svm_nodes.size() - 1;
+
+ generate_multi_closure(root_node, cl1in->link->parent, state);
+
+ /* Fill in jump instruction location to be after closure. */
+ current_svm_nodes[node_jump_skip_index].y = current_svm_nodes.size() -
+ node_jump_skip_index - 1;
+ }
+
+ /* generate instructions for input closure 2 */
+ if (cl2in->link) {
+ /* Add instruction to skip closure and its dependencies if mix
+ * weight is zero.
+ */
+ current_svm_nodes.push_back_slow(make_int4(NODE_JUMP_IF_ZERO, 0, stack_assign(facin), 0));
+ int node_jump_skip_index = current_svm_nodes.size() - 1;
+
+ generate_multi_closure(root_node, cl2in->link->parent, state);
+
+ /* Fill in jump instruction location to be after closure. */
+ current_svm_nodes[node_jump_skip_index].y = current_svm_nodes.size() -
+ node_jump_skip_index - 1;
+ }
+
+ /* unassign */
+ facin->stack_offset = SVM_STACK_INVALID;
+ }
+ else {
+ /* execute closures and their dependencies, no runtime checks
+ * to skip closures here because was already optimized due to
+ * fixed weight or add closure that always needs both */
+ if (cl1in->link)
+ generate_multi_closure(root_node, cl1in->link->parent, state);
+ if (cl2in->link)
+ generate_multi_closure(root_node, cl2in->link->parent, state);
+ }
+ }
+ else {
+ generate_closure_node(node, state);
+ }
+
+ state->nodes_done.insert(node);
+ state->nodes_done_flag[node->id] = true;
}
-
void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
- /* Converting a shader graph into svm_nodes that can be executed
- * sequentially on the virtual machine is fairly simple. We can keep
- * looping over nodes and each time all the inputs of a node are
- * ready, we add svm_nodes for it that read the inputs from the
- * stack and write outputs back to the stack.
- *
- * With the SVM, we always sample only a single closure. We can think
- * of all closures nodes as a binary tree with mix closures as inner
- * nodes and other closures as leafs. The SVM will traverse that tree,
- * each time deciding to go left or right depending on the mix weights,
- * until a closure is found.
- *
- * We only execute nodes that are needed for the mix weights and chosen
- * closure.
- */
-
- current_type = type;
- current_graph = graph;
-
- /* get input in output node */
- ShaderNode *node = graph->output();
- ShaderInput *clin = NULL;
-
- switch(type) {
- case SHADER_TYPE_SURFACE:
- clin = node->input("Surface");
- break;
- case SHADER_TYPE_VOLUME:
- clin = node->input("Volume");
- break;
- case SHADER_TYPE_DISPLACEMENT:
- clin = node->input("Displacement");
- break;
- case SHADER_TYPE_BUMP:
- clin = node->input("Normal");
- break;
- default:
- assert(0);
- break;
- }
-
- /* clear all compiler state */
- memset((void *)&active_stack, 0, sizeof(active_stack));
- current_svm_nodes.clear();
-
- foreach(ShaderNode *node_iter, graph->nodes) {
- foreach(ShaderInput *input, node_iter->inputs)
- input->stack_offset = SVM_STACK_INVALID;
- foreach(ShaderOutput *output, node_iter->outputs)
- output->stack_offset = SVM_STACK_INVALID;
- }
-
- /* for the bump shader we need add a node to store the shader state */
- bool need_bump_state = (type == SHADER_TYPE_BUMP) && (shader->displacement_method == DISPLACE_BOTH);
- int bump_state_offset = SVM_STACK_INVALID;
- if(need_bump_state) {
- bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
- add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
- }
-
- if(shader->used) {
- if(clin->link) {
- bool generate = false;
-
- switch(type) {
- case SHADER_TYPE_SURFACE: /* generate surface shader */
- generate = true;
- shader->has_surface = true;
- break;
- case SHADER_TYPE_VOLUME: /* generate volume shader */
- generate = true;
- shader->has_volume = true;
- break;
- case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
- generate = true;
- shader->has_displacement = true;
- break;
- case SHADER_TYPE_BUMP: /* generate bump shader */
- generate = true;
- break;
- default:
- break;
- }
-
- if(generate) {
- CompilerState state(graph);
- generate_multi_closure(clin->link->parent,
- clin->link->parent,
- &state);
- }
- }
-
- /* compile output node */
- node->compile(*this);
- }
-
- /* add node to restore state after bump shader has finished */
- if(need_bump_state) {
- add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
- }
-
- /* if compile failed, generate empty shader */
- if(compile_failed) {
- current_svm_nodes.clear();
- compile_failed = false;
- }
-
- /* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader it ends here */
- if(type != SHADER_TYPE_BUMP) {
- add_node(NODE_END, 0, 0, 0);
- }
-}
-
-void SVMCompiler::compile(Scene *scene,
- Shader *shader,
- array<int4>& svm_nodes,
- int index,
- Summary *summary)
-{
- /* copy graph for shader with bump mapping */
- ShaderNode *output = shader->graph->output();
- int start_num_svm_nodes = svm_nodes.size();
-
- const double time_start = time_dt();
-
- bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
- output->input("Surface")->link && output->input("Displacement")->link;
-
- /* finalize */
- {
- scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
- shader->graph->finalize(scene,
- has_bump,
- shader->has_integrator_dependency,
- shader->displacement_method == DISPLACE_BOTH);
- }
-
- current_shader = shader;
-
- shader->has_surface = false;
- shader->has_surface_emission = false;
- shader->has_surface_transparent = false;
- shader->has_surface_bssrdf = false;
- shader->has_bump = has_bump;
- shader->has_bssrdf_bump = has_bump;
- shader->has_volume = false;
- shader->has_displacement = false;
- shader->has_surface_spatial_varying = false;
- shader->has_volume_spatial_varying = false;
- shader->has_object_dependency = false;
- shader->has_attribute_dependency = false;
- shader->has_integrator_dependency = false;
-
- /* generate bump shader */
- if(has_bump) {
- scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
- svm_nodes[index].y = svm_nodes.size();
- svm_nodes.append(current_svm_nodes);
- }
-
- /* generate surface shader */
- {
- scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
- /* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
- if(!has_bump) {
- svm_nodes[index].y = svm_nodes.size();
- }
- svm_nodes.append(current_svm_nodes);
- }
-
- /* generate volume shader */
- {
- scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
- svm_nodes[index].z = svm_nodes.size();
- svm_nodes.append(current_svm_nodes);
- }
-
- /* generate displacement shader */
- {
- scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL);
- compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
- svm_nodes[index].w = svm_nodes.size();
- svm_nodes.append(current_svm_nodes);
- }
-
- /* Fill in summary information. */
- if(summary != NULL) {
- summary->time_total = time_dt() - time_start;
- summary->peak_stack_usage = max_stack_use;
- summary->num_svm_nodes = svm_nodes.size() - start_num_svm_nodes;
- }
+ /* Converting a shader graph into svm_nodes that can be executed
+ * sequentially on the virtual machine is fairly simple. We can keep
+ * looping over nodes and each time all the inputs of a node are
+ * ready, we add svm_nodes for it that read the inputs from the
+ * stack and write outputs back to the stack.
+ *
+ * With the SVM, we always sample only a single closure. We can think
+ * of all closures nodes as a binary tree with mix closures as inner
+ * nodes and other closures as leafs. The SVM will traverse that tree,
+ * each time deciding to go left or right depending on the mix weights,
+ * until a closure is found.
+ *
+ * We only execute nodes that are needed for the mix weights and chosen
+ * closure.
+ */
+
+ current_type = type;
+ current_graph = graph;
+
+ /* get input in output node */
+ ShaderNode *node = graph->output();
+ ShaderInput *clin = NULL;
+
+ switch (type) {
+ case SHADER_TYPE_SURFACE:
+ clin = node->input("Surface");
+ break;
+ case SHADER_TYPE_VOLUME:
+ clin = node->input("Volume");
+ break;
+ case SHADER_TYPE_DISPLACEMENT:
+ clin = node->input("Displacement");
+ break;
+ case SHADER_TYPE_BUMP:
+ clin = node->input("Normal");
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ /* clear all compiler state */
+ memset((void *)&active_stack, 0, sizeof(active_stack));
+ current_svm_nodes.clear();
+
+ foreach (ShaderNode *node_iter, graph->nodes) {
+ foreach (ShaderInput *input, node_iter->inputs)
+ input->stack_offset = SVM_STACK_INVALID;
+ foreach (ShaderOutput *output, node_iter->outputs)
+ output->stack_offset = SVM_STACK_INVALID;
+ }
+
+ /* for the bump shader we need add a node to store the shader state */
+ bool need_bump_state = (type == SHADER_TYPE_BUMP) &&
+ (shader->displacement_method == DISPLACE_BOTH);
+ int bump_state_offset = SVM_STACK_INVALID;
+ if (need_bump_state) {
+ bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
+ add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
+ }
+
+ if (shader->used) {
+ if (clin->link) {
+ bool generate = false;
+
+ switch (type) {
+ case SHADER_TYPE_SURFACE: /* generate surface shader */
+ generate = true;
+ shader->has_surface = true;
+ break;
+ case SHADER_TYPE_VOLUME: /* generate volume shader */
+ generate = true;
+ shader->has_volume = true;
+ break;
+ case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
+ generate = true;
+ shader->has_displacement = true;
+ break;
+ case SHADER_TYPE_BUMP: /* generate bump shader */
+ generate = true;
+ break;
+ default:
+ break;
+ }
+
+ if (generate) {
+ CompilerState state(graph);
+ generate_multi_closure(clin->link->parent, clin->link->parent, &state);
+ }
+ }
+
+ /* compile output node */
+ node->compile(*this);
+ }
+
+ /* add node to restore state after bump shader has finished */
+ if (need_bump_state) {
+ add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
+ }
+
+ /* if compile failed, generate empty shader */
+ if (compile_failed) {
+ current_svm_nodes.clear();
+ compile_failed = false;
+ }
+
+ /* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader it ends here */
+ if (type != SHADER_TYPE_BUMP) {
+ add_node(NODE_END, 0, 0, 0);
+ }
+}
+
+void SVMCompiler::compile(
+ Scene *scene, Shader *shader, array<int4> &svm_nodes, int index, Summary *summary)
+{
+ /* copy graph for shader with bump mapping */
+ ShaderNode *output = shader->graph->output();
+ int start_num_svm_nodes = svm_nodes.size();
+
+ const double time_start = time_dt();
+
+ bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
+ output->input("Surface")->link && output->input("Displacement")->link;
+
+ /* finalize */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_finalize : NULL);
+ shader->graph->finalize(scene,
+ has_bump,
+ shader->has_integrator_dependency,
+ shader->displacement_method == DISPLACE_BOTH);
+ }
+
+ current_shader = shader;
+
+ shader->has_surface = false;
+ shader->has_surface_emission = false;
+ shader->has_surface_transparent = false;
+ shader->has_surface_bssrdf = false;
+ shader->has_bump = has_bump;
+ shader->has_bssrdf_bump = has_bump;
+ shader->has_volume = false;
+ shader->has_displacement = false;
+ shader->has_surface_spatial_varying = false;
+ shader->has_volume_spatial_varying = false;
+ shader->has_object_dependency = false;
+ shader->has_attribute_dependency = false;
+ shader->has_integrator_dependency = false;
+
+ /* generate bump shader */
+ if (has_bump) {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_bump : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
+ svm_nodes[index].y = svm_nodes.size();
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* generate surface shader */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_surface : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
+ /* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
+ if (!has_bump) {
+ svm_nodes[index].y = svm_nodes.size();
+ }
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* generate volume shader */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_volume : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
+ svm_nodes[index].z = svm_nodes.size();
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* generate displacement shader */
+ {
+ scoped_timer timer((summary != NULL) ? &summary->time_generate_displacement : NULL);
+ compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
+ svm_nodes[index].w = svm_nodes.size();
+ svm_nodes.append(current_svm_nodes);
+ }
+
+ /* Fill in summary information. */
+ if (summary != NULL) {
+ summary->time_total = time_dt() - time_start;
+ summary->peak_stack_usage = max_stack_use;
+ summary->num_svm_nodes = svm_nodes.size() - start_num_svm_nodes;
+ }
}
/* Compiler summary implementation. */
SVMCompiler::Summary::Summary()
- : num_svm_nodes(0),
- peak_stack_usage(0),
- time_finalize(0.0),
- time_generate_surface(0.0),
- time_generate_bump(0.0),
- time_generate_volume(0.0),
- time_generate_displacement(0.0),
- time_total(0.0)
+ : num_svm_nodes(0),
+ peak_stack_usage(0),
+ time_finalize(0.0),
+ time_generate_surface(0.0),
+ time_generate_bump(0.0),
+ time_generate_volume(0.0),
+ time_generate_displacement(0.0),
+ time_total(0.0)
{
}
string SVMCompiler::Summary::full_report() const
{
- string report = "";
- report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
- report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
+ string report = "";
+ report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
+ report += string_printf("Peak stack usage: %d\n", peak_stack_usage);
- report += string_printf("Time (in seconds):\n");
- report += string_printf("Finalize: %f\n", time_finalize);
- report += string_printf(" Surface: %f\n", time_generate_surface);
- report += string_printf(" Bump: %f\n", time_generate_bump);
- report += string_printf(" Volume: %f\n", time_generate_volume);
- report += string_printf(" Displacement: %f\n", time_generate_displacement);
- report += string_printf("Generate: %f\n", time_generate_surface +
- time_generate_bump +
- time_generate_volume +
- time_generate_displacement);
- report += string_printf("Total: %f\n", time_total);
+ report += string_printf("Time (in seconds):\n");
+ report += string_printf("Finalize: %f\n", time_finalize);
+ report += string_printf(" Surface: %f\n", time_generate_surface);
+ report += string_printf(" Bump: %f\n", time_generate_bump);
+ report += string_printf(" Volume: %f\n", time_generate_volume);
+ report += string_printf(" Displacement: %f\n", time_generate_displacement);
+ report += string_printf("Generate: %f\n",
+ time_generate_surface + time_generate_bump + time_generate_volume +
+ time_generate_displacement);
+ report += string_printf("Total: %f\n", time_total);
- return report;
+ return report;
}
/* Global state of the compiler. */
SVMCompiler::CompilerState::CompilerState(ShaderGraph *graph)
{
- int max_id = 0;
- foreach(ShaderNode *node, graph->nodes) {
- max_id = max(node->id, max_id);
- }
- nodes_done_flag.resize(max_id + 1, false);
+ int max_id = 0;
+ foreach (ShaderNode *node, graph->nodes) {
+ max_id = max(node->id, max_id);
+ }
+ nodes_done_flag.resize(max_id + 1, false);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index ddf35602fa6..d6964fb158b 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -40,186 +40,196 @@ class ShaderOutput;
/* Shader Manager */
class SVMShaderManager : public ShaderManager {
-public:
- SVMShaderManager();
- ~SVMShaderManager();
+ public:
+ SVMShaderManager();
+ ~SVMShaderManager();
- void reset(Scene *scene);
+ void reset(Scene *scene);
- void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_free(Device *device, DeviceScene *dscene, Scene *scene);
+ void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
+ void device_free(Device *device, DeviceScene *dscene, Scene *scene);
-protected:
- /* Lock used to synchronize threaded nodes compilation. */
- thread_spin_lock nodes_lock_;
+ protected:
+ /* Lock used to synchronize threaded nodes compilation. */
+ thread_spin_lock nodes_lock_;
- void device_update_shader(Scene *scene,
- Shader *shader,
- Progress *progress,
- array<int4> *global_svm_nodes);
+ void device_update_shader(Scene *scene,
+ Shader *shader,
+ Progress *progress,
+ array<int4> *global_svm_nodes);
};
/* Graph Compiler */
class SVMCompiler {
-public:
- struct Summary {
- Summary();
-
- /* Number of SVM nodes shader was compiled into. */
- int num_svm_nodes;
-
- /* Peak stack usage during shader evaluation. */
- int peak_stack_usage;
-
- /* Time spent on surface graph finalization. */
- double time_finalize;
-
- /* Time spent on generating SVM nodes for surface shader. */
- double time_generate_surface;
-
- /* Time spent on generating SVM nodes for bump shader. */
- double time_generate_bump;
-
- /* Time spent on generating SVM nodes for volume shader. */
- double time_generate_volume;
-
- /* Time spent on generating SVM nodes for displacement shader. */
- double time_generate_displacement;
-
- /* Total time spent on all routines. */
- double time_total;
-
- /* A full multiline description of the state of the compiler after
- * compilation.
- */
- string full_report() const;
- };
-
- SVMCompiler(ShaderManager *shader_manager,
- ImageManager *image_manager,
- LightManager *light_manager);
- void compile(Scene *scene,
- Shader *shader,
- array<int4>& svm_nodes,
- int index,
- Summary *summary = NULL);
-
- int stack_assign(ShaderOutput *output);
- int stack_assign(ShaderInput *input);
- int stack_assign_if_linked(ShaderInput *input);
- int stack_assign_if_linked(ShaderOutput *output);
- int stack_find_offset(int size);
- int stack_find_offset(SocketType::Type type);
- void stack_clear_offset(SocketType::Type type, int offset);
- void stack_link(ShaderInput *input, ShaderOutput *output);
-
- void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0);
- void add_node(int a = 0, int b = 0, int c = 0, int d = 0);
- void add_node(ShaderNodeType type, const float3& f);
- void add_node(const float4& f);
- uint attribute(ustring name);
- uint attribute(AttributeStandard std);
- uint attribute_standard(ustring name);
- uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
- uint closure_mix_weight_offset() { return mix_weight_offset; }
-
- ShaderType output_type() { return current_type; }
-
- ImageManager *image_manager;
- ShaderManager *shader_manager;
- LightManager *light_manager;
- bool background;
-
-protected:
- /* stack */
- struct Stack {
- Stack() { memset(users, 0, sizeof(users)); }
- Stack(const Stack& other) { memcpy(users, other.users, sizeof(users)); }
- Stack& operator=(const Stack& other) { memcpy(users, other.users, sizeof(users)); return *this; }
-
- bool empty()
- {
- for(int i = 0; i < SVM_STACK_SIZE; i++)
- if(users[i])
- return false;
-
- return true;
- }
-
- void print()
- {
- printf("stack <");
-
- for(int i = 0; i < SVM_STACK_SIZE; i++)
- printf((users[i])? "*": " ");
-
- printf(">\n");
- }
-
- int users[SVM_STACK_SIZE];
- };
-
- /* Global state of the compiler accessible from the compilation routines. */
- struct CompilerState {
- explicit CompilerState(ShaderGraph *graph);
-
- /* ** Global state, used by various compilation steps. ** */
-
- /* Set of nodes which were already compiled. */
- ShaderNodeSet nodes_done;
-
- /* Set of closures which were already compiled. */
- ShaderNodeSet closure_done;
-
- /* ** SVM nodes generation state ** */
-
- /* Flag whether the node with corresponding ID was already compiled or
- * not. Array element with index i corresponds to a node with such if.
- *
- * TODO(sergey): This is actually a copy of nodes_done just in another
- * notation. We can de-duplicate this storage actually after switching
- * all areas to use this flags array.
- */
- vector<bool> nodes_done_flag;
- };
-
- void stack_clear_temporary(ShaderNode *node);
- int stack_size(SocketType::Type type);
- void stack_clear_users(ShaderNode *node, ShaderNodeSet& done);
-
- /* single closure */
- void find_dependencies(ShaderNodeSet& dependencies,
- const ShaderNodeSet& done,
- ShaderInput *input,
- ShaderNode *skip_node = NULL);
- void generate_node(ShaderNode *node, ShaderNodeSet& done);
- void generate_closure_node(ShaderNode *node, CompilerState *state);
- void generated_shared_closure_nodes(ShaderNode *root_node,
- ShaderNode *node,
- CompilerState *state,
- const ShaderNodeSet& shared);
- void generate_svm_nodes(const ShaderNodeSet& nodes,
- CompilerState *state);
-
- /* multi closure */
- void generate_multi_closure(ShaderNode *root_node,
- ShaderNode *node,
- CompilerState *state);
-
- /* compile */
- void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
-
- array<int4> current_svm_nodes;
- ShaderType current_type;
- Shader *current_shader;
- ShaderGraph *current_graph;
- Stack active_stack;
- int max_stack_use;
- uint mix_weight_offset;
- bool compile_failed;
+ public:
+ struct Summary {
+ Summary();
+
+ /* Number of SVM nodes shader was compiled into. */
+ int num_svm_nodes;
+
+ /* Peak stack usage during shader evaluation. */
+ int peak_stack_usage;
+
+ /* Time spent on surface graph finalization. */
+ double time_finalize;
+
+ /* Time spent on generating SVM nodes for surface shader. */
+ double time_generate_surface;
+
+ /* Time spent on generating SVM nodes for bump shader. */
+ double time_generate_bump;
+
+ /* Time spent on generating SVM nodes for volume shader. */
+ double time_generate_volume;
+
+ /* Time spent on generating SVM nodes for displacement shader. */
+ double time_generate_displacement;
+
+ /* Total time spent on all routines. */
+ double time_total;
+
+ /* A full multiline description of the state of the compiler after
+ * compilation.
+ */
+ string full_report() const;
+ };
+
+ SVMCompiler(ShaderManager *shader_manager,
+ ImageManager *image_manager,
+ LightManager *light_manager);
+ void compile(
+ Scene *scene, Shader *shader, array<int4> &svm_nodes, int index, Summary *summary = NULL);
+
+ int stack_assign(ShaderOutput *output);
+ int stack_assign(ShaderInput *input);
+ int stack_assign_if_linked(ShaderInput *input);
+ int stack_assign_if_linked(ShaderOutput *output);
+ int stack_find_offset(int size);
+ int stack_find_offset(SocketType::Type type);
+ void stack_clear_offset(SocketType::Type type, int offset);
+ void stack_link(ShaderInput *input, ShaderOutput *output);
+
+ void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0);
+ void add_node(int a = 0, int b = 0, int c = 0, int d = 0);
+ void add_node(ShaderNodeType type, const float3 &f);
+ void add_node(const float4 &f);
+ uint attribute(ustring name);
+ uint attribute(AttributeStandard std);
+ uint attribute_standard(ustring name);
+ uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0);
+ uint closure_mix_weight_offset()
+ {
+ return mix_weight_offset;
+ }
+
+ ShaderType output_type()
+ {
+ return current_type;
+ }
+
+ ImageManager *image_manager;
+ ShaderManager *shader_manager;
+ LightManager *light_manager;
+ bool background;
+
+ protected:
+ /* stack */
+ struct Stack {
+ Stack()
+ {
+ memset(users, 0, sizeof(users));
+ }
+ Stack(const Stack &other)
+ {
+ memcpy(users, other.users, sizeof(users));
+ }
+ Stack &operator=(const Stack &other)
+ {
+ memcpy(users, other.users, sizeof(users));
+ return *this;
+ }
+
+ bool empty()
+ {
+ for (int i = 0; i < SVM_STACK_SIZE; i++)
+ if (users[i])
+ return false;
+
+ return true;
+ }
+
+ void print()
+ {
+ printf("stack <");
+
+ for (int i = 0; i < SVM_STACK_SIZE; i++)
+ printf((users[i]) ? "*" : " ");
+
+ printf(">\n");
+ }
+
+ int users[SVM_STACK_SIZE];
+ };
+
+ /* Global state of the compiler accessible from the compilation routines. */
+ struct CompilerState {
+ explicit CompilerState(ShaderGraph *graph);
+
+ /* ** Global state, used by various compilation steps. ** */
+
+ /* Set of nodes which were already compiled. */
+ ShaderNodeSet nodes_done;
+
+ /* Set of closures which were already compiled. */
+ ShaderNodeSet closure_done;
+
+ /* ** SVM nodes generation state ** */
+
+ /* Flag whether the node with corresponding ID was already compiled or
+ * not. Array element with index i corresponds to a node with such if.
+ *
+ * TODO(sergey): This is actually a copy of nodes_done just in another
+ * notation. We can de-duplicate this storage actually after switching
+ * all areas to use this flags array.
+ */
+ vector<bool> nodes_done_flag;
+ };
+
+ void stack_clear_temporary(ShaderNode *node);
+ int stack_size(SocketType::Type type);
+ void stack_clear_users(ShaderNode *node, ShaderNodeSet &done);
+
+ /* single closure */
+ void find_dependencies(ShaderNodeSet &dependencies,
+ const ShaderNodeSet &done,
+ ShaderInput *input,
+ ShaderNode *skip_node = NULL);
+ void generate_node(ShaderNode *node, ShaderNodeSet &done);
+ void generate_closure_node(ShaderNode *node, CompilerState *state);
+ void generated_shared_closure_nodes(ShaderNode *root_node,
+ ShaderNode *node,
+ CompilerState *state,
+ const ShaderNodeSet &shared);
+ void generate_svm_nodes(const ShaderNodeSet &nodes, CompilerState *state);
+
+ /* multi closure */
+ void generate_multi_closure(ShaderNode *root_node, ShaderNode *node, CompilerState *state);
+
+ /* compile */
+ void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
+
+ array<int4> current_svm_nodes;
+ ShaderType current_type;
+ Shader *current_shader;
+ ShaderGraph *current_graph;
+ Stack active_stack;
+ int max_stack_use;
+ uint mix_weight_offset;
+ bool compile_failed;
};
CCL_NAMESPACE_END
-#endif /* __SVM_H__ */
+#endif /* __SVM_H__ */
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
index ddbb138f059..d88925939e3 100644
--- a/intern/cycles/render/tables.cpp
+++ b/intern/cycles/render/tables.cpp
@@ -26,92 +26,92 @@ CCL_NAMESPACE_BEGIN
LookupTables::LookupTables()
{
- need_update = true;
+ need_update = true;
}
LookupTables::~LookupTables()
{
- assert(lookup_tables.size() == 0);
+ assert(lookup_tables.size() == 0);
}
void LookupTables::device_update(Device *, DeviceScene *dscene)
{
- if(!need_update)
- return;
+ if (!need_update)
+ return;
- VLOG(1) << "Total " << lookup_tables.size() << " lookup tables.";
+ VLOG(1) << "Total " << lookup_tables.size() << " lookup tables.";
- if(lookup_tables.size() > 0)
- dscene->lookup_table.copy_to_device();
+ if (lookup_tables.size() > 0)
+ dscene->lookup_table.copy_to_device();
- need_update = false;
+ need_update = false;
}
void LookupTables::device_free(Device *, DeviceScene *dscene)
{
- dscene->lookup_table.free();
+ dscene->lookup_table.free();
}
static size_t round_up_to_multiple(size_t size, size_t chunk)
{
- return ((size + chunk - 1)/chunk) * chunk;
+ return ((size + chunk - 1) / chunk) * chunk;
}
-size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data)
+size_t LookupTables::add_table(DeviceScene *dscene, vector<float> &data)
{
- assert(data.size() > 0);
+ assert(data.size() > 0);
- need_update = true;
+ need_update = true;
- Table new_table;
- new_table.offset = 0;
- new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);
+ Table new_table;
+ new_table.offset = 0;
+ new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);
- /* find space to put lookup table */
- list<Table>::iterator table;
+ /* find space to put lookup table */
+ list<Table>::iterator table;
- for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
- if(new_table.offset + new_table.size <= table->offset) {
- lookup_tables.insert(table, new_table);
- break;
- }
- else
- new_table.offset = table->offset + table->size;
- }
+ for (table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+ if (new_table.offset + new_table.size <= table->offset) {
+ lookup_tables.insert(table, new_table);
+ break;
+ }
+ else
+ new_table.offset = table->offset + table->size;
+ }
- if(table == lookup_tables.end()) {
- /* add at the end */
- lookup_tables.push_back(new_table);
- dscene->lookup_table.resize(new_table.offset + new_table.size);
- }
+ if (table == lookup_tables.end()) {
+ /* add at the end */
+ lookup_tables.push_back(new_table);
+ dscene->lookup_table.resize(new_table.offset + new_table.size);
+ }
- /* copy table data and return offset */
- float *dtable = dscene->lookup_table.data();
- memcpy(dtable + new_table.offset, &data[0], sizeof(float) * data.size());
+ /* copy table data and return offset */
+ float *dtable = dscene->lookup_table.data();
+ memcpy(dtable + new_table.offset, &data[0], sizeof(float) * data.size());
- return new_table.offset;
+ return new_table.offset;
}
void LookupTables::remove_table(size_t *offset)
{
- if(*offset == TABLE_OFFSET_INVALID) {
- /* The table isn't even allocated, so just return here. */
- return;
- }
+ if (*offset == TABLE_OFFSET_INVALID) {
+ /* The table isn't even allocated, so just return here. */
+ return;
+ }
- need_update = true;
+ need_update = true;
- list<Table>::iterator table;
+ list<Table>::iterator table;
- for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
- if(table->offset == *offset) {
- lookup_tables.erase(table);
- *offset = TABLE_OFFSET_INVALID;
- return;
- }
- }
+ for (table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+ if (table->offset == *offset) {
+ lookup_tables.erase(table);
+ *offset = TABLE_OFFSET_INVALID;
+ return;
+ }
+ }
- assert(table != lookup_tables.end());
+ assert(table != lookup_tables.end());
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h
index 709333cb1b6..12b59bb0aeb 100644
--- a/intern/cycles/render/tables.h
+++ b/intern/cycles/render/tables.h
@@ -29,25 +29,25 @@ enum { TABLE_CHUNK_SIZE = 256 };
enum { TABLE_OFFSET_INVALID = -1 };
class LookupTables {
-public:
- struct Table {
- size_t offset;
- size_t size;
- };
+ public:
+ struct Table {
+ size_t offset;
+ size_t size;
+ };
- bool need_update;
- list<Table> lookup_tables;
+ bool need_update;
+ list<Table> lookup_tables;
- LookupTables();
- ~LookupTables();
+ LookupTables();
+ ~LookupTables();
- void device_update(Device *device, DeviceScene *dscene);
- void device_free(Device *device, DeviceScene *dscene);
+ void device_update(Device *device, DeviceScene *dscene);
+ void device_free(Device *device, DeviceScene *dscene);
- size_t add_table(DeviceScene *dscene, vector<float>& data);
- void remove_table(size_t *offset);
+ size_t add_table(DeviceScene *dscene, vector<float> &data);
+ void remove_table(size_t *offset);
};
CCL_NAMESPACE_END
-#endif /* __TABLES_H__ */
+#endif /* __TABLES_H__ */
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index dc863b067b0..3148b5ef664 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -25,89 +25,93 @@ CCL_NAMESPACE_BEGIN
namespace {
class TileComparator {
-public:
- TileComparator(TileOrder order_, int2 center_, Tile *tiles_)
- : order(order_),
- center(center_),
- tiles(tiles_)
- {}
-
- bool operator()(int a, int b)
- {
- switch(order) {
- case TILE_CENTER:
- {
- float2 dist_a = make_float2(center.x - (tiles[a].x + tiles[a].w/2),
- center.y - (tiles[a].y + tiles[a].h/2));
- float2 dist_b = make_float2(center.x - (tiles[b].x + tiles[b].w/2),
- center.y - (tiles[b].y + tiles[b].h/2));
- return dot(dist_a, dist_a) < dot(dist_b, dist_b);
- }
- case TILE_LEFT_TO_RIGHT:
- return (tiles[a].x == tiles[b].x)? (tiles[a].y < tiles[b].y): (tiles[a].x < tiles[b].x);
- case TILE_RIGHT_TO_LEFT:
- return (tiles[a].x == tiles[b].x)? (tiles[a].y < tiles[b].y): (tiles[a].x > tiles[b].x);
- case TILE_TOP_TO_BOTTOM:
- return (tiles[a].y == tiles[b].y)? (tiles[a].x < tiles[b].x): (tiles[a].y > tiles[b].y);
- case TILE_BOTTOM_TO_TOP:
- default:
- return (tiles[a].y == tiles[b].y)? (tiles[a].x < tiles[b].x): (tiles[a].y < tiles[b].y);
- }
- }
-
-protected:
- TileOrder order;
- int2 center;
- Tile *tiles;
+ public:
+ TileComparator(TileOrder order_, int2 center_, Tile *tiles_)
+ : order(order_), center(center_), tiles(tiles_)
+ {
+ }
+
+ bool operator()(int a, int b)
+ {
+ switch (order) {
+ case TILE_CENTER: {
+ float2 dist_a = make_float2(center.x - (tiles[a].x + tiles[a].w / 2),
+ center.y - (tiles[a].y + tiles[a].h / 2));
+ float2 dist_b = make_float2(center.x - (tiles[b].x + tiles[b].w / 2),
+ center.y - (tiles[b].y + tiles[b].h / 2));
+ return dot(dist_a, dist_a) < dot(dist_b, dist_b);
+ }
+ case TILE_LEFT_TO_RIGHT:
+ return (tiles[a].x == tiles[b].x) ? (tiles[a].y < tiles[b].y) : (tiles[a].x < tiles[b].x);
+ case TILE_RIGHT_TO_LEFT:
+ return (tiles[a].x == tiles[b].x) ? (tiles[a].y < tiles[b].y) : (tiles[a].x > tiles[b].x);
+ case TILE_TOP_TO_BOTTOM:
+ return (tiles[a].y == tiles[b].y) ? (tiles[a].x < tiles[b].x) : (tiles[a].y > tiles[b].y);
+ case TILE_BOTTOM_TO_TOP:
+ default:
+ return (tiles[a].y == tiles[b].y) ? (tiles[a].x < tiles[b].x) : (tiles[a].y < tiles[b].y);
+ }
+ }
+
+ protected:
+ TileOrder order;
+ int2 center;
+ Tile *tiles;
};
inline int2 hilbert_index_to_pos(int n, int d)
{
- int2 r, xy = make_int2(0, 0);
- for(int s = 1; s < n; s *= 2) {
- r.x = (d >> 1) & 1;
- r.y = (d ^ r.x) & 1;
- if(!r.y) {
- if(r.x) {
- xy = make_int2(s-1, s-1) - xy;
- }
- swap(xy.x, xy.y);
- }
- xy += r*make_int2(s, s);
- d >>= 2;
- }
- return xy;
+ int2 r, xy = make_int2(0, 0);
+ for (int s = 1; s < n; s *= 2) {
+ r.x = (d >> 1) & 1;
+ r.y = (d ^ r.x) & 1;
+ if (!r.y) {
+ if (r.x) {
+ xy = make_int2(s - 1, s - 1) - xy;
+ }
+ swap(xy.x, xy.y);
+ }
+ xy += r * make_int2(s, s);
+ d >>= 2;
+ }
+ return xy;
}
enum SpiralDirection {
- DIRECTION_UP,
- DIRECTION_LEFT,
- DIRECTION_DOWN,
- DIRECTION_RIGHT,
+ DIRECTION_UP,
+ DIRECTION_LEFT,
+ DIRECTION_DOWN,
+ DIRECTION_RIGHT,
};
-} /* namespace */
-
-TileManager::TileManager(bool progressive_, int num_samples_, int2 tile_size_, int start_resolution_,
- bool preserve_tile_device_, bool background_, TileOrder tile_order_,
- int num_devices_, int pixel_size_)
+} /* namespace */
+
+TileManager::TileManager(bool progressive_,
+ int num_samples_,
+ int2 tile_size_,
+ int start_resolution_,
+ bool preserve_tile_device_,
+ bool background_,
+ TileOrder tile_order_,
+ int num_devices_,
+ int pixel_size_)
{
- progressive = progressive_;
- tile_size = tile_size_;
- tile_order = tile_order_;
- start_resolution = start_resolution_;
- pixel_size = pixel_size_;
- num_samples = num_samples_;
- num_devices = num_devices_;
- preserve_tile_device = preserve_tile_device_;
- background = background_;
- schedule_denoising = false;
-
- range_start_sample = 0;
- range_num_samples = -1;
-
- BufferParams buffer_params;
- reset(buffer_params, 0);
+ progressive = progressive_;
+ tile_size = tile_size_;
+ tile_order = tile_order_;
+ start_resolution = start_resolution_;
+ pixel_size = pixel_size_;
+ num_samples = num_samples_;
+ num_devices = num_devices_;
+ preserve_tile_device = preserve_tile_device_;
+ background = background_;
+ schedule_denoising = false;
+
+ range_start_sample = 0;
+ range_num_samples = -1;
+
+ BufferParams buffer_params;
+ reset(buffer_params, 0);
}
TileManager::~TileManager()
@@ -116,422 +120,422 @@ TileManager::~TileManager()
void TileManager::device_free()
{
- if(schedule_denoising || progressive) {
- for(int i = 0; i < state.tiles.size(); i++) {
- delete state.tiles[i].buffers;
- state.tiles[i].buffers = NULL;
- }
- }
-
- state.tiles.clear();
+ if (schedule_denoising || progressive) {
+ for (int i = 0; i < state.tiles.size(); i++) {
+ delete state.tiles[i].buffers;
+ state.tiles[i].buffers = NULL;
+ }
+ }
+
+ state.tiles.clear();
}
static int get_divider(int w, int h, int start_resolution)
{
- int divider = 1;
- if(start_resolution != INT_MAX) {
- while(w*h > start_resolution*start_resolution) {
- w = max(1, w/2);
- h = max(1, h/2);
-
- divider <<= 1;
- }
- }
- return divider;
+ int divider = 1;
+ if (start_resolution != INT_MAX) {
+ while (w * h > start_resolution * start_resolution) {
+ w = max(1, w / 2);
+ h = max(1, h / 2);
+
+ divider <<= 1;
+ }
+ }
+ return divider;
}
-void TileManager::reset(BufferParams& params_, int num_samples_)
+void TileManager::reset(BufferParams &params_, int num_samples_)
{
- params = params_;
-
- set_samples(num_samples_);
-
- state.buffer = BufferParams();
- state.sample = range_start_sample - 1;
- state.num_tiles = 0;
- state.num_samples = 0;
- state.resolution_divider = get_divider(params.width, params.height, start_resolution);
- state.render_tiles.clear();
- state.denoising_tiles.clear();
- device_free();
+ params = params_;
+
+ set_samples(num_samples_);
+
+ state.buffer = BufferParams();
+ state.sample = range_start_sample - 1;
+ state.num_tiles = 0;
+ state.num_samples = 0;
+ state.resolution_divider = get_divider(params.width, params.height, start_resolution);
+ state.render_tiles.clear();
+ state.denoising_tiles.clear();
+ device_free();
}
void TileManager::set_samples(int num_samples_)
{
- num_samples = num_samples_;
-
- /* No real progress indication is possible when using unlimited samples. */
- if(num_samples == INT_MAX) {
- state.total_pixel_samples = 0;
- }
- else {
- uint64_t pixel_samples = 0;
- /* While rendering in the viewport, the initial preview resolution is increased to the native resolution
- * before the actual rendering begins. Therefore, additional pixel samples will be rendered. */
- int divider = max(get_divider(params.width, params.height, start_resolution) / 2, pixel_size);
- while(divider > pixel_size) {
- int image_w = max(1, params.width/divider);
- int image_h = max(1, params.height/divider);
- pixel_samples += image_w * image_h;
- divider >>= 1;
- }
-
- int image_w = max(1, params.width/divider);
- int image_h = max(1, params.height/divider);
- state.total_pixel_samples = pixel_samples + (uint64_t)get_num_effective_samples() * image_w*image_h;
- if(schedule_denoising) {
- state.total_pixel_samples += params.width*params.height;
- }
- }
+ num_samples = num_samples_;
+
+ /* No real progress indication is possible when using unlimited samples. */
+ if (num_samples == INT_MAX) {
+ state.total_pixel_samples = 0;
+ }
+ else {
+ uint64_t pixel_samples = 0;
+ /* While rendering in the viewport, the initial preview resolution is increased to the native resolution
+ * before the actual rendering begins. Therefore, additional pixel samples will be rendered. */
+ int divider = max(get_divider(params.width, params.height, start_resolution) / 2, pixel_size);
+ while (divider > pixel_size) {
+ int image_w = max(1, params.width / divider);
+ int image_h = max(1, params.height / divider);
+ pixel_samples += image_w * image_h;
+ divider >>= 1;
+ }
+
+ int image_w = max(1, params.width / divider);
+ int image_h = max(1, params.height / divider);
+ state.total_pixel_samples = pixel_samples +
+ (uint64_t)get_num_effective_samples() * image_w * image_h;
+ if (schedule_denoising) {
+ state.total_pixel_samples += params.width * params.height;
+ }
+ }
}
/* If sliced is false, splits image into tiles and assigns equal amount of tiles to every render device.
* If sliced is true, slice image into as much pieces as how many devices are rendering this image. */
int TileManager::gen_tiles(bool sliced)
{
- int resolution = state.resolution_divider;
- int image_w = max(1, params.width/resolution);
- int image_h = max(1, params.height/resolution);
- int2 center = make_int2(image_w/2, image_h/2);
-
- int num_logical_devices = preserve_tile_device? num_devices: 1;
- int num = min(image_h, num_logical_devices);
- int slice_num = sliced? num: 1;
- int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
-
- device_free();
- state.render_tiles.clear();
- state.denoising_tiles.clear();
- state.render_tiles.resize(num);
- state.denoising_tiles.resize(num);
- state.tile_stride = tile_w;
- vector<list<int> >::iterator tile_list;
- tile_list = state.render_tiles.begin();
-
- if(tile_order == TILE_HILBERT_SPIRAL) {
- assert(!sliced);
-
- int tile_h = (tile_size.y >= image_h) ? 1 : divide_up(image_h, tile_size.y);
- state.tiles.resize(tile_w*tile_h);
-
- /* Size of blocks in tiles, must be a power of 2 */
- const int hilbert_size = (max(tile_size.x, tile_size.y) <= 12)? 8: 4;
-
- int tiles_per_device = divide_up(tile_w * tile_h, num);
- int cur_device = 0, cur_tiles = 0;
-
- int2 block_size = tile_size * make_int2(hilbert_size, hilbert_size);
- /* Number of blocks to fill the image */
- int blocks_x = (block_size.x >= image_w)? 1: divide_up(image_w, block_size.x);
- int blocks_y = (block_size.y >= image_h)? 1: divide_up(image_h, block_size.y);
- int n = max(blocks_x, blocks_y) | 0x1; /* Side length of the spiral (must be odd) */
- /* Offset of spiral (to keep it centered) */
- int2 offset = make_int2((image_w - n*block_size.x)/2, (image_h - n*block_size.y)/2);
- offset = (offset / tile_size) * tile_size; /* Round to tile border. */
-
- int2 block = make_int2(0, 0); /* Current block */
- SpiralDirection prev_dir = DIRECTION_UP, dir = DIRECTION_UP;
- for(int i = 0;;) {
- /* Generate the tiles in the current block. */
- for(int hilbert_index = 0; hilbert_index < hilbert_size*hilbert_size; hilbert_index++) {
- int2 tile, hilbert_pos = hilbert_index_to_pos(hilbert_size, hilbert_index);
- /* Rotate block according to spiral direction. */
- if(prev_dir == DIRECTION_UP && dir == DIRECTION_UP) {
- tile = make_int2(hilbert_pos.y, hilbert_pos.x);
- }
- else if(dir == DIRECTION_LEFT || prev_dir == DIRECTION_LEFT) {
- tile = hilbert_pos;
- }
- else if(dir == DIRECTION_DOWN) {
- tile = make_int2(hilbert_size-1-hilbert_pos.y, hilbert_size-1-hilbert_pos.x);
- }
- else {
- tile = make_int2(hilbert_size-1-hilbert_pos.x, hilbert_size-1-hilbert_pos.y);
- }
-
- int2 pos = block*block_size + tile*tile_size + offset;
- /* Only add tiles which are in the image (tiles outside of the image can be generated since the spiral is always square). */
- if(pos.x >= 0 && pos.y >= 0 && pos.x < image_w && pos.y < image_h) {
- int w = min(tile_size.x, image_w - pos.x);
- int h = min(tile_size.y, image_h - pos.y);
- int2 ipos = pos / tile_size;
- int idx = ipos.y*tile_w + ipos.x;
- state.tiles[idx] = Tile(idx, pos.x, pos.y, w, h, cur_device, Tile::RENDER);
- tile_list->push_front(idx);
- cur_tiles++;
-
- if(cur_tiles == tiles_per_device) {
- tile_list++;
- cur_tiles = 0;
- cur_device++;
- }
- }
- }
-
- /* Stop as soon as the spiral has reached the center block. */
- if(block.x == (n-1)/2 && block.y == (n-1)/2)
- break;
-
- /* Advance to next block. */
- prev_dir = dir;
- switch(dir) {
- case DIRECTION_UP:
- block.y++;
- if(block.y == (n-i-1)) {
- dir = DIRECTION_LEFT;
- }
- break;
- case DIRECTION_LEFT:
- block.x++;
- if(block.x == (n-i-1)) {
- dir = DIRECTION_DOWN;
- }
- break;
- case DIRECTION_DOWN:
- block.y--;
- if(block.y == i) {
- dir = DIRECTION_RIGHT;
- }
- break;
- case DIRECTION_RIGHT:
- block.x--;
- if(block.x == i+1) {
- dir = DIRECTION_UP;
- i++;
- }
- break;
- }
- }
- return tile_w*tile_h;
- }
-
- int idx = 0;
- for(int slice = 0; slice < slice_num; slice++) {
- int slice_y = (image_h/slice_num)*slice;
- int slice_h = (slice == slice_num-1)? image_h - slice*(image_h/slice_num): image_h/slice_num;
-
- int tile_h = (tile_size.y >= slice_h)? 1: divide_up(slice_h, tile_size.y);
-
- int tiles_per_device = divide_up(tile_w * tile_h, num);
- int cur_device = 0, cur_tiles = 0;
-
- for(int tile_y = 0; tile_y < tile_h; tile_y++) {
- for(int tile_x = 0; tile_x < tile_w; tile_x++, idx++) {
- int x = tile_x * tile_size.x;
- int y = tile_y * tile_size.y;
- int w = (tile_x == tile_w-1)? image_w - x: tile_size.x;
- int h = (tile_y == tile_h-1)? slice_h - y: tile_size.y;
-
- state.tiles.push_back(Tile(idx, x, y + slice_y, w, h, sliced? slice: cur_device, Tile::RENDER));
- tile_list->push_back(idx);
-
- if(!sliced) {
- cur_tiles++;
-
- if(cur_tiles == tiles_per_device) {
- /* Tiles are already generated in Bottom-to-Top order, so no sort is necessary in that case. */
- if(tile_order != TILE_BOTTOM_TO_TOP) {
- tile_list->sort(TileComparator(tile_order, center, &state.tiles[0]));
- }
- tile_list++;
- cur_tiles = 0;
- cur_device++;
- }
- }
- }
- }
- if(sliced) {
- tile_list++;
- }
- }
-
- return idx;
+ int resolution = state.resolution_divider;
+ int image_w = max(1, params.width / resolution);
+ int image_h = max(1, params.height / resolution);
+ int2 center = make_int2(image_w / 2, image_h / 2);
+
+ int num_logical_devices = preserve_tile_device ? num_devices : 1;
+ int num = min(image_h, num_logical_devices);
+ int slice_num = sliced ? num : 1;
+ int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
+
+ device_free();
+ state.render_tiles.clear();
+ state.denoising_tiles.clear();
+ state.render_tiles.resize(num);
+ state.denoising_tiles.resize(num);
+ state.tile_stride = tile_w;
+ vector<list<int>>::iterator tile_list;
+ tile_list = state.render_tiles.begin();
+
+ if (tile_order == TILE_HILBERT_SPIRAL) {
+ assert(!sliced);
+
+ int tile_h = (tile_size.y >= image_h) ? 1 : divide_up(image_h, tile_size.y);
+ state.tiles.resize(tile_w * tile_h);
+
+ /* Size of blocks in tiles, must be a power of 2 */
+ const int hilbert_size = (max(tile_size.x, tile_size.y) <= 12) ? 8 : 4;
+
+ int tiles_per_device = divide_up(tile_w * tile_h, num);
+ int cur_device = 0, cur_tiles = 0;
+
+ int2 block_size = tile_size * make_int2(hilbert_size, hilbert_size);
+ /* Number of blocks to fill the image */
+ int blocks_x = (block_size.x >= image_w) ? 1 : divide_up(image_w, block_size.x);
+ int blocks_y = (block_size.y >= image_h) ? 1 : divide_up(image_h, block_size.y);
+ int n = max(blocks_x, blocks_y) | 0x1; /* Side length of the spiral (must be odd) */
+ /* Offset of spiral (to keep it centered) */
+ int2 offset = make_int2((image_w - n * block_size.x) / 2, (image_h - n * block_size.y) / 2);
+ offset = (offset / tile_size) * tile_size; /* Round to tile border. */
+
+ int2 block = make_int2(0, 0); /* Current block */
+ SpiralDirection prev_dir = DIRECTION_UP, dir = DIRECTION_UP;
+ for (int i = 0;;) {
+ /* Generate the tiles in the current block. */
+ for (int hilbert_index = 0; hilbert_index < hilbert_size * hilbert_size; hilbert_index++) {
+ int2 tile, hilbert_pos = hilbert_index_to_pos(hilbert_size, hilbert_index);
+ /* Rotate block according to spiral direction. */
+ if (prev_dir == DIRECTION_UP && dir == DIRECTION_UP) {
+ tile = make_int2(hilbert_pos.y, hilbert_pos.x);
+ }
+ else if (dir == DIRECTION_LEFT || prev_dir == DIRECTION_LEFT) {
+ tile = hilbert_pos;
+ }
+ else if (dir == DIRECTION_DOWN) {
+ tile = make_int2(hilbert_size - 1 - hilbert_pos.y, hilbert_size - 1 - hilbert_pos.x);
+ }
+ else {
+ tile = make_int2(hilbert_size - 1 - hilbert_pos.x, hilbert_size - 1 - hilbert_pos.y);
+ }
+
+ int2 pos = block * block_size + tile * tile_size + offset;
+ /* Only add tiles which are in the image (tiles outside of the image can be generated since the spiral is always square). */
+ if (pos.x >= 0 && pos.y >= 0 && pos.x < image_w && pos.y < image_h) {
+ int w = min(tile_size.x, image_w - pos.x);
+ int h = min(tile_size.y, image_h - pos.y);
+ int2 ipos = pos / tile_size;
+ int idx = ipos.y * tile_w + ipos.x;
+ state.tiles[idx] = Tile(idx, pos.x, pos.y, w, h, cur_device, Tile::RENDER);
+ tile_list->push_front(idx);
+ cur_tiles++;
+
+ if (cur_tiles == tiles_per_device) {
+ tile_list++;
+ cur_tiles = 0;
+ cur_device++;
+ }
+ }
+ }
+
+ /* Stop as soon as the spiral has reached the center block. */
+ if (block.x == (n - 1) / 2 && block.y == (n - 1) / 2)
+ break;
+
+ /* Advance to next block. */
+ prev_dir = dir;
+ switch (dir) {
+ case DIRECTION_UP:
+ block.y++;
+ if (block.y == (n - i - 1)) {
+ dir = DIRECTION_LEFT;
+ }
+ break;
+ case DIRECTION_LEFT:
+ block.x++;
+ if (block.x == (n - i - 1)) {
+ dir = DIRECTION_DOWN;
+ }
+ break;
+ case DIRECTION_DOWN:
+ block.y--;
+ if (block.y == i) {
+ dir = DIRECTION_RIGHT;
+ }
+ break;
+ case DIRECTION_RIGHT:
+ block.x--;
+ if (block.x == i + 1) {
+ dir = DIRECTION_UP;
+ i++;
+ }
+ break;
+ }
+ }
+ return tile_w * tile_h;
+ }
+
+ int idx = 0;
+ for (int slice = 0; slice < slice_num; slice++) {
+ int slice_y = (image_h / slice_num) * slice;
+ int slice_h = (slice == slice_num - 1) ? image_h - slice * (image_h / slice_num) :
+ image_h / slice_num;
+
+ int tile_h = (tile_size.y >= slice_h) ? 1 : divide_up(slice_h, tile_size.y);
+
+ int tiles_per_device = divide_up(tile_w * tile_h, num);
+ int cur_device = 0, cur_tiles = 0;
+
+ for (int tile_y = 0; tile_y < tile_h; tile_y++) {
+ for (int tile_x = 0; tile_x < tile_w; tile_x++, idx++) {
+ int x = tile_x * tile_size.x;
+ int y = tile_y * tile_size.y;
+ int w = (tile_x == tile_w - 1) ? image_w - x : tile_size.x;
+ int h = (tile_y == tile_h - 1) ? slice_h - y : tile_size.y;
+
+ state.tiles.push_back(
+ Tile(idx, x, y + slice_y, w, h, sliced ? slice : cur_device, Tile::RENDER));
+ tile_list->push_back(idx);
+
+ if (!sliced) {
+ cur_tiles++;
+
+ if (cur_tiles == tiles_per_device) {
+ /* Tiles are already generated in Bottom-to-Top order, so no sort is necessary in that case. */
+ if (tile_order != TILE_BOTTOM_TO_TOP) {
+ tile_list->sort(TileComparator(tile_order, center, &state.tiles[0]));
+ }
+ tile_list++;
+ cur_tiles = 0;
+ cur_device++;
+ }
+ }
+ }
+ }
+ if (sliced) {
+ tile_list++;
+ }
+ }
+
+ return idx;
}
void TileManager::gen_render_tiles()
{
- /* Regenerate just the render tiles for progressive render. */
- foreach(Tile& tile, state.tiles) {
- state.render_tiles[tile.device].push_back(tile.index);
- }
+ /* Regenerate just the render tiles for progressive render. */
+ foreach (Tile &tile, state.tiles) {
+ state.render_tiles[tile.device].push_back(tile.index);
+ }
}
void TileManager::set_tiles()
{
- int resolution = state.resolution_divider;
- int image_w = max(1, params.width/resolution);
- int image_h = max(1, params.height/resolution);
+ int resolution = state.resolution_divider;
+ int image_w = max(1, params.width / resolution);
+ int image_h = max(1, params.height / resolution);
- state.num_tiles = gen_tiles(!background);
+ state.num_tiles = gen_tiles(!background);
- state.buffer.width = image_w;
- state.buffer.height = image_h;
+ state.buffer.width = image_w;
+ state.buffer.height = image_h;
- state.buffer.full_x = params.full_x/resolution;
- state.buffer.full_y = params.full_y/resolution;
- state.buffer.full_width = max(1, params.full_width/resolution);
- state.buffer.full_height = max(1, params.full_height/resolution);
+ state.buffer.full_x = params.full_x / resolution;
+ state.buffer.full_y = params.full_y / resolution;
+ state.buffer.full_width = max(1, params.full_width / resolution);
+ state.buffer.full_height = max(1, params.full_height / resolution);
}
int TileManager::get_neighbor_index(int index, int neighbor)
{
- static const int dx[] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}, dy[] = {-1, -1, -1, 0, 0, 1, 1, 1, 0};
+ static const int dx[] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}, dy[] = {-1, -1, -1, 0, 0, 1, 1, 1, 0};
- int resolution = state.resolution_divider;
- int image_w = max(1, params.width/resolution);
- int image_h = max(1, params.height/resolution);
- int tile_w = (tile_size.x >= image_w)? 1: divide_up(image_w, tile_size.x);
- int tile_h = (tile_size.y >= image_h)? 1: divide_up(image_h, tile_size.y);
+ int resolution = state.resolution_divider;
+ int image_w = max(1, params.width / resolution);
+ int image_h = max(1, params.height / resolution);
+ int tile_w = (tile_size.x >= image_w) ? 1 : divide_up(image_w, tile_size.x);
+ int tile_h = (tile_size.y >= image_h) ? 1 : divide_up(image_h, tile_size.y);
- int nx = state.tiles[index].x/tile_size.x + dx[neighbor], ny = state.tiles[index].y/tile_size.y + dy[neighbor];
- if(nx < 0 || ny < 0 || nx >= tile_w || ny >= tile_h)
- return -1;
+ int nx = state.tiles[index].x / tile_size.x + dx[neighbor],
+ ny = state.tiles[index].y / tile_size.y + dy[neighbor];
+ if (nx < 0 || ny < 0 || nx >= tile_w || ny >= tile_h)
+ return -1;
- return ny*state.tile_stride + nx;
+ return ny * state.tile_stride + nx;
}
/* Checks whether all neighbors of a tile (as well as the tile itself) are at least at state min_state. */
bool TileManager::check_neighbor_state(int index, Tile::State min_state)
{
- if(index < 0 || state.tiles[index].state < min_state) {
- return false;
- }
- for(int neighbor = 0; neighbor < 9; neighbor++) {
- int nindex = get_neighbor_index(index, neighbor);
- /* Out-of-bounds tiles don't matter. */
- if(nindex >= 0 && state.tiles[nindex].state < min_state) {
- return false;
- }
- }
-
- return true;
+ if (index < 0 || state.tiles[index].state < min_state) {
+ return false;
+ }
+ for (int neighbor = 0; neighbor < 9; neighbor++) {
+ int nindex = get_neighbor_index(index, neighbor);
+ /* Out-of-bounds tiles don't matter. */
+ if (nindex >= 0 && state.tiles[nindex].state < min_state) {
+ return false;
+ }
+ }
+
+ return true;
}
/* Returns whether the tile should be written (and freed if no denoising is used) instead of updating. */
bool TileManager::finish_tile(int index, bool &delete_tile)
{
- delete_tile = false;
-
- if(progressive) {
- return true;
- }
-
- switch(state.tiles[index].state) {
- case Tile::RENDER:
- {
- if(!schedule_denoising) {
- state.tiles[index].state = Tile::DONE;
- delete_tile = true;
- return true;
- }
- state.tiles[index].state = Tile::RENDERED;
- /* For each neighbor and the tile itself, check whether all of its neighbors have been rendered. If yes, it can be denoised. */
- for(int neighbor = 0; neighbor < 9; neighbor++) {
- int nindex = get_neighbor_index(index, neighbor);
- if(check_neighbor_state(nindex, Tile::RENDERED)) {
- state.tiles[nindex].state = Tile::DENOISE;
- state.denoising_tiles[state.tiles[nindex].device].push_back(nindex);
- }
- }
- return false;
- }
- case Tile::DENOISE:
- {
- state.tiles[index].state = Tile::DENOISED;
- /* For each neighbor and the tile itself, check whether all of its neighbors have been denoised. If yes, it can be freed. */
- for(int neighbor = 0; neighbor < 9; neighbor++) {
- int nindex = get_neighbor_index(index, neighbor);
- if(check_neighbor_state(nindex, Tile::DENOISED)) {
- state.tiles[nindex].state = Tile::DONE;
- /* It can happen that the tile just finished denoising and already can be freed here.
- * However, in that case it still has to be written before deleting, so we can't delete it yet. */
- if(neighbor == 8) {
- delete_tile = true;
- }
- else {
- delete state.tiles[nindex].buffers;
- state.tiles[nindex].buffers = NULL;
- }
- }
- }
- return true;
- }
- default:
- assert(false);
- return true;
- }
+ delete_tile = false;
+
+ if (progressive) {
+ return true;
+ }
+
+ switch (state.tiles[index].state) {
+ case Tile::RENDER: {
+ if (!schedule_denoising) {
+ state.tiles[index].state = Tile::DONE;
+ delete_tile = true;
+ return true;
+ }
+ state.tiles[index].state = Tile::RENDERED;
+ /* For each neighbor and the tile itself, check whether all of its neighbors have been rendered. If yes, it can be denoised. */
+ for (int neighbor = 0; neighbor < 9; neighbor++) {
+ int nindex = get_neighbor_index(index, neighbor);
+ if (check_neighbor_state(nindex, Tile::RENDERED)) {
+ state.tiles[nindex].state = Tile::DENOISE;
+ state.denoising_tiles[state.tiles[nindex].device].push_back(nindex);
+ }
+ }
+ return false;
+ }
+ case Tile::DENOISE: {
+ state.tiles[index].state = Tile::DENOISED;
+ /* For each neighbor and the tile itself, check whether all of its neighbors have been denoised. If yes, it can be freed. */
+ for (int neighbor = 0; neighbor < 9; neighbor++) {
+ int nindex = get_neighbor_index(index, neighbor);
+ if (check_neighbor_state(nindex, Tile::DENOISED)) {
+ state.tiles[nindex].state = Tile::DONE;
+ /* It can happen that the tile just finished denoising and already can be freed here.
+ * However, in that case it still has to be written before deleting, so we can't delete it yet. */
+ if (neighbor == 8) {
+ delete_tile = true;
+ }
+ else {
+ delete state.tiles[nindex].buffers;
+ state.tiles[nindex].buffers = NULL;
+ }
+ }
+ }
+ return true;
+ }
+ default:
+ assert(false);
+ return true;
+ }
}
-bool TileManager::next_tile(Tile* &tile, int device)
+bool TileManager::next_tile(Tile *&tile, int device)
{
- int logical_device = preserve_tile_device? device: 0;
+ int logical_device = preserve_tile_device ? device : 0;
- if(logical_device >= state.render_tiles.size())
- return false;
+ if (logical_device >= state.render_tiles.size())
+ return false;
- if(!state.denoising_tiles[logical_device].empty()) {
- int idx = state.denoising_tiles[logical_device].front();
- state.denoising_tiles[logical_device].pop_front();
- tile = &state.tiles[idx];
- return true;
- }
+ if (!state.denoising_tiles[logical_device].empty()) {
+ int idx = state.denoising_tiles[logical_device].front();
+ state.denoising_tiles[logical_device].pop_front();
+ tile = &state.tiles[idx];
+ return true;
+ }
- if(state.render_tiles[logical_device].empty())
- return false;
+ if (state.render_tiles[logical_device].empty())
+ return false;
- int idx = state.render_tiles[logical_device].front();
- state.render_tiles[logical_device].pop_front();
- tile = &state.tiles[idx];
- return true;
+ int idx = state.render_tiles[logical_device].front();
+ state.render_tiles[logical_device].pop_front();
+ tile = &state.tiles[idx];
+ return true;
}
bool TileManager::done()
{
- int end_sample = (range_num_samples == -1)
- ? num_samples
- : range_start_sample + range_num_samples;
- return (state.resolution_divider == pixel_size) &&
- (state.sample+state.num_samples >= end_sample);
+ int end_sample = (range_num_samples == -1) ? num_samples :
+ range_start_sample + range_num_samples;
+ return (state.resolution_divider == pixel_size) &&
+ (state.sample + state.num_samples >= end_sample);
}
bool TileManager::next()
{
- if(done())
- return false;
-
- if(progressive && state.resolution_divider > pixel_size) {
- state.sample = 0;
- state.resolution_divider = max(state.resolution_divider/2, pixel_size);
- state.num_samples = 1;
- set_tiles();
- }
- else {
- state.sample++;
-
- if(progressive)
- state.num_samples = 1;
- else if(range_num_samples == -1)
- state.num_samples = num_samples;
- else
- state.num_samples = range_num_samples;
-
- state.resolution_divider = pixel_size;
-
- if(state.sample == range_start_sample) {
- set_tiles();
- }
- else {
- gen_render_tiles();
- }
- }
-
- return true;
+ if (done())
+ return false;
+
+ if (progressive && state.resolution_divider > pixel_size) {
+ state.sample = 0;
+ state.resolution_divider = max(state.resolution_divider / 2, pixel_size);
+ state.num_samples = 1;
+ set_tiles();
+ }
+ else {
+ state.sample++;
+
+ if (progressive)
+ state.num_samples = 1;
+ else if (range_num_samples == -1)
+ state.num_samples = num_samples;
+ else
+ state.num_samples = range_num_samples;
+
+ state.resolution_divider = pixel_size;
+
+ if (state.sample == range_start_sample) {
+ set_tiles();
+ }
+ else {
+ gen_render_tiles();
+ }
+ }
+
+ return true;
}
int TileManager::get_num_effective_samples()
{
- return (range_num_samples == -1) ? num_samples
- : range_num_samples;
+ return (range_num_samples == -1) ? num_samples : range_num_samples;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 2835c793073..017c1af0ead 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -27,131 +27,144 @@ CCL_NAMESPACE_BEGIN
/* Tile */
class Tile {
-public:
- int index;
- int x, y, w, h;
- int device;
- /* RENDER: The tile has to be rendered.
- * RENDERED: The tile has been rendered, but can't be denoised yet (waiting for neighbors).
- * DENOISE: The tile can be denoised now.
- * DENOISED: The tile has been denoised, but can't be freed yet (waiting for neighbors).
- * DONE: The tile is finished and has been freed. */
- typedef enum { RENDER = 0, RENDERED, DENOISE, DENOISED, DONE } State;
- State state;
- RenderBuffers *buffers;
-
- Tile()
- {}
-
- Tile(int index_, int x_, int y_, int w_, int h_, int device_, State state_ = RENDER)
- : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), state(state_), buffers(NULL) {}
+ public:
+ int index;
+ int x, y, w, h;
+ int device;
+ /* RENDER: The tile has to be rendered.
+ * RENDERED: The tile has been rendered, but can't be denoised yet (waiting for neighbors).
+ * DENOISE: The tile can be denoised now.
+ * DENOISED: The tile has been denoised, but can't be freed yet (waiting for neighbors).
+ * DONE: The tile is finished and has been freed. */
+ typedef enum { RENDER = 0, RENDERED, DENOISE, DENOISED, DONE } State;
+ State state;
+ RenderBuffers *buffers;
+
+ Tile()
+ {
+ }
+
+ Tile(int index_, int x_, int y_, int w_, int h_, int device_, State state_ = RENDER)
+ : index(index_), x(x_), y(y_), w(w_), h(h_), device(device_), state(state_), buffers(NULL)
+ {
+ }
};
/* Tile order */
/* Note: this should match enum_tile_order in properties.py */
enum TileOrder {
- TILE_CENTER = 0,
- TILE_RIGHT_TO_LEFT = 1,
- TILE_LEFT_TO_RIGHT = 2,
- TILE_TOP_TO_BOTTOM = 3,
- TILE_BOTTOM_TO_TOP = 4,
- TILE_HILBERT_SPIRAL = 5,
+ TILE_CENTER = 0,
+ TILE_RIGHT_TO_LEFT = 1,
+ TILE_LEFT_TO_RIGHT = 2,
+ TILE_TOP_TO_BOTTOM = 3,
+ TILE_BOTTOM_TO_TOP = 4,
+ TILE_HILBERT_SPIRAL = 5,
};
/* Tile Manager */
class TileManager {
-public:
- BufferParams params;
-
- struct State {
- vector<Tile> tiles;
- int tile_stride;
- BufferParams buffer;
- int sample;
- int num_samples;
- int resolution_divider;
- int num_tiles;
-
- /* Total samples over all pixels: Generally num_samples*num_pixels,
- * but can be higher due to the initial resolution division for previews. */
- uint64_t total_pixel_samples;
-
- /* These lists contain the indices of the tiles to be rendered/denoised and are used
- * when acquiring a new tile for the device.
- * Each list in each vector is for one logical device. */
- vector<list<int> > render_tiles;
- vector<list<int> > denoising_tiles;
- } state;
-
- int num_samples;
-
- TileManager(bool progressive, int num_samples, int2 tile_size, int start_resolution,
- bool preserve_tile_device, bool background, TileOrder tile_order, int num_devices = 1, int pixel_size = 1);
- ~TileManager();
-
- void device_free();
- void reset(BufferParams& params, int num_samples);
- void set_samples(int num_samples);
- bool next();
- bool next_tile(Tile* &tile, int device = 0);
- bool finish_tile(int index, bool& delete_tile);
- bool done();
-
- void set_tile_order(TileOrder tile_order_) { tile_order = tile_order_; }
-
- /* ** Sample range rendering. ** */
-
- /* Start sample in the range. */
- int range_start_sample;
-
- /* Number to samples in the rendering range. */
- int range_num_samples;
-
- /* Get number of actual samples to render. */
- int get_num_effective_samples();
-
- /* Schedule tiles for denoising after they've been rendered. */
- bool schedule_denoising;
-protected:
-
- void set_tiles();
-
- bool progressive;
- int2 tile_size;
- TileOrder tile_order;
- int start_resolution;
- int pixel_size;
- int num_devices;
-
- /* in some cases it is important that the same tile will be returned for the same
- * device it was originally generated for (i.e. viewport rendering when buffer is
- * allocating once for tile and then always used by it)
- *
- * in other cases any tile could be handled by any device (i.e. final rendering
- * without progressive refine)
- */
- bool preserve_tile_device;
-
- /* for background render tiles should exactly match render parts generated from
- * blender side, which means image first gets split into tiles and then tiles are
- * assigning to render devices
- *
- * however viewport rendering expects tiles to be allocated in a special way,
- * meaning image is being sliced horizontally first and every device handles
- * it's own slice
- */
- bool background;
-
- /* Generate tile list, return number of tiles. */
- int gen_tiles(bool sliced);
- void gen_render_tiles();
-
- int get_neighbor_index(int index, int neighbor);
- bool check_neighbor_state(int index, Tile::State state);
+ public:
+ BufferParams params;
+
+ struct State {
+ vector<Tile> tiles;
+ int tile_stride;
+ BufferParams buffer;
+ int sample;
+ int num_samples;
+ int resolution_divider;
+ int num_tiles;
+
+ /* Total samples over all pixels: Generally num_samples*num_pixels,
+ * but can be higher due to the initial resolution division for previews. */
+ uint64_t total_pixel_samples;
+
+ /* These lists contain the indices of the tiles to be rendered/denoised and are used
+ * when acquiring a new tile for the device.
+ * Each list in each vector is for one logical device. */
+ vector<list<int>> render_tiles;
+ vector<list<int>> denoising_tiles;
+ } state;
+
+ int num_samples;
+
+ TileManager(bool progressive,
+ int num_samples,
+ int2 tile_size,
+ int start_resolution,
+ bool preserve_tile_device,
+ bool background,
+ TileOrder tile_order,
+ int num_devices = 1,
+ int pixel_size = 1);
+ ~TileManager();
+
+ void device_free();
+ void reset(BufferParams &params, int num_samples);
+ void set_samples(int num_samples);
+ bool next();
+ bool next_tile(Tile *&tile, int device = 0);
+ bool finish_tile(int index, bool &delete_tile);
+ bool done();
+
+ void set_tile_order(TileOrder tile_order_)
+ {
+ tile_order = tile_order_;
+ }
+
+ /* ** Sample range rendering. ** */
+
+ /* Start sample in the range. */
+ int range_start_sample;
+
+ /* Number to samples in the rendering range. */
+ int range_num_samples;
+
+ /* Get number of actual samples to render. */
+ int get_num_effective_samples();
+
+ /* Schedule tiles for denoising after they've been rendered. */
+ bool schedule_denoising;
+
+ protected:
+ void set_tiles();
+
+ bool progressive;
+ int2 tile_size;
+ TileOrder tile_order;
+ int start_resolution;
+ int pixel_size;
+ int num_devices;
+
+ /* in some cases it is important that the same tile will be returned for the same
+ * device it was originally generated for (i.e. viewport rendering when buffer is
+ * allocating once for tile and then always used by it)
+ *
+ * in other cases any tile could be handled by any device (i.e. final rendering
+ * without progressive refine)
+ */
+ bool preserve_tile_device;
+
+ /* for background render tiles should exactly match render parts generated from
+ * blender side, which means image first gets split into tiles and then tiles are
+ * assigning to render devices
+ *
+ * however viewport rendering expects tiles to be allocated in a special way,
+ * meaning image is being sliced horizontally first and every device handles
+ * it's own slice
+ */
+ bool background;
+
+ /* Generate tile list, return number of tiles. */
+ int gen_tiles(bool sliced);
+ void gen_render_tiles();
+
+ int get_neighbor_index(int index, int neighbor);
+ bool check_neighbor_state(int index, Tile::State state);
};
CCL_NAMESPACE_END
-#endif /* __TILE_H__ */
+#endif /* __TILE_H__ */