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:
-rw-r--r--CMakeLists.txt3
-rw-r--r--intern/cycles/CMakeLists.txt5
-rw-r--r--intern/cycles/blender/addon/ui.py36
-rw-r--r--intern/cycles/blender/blender_mesh.cpp8
-rw-r--r--intern/cycles/blender/blender_object.cpp24
-rw-r--r--intern/cycles/blender/blender_sync.cpp24
-rw-r--r--intern/cycles/blender/blender_sync.h14
-rw-r--r--intern/cycles/device/device.cpp10
-rw-r--r--intern/cycles/device/device_cuda.cpp19
-rw-r--r--intern/cycles/device/device_multi.cpp34
-rw-r--r--intern/cycles/kernel/kernel_emission.h41
-rw-r--r--intern/cycles/kernel/kernel_globals.h4
-rw-r--r--intern/cycles/kernel/kernel_light.h12
-rw-r--r--intern/cycles/kernel/kernel_path.h99
-rw-r--r--intern/cycles/kernel/kernel_shader.h338
-rw-r--r--intern/cycles/kernel/kernel_types.h76
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp249
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h18
-rw-r--r--intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h20
-rw-r--r--intern/cycles/kernel/svm/bsdf_diffuse.h28
-rw-r--r--intern/cycles/kernel/svm/bsdf_microfacet.h84
-rw-r--r--intern/cycles/kernel/svm/bsdf_reflection.h16
-rw-r--r--intern/cycles/kernel/svm/bsdf_refraction.h18
-rw-r--r--intern/cycles/kernel/svm/bsdf_transparent.h14
-rw-r--r--intern/cycles/kernel/svm/bsdf_ward.h30
-rw-r--r--intern/cycles/kernel/svm/bsdf_westin.h44
-rw-r--r--intern/cycles/kernel/svm/emissive.h27
-rw-r--r--intern/cycles/kernel/svm/svm.h40
-rw-r--r--intern/cycles/kernel/svm/svm_bsdf.h106
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h279
-rw-r--r--intern/cycles/kernel/svm/svm_types.h10
-rw-r--r--intern/cycles/kernel/svm/volume.h2
-rw-r--r--intern/cycles/render/light.cpp60
-rw-r--r--intern/cycles/render/mesh.cpp5
-rw-r--r--intern/cycles/render/nodes.cpp13
-rw-r--r--intern/cycles/render/object.cpp12
-rw-r--r--intern/cycles/render/session.cpp2
-rw-r--r--intern/cycles/render/session.h2
-rw-r--r--intern/cycles/render/svm.cpp99
-rw-r--r--intern/cycles/render/svm.h6
-rw-r--r--intern/cycles/render/tile.cpp2
-rw-r--r--intern/cycles/util/util_path.cpp9
-rw-r--r--intern/cycles/util/util_path.h1
43 files changed, 1235 insertions, 708 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 279644550c2..c24817fc672 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -207,11 +207,10 @@ option(WITH_API_INSTALL "Copy API header files into the blender install fold
# Cycles
option(WITH_CYCLES "Enable Cycles Render Engine" ON)
OPTION(WITH_CYCLES_OSL "Build with Open Shading Language support" OFF)
-OPTION(WITH_CYCLES_CUDA "Build with CUDA support" OFF)
+OPTION(WITH_CYCLES_CUDA "Build with CUDA binaries" OFF)
OPTION(WITH_CYCLES_BLENDER "Build Blender Python extension" ON)
OPTION(WITH_CYCLES_PARTIO "Build with Partio point cloud support (unfinished)" OFF)
OPTION(WITH_CYCLES_NETWORK "Build with network rendering support (unfinished)" OFF)
-OPTION(WITH_CYCLES_MULTI "Build with network rendering support (unfinished)" OFF)
OPTION(WITH_CYCLES_TEST "Build cycles test application" OFF)
# disable for now, but plan to support on all platforms eventually
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 05b9d4ad3bb..74bac846aa4 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -41,10 +41,6 @@ if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK)
endif()
-if(WITH_CYCLES_MULTI)
- add_definitions(-DWITH_MULTI)
-endif()
-
if(WITH_CYCLES_CUDA)
add_definitions(-DWITH_CUDA_BINARIES)
endif()
@@ -59,6 +55,7 @@ endif()
add_definitions(-DWITH_OPENCL)
add_definitions(-DWITH_CUDA)
+add_definitions(-DWITH_MULTI)
include_directories(
${BOOST_INCLUDE_DIR}
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index da99e4e23d6..992a698bbdd 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -140,6 +140,42 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(cscene, "debug_bvh_type", text="")
sub.prop(cscene, "debug_use_spatial_splits")
+class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
+ bl_label = "Layers"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+
+ # row = layout.row()
+ # row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
+
+ # col = row.column(align=True)
+ # col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
+ # col.operator("scene.render_layer_remove", icon='ZOOMOUT', text="")
+
+ row = layout.row()
+ # rl = rd.layers.active
+ rl = rd.layers[0]
+ row.prop(rl, "name")
+ #row.prop(rd, "use_single_layer", text="", icon_only=True)
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(scene, "layers", text="Scene")
+
+ col = split.column()
+ col.prop(rl, "layers", text="Layer")
+
+ layout.separator()
+
+ layout.prop(rl, "material_override", text="Material")
+
class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 3fe4fa60a16..f981be66eb4 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -223,8 +223,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
vector<uint> used_shaders;
BL::Object::material_slots_iterator slot;
- for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot)
- find_shader(slot->material(), used_shaders);
+ for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
+ if(render_layer.material_override)
+ find_shader(render_layer.material_override, used_shaders);
+ else
+ find_shader(slot->material(), used_shaders);
+ }
if(used_shaders.size() == 0)
used_shaders.push_back(scene->default_surface);
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index f1ba2dba2f5..e693efb2d7f 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -108,7 +108,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
/* Object */
-void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm)
+void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint visibility)
{
/* light is handled separately */
if(object_is_light(b_ob)) {
@@ -130,7 +130,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
object->name = b_ob.name();
object->tfm = tfm;
- object->visibility = object_ray_visibility(b_ob);
+ object->visibility = object_ray_visibility(b_ob) & visibility;
if(b_parent.ptr.data != b_ob.ptr.data)
object->visibility &= object_ray_visibility(b_parent);
@@ -147,12 +147,8 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
{
/* layer data */
- uint layer;
-
- if(b_v3d)
- layer = get_layer(b_v3d.layers());
- else
- layer = get_layer(b_scene.layers());
+ uint scene_layer = render_layer.scene_layer;
+ uint layer = render_layer.layer;
/* prepare for sync */
light_map.pre_sync();
@@ -165,8 +161,14 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
for(b_scene.objects.begin(b_ob); b_ob != b_scene.objects.end(); ++b_ob) {
bool hide = (b_v3d)? b_ob->hide(): b_ob->hide_render();
+ uint ob_layer = get_layer(b_ob->layers());
+
+ if(!hide && (ob_layer & scene_layer)) {
+ uint visibility = PATH_RAY_ALL;
+
+ if(!(ob_layer & layer))
+ visibility &= ~PATH_RAY_CAMERA;
- if(!hide && get_layer(b_ob->layers()) & layer) {
if(b_ob->is_duplicator()) {
/* dupli objects */
object_create_duplilist(*b_ob, b_scene);
@@ -176,7 +178,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
Transform tfm = get_transform(b_dup->matrix());
- sync_object(*b_ob, b_index, b_dup->object(), tfm);
+ sync_object(*b_ob, b_index, b_dup->object(), tfm, visibility);
b_index++;
}
@@ -185,7 +187,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
else {
/* object itself */
Transform tfm = get_transform(b_ob->matrix_world());
- sync_object(*b_ob, 0, *b_ob, tfm);
+ sync_object(*b_ob, 0, *b_ob, tfm, visibility);
}
}
}
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index ea5d0a1a3c6..b9d35a02a78 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -118,6 +118,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d)
{
sync_integrator();
sync_film();
+ sync_render_layer(b_v3d);
sync_shaders();
sync_objects(b_v3d);
}
@@ -172,6 +173,29 @@ void BlenderSync::sync_film()
filter->tag_update(scene);
}
+/* Render Layer */
+
+void BlenderSync::sync_render_layer(BL::SpaceView3D b_v3d)
+{
+ if(b_v3d) {
+ render_layer.scene_layer = get_layer(b_v3d.layers());
+ render_layer.layer = render_layer.scene_layer;
+ render_layer.material_override = PointerRNA_NULL;
+ }
+ else {
+ BL::RenderSettings r = b_scene.render();
+ BL::RenderSettings::layers_iterator b_rlay;
+
+ for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
+ render_layer.scene_layer = get_layer(b_scene.layers());
+ render_layer.layer = get_layer(b_rlay->layers());
+ render_layer.material_override = b_rlay->material_override();
+
+ break; /* single layer for now */
+ }
+ }
+}
+
/* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene b_scene)
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index fe60f42bc75..48e755b3dcd 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -72,11 +72,12 @@ private:
void sync_integrator();
void sync_view();
void sync_world();
+ void sync_render_layer(BL::SpaceView3D b_v3d);
void sync_shaders();
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
- void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm);
+ void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint visibility);
void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
/* util */
@@ -99,6 +100,17 @@ private:
Scene *scene;
bool preview;
+
+ struct RenderLayerInfo {
+ RenderLayerInfo()
+ : scene_layer(0), layer(0),
+ material_override(PointerRNA_NULL)
+ {}
+
+ uint scene_layer;
+ uint layer;
+ BL::Material material_override;
+ } render_layer;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index e21dce45d80..ab57d7cfe86 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -84,7 +84,7 @@ void Device::pixels_alloc(device_memory& mem)
void Device::pixels_copy_from(device_memory& mem, int y, int w, int h)
{
- mem_copy_from(mem, sizeof(uchar)*4*y*w, sizeof(uchar)*4*w*h);
+ mem_copy_from(mem, sizeof(uint8_t)*4*y*w, sizeof(uint8_t)*4*w*h);
}
void Device::pixels_free(device_memory& mem)
@@ -104,7 +104,13 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int width, in
glPixelZoom((float)width/(float)w, (float)height/(float)h);
glRasterPos2f(0, y);
- glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)rgba.data_pointer);
+ uint8_t *pixels = (uint8_t*)rgba.data_pointer;
+
+ /* for multi devices, this assumes the ineffecient method that we allocate
+ all pixels on the device even though we only render to a subset */
+ pixels += sizeof(uint8_t)*4*y*w;
+
+ glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glRasterPos2f(0.0f, 0.0f);
glPixelZoom(1.0f, 1.0f);
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 49ffd3d0834..7fc0afce1ac 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -232,11 +232,16 @@ public:
double starttime = time_dt();
printf("Compiling CUDA kernel ...\n");
+ path_create_directories(cubin);
+
string command = string_printf("%s -arch=sm_%d%d -m%d --cubin \"%s\" --use_fast_math "
"-o \"%s\" --ptxas-options=\"-v\" --maxrregcount=%d --opencc-options -OPT:Olimit=0 -I\"%s\" -DNVCC",
nvcc.c_str(), major, minor, machine, kernel.c_str(), cubin.c_str(), maxreg, include.c_str());
- system(command.c_str());
+ if(system(command.c_str()) == -1) {
+ fprintf(stderr, "Failed to execute compilation command.\n");
+ return "";
+ }
/* verify if compilation succeeded */
if(!path_exists(cubin)) {
@@ -708,9 +713,13 @@ public:
cuda_push_context();
+ /* for multi devices, this assumes the ineffecient method that we allocate
+ all pixels on the device even though we only render to a subset */
+ size_t offset = sizeof(uint8_t)*4*y*w;
+
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pmem.cuPBO);
glBindTexture(GL_TEXTURE_2D, pmem.cuTexId);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (void*)offset);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glEnable(GL_TEXTURE_2D);
@@ -729,11 +738,11 @@ public:
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.0f);
- glTexCoord2f((float)w/(float)width, 0);
+ glTexCoord2f((float)w/(float)pmem.w, 0.0f);
glVertex2f((float)width, 0.0f);
- glTexCoord2f((float)w/(float)width, (float)h/(float)height);
+ glTexCoord2f((float)w/(float)pmem.w, (float)h/(float)pmem.h);
glVertex2f((float)width, (float)height);
- glTexCoord2f(0.0f, (float)h/(float)height);
+ glTexCoord2f(0.0f, (float)h/(float)pmem.h);
glVertex2f(0.0f, (float)height);
glEnd();
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index cae63596d3b..f2f6251685e 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -47,9 +47,6 @@ public:
MultiDevice(bool background_)
: unique_ptr(1)
{
- /* enforce background for now */
- background = true;
-
Device *device;
/* add CPU device */
@@ -125,6 +122,15 @@ public:
return desc.str();
}
+ bool load_kernels()
+ {
+ foreach(SubDevice& sub, devices)
+ if(!sub.device->load_kernels())
+ return false;
+
+ return true;
+ }
+
void mem_alloc(device_memory& mem, MemoryType type)
{
foreach(SubDevice& sub, devices) {
@@ -219,12 +225,26 @@ public:
void pixels_alloc(device_memory& mem)
{
- Device::pixels_alloc(mem);
+ foreach(SubDevice& sub, devices) {
+ mem.device_pointer = 0;
+ sub.device->pixels_alloc(mem);
+ sub.ptr_map[unique_ptr] = mem.device_pointer;
+ }
+
+ mem.device_pointer = unique_ptr++;
}
void pixels_free(device_memory& mem)
{
- Device::pixels_free(mem);
+ device_ptr tmp = mem.device_pointer;
+
+ foreach(SubDevice& sub, devices) {
+ mem.device_pointer = sub.ptr_map[tmp];
+ sub.device->pixels_free(mem);
+ sub.ptr_map.erase(sub.ptr_map.find(tmp));
+ }
+
+ mem.device_pointer = 0;
}
void pixels_copy_from(device_memory& mem, int y, int w, int h)
@@ -248,14 +268,16 @@ public:
{
device_ptr tmp = rgba.device_pointer;
int i = 0, sub_h = h/devices.size();
+ int sub_height = height/devices.size();
foreach(SubDevice& sub, devices) {
int sy = y + i*sub_h;
int sh = (i == (int)devices.size() - 1)? h - sub_h*i: sub_h;
+ int sheight = (i == (int)devices.size() - 1)? height - sub_height*i: sub_height;
/* adjust math for w/width */
rgba.device_pointer = sub.ptr_map[tmp];
- sub.device->draw_pixels(rgba, sy, w, sh, width, height, transparent);
+ sub.device->draw_pixels(rgba, sy, w, sh, width, sheight, transparent);
i++;
}
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 6b6033e9ebd..58c9183e58a 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -46,20 +46,29 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
return eval;
}
-__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, float rando,
- float randu, float randv, Ray *ray, float3 *eval)
+__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
+ float randt, float rando, float randu, float randv, Ray *ray, float3 *eval)
{
- /* sample a position on a light */
LightSample ls;
- light_sample(kg, randt, randu, randv, sd->P, &ls);
+#ifdef __MULTI_LIGHT__
+ if(lindex != -1) {
+ /* sample position on a specified light */
+ light_select(kg, lindex, randu, randv, sd->P, &ls);
+ }
+ else
+#endif
+ {
+ /* sample a light and position on int */
+ light_sample(kg, randt, randu, randv, sd->P, &ls);
+ }
/* compute incoming direction and distance */
float t;
float3 omega_in = normalize_len(ls.P - sd->P, &t);
/* compute pdf */
- float pdf = light_pdf(kg, &ls, -omega_in, t);
+ float pdf = light_sample_pdf(kg, &ls, -omega_in, t);
/* evaluate closure */
*eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -omega_in);
@@ -67,6 +76,8 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, fl
if(is_zero(*eval) || pdf == 0.0f)
return false;
+ /* todo: use visbility flag to skip lights */
+
/* evaluate BSDF at shading point */
float bsdf_pdf;
float3 bsdf_eval = shader_bsdf_eval(kg, sd, omega_in, &bsdf_pdf);
@@ -88,10 +99,22 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, fl
*eval *= 0.25f;
}
- /* setup ray */
- ray->P = ray_offset(sd->P, sd->Ng);
- ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
- ray->D = normalize_len(ray->D, &ray->t);
+#if 0
+ /* todo: implement this in light */
+ bool no_shadow = true;
+
+ if(no_shadow) {
+ ray->t = 0.0f;
+ }
+ else {
+#endif
+ /* setup ray */
+ ray->P = ray_offset(sd->P, sd->Ng);
+ ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
+ ray->D = normalize_len(ray->D, &ray->t);
+#if 0
+ }
+#endif
return true;
}
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index f37b27cc9f4..a1b23128b38 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -20,7 +20,7 @@
#ifdef __KERNEL_CPU__
-#ifdef WITH_OSL
+#ifdef __OSL__
#include "osl_globals.h"
#endif
@@ -43,7 +43,7 @@ typedef struct KernelGlobals {
KernelData __data;
-#ifdef WITH_OSL
+#ifdef __OSL__
/* On the CPU, we also have the OSL globals here. Most data structures are shared
with SVM, the difference is in the shaders and object/mesh attributes. */
OSLGlobals osl;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 5164e5deea2..77e73e932ef 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -129,7 +129,7 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
}
}
-__device float light_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
+__device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
{
float pdf;
@@ -141,5 +141,15 @@ __device float light_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
return pdf;
}
+__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls)
+{
+ point_light_sample(kg, index, randu, randv, P, ls);
+}
+
+__device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
+{
+ return point_light_pdf(kg, t);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index b073cd49a8c..815eb4a1d53 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -162,6 +162,86 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
return average(throughput);
}
+#ifdef __TRANSPARENT_SHADOWS__
+__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
+{
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+ int shader = __float_as_int(Ns.w);
+
+ /* todo: add shader flag to check this */
+
+ return true;
+}
+#endif
+
+__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L)
+{
+ if(ray->t == 0.0f)
+ return false;
+
+ bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW, isect);
+
+#ifdef __TRANSPARENT_SHADOWS__
+ if(result && kernel_data.integrator.transparent_shadows) {
+ /* transparent shadows work in such a way to try to minimize overhead
+ in cases where we don't need them. after a regular shadow ray is
+ cast we check if the hit primitive was potentially transparent, and
+ only in that case start marching. this gives on extra ray cast for
+ the cases were we do want transparency */
+ if(shader_transparent_shadow(kg, isect)) {
+ /* todo: fix double contribution from indirect for triangle lights */
+ /* if(kernel_data.integrator.transparent_shadows && (path_flag & PATH_RAY_TRANSPARENT)) */
+
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D*ray->t;
+ int bounce = state->transparent_bounce;
+
+ for(;;) {
+ if(bounce >= kernel_data.integrator.transparent_max_bounce) {
+ return true;
+ }
+ else if(bounce >= kernel_data.integrator.transparent_min_bounce) {
+ /* todo: get random number somewhere for probabilistic terminate */
+#if 0
+ float probability = average(throughput);
+ float terminate = 0.0f; /* todo: get this random number */
+
+ if(terminate >= probability)
+ return true;
+
+ throughput /= probability;
+#endif
+ }
+
+ /* todo: fix it so we get first hit */
+ if(!scene_intersect(kg, ray, PATH_RAY_SHADOW, isect)) {
+ *light_L *= throughput;
+ return false;
+ }
+ if(!shader_transparent_shadow(kg, isect))
+ return true;
+
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, isect, ray);
+ shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW); /* todo: state flag? */
+
+ throughput *= shader_bsdf_transparency(kg, &sd);
+
+ ray->P = ray_offset(sd.P, -sd.Ng);
+ ray->t = len(Pend - ray->P);
+
+ bounce++;
+ }
+
+ return true;
+ }
+ }
+#endif
+
+ return result;
+}
+
__device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
{
/* initialize */
@@ -247,13 +327,22 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
Ray light_ray;
float3 light_L;
- /* todo: use visbility flag to skip lights */
+#ifdef __MULTI_LIGHT__
+ /* index -1 means randomly sample from distribution */
+ int i = (kernel_data.integrator.num_distribution)? -1: 0;
- if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
- /* trace shadow ray */
- if(!scene_intersect(kg, &light_ray, PATH_RAY_SHADOW, &isect))
- L += throughput*light_L;
+ for(; i < kernel_data.integrator.num_all_lights; i++) {
+#else
+ const int i = -1;
+#endif
+ if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
+ /* trace shadow ray */
+ if(!shadow_blocked(kg, &state, &light_ray, &isect, &light_L))
+ L += throughput*light_L;
+ }
+#ifdef __MULTI_LIGHT__
}
+#endif
}
}
#endif
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 92d920b5c61..0cf2091590c 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -26,14 +26,19 @@
*
*/
+
+#ifdef __OSL__
+
+#include "osl_shader.h"
+
+#else
+
#include "svm/bsdf.h"
#include "svm/emissive.h"
#include "svm/volume.h"
#include "svm/svm_bsdf.h"
#include "svm/svm.h"
-#ifdef WITH_OSL
-#include "osl_shader.h"
#endif
CCL_NAMESPACE_BEGIN
@@ -270,96 +275,201 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
/* BSDF */
-__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
- float randu, float randv, float3 *eval,
- float3 *omega_in, differential3 *domega_in, float *pdf)
+#ifdef __MULTI_CLOSURE__
+
+__device_inline float3 _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
+ int skip_bsdf, float3 sum_eval, float sum_pdf, float sum_sample_weight)
{
- int label;
+ for(int i = 0; i< sd->num_closure; i++) {
+ if(i == skip_bsdf)
+ continue;
- *pdf = 0.0f;
+ const ShaderClosure *sc = &sd->closure[i];
-#ifdef WITH_OSL
- if(kg->osl.use)
- label = OSLShader::bsdf_sample(sd, randu, randv, *eval, *omega_in, *domega_in, *pdf);
- else
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ float bsdf_pdf = 0.0f;
+#ifdef __OSL__
+ float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf);
+#else
+ float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
#endif
- label = svm_bsdf_sample(sd, randu, randv, eval, omega_in, domega_in, pdf);
- return label;
+ if(bsdf_pdf != 0.0f) {
+ sum_eval += eval*sc->weight;
+ sum_pdf += bsdf_pdf*sc->sample_weight;
+ }
+
+ sum_sample_weight += sc->sample_weight;
+ }
+ }
+
+ *pdf = sum_pdf/sum_sample_weight;
+ return sum_eval;
}
+#endif
+
__device float3 shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
const float3 omega_in, float *pdf)
{
- float3 eval;
-
+#ifdef __MULTI_CLOSURE__
+ return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, make_float3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f);
+#else
+ const ShaderClosure *sc = &sd->closure;
*pdf = 0.0f;
+ return svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight;
+#endif
+}
-#ifdef WITH_OSL
- if(kg->osl.use)
- eval = OSLShader::bsdf_eval(sd, omega_in, *pdf);
- else
+__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
+ float randu, float randv, float3 *eval,
+ float3 *omega_in, differential3 *domega_in, float *pdf)
+{
+#ifdef __MULTI_CLOSURE__
+ int sampled = 0;
+
+ if(sd->num_closure > 1) {
+ /* pick a BSDF closure based on sample weights */
+ float sum = 0.0f;
+
+ for(sampled = 0; sampled < sd->num_closure; sampled++) {
+ const ShaderClosure *sc = &sd->closure[sampled];
+
+ if(CLOSURE_IS_BSDF(sc->type))
+ sum += sc->sample_weight;
+ }
+
+ float r = sd->randb_closure*sum;
+ sum = 0.0f;
+
+ for(sampled = 0; sampled < sd->num_closure; sampled++) {
+ const ShaderClosure *sc = &sd->closure[sampled];
+
+ if(CLOSURE_IS_BSDF(sc->type)) {
+ sum += sd->closure[sampled].sample_weight;
+
+ if(r <= sum)
+ break;
+ }
+ }
+
+ if(sampled == sd->num_closure) {
+ *pdf = 0.0f;
+ return LABEL_NONE;
+ }
+ }
+
+ const ShaderClosure *sc = &sd->closure[sampled];
+ int label;
+
+ *pdf = 0.0f;
+#ifdef __OSL__
+ label = OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
+#else
+ label = svm_bsdf_sample(sd, sc, randu, randv, eval, omega_in, domega_in, pdf);
#endif
- eval = svm_bsdf_eval(sd, omega_in, pdf);
- return eval;
+ *eval *= sc->weight;
+
+ if(sd->num_closure > 1 && *pdf != 0.0f) {
+ float sweight = sc->sample_weight;
+ *eval = _shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, *eval, *pdf*sweight, sweight);
+ }
+
+ return label;
+#else
+ /* sample the single closure that we picked */
+ *pdf = 0.0f;
+ int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, eval, omega_in, domega_in, pdf);
+ *eval *= sd->closure.weight;
+ return label;
+#endif
}
__device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
{
-#ifdef WITH_OSL
- if(!kg->osl.use)
+#ifndef __OSL__
+#ifdef __MULTI_CLOSURE__
+ for(int i = 0; i< sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BSDF(sc->type))
+ svm_bsdf_blur(sc, roughness);
+ }
+#else
+ svm_bsdf_blur(&sd->closure, roughness);
+#endif
#endif
- svm_bsdf_blur(sd, roughness);
}
-/* Emission */
-
-__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
+__device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- return OSLShader::emissive_eval(sd);
+#ifdef __MULTI_CLOSURE__
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i< sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // XXX osl
+ eval += sc->weight;
}
+
+ return eval;
+#else
+ if(sd->closure.type == CLOSURE_BSDF_TRANSPARENT_ID)
+ return sd->closure.weight;
else
+ return make_float3(0.0f, 0.0f, 0.0f);
#endif
- {
- return svm_emissive_eval(sd);
- }
}
-__device void shader_emissive_sample(KernelGlobals *kg, ShaderData *sd,
- float randu, float randv, float3 *eval, float3 *I, float *pdf)
+
+/* Emission */
+
+__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- OSLShader::emissive_sample(sd, randu, randv, eval, I, pdf);
- }
- else
+#ifdef __MULTI_CLOSURE__
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_EMISSION(sc->type)) {
+#ifdef __OSL__
+ eval += OSLShader::emissive_eval(sd)*sc->weight;
+#else
+ eval += svm_emissive_eval(sd, sc)*sc->weight;
#endif
- {
- svm_emissive_sample(sd, randu, randv, eval, I, pdf);
+ }
}
+
+ return eval;
+#else
+ return svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
+#endif
}
/* Holdout */
__device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- return OSLShader::holdout_eval(sd);
+#ifdef __MULTI_CLOSURE__
+ float3 weight = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_HOLDOUT(sc->type))
+ weight += sc->weight;
}
- else
-#endif
- {
-#ifdef __SVM__
- if(sd->svm_closure == CLOSURE_HOLDOUT_ID)
- return make_float3(1.0f, 1.0f, 1.0f);
- else
+
+ return weight;
+#else
+ if(sd->closure.type == CLOSURE_HOLDOUT_ID)
+ return make_float3(1.0f, 1.0f, 1.0f);
+
+ return make_float3(0.0f, 0.0f, 0.0f);
#endif
- return make_float3(0.0f, 0.0f, 0.0f);
- }
}
/* Surface Evaluation */
@@ -367,54 +477,54 @@ __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
__device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
float randb, int path_flag)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- OSLShader::eval_surface(kg, sd, randb, path_flag);
- }
- else
-#endif
- {
+#ifdef __OSL__
+ OSLShader::eval_surface(kg, sd, randb, path_flag);
+#else
+
#ifdef __SVM__
- svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
+ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
#else
- bsdf_diffuse_setup(sd, sd->N);
- sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
+ bsdf_diffuse_setup(sd, &sd->closure);
+ sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f);
#endif
-#ifdef __CAUSTICS_TRICKS__
- /* caustic tricks */
- if((path_flag & PATH_RAY_DIFFUSE) && (sd->flag & SD_BSDF_GLOSSY)) {
- if(kernel_data.integrator.no_caustics) {
- sd->flag &= ~(SD_BSDF_GLOSSY|SD_BSDF_HAS_EVAL|SD_EMISSION);
- sd->svm_closure = NBUILTIN_CLOSURES;
- sd->svm_closure_weight = make_float3(0.0f, 0.0f, 0.0f);
- }
- else if(kernel_data.integrator.blur_caustics > 0.0f)
- shader_bsdf_blur(kg, sd, kernel_data.integrator.blur_caustics);
- }
#endif
- }
}
/* Background Evaluation */
__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- return OSLShader::eval_background(kg, sd, path_flag);
+#ifdef __OSL__
+ return OSLShader::eval_background(kg, sd, path_flag);
+#else
+
+#ifdef __SVM__
+ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
+
+#ifdef __MULTI_CLOSURE__
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i< sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_BACKGROUND(sc->type))
+ eval += sc->weight;
}
+
+ return eval;
+#else
+ if(sd->closure.type == CLOSURE_BACKGROUND_ID)
+ return sd->closure.weight;
else
+ return make_float3(0.8f, 0.8f, 0.8f);
#endif
- {
-#ifdef __SVM__
- svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
+
#else
- sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
+ return make_float3(0.8f, 0.8f, 0.8f);
#endif
- return sd->svm_closure_weight;
- }
+#endif
}
/* Volume */
@@ -422,15 +532,25 @@ __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int pa
__device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
float3 omega_in, float3 omega_out)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- OSLShader::volume_eval_phase(sd, omega_in, omega_out);
- }
- else
+#ifdef __MULTI_CLOSURE__
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i< sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_VOLUME(sc->type)) {
+#ifdef __OSL__
+ eval += OSLShader::volume_eval_phase(sd, omega_in, omega_out);
+#else
+ eval += volume_eval_phase(sd, sc, omega_in, omega_out);
#endif
- {
- return volume_eval_phase(sd, omega_in, omega_out);
+ }
}
+
+ return eval;
+#else
+ return volume_eval_phase(sd, &sd->closure, omega_in, omega_out);
+#endif
}
/* Volume Evaluation */
@@ -438,17 +558,13 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
__device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
float randb, int path_flag)
{
-#ifdef WITH_OSL
- if(kg->osl.use) {
- OSLShader::eval_volume(kg, sd, randb, path_flag);
- }
- else
-#endif
- {
#ifdef __SVM__
- svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
+#ifdef __OSL__
+ OSLShader::eval_volume(kg, sd, randb, path_flag);
+#else
+ svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
+#endif
#endif
- }
}
/* Displacement Evaluation */
@@ -456,27 +572,21 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
{
/* this will modify sd->P */
-
-#ifdef WITH_OSL
- if(kg->osl.use) {
- OSLShader::eval_displacement(kg, sd);
- }
- else
-#endif
- {
#ifdef __SVM__
- svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
+#ifdef __OSL__
+ OSLShader::eval_displacement(kg, sd);
+#else
+ svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
+#endif
#endif
- }
}
/* Free ShaderData */
__device void shader_release(KernelGlobals *kg, ShaderData *sd)
{
-#ifdef WITH_OSL
- if(kg->osl.use)
- OSLShader::release(kg, sd);
+#ifdef __OSL__
+ OSLShader::release(kg, sd);
#endif
}
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 1417f2d5110..d3012324739 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -34,6 +34,9 @@ CCL_NAMESPACE_BEGIN
#define __BACKGROUND__
#define __CAUSTICS_TRICKS__
#define __VISIBILITY_FLAG__
+#define __RAY_DIFFERENTIALS__
+#define __CAMERA_CLIPPING__
+#define __INTERSECTION_REFINE__
#ifndef __KERNEL_OPENCL__
#define __SVM__
@@ -42,9 +45,13 @@ CCL_NAMESPACE_BEGIN
#define __HOLDOUT__
#endif
-#define __RAY_DIFFERENTIALS__
-#define __CAMERA_CLIPPING__
-#define __INTERSECTION_REFINE__
+#ifdef __KERNEL_CPU__
+//#define __MULTI_CLOSURE__
+//#define __MULTI_LIGHT__
+//#define __TRANSPARENT_SHADOWS__
+//#define __OSL__
+#endif
+
//#define __SOBOL_FULL_SCREEN__
//#define __MODIFY_TP__
//#define __QBVH__
@@ -179,20 +186,27 @@ typedef enum AttributeElement {
ATTR_ELEMENT_NONE
} AttributeElement;
-/* OSL data */
+/* Closure data */
-#if !defined(__KERNEL_GPU__) && defined(WITH_OSL)
+#define MAX_CLOSURE 8
-#define MAX_OSL_CLOSURE 8
-
-struct FlatClosure {
- void *prim;
+typedef struct ShaderClosure {
+ ClosureType type;
float3 weight;
+
+#ifdef __MULTI_CLOSURE__
float sample_weight;
-};
+#endif
+#ifdef __OSL__
+ void *prim;
+#else
+ float data0;
+ float data1;
#endif
+} ShaderClosure;
+
/* Shader Data
*
* Main shader state at a point on the surface or in a volume. All coordinates
@@ -244,34 +258,18 @@ typedef struct ShaderData {
float3 dPdu, dPdv;
#endif
- /* SVM closure data. we always sample a single closure, to get fixed
- * memory usage, svm_closure_data contains closure parameters. */
- ClosureType svm_closure;
- float3 svm_closure_weight;
- float svm_closure_data0;
- float svm_closure_data1;
-
-#if !defined(__KERNEL_GPU__) && defined(WITH_OSL)
- /* OSL closure data and context. we store all closures flattened into
- * lists per type, different from SVM. */
- struct {
- FlatClosure bsdf[MAX_OSL_CLOSURE];
- FlatClosure emissive[MAX_OSL_CLOSURE];
- FlatClosure volume[MAX_OSL_CLOSURE];
-
- int num_bsdf;
- int num_emissive;
- int num_volume;
-
- float bsdf_sample_sum;
- float emissive_sample_sum;
- float volume_sample_sum;
-
- float3 holdout_weight;
-
- float randb;
- } osl_closure;
+#ifdef __MULTI_CLOSURE__
+ /* Closure data, we store a fixed array of closures */
+ ShaderClosure closure[MAX_CLOSURE];
+ int num_closure;
+ float randb_closure;
+#else
+ /* Closure data, with a single sampled closure for low memory usage */
+ ShaderClosure closure;
+#endif
+#ifdef __OSL__
+ /* OSL context */
void *osl_ctx;
#endif
} ShaderData;
@@ -352,11 +350,11 @@ typedef struct KernelSunSky {
typedef struct KernelIntegrator {
/* emission */
int use_emission;
- int num_triangles;
int num_distribution;
- int num_lights;
+ int num_all_lights;
float pdf_triangles;
float pdf_lights;
+ float pdf_pad;
/* bounces */
int min_bounce;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 73ff4f41423..3f0b1610181 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -119,13 +119,13 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if(prim) {
- FlatClosure flat;
- flat.prim = prim;
- flat.weight = weight;
+ ShaderClosure sc;
+ sc.prim = prim;
+ sc.weight = weight;
switch(prim->category()) {
case ClosurePrimitive::BSDF: {
- if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+ if(sd->num_closure == MAX_CLOSURE)
return;
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim;
@@ -140,7 +140,8 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
float sample_weight = fabsf(average(weight))*albedo;
float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight;
- flat.sample_weight = sample_weight;
+ sc.sample_weight = sample_weight;
+ sc.type = CLOSURE_BSDF_ID;
sd->osl_closure.bsdf_sample_sum = sample_sum;
/* scattering flags */
@@ -152,29 +153,35 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->flag |= SD_BSDF;
/* add */
- sd->osl_closure.bsdf[sd->osl_closure.num_bsdf++] = flat;
+ sd->closure[sd->num_closure++] = sc;
break;
}
case ClosurePrimitive::Emissive: {
- if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+ if(sd->num_closure == MAX_CLOSURE)
return;
/* sample weight */
float sample_weight = fabsf(average(weight));
float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight;
- flat.sample_weight = sample_weight;
+ sc.sample_weight = sample_weight;
+ sc.type = CLOSURE_EMISSION_ID;
sd->osl_closure.emissive_sample_sum = sample_sum;
/* flag */
sd->flag |= SD_EMISSION;
- sd->osl_closure.emissive[sd->osl_closure.num_emissive++] = flat;
+ sd->closure[sd->num_closure++] = sc;
break;
}
case ClosurePrimitive::Holdout:
- sd->osl_closure.holdout_weight += weight;
+ if(sd->num_closure == MAX_CLOSURE)
+ return;
+
+ sc.sample_weight = 0.0f;
+ sc.type = CLOSURE_HOLDOUT_ID;
sd->flag |= SD_HOLDOUT;
+ sd->closure[sd->num_closure++] = sc;
break;
case ClosurePrimitive::BSSRDF:
case ClosurePrimitive::Debug:
@@ -213,12 +220,8 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
/* flatten closure tree */
- sd->osl_closure.bsdf_sample_sum = 0.0f;
- sd->osl_closure.emissive_sample_sum = 0.0f;
- sd->osl_closure.num_bsdf = 0;
- sd->osl_closure.num_emissive = 0;
- sd->osl_closure.holdout_weight = make_float3(0.0f, 0.0f, 0.0f);
- sd->osl_closure.randb = randb;
+ sd->num_closure = 0;
+ sd->randb_closure = randb;
if(globals->Ci) {
bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
@@ -292,24 +295,25 @@ static void flatten_volume_closure_tree(ShaderData *sd,
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if(prim) {
- FlatClosure flat;
- flat.prim = prim;
- flat.weight = weight;
+ ShaderClosure sc;
+ sc.prim = prim;
+ sc.weight = weight;
switch(prim->category()) {
case ClosurePrimitive::Volume: {
- if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE)
+ if(sd->num_closure == MAX_CLOSURE)
return;
/* sample weight */
float sample_weight = fabsf(average(weight));
float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight;
- flat.sample_weight = sample_weight;
+ sc.sample_weight = sample_weight;
+ sc.type = CLOSURE_VOLUME_ID;
sd->osl_closure.volume_sample_sum = sample_sum;
/* add */
- sd->osl_closure.volume[sd->osl_closure.num_volume++] = flat;
+ sd->closure[sd->num_closure++] = sc;
break;
}
case ClosurePrimitive::Holdout:
@@ -389,183 +393,76 @@ void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
/* BSDF Closure */
-int OSLShader::bsdf_sample(const ShaderData *sd, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
+int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
{
- OSL::BSDFClosure *sample_bsdf = NULL;
+ OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure*)sc->prim;
int label = LABEL_NONE;
- float r = sd->osl_closure.randb*sd->osl_closure.bsdf_sample_sum;
- float sample_sum = 0.0f;
pdf = 0.0f;
- if(sd->osl_closure.bsdf_sample_sum == 0.0f)
- return LABEL_NONE;
-
- /* find a closure to sample */
- for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
- const FlatClosure *flat = &sd->osl_closure.bsdf[i];
- sample_sum += flat->sample_weight;
-
- if(r > sample_sum)
- continue;
-
- /* sample BSDF closure */
- sample_bsdf = (OSL::BSDFClosure*)flat->prim;
- ustring ulabel;
-
- ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
- TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
- randu, randv,
- TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
- pdf, TO_COLOR3(eval));
-
- /* convert OSL label */
- if(ulabel == OSL::Labels::REFLECT)
- label = LABEL_REFLECT;
- else if(ulabel == OSL::Labels::TRANSMIT)
- label = LABEL_TRANSMIT;
- else
- return LABEL_NONE; /* sampling failed */
-
- /* convert scattering to our bitflag label */
- ustring uscattering = sample_bsdf->scattering();
-
- if(uscattering == OSL::Labels::DIFFUSE)
- label |= LABEL_DIFFUSE;
- else if(uscattering == OSL::Labels::GLOSSY)
- label |= LABEL_GLOSSY;
- else if(uscattering == OSL::Labels::SINGULAR)
- label |= LABEL_SINGULAR;
- else
- label |= LABEL_TRANSPARENT;
-
- /* eval + pdf */
- eval *= flat->weight;
- pdf *= flat->sample_weight;
-
- break;
- }
-
- if(!sample_bsdf || pdf == 0.0f)
- return LABEL_NONE;
-
- /* add eval/pdf from other BSDF closures */
- for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
- const FlatClosure *flat = &sd->osl_closure.bsdf[i];
- OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
-
- if(bsdf != sample_bsdf) {
- OSL::Color3 bsdf_eval;
- float bsdf_pdf = 0.0f;
-
- if(dot(sd->Ng, omega_in) >= 0.0f)
- bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
- else
- bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
-
- if(bsdf_pdf != 0.0f) {
- eval += TO_FLOAT3(bsdf_eval)*flat->weight;
- pdf += bsdf_pdf*flat->sample_weight;
- }
- }
- }
-
- pdf *= 1.0f/(sd->osl_closure.bsdf_sample_sum);
+ /* sample BSDF closure */
+ ustring ulabel;
+
+ ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
+ TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
+ randu, randv,
+ TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
+ pdf, TO_COLOR3(eval));
+
+ /* convert OSL label */
+ if(ulabel == OSL::Labels::REFLECT)
+ label = LABEL_REFLECT;
+ else if(ulabel == OSL::Labels::TRANSMIT)
+ label = LABEL_TRANSMIT;
+ else
+ return LABEL_NONE; /* sampling failed */
+
+ /* convert scattering to our bitflag label */
+ ustring uscattering = sample_bsdf->scattering();
+
+ if(uscattering == OSL::Labels::DIFFUSE)
+ label |= LABEL_DIFFUSE;
+ else if(uscattering == OSL::Labels::GLOSSY)
+ label |= LABEL_GLOSSY;
+ else if(uscattering == OSL::Labels::SINGULAR)
+ label |= LABEL_SINGULAR;
+ else
+ label |= LABEL_TRANSPARENT;
return label;
}
-float3 OSLShader::bsdf_eval(const ShaderData *sd, const float3& omega_in, float& pdf)
+float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
-
- pdf = 0.0f;
-
- for(int i = 0; i < sd->osl_closure.num_bsdf; i++) {
- const FlatClosure *flat = &sd->osl_closure.bsdf[i];
- OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
- OSL::Color3 bsdf_eval;
- float bsdf_pdf = 0.0f;
-
- if(dot(sd->Ng, omega_in) >= 0.0f)
- bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
- else
- bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), bsdf_pdf);
-
- if(bsdf_pdf != 0.0f) {
- eval += TO_FLOAT3(bsdf_eval)*flat->weight;
- pdf += bsdf_pdf*flat->sample_weight;
- }
- }
-
- pdf *= 1.0f/sd->osl_closure.bsdf_sample_sum;
+ OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim;
+ OSL::Color3 bsdf_eval;
- return eval;
+ if(dot(sd->Ng, omega_in) >= 0.0f)
+ bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
+ else
+ bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
+
+ return TO_FLOAT3(bsdf_eval);
}
/* Emissive Closure */
-float3 OSLShader::emissive_eval(const ShaderData *sd)
+float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < sd->osl_closure.num_emissive; i++) {
- const FlatClosure *flat = &sd->osl_closure.emissive[i];
- OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)flat->prim;
- OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
- eval += TO_FLOAT3(emissive_eval)*flat->weight;
- }
+ OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)sc->prim;
+ OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
+ eval += TO_FLOAT3(emissive_eval);
return eval;
}
-void OSLShader::emissive_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *I, float *pdf)
-{
- float r = sd->osl_closure.randb*sd->osl_closure.emissive_sample_sum;
- float sample_sum = 0.0f;
-
- *pdf = 0.0f;
-
- if(sd->osl_closure.emissive_sample_sum == 0.0f)
- return;
-
- /* find a closure to sample */
- for(int i = 0; i < sd->osl_closure.num_emissive; i++) {
- const FlatClosure *flat = &sd->osl_closure.emissive[i];
- sample_sum += flat->sample_weight;
-
- if(r <= sample_sum) {
- /* sample emissive closure */
- OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)flat->prim;
- emissive->sample(TO_VEC3(sd->Ng), randu, randv, TO_VEC3(*I), *pdf);
- *eval = flat->weight;
- *pdf *= flat->sample_weight/sd->osl_closure.emissive_sample_sum;
- return;
- }
- }
-}
-
/* Volume Closure */
-float3 OSLShader::volume_eval_phase(const ShaderData *sd, const float3 omega_in, const float3 omega_out)
-{
- float3 eval = make_float3(0.0f, 0.0f, 0.0f);
-
- for(int i = 0; i < sd->osl_closure.num_volume; i++) {
- const FlatClosure *flat = &sd->osl_closure.volume[i];
- OSL::VolumeClosure *volume = (OSL::VolumeClosure*)flat->prim;
- OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
- eval += TO_FLOAT3(volume_eval)*flat->weight;
- }
-
- return eval;
-}
-
-/* Holdout Closure */
-
-float3 OSLShader::holdout_eval(const ShaderData *sd)
+float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
- return sd->osl_closure.holdout_weight;
+ OSL::VolumeClosure *volume = (OSL::VolumeClosure*)sc->prim;
+ OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
+ return TO_FLOAT3(volume_eval)*sc->weight;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 9b578b159ae..6b1d402989b 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -46,6 +46,7 @@ namespace OSL = ::OSL;
class OSLRenderServices;
class Scene;
+class ShaderClosure;
class ShaderData;
class differential3;
class KernelGlobals;
@@ -66,15 +67,16 @@ public:
static void eval_displacement(KernelGlobals *kg, ShaderData *sd);
/* sample & eval */
- static int bsdf_sample(const ShaderData *sd, float randu, float randv,
+ static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
+ float randu, float randv,
float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
- static float3 bsdf_eval(const ShaderData *sd, const float3& omega_in, float& pdf);
- static float3 emissive_eval(const ShaderData *sd);
- static void emissive_sample(const ShaderData *sd, float randu, float randv,
- float3 *eval, float3 *I, float *pdf);
- static float3 volume_eval_phase(const ShaderData *sd, const float3 omega_in,
- const float3 omega_out);
- static float3 holdout_eval(const ShaderData *sd);
+ static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
+ const float3& omega_in, float& pdf);
+
+ static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
+
+ static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc,
+ const float3 omega_in, const float3 omega_out);
/* release */
static void release(KernelGlobals *kg, const ShaderData *sd);
diff --git a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h
index e94b33efaae..e16efebf5bb 100644
--- a/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/svm/bsdf_ashikhmin_velvet.h
@@ -40,24 +40,24 @@ typedef struct BsdfAshikhminVelvetClosure {
float m_invsigma2;
} BsdfAshikhminVelvetClosure;
-__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, float3 N, float sigma)
+__device void bsdf_ashikhmin_velvet_setup(ShaderData *sd, ShaderClosure *sc, float sigma)
{
sigma = fmaxf(sigma, 0.01f);
float m_invsigma2 = 1.0f/(sigma * sigma);
- sd->svm_closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+ sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
- sd->svm_closure_data0 = m_invsigma2;
+ sc->data0 = m_invsigma2;
}
-__device void bsdf_ashikhmin_velvet_blur(ShaderData *sd, float roughness)
+__device void bsdf_ashikhmin_velvet_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_invsigma2 = sd->svm_closure_data0;
+ float m_invsigma2 = sc->data0;
float3 m_N = sd->N;
float cosNO = dot(m_N, I);
@@ -89,19 +89,19 @@ __device float3 bsdf_ashikhmin_velvet_eval_reflect(const ShaderData *sd, const f
return make_float3(0, 0, 0);
}
-__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_ashikhmin_velvet_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_ashikhmin_velvet_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_invsigma2 = sd->svm_closure_data0;
+ float m_invsigma2 = sc->data0;
float3 m_N = sd->N;
// we are viewing the surface from above - send a ray out with uniform
diff --git a/intern/cycles/kernel/svm/bsdf_diffuse.h b/intern/cycles/kernel/svm/bsdf_diffuse.h
index a917db86ff5..e8a002cb84c 100644
--- a/intern/cycles/kernel/svm/bsdf_diffuse.h
+++ b/intern/cycles/kernel/svm/bsdf_diffuse.h
@@ -41,17 +41,17 @@ typedef struct BsdfDiffuseClosure {
//float3 m_N;
} BsdfDiffuseClosure;
-__device void bsdf_diffuse_setup(ShaderData *sd, float3 N)
+__device void bsdf_diffuse_setup(ShaderData *sd, ShaderClosure *sc)
{
- sd->svm_closure = CLOSURE_BSDF_DIFFUSE_ID;
+ sc->type = CLOSURE_BSDF_DIFFUSE_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
}
-__device void bsdf_diffuse_blur(ShaderData *sd, float roughness)
+__device void bsdf_diffuse_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 m_N = sd->N;
@@ -60,17 +60,17 @@ __device float3 bsdf_diffuse_eval_reflect(const ShaderData *sd, const float3 I,
return make_float3(cos_pi, cos_pi, cos_pi);
}
-__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_diffuse_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_diffuse_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_diffuse_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_diffuse_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_diffuse_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
float3 m_N = sd->N;
@@ -99,22 +99,22 @@ typedef struct BsdfTranslucentClosure {
//float3 m_N;
} BsdfTranslucentClosure;
-__device void bsdf_translucent_setup(ShaderData *sd, float3 N)
+__device void bsdf_translucent_setup(ShaderData *sd, ShaderClosure *sc)
{
- sd->svm_closure = CLOSURE_BSDF_TRANSLUCENT_ID;
+ sc->type = CLOSURE_BSDF_TRANSLUCENT_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL;
}
-__device void bsdf_translucent_blur(ShaderData *sd, float roughness)
+__device void bsdf_translucent_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_translucent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
float3 m_N = sd->N;
@@ -123,12 +123,12 @@ __device float3 bsdf_translucent_eval_transmit(const ShaderData *sd, const float
return make_float3 (cos_pi, cos_pi, cos_pi);
}
-__device float bsdf_translucent_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_translucent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_translucent_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_translucent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
float3 m_N = sd->N;
diff --git a/intern/cycles/kernel/svm/bsdf_microfacet.h b/intern/cycles/kernel/svm/bsdf_microfacet.h
index 0ca37eedc22..3acd3ba4c85 100644
--- a/intern/cycles/kernel/svm/bsdf_microfacet.h
+++ b/intern/cycles/kernel/svm/bsdf_microfacet.h
@@ -43,34 +43,34 @@ typedef struct BsdfMicrofacetGGXClosure {
float m_eta;
} BsdfMicrofacetGGXClosure;
-__device void bsdf_microfacet_ggx_setup(ShaderData *sd, float3 N, float ag, float eta, bool refractive)
+__device void bsdf_microfacet_ggx_setup(ShaderData *sd, ShaderClosure *sc, float ag, float eta, bool refractive)
{
float m_ag = clamp(ag, 1e-5f, 1.0f);
float m_eta = eta;
- sd->svm_closure_data0 = m_ag;
- sd->svm_closure_data1 = m_eta;
+ sc->data0 = m_ag;
+ sc->data1 = m_eta;
if(refractive)
- sd->svm_closure = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
else
- sd->svm_closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
-__device void bsdf_microfacet_ggx_blur(ShaderData *sd, float roughness)
+__device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
{
- float m_ag = sd->svm_closure_data0;
+ float m_ag = sc->data0;
m_ag = fmaxf(roughness, m_ag);
- sd->svm_closure_data0 = m_ag;
+ sc->data0 = m_ag;
}
-__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ag = sd->svm_closure_data0;
- //float m_eta = sd->svm_closure_data1;
- int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float m_ag = sc->data0;
+ //float m_eta = sc->data1;
+ int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N;
if(m_refractive) return make_float3 (0, 0, 0);
@@ -103,11 +103,11 @@ __device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderData *sd, const flo
return make_float3 (0, 0, 0);
}
-__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ag = sd->svm_closure_data0;
- float m_eta = sd->svm_closure_data1;
- int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float m_ag = sc->data0;
+ float m_eta = sc->data1;
+ int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N;
if(!m_refractive) return make_float3 (0, 0, 0);
@@ -139,16 +139,16 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderData *sd, const fl
return make_float3 (out, out, out);
}
-__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_microfacet_ggx_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_microfacet_ggx_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_ag = sd->svm_closure_data0;
- float m_eta = sd->svm_closure_data1;
- int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ float m_ag = sc->data0;
+ float m_eta = sc->data1;
+ int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N;
float cosNO = dot(m_N, sd->I);
@@ -268,34 +268,34 @@ typedef struct BsdfMicrofacetBeckmannClosure {
float m_eta;
} BsdfMicrofacetBeckmannClosure;
-__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, float3 N, float ab, float eta, bool refractive)
+__device void bsdf_microfacet_beckmann_setup(ShaderData *sd, ShaderClosure *sc, float ab, float eta, bool refractive)
{
float m_ab = clamp(ab, 1e-5f, 1.0f);
float m_eta = eta;
- sd->svm_closure_data0 = m_ab;
- sd->svm_closure_data1 = m_eta;
+ sc->data0 = m_ab;
+ sc->data1 = m_eta;
if(refractive)
- sd->svm_closure = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
else
- sd->svm_closure = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
-__device void bsdf_microfacet_beckmann_blur(ShaderData *sd, float roughness)
+__device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
{
- float m_ab = sd->svm_closure_data0;
+ float m_ab = sc->data0;
m_ab = fmaxf(roughness, m_ab);
- sd->svm_closure_data0 = m_ab;
+ sc->data0 = m_ab;
}
-__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ab = sd->svm_closure_data0;
- //float m_eta = sd->svm_closure_data1;
- int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float m_ab = sc->data0;
+ //float m_eta = sc->data1;
+ int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N;
if(m_refractive) return make_float3 (0, 0, 0);
@@ -330,11 +330,11 @@ __device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderData *sd, cons
return make_float3 (0, 0, 0);
}
-__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ab = sd->svm_closure_data0;
- float m_eta = sd->svm_closure_data1;
- int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float m_ab = sc->data0;
+ float m_eta = sc->data1;
+ int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N;
if(!m_refractive) return make_float3 (0, 0, 0);
@@ -368,16 +368,16 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderData *sd, con
return make_float3 (out, out, out);
}
-__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_microfacet_beckmann_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_microfacet_beckmann_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_ab = sd->svm_closure_data0;
- float m_eta = sd->svm_closure_data1;
- int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ float m_ab = sc->data0;
+ float m_eta = sc->data1;
+ int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N;
float cosNO = dot(m_N, sd->I);
diff --git a/intern/cycles/kernel/svm/bsdf_reflection.h b/intern/cycles/kernel/svm/bsdf_reflection.h
index 4dad61704df..f00b72c4869 100644
--- a/intern/cycles/kernel/svm/bsdf_reflection.h
+++ b/intern/cycles/kernel/svm/bsdf_reflection.h
@@ -41,34 +41,34 @@ typedef struct BsdfReflectionClosure {
//float3 m_N;
} BsdfReflectionClosure;
-__device void bsdf_reflection_setup(ShaderData *sd, float3 N)
+__device void bsdf_reflection_setup(ShaderData *sd, ShaderClosure *sc)
{
- sd->svm_closure = CLOSURE_BSDF_REFLECTION_ID;
+ sc->type = CLOSURE_BSDF_REFLECTION_ID;
sd->flag |= SD_BSDF;
}
-__device void bsdf_reflection_blur(ShaderData *sd, float roughness)
+__device void bsdf_reflection_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_reflection_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_reflection_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_reflection_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_reflection_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_reflection_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_reflection_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sd->svm_closure_data;
+ //const BsdfReflectionClosure *self = (const BsdfReflectionClosure*)sc->data;
float3 m_N = sd->N;
// only one direction is possible
diff --git a/intern/cycles/kernel/svm/bsdf_refraction.h b/intern/cycles/kernel/svm/bsdf_refraction.h
index 93bd747eb31..07ef8633e0d 100644
--- a/intern/cycles/kernel/svm/bsdf_refraction.h
+++ b/intern/cycles/kernel/svm/bsdf_refraction.h
@@ -41,36 +41,36 @@ typedef struct BsdfRefractionClosure {
float m_eta;
} BsdfRefractionClosure;
-__device void bsdf_refraction_setup(ShaderData *sd, float3 N, float eta)
+__device void bsdf_refraction_setup(ShaderData *sd, ShaderClosure *sc, float eta)
{
- sd->svm_closure_data0 = eta;
+ sc->data0 = eta;
- sd->svm_closure = CLOSURE_BSDF_REFRACTION_ID;
+ sc->type = CLOSURE_BSDF_REFRACTION_ID;
sd->flag |= SD_BSDF;
}
-__device void bsdf_refraction_blur(ShaderData *sd, float roughness)
+__device void bsdf_refraction_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_refraction_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_refraction_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_refraction_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_refraction_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_refraction_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_refraction_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_eta = sd->svm_closure_data0;
+ float m_eta = sc->data0;
float3 m_N = sd->N;
float3 R, T;
diff --git a/intern/cycles/kernel/svm/bsdf_transparent.h b/intern/cycles/kernel/svm/bsdf_transparent.h
index 1674f04955e..4425c4bf104 100644
--- a/intern/cycles/kernel/svm/bsdf_transparent.h
+++ b/intern/cycles/kernel/svm/bsdf_transparent.h
@@ -35,32 +35,32 @@
CCL_NAMESPACE_BEGIN
-__device void bsdf_transparent_setup(ShaderData *sd)
+__device void bsdf_transparent_setup(ShaderData *sd, ShaderClosure *sc)
{
- sd->svm_closure = CLOSURE_BSDF_TRANSPARENT_ID;
+ sc->type = CLOSURE_BSDF_TRANSPARENT_ID;
sd->flag |= SD_BSDF;
}
-__device void bsdf_transparent_blur(ShaderData *sd, float roughness)
+__device void bsdf_transparent_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_transparent_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_transparent_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_transparent_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_transparent_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_transparent_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_transparent_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
// only one direction is possible
*omega_in = -sd->I;
diff --git a/intern/cycles/kernel/svm/bsdf_ward.h b/intern/cycles/kernel/svm/bsdf_ward.h
index 18967b3981e..d46baf099a6 100644
--- a/intern/cycles/kernel/svm/bsdf_ward.h
+++ b/intern/cycles/kernel/svm/bsdf_ward.h
@@ -44,28 +44,28 @@ typedef struct BsdfWardClosure {
float m_ay;
} BsdfWardClosure;
-__device void bsdf_ward_setup(ShaderData *sd, float3 N, float3 T, float ax, float ay)
+__device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float3 T, float ax, float ay)
{
float m_ax = clamp(ax, 1e-5f, 1.0f);
float m_ay = clamp(ay, 1e-5f, 1.0f);
- sd->svm_closure_data0 = m_ax;
- sd->svm_closure_data1 = m_ay;
+ sc->data0 = m_ax;
+ sc->data1 = m_ay;
- sd->svm_closure = CLOSURE_BSDF_WARD_ID;
+ sc->type = CLOSURE_BSDF_WARD_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
}
-__device void bsdf_ward_blur(ShaderData *sd, float roughness)
+__device void bsdf_ward_blur(ShaderClosure *sc, float roughness)
{
- sd->svm_closure_data0 = fmaxf(roughness, sd->svm_closure_data0);
- sd->svm_closure_data1 = fmaxf(roughness, sd->svm_closure_data1);
+ sc->data0 = fmaxf(roughness, sc->data0);
+ sc->data1 = fmaxf(roughness, sc->data1);
}
-__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_ax = sd->svm_closure_data0;
- float m_ay = sd->svm_closure_data1;
+ float m_ax = sc->data0;
+ float m_ay = sc->data1;
float3 m_N = sd->N;
float3 m_T = normalize(sd->dPdu);
@@ -93,20 +93,20 @@ __device float3 bsdf_ward_eval_reflect(const ShaderData *sd, const float3 I, con
return make_float3 (0, 0, 0);
}
-__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_ward_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_ward_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_ward_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_ward_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_ward_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_ax = sd->svm_closure_data0;
- float m_ay = sd->svm_closure_data1;
+ float m_ax = sc->data0;
+ float m_ay = sc->data1;
float3 m_N = sd->N;
float3 m_T = normalize(sd->dPdu);
diff --git a/intern/cycles/kernel/svm/bsdf_westin.h b/intern/cycles/kernel/svm/bsdf_westin.h
index 0f38deb0885..21e5018c489 100644
--- a/intern/cycles/kernel/svm/bsdf_westin.h
+++ b/intern/cycles/kernel/svm/bsdf_westin.h
@@ -42,26 +42,26 @@ typedef struct BsdfWestinBackscatterClosure {
float m_invroughness;
} BsdfWestinBackscatterClosure;
-__device void bsdf_westin_backscatter_setup(ShaderData *sd, float3 N, float roughness)
+__device void bsdf_westin_backscatter_setup(ShaderData *sd, ShaderClosure *sc, float roughness)
{
roughness = clamp(roughness, 1e-5f, 1.0f);
float m_invroughness = 1.0f/roughness;
- sd->svm_closure = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
+ sc->type = CLOSURE_BSDF_WESTIN_BACKSCATTER_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
- sd->svm_closure_data0 = m_invroughness;
+ sc->data0 = m_invroughness;
}
-__device void bsdf_westin_backscatter_blur(ShaderData *sd, float roughness)
+__device void bsdf_westin_backscatter_blur(ShaderClosure *sc, float roughness)
{
- float m_invroughness = sd->svm_closure_data0;
+ float m_invroughness = sc->data0;
m_invroughness = min(1.0f/roughness, m_invroughness);
- sd->svm_closure_data0 = m_invroughness;
+ sc->data0 = m_invroughness;
}
-__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_invroughness = sd->svm_closure_data0;
+ float m_invroughness = sc->data0;
float3 m_N = sd->N;
// pdf is implicitly 0 (no indirect sampling)
@@ -76,19 +76,19 @@ __device float3 bsdf_westin_backscatter_eval_reflect(const ShaderData *sd, const
return make_float3 (0, 0, 0);
}
-__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_backscatter_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_westin_backscatter_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_westin_backscatter_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_westin_backscatter_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_invroughness = sd->svm_closure_data0;
+ float m_invroughness = sc->data0;
float3 m_N = sd->N;
float cosNO = dot(m_N, sd->I);
@@ -137,20 +137,20 @@ typedef struct BsdfWestinSheenClosure {
float m_edginess;
} BsdfWestinSheenClosure;
-__device void bsdf_westin_sheen_setup(ShaderData *sd, float3 N, float edginess)
+__device void bsdf_westin_sheen_setup(ShaderData *sd, ShaderClosure *sc, float edginess)
{
- sd->svm_closure = CLOSURE_BSDF_WESTIN_SHEEN_ID;
+ sc->type = CLOSURE_BSDF_WESTIN_SHEEN_ID;
sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
- sd->svm_closure_data0 = edginess;
+ sc->data0 = edginess;
}
-__device void bsdf_westin_sheen_blur(ShaderData *sd, float roughness)
+__device void bsdf_westin_sheen_blur(ShaderClosure *sc, float roughness)
{
}
-__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float m_edginess = sd->svm_closure_data0;
+ float m_edginess = sc->data0;
float3 m_N = sd->N;
// pdf is implicitly 0 (no indirect sampling)
@@ -165,19 +165,19 @@ __device float3 bsdf_westin_sheen_eval_reflect(const ShaderData *sd, const float
return make_float3 (0, 0, 0);
}
-__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const float3 I, const float3 omega_in, float *pdf)
+__device float3 bsdf_westin_sheen_eval_transmit(const ShaderData *sd, const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
return make_float3(0.0f, 0.0f, 0.0f);
}
-__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const float3 I)
+__device float bsdf_westin_sheen_albedo(const ShaderData *sd, const ShaderClosure *sc, const float3 I)
{
return 1.0f;
}
-__device int bsdf_westin_sheen_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
+__device int bsdf_westin_sheen_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
{
- float m_edginess = sd->svm_closure_data0;
+ float m_edginess = sc->data0;
float3 m_N = sd->N;
// we are viewing the surface from the right side - send a ray out with cosine
diff --git a/intern/cycles/kernel/svm/emissive.h b/intern/cycles/kernel/svm/emissive.h
index ed2b2e4aee8..8bd31751fb3 100644
--- a/intern/cycles/kernel/svm/emissive.h
+++ b/intern/cycles/kernel/svm/emissive.h
@@ -42,23 +42,6 @@ __device float3 emissive_eval(const float3 Ng, const float3 I)
return make_float3(res, res, res);
}
-__device void emissive_sample(const float3 Ng, float randu, float randv, float3 *I, float *pdf)
-{
- // We don't do anything sophisticated here for the step
- // We just sample the whole cone uniformly to the cosine
- float3 T, B;
- make_orthonormals(Ng, &T, &B);
- float phi = 2 * M_PI_F * randu;
-
- float cosTheta = sqrtf(1.0f - 1.0f * randv);
- float sinTheta = sqrtf(1.0f - cosTheta * cosTheta);
- *I = (cosf(phi) * sinTheta) * T +
- (sinf(phi) * sinTheta) * B +
- cosTheta * Ng;
-
- *pdf = M_1_PI_F;
-}
-
/// Return the probability distribution function in the direction I,
/// given the parameters and the light's surface normal. This MUST match
/// the PDF computed by sample().
@@ -68,15 +51,9 @@ __device float emissive_pdf(const float3 Ng, const float3 I)
return (cosNO > 0.0f)? M_1_PI_F: 0.0f;
}
-__device float3 svm_emissive_eval(ShaderData *sd)
-{
- return sd->svm_closure_weight*emissive_eval(sd->Ng, sd->I);
-}
-
-__device void svm_emissive_sample(ShaderData *sd, float randu, float randv, float3 *eval, float3 *I, float *pdf)
+__device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc)
{
- *eval = sd->svm_closure_weight;
- emissive_sample(sd->Ng, randu, randv, I, pdf);
+ return emissive_eval(sd->Ng, sd->I);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 989c37c3cd0..a5d95c1b394 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -47,14 +47,14 @@ CCL_NAMESPACE_BEGIN
/* Stack */
-__device float3 stack_load_float3(float *stack, uint a)
+__device_inline float3 stack_load_float3(float *stack, uint a)
{
kernel_assert(a+2 < SVM_STACK_SIZE);
return make_float3(stack[a+0], stack[a+1], stack[a+2]);
}
-__device void stack_store_float3(float *stack, uint a, float3 f)
+__device_inline void stack_store_float3(float *stack, uint a, float3 f)
{
kernel_assert(a+2 < SVM_STACK_SIZE);
@@ -63,40 +63,40 @@ __device void stack_store_float3(float *stack, uint a, float3 f)
stack[a+2] = f.z;
}
-__device float stack_load_float(float *stack, uint a)
+__device_inline float stack_load_float(float *stack, uint a)
{
kernel_assert(a < SVM_STACK_SIZE);
return stack[a];
}
-__device float stack_load_float_default(float *stack, uint a, uint value)
+__device_inline float stack_load_float_default(float *stack, uint a, uint value)
{
return (a == (uint)SVM_STACK_INVALID)? __int_as_float(value): stack_load_float(stack, a);
}
-__device void stack_store_float(float *stack, uint a, float f)
+__device_inline void stack_store_float(float *stack, uint a, float f)
{
kernel_assert(a < SVM_STACK_SIZE);
stack[a] = f;
}
-__device bool stack_valid(uint a)
+__device_inline bool stack_valid(uint a)
{
return a != (uint)SVM_STACK_INVALID;
}
/* Reading Nodes */
-__device uint4 read_node(KernelGlobals *kg, int *offset)
+__device_inline uint4 read_node(KernelGlobals *kg, int *offset)
{
uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
(*offset)++;
return node;
}
-__device float4 read_node_float(KernelGlobals *kg, int *offset)
+__device_inline float4 read_node_float(KernelGlobals *kg, int *offset)
{
uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
float4 f = make_float4(__int_as_float(node.x), __int_as_float(node.y), __int_as_float(node.z), __int_as_float(node.w));
@@ -104,7 +104,7 @@ __device float4 read_node_float(KernelGlobals *kg, int *offset)
return f;
}
-__device void decode_node_uchar4(uint i, uint *x, uint *y, uint *z, uint *w)
+__device_inline void decode_node_uchar4(uint i, uint *x, uint *y, uint *z, uint *w)
{
if(x) *x = (i & 0xFF);
if(y) *y = ((i >> 8) & 0xFF);
@@ -154,8 +154,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
float closure_weight = 1.0f;
int offset = sd->shader;
- sd->svm_closure = NBUILTIN_CLOSURES;
- sd->svm_closure_weight = make_float3(0.0f, 0.0f, 0.0f);
+#ifdef __MULTI_CLOSURE__
+ sd->num_closure = 0;
+ sd->randb_closure = randb;
+#else
+ sd->closure.type = NBUILTIN_CLOSURES;
+#endif
while(1) {
uint4 node = read_node(kg, &offset);
@@ -169,16 +173,16 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
break;
}
case NODE_CLOSURE_BSDF:
- svm_node_closure_bsdf(sd, stack, node, randb);
+ svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag);
break;
case NODE_CLOSURE_EMISSION:
- svm_node_closure_emission(sd);
+ svm_node_closure_emission(sd, stack, node);
break;
case NODE_CLOSURE_BACKGROUND:
- svm_node_closure_background(sd);
+ svm_node_closure_background(sd, node);
break;
case NODE_CLOSURE_HOLDOUT:
- svm_node_closure_holdout(sd);
+ svm_node_closure_holdout(sd, stack, node);
break;
case NODE_CLOSURE_SET_WEIGHT:
svm_node_closure_set_weight(sd, node.y, node.z, node.w);
@@ -190,7 +194,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
svm_node_emission_weight(kg, sd, stack, node);
break;
case NODE_MIX_CLOSURE:
- svm_node_mix_closure(sd, stack, node.y, node.z, &offset, &randb);
+ svm_node_mix_closure(sd, stack, node, &offset, &randb);
break;
case NODE_ADD_CLOSURE:
svm_node_add_closure(sd, stack, node.y, node.z, &offset, &randb, &closure_weight);
@@ -307,7 +311,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
break;
case NODE_END:
default:
- sd->svm_closure_weight *= closure_weight;
+#ifndef __MULTI_CLOSURE__
+ sd->closure.weight *= closure_weight;
+#endif
return;
}
}
diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h
index 22985e9ace5..a1b39c6ca1e 100644
--- a/intern/cycles/kernel/svm/svm_bsdf.h
+++ b/intern/cycles/kernel/svm/svm_bsdf.h
@@ -29,48 +29,48 @@
CCL_NAMESPACE_BEGIN
-__device int svm_bsdf_sample(const ShaderData *sd, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+__device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
{
int label;
- switch(sd->svm_closure) {
+ switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
- label = bsdf_diffuse_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_diffuse_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID:
- label = bsdf_translucent_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_translucent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- label = bsdf_reflection_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_reflection_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- label = bsdf_refraction_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_refraction_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- label = bsdf_transparent_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_transparent_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- label = bsdf_microfacet_ggx_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_microfacet_ggx_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- label = bsdf_microfacet_beckmann_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_microfacet_beckmann_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID:
- label = bsdf_ward_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_ward_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- label = bsdf_ashikhmin_velvet_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_ashikhmin_velvet_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- label = bsdf_westin_backscatter_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_westin_backscatter_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- label = bsdf_westin_sheen_sample(sd, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = bsdf_westin_sheen_sample(sd, sc, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
default:
@@ -78,53 +78,51 @@ __device int svm_bsdf_sample(const ShaderData *sd, float randu, float randv, flo
break;
}
- *eval *= sd->svm_closure_weight;
-
return label;
}
-__device float3 svm_bsdf_eval(const ShaderData *sd, const float3 omega_in, float *pdf)
+__device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
{
float3 eval;
if(dot(sd->Ng, omega_in) >= 0.0f) {
- switch(sd->svm_closure) {
+ switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
- eval = bsdf_diffuse_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_reflection_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_refraction_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_transparent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_ggx_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_beckmann_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID:
- eval = bsdf_ward_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_ward_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_ashikhmin_velvet_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- eval = bsdf_westin_backscatter_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_westin_backscatter_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- eval = bsdf_westin_sheen_eval_reflect(sd, sd->I, omega_in, pdf);
+ eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
default:
eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -132,43 +130,43 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const float3 omega_in, float
}
}
else {
- switch(sd->svm_closure) {
+ switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
- eval = bsdf_diffuse_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_reflection_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_refraction_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_transparent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_ggx_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_microfacet_beckmann_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID:
- eval = bsdf_ward_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_ward_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_ashikhmin_velvet_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- eval = bsdf_westin_backscatter_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_westin_backscatter_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- eval = bsdf_westin_sheen_eval_transmit(sd, sd->I, omega_in, pdf);
+ eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
default:
eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -176,50 +174,48 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const float3 omega_in, float
}
}
- eval *= sd->svm_closure_weight;
-
return eval;
}
-__device void svm_bsdf_blur(ShaderData *sd, float roughness)
+__device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
{
- switch(sd->svm_closure) {
+ switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
- bsdf_diffuse_blur(sd, roughness);
+ bsdf_diffuse_blur(sc, roughness);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
- bsdf_translucent_blur(sd, roughness);
+ bsdf_translucent_blur(sc, roughness);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- bsdf_reflection_blur(sd, roughness);
+ bsdf_reflection_blur(sc, roughness);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- bsdf_refraction_blur(sd, roughness);
+ bsdf_refraction_blur(sc, roughness);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- bsdf_transparent_blur(sd, roughness);
+ bsdf_transparent_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- bsdf_microfacet_ggx_blur(sd, roughness);
+ bsdf_microfacet_ggx_blur(sc, roughness);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- bsdf_microfacet_beckmann_blur(sd, roughness);
+ bsdf_microfacet_beckmann_blur(sc, roughness);
break;
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID:
- bsdf_ward_blur(sd, roughness);
+ bsdf_ward_blur(sc, roughness);
break;
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- bsdf_ashikhmin_velvet_blur(sd, roughness);
+ bsdf_ashikhmin_velvet_blur(sc, roughness);
break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
- bsdf_westin_backscatter_blur(sd, roughness);
+ bsdf_westin_backscatter_blur(sc, roughness);
break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
- bsdf_westin_sheen_blur(sd, roughness);
+ bsdf_westin_sheen_blur(sc, roughness);
break;
default:
break;
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 1efadcefbd5..aaf2926f60d 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -20,28 +20,92 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */
-__device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, float randb)
+__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
+{
+ if(type == CLOSURE_BSDF_REFRACTION_ID) {
+ if(refract)
+ bsdf_refraction_setup(sd, sc, eta);
+ else
+ bsdf_reflection_setup(sd, sc);
+ }
+ else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
+ bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract);
+ }
+ else
+ bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract);
+}
+
+__device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd)
+{
+#ifdef __MULTI_CLOSURE__
+ ShaderClosure *sc = &sd->closure[sd->num_closure];
+
+ if(sd->num_closure < MAX_CLOSURE)
+ sd->num_closure++;
+
+ return sc;
+#else
+ return &sd->closure;
+#endif
+}
+
+__device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight)
+{
+#ifdef __MULTI_CLOSURE__
+ sc->weight *= mix_weight;
+ sc->sample_weight = fabsf(average(sc->weight));
+#endif
+}
+
+__device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag)
{
uint type, param1_offset, param2_offset;
+
+#ifdef __MULTI_CLOSURE__
+ uint mix_weight_offset;
+ decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
+ float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f);
+
+ if(mix_weight == 0.0f)
+ return;
+#else
decode_node_uchar4(node.y, &type, &param1_offset, &param2_offset, NULL);
+ float mix_weight = 1.0f;
+#endif
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z);
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w);
switch(type) {
- case CLOSURE_BSDF_DIFFUSE_ID:
- bsdf_diffuse_setup(sd, sd->N);
+ case CLOSURE_BSDF_DIFFUSE_ID: {
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+ bsdf_diffuse_setup(sd, sc);
break;
- case CLOSURE_BSDF_TRANSLUCENT_ID:
- bsdf_translucent_setup(sd, sd->N);
+ }
+ case CLOSURE_BSDF_TRANSLUCENT_ID: {
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+ bsdf_translucent_setup(sd, sc);
break;
- case CLOSURE_BSDF_TRANSPARENT_ID:
- bsdf_transparent_setup(sd);
+ }
+ case CLOSURE_BSDF_TRANSPARENT_ID: {
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+ bsdf_transparent_setup(sd, sc);
break;
+ }
case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
- /* roughness */
+#ifdef __CAUSTICS_TRICKS__
+ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
+
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+
/* index of refraction */
float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f);
eta = 1.0f/eta;
@@ -49,26 +113,22 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
/* fresnel */
float cosNO = dot(sd->N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta);
+ float roughness = param1;
- sd->svm_closure_weight *= fresnel;
+ sc->weight *= fresnel;
/* setup bsdf */
- if(type == CLOSURE_BSDF_REFLECTION_ID) {
- bsdf_reflection_setup(sd, sd->N);
- }
- else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) {
- float roughness = param1;
- bsdf_microfacet_beckmann_setup(sd, sd->N, roughness, eta, false);
- }
- else {
- float roughness = param1;
- bsdf_microfacet_ggx_setup(sd, sd->N, roughness, eta, false);
- }
+ svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
break;
}
case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
+#ifdef __CAUSTICS_TRICKS__
+ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
+
/* index of refraction */
float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f);
eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
@@ -76,34 +136,58 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
/* fresnel */
float cosNO = dot(sd->N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta);
- bool refract = (fresnel < randb);
+ float roughness = param1;
+
+#ifdef __MULTI_CLOSURE__
+ /* reflection */
+ ShaderClosure *sc = svm_node_closure_get(sd);
+
+ float3 weight = sc->weight;
+ float sample_weight = sc->sample_weight;
+
+ svm_node_closure_set_mix_weight(sc, mix_weight*fresnel);
+ svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
+
+ /* refraction */
+ sc = svm_node_closure_get(sd);
+
+ sc->weight = weight;
+ sc->sample_weight = sample_weight;
+
+ svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel));
+ svm_node_glossy_setup(sd, sc, type, eta, roughness, true);
+#else
+ ShaderClosure *sc = svm_node_closure_get(sd);
+
+ bool refract = (randb > fresnel);
+
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+ svm_node_glossy_setup(sd, sc, type, eta, roughness, refract);
+#endif
- /* setup bsdf */
- if(type == CLOSURE_BSDF_REFRACTION_ID) {
- if(refract)
- bsdf_refraction_setup(sd, sd->N, eta);
- else
- bsdf_reflection_setup(sd, sd->N);
- }
- else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
- float roughness = param1;
- bsdf_microfacet_beckmann_setup(sd, sd->N, roughness, eta, refract);
- }
- else {
- float roughness = param1;
- bsdf_microfacet_ggx_setup(sd, sd->N, roughness, eta, refract);
- }
break;
}
#ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID: {
+#ifdef __CAUSTICS_TRICKS__
+ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
+
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+
float roughness_u = param1;
float roughness_v = param2;
- bsdf_ward_setup(sd, sd->N, normalize(sd->dPdu), roughness_u, roughness_v);
+
+ bsdf_ward_setup(sd, sc, normalize(sd->dPdu), roughness_u, roughness_v);
break;
}
#endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+
/* sigma */
float sigma = clamp(param1, 0.0f, 1.0f);
@@ -115,55 +199,107 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
float cosNO = dot(sd->N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta);
- sd->svm_closure_weight *= fresnel;
+ sc->weight *= fresnel;
- bsdf_ashikhmin_velvet_setup(sd, sd->N, sigma);
+ bsdf_ashikhmin_velvet_setup(sd, sc, sigma);
break;
}
default:
- return;
+ break;
}
}
-__device void svm_node_closure_emission(ShaderData *sd)
+__device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node)
{
- sd->svm_closure = CLOSURE_EMISSION_ID;
+#ifdef __MULTI_CLOSURE__
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ uint mix_weight_offset = node.y;
+
+ if(stack_valid(mix_weight_offset)) {
+ float mix_weight = stack_load_float(stack, mix_weight_offset);
+
+ if(mix_weight == 0.0f)
+ return;
+
+ sc->weight *= mix_weight;
+ }
+#else
+ ShaderClosure *sc = &sd->closure;
+#endif
+
+ sc->type = CLOSURE_EMISSION_ID;
sd->flag |= SD_EMISSION;
}
-__device void svm_node_closure_background(ShaderData *sd)
+__device void svm_node_closure_background(ShaderData *sd, uint4 node)
{
- sd->svm_closure = CLOSURE_BACKGROUND_ID;
+#ifdef __MULTI_CLOSURE__
+ ShaderClosure *sc = svm_node_closure_get(sd);
+#else
+ ShaderClosure *sc = &sd->closure;
+#endif
+
+ sc->type = CLOSURE_BACKGROUND_ID;
}
-__device void svm_node_closure_holdout(ShaderData *sd)
+__device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
{
- sd->svm_closure = CLOSURE_HOLDOUT_ID;
+#ifdef __MULTI_CLOSURE__
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ uint mix_weight_offset = node.y;
+
+ if(stack_valid(mix_weight_offset)) {
+ float mix_weight = stack_load_float(stack, mix_weight_offset);
+
+ if(mix_weight == 0.0f)
+ return;
+
+ sc->weight = make_float3(mix_weight, mix_weight, mix_weight);
+ }
+ else
+ sc->weight = make_float3(1.0f, 1.0f, 1.0f);
+
+ sc->sample_weight = 0.0f;
+#else
+ ShaderClosure *sc = &sd->closure;
+#endif
+
+ sc->type = CLOSURE_HOLDOUT_ID;
sd->flag |= SD_HOLDOUT;
}
/* Closure Nodes */
+__device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
+{
+#ifdef __MULTI_CLOSURE__
+ sd->closure[sd->num_closure].weight = weight;
+#else
+ sd->closure.weight = weight;
+#endif
+}
+
__device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
{
- sd->svm_closure_weight.x = __int_as_float(r);
- sd->svm_closure_weight.y = __int_as_float(g);
- sd->svm_closure_weight.z = __int_as_float(b);
+ float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
+ svm_node_closure_store_weight(sd, weight);
}
__device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b)
{
- sd->svm_closure_weight.x = __int_as_float(r);
- sd->svm_closure_weight.y = __int_as_float(g);
- sd->svm_closure_weight.z = __int_as_float(b);
+ float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
if(sd->object != ~0)
- sd->svm_closure_weight /= object_surface_area(kg, sd->object);
+ weight /= object_surface_area(kg, sd->object);
+
+ svm_node_closure_store_weight(sd, weight);
}
__device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset)
{
- sd->svm_closure_weight = stack_load_float3(stack, weight_offset);
+ float3 weight = stack_load_float3(stack, weight_offset);
+
+ svm_node_closure_store_weight(sd, weight);
}
__device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
@@ -172,37 +308,59 @@ __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float
uint strength_offset = node.z;
uint total_power = node.w;
- sd->svm_closure_weight = stack_load_float3(stack, color_offset)*stack_load_float(stack, strength_offset);
+ float3 weight = stack_load_float3(stack, color_offset)*stack_load_float(stack, strength_offset);
if(total_power && sd->object != ~0)
- sd->svm_closure_weight /= object_surface_area(kg, sd->object);
+ weight /= object_surface_area(kg, sd->object);
+
+ svm_node_closure_store_weight(sd, weight);
}
__device void svm_node_mix_closure(ShaderData *sd, float *stack,
- uint weight_offset, uint node_jump, int *offset, float *randb)
+ uint4 node, int *offset, float *randb)
{
+#ifdef __MULTI_CLOSURE__
+ /* fetch weight from blend input, previous mix closures,
+ and write to stack to be used by closure nodes later */
+ uint weight_offset, in_weight_offset, weight1_offset, weight2_offset;
+ decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
+
float weight = stack_load_float(stack, weight_offset);
- weight = clamp(weight, 0.0f, 1.0f);
+ float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f;
+ if(stack_valid(weight1_offset))
+ stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight));
+ if(stack_valid(weight2_offset))
+ stack_store_float(stack, weight2_offset, in_weight*weight);
+#else
/* pick a closure and make the random number uniform over 0..1 again.
closure 1 starts on the next node, for closure 2 the start is at an
offset from the current node, so we jump */
+ uint weight_offset = node.y;
+ uint node_jump = node.z;
+ float weight = stack_load_float(stack, weight_offset);
+ weight = clamp(weight, 0.0f, 1.0f);
+
if(*randb < weight) {
*offset += node_jump;
*randb = *randb/weight;
}
else
*randb = (*randb - weight)/(1.0f - weight);
+#endif
}
__device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
uint node_jump, int *offset, float *randb, float *closure_weight)
{
- float weight = 0.5f;
-
+#ifdef __MULTI_CLOSURE__
+ /* nothing to do, handled in compiler */
+#else
/* pick one of the two closures with probability 0.5. sampling quality
is not going to be great, for that we'd need to evaluate the weights
of the two closures being added */
+ float weight = 0.5f;
+
if(*randb < weight) {
*offset += node_jump;
*randb = *randb/weight;
@@ -211,6 +369,7 @@ __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
*randb = (*randb - weight)/(1.0f - weight);
*closure_weight *= 2.0f;
+#endif
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 758ba25c07a..98e4a5ee583 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -258,6 +258,7 @@ typedef enum ShaderType {
/* Closure */
typedef enum ClosureType {
+ CLOSURE_BSDF_ID,
CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,
CLOSURE_BSDF_REFLECTION_ID,
@@ -272,16 +273,25 @@ typedef enum ClosureType {
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_WESTIN_SHEEN_ID,
+
CLOSURE_BSSRDF_CUBIC_ID,
CLOSURE_EMISSION_ID,
CLOSURE_DEBUG_ID,
CLOSURE_BACKGROUND_ID,
CLOSURE_HOLDOUT_ID,
CLOSURE_SUBSURFACE_ID,
+ CLOSURE_VOLUME_ID,
NBUILTIN_CLOSURES
} ClosureType;
+/* watch this, being lazy with memory usage */
+#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_WESTIN_SHEEN_ID)
+#define CLOSURE_IS_VOLUME(type) (type == CLOSURE_VOLUME_ID)
+#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
+#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
+#define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
+
CCL_NAMESPACE_END
#endif /* __SVM_TYPES_H__ */
diff --git a/intern/cycles/kernel/svm/volume.h b/intern/cycles/kernel/svm/volume.h
index 32e0601ee00..dc377b5c595 100644
--- a/intern/cycles/kernel/svm/volume.h
+++ b/intern/cycles/kernel/svm/volume.h
@@ -34,7 +34,7 @@ CCL_NAMESPACE_BEGIN
/* VOLUME CLOSURE */
-__device float3 volume_eval_phase(ShaderData *sd, const float3 omega_in, const float3 omega_out)
+__device float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{
return make_float3(1.0f, 1.0f, 1.0f);
}
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index feb9e35e785..b13cab55404 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -55,6 +55,9 @@ LightManager::~LightManager()
void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
+ /* option to always sample all point lights */
+ bool multi_light = false;
+
/* count */
size_t num_lights = scene->lights.size();
size_t num_triangles = 0;
@@ -82,7 +85,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
}
}
- size_t num_distribution = num_triangles + num_lights;
+ size_t num_distribution = num_triangles;
+
+ if(!multi_light)
+ num_distribution += num_lights;
/* emission area */
float4 *distribution = dscene->light_distribution.resize(num_distribution + 1);
@@ -137,14 +143,16 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
float trianglearea = totarea;
/* point lights */
- float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
-
- for(size_t i = 0; i < scene->lights.size(); i++, offset++) {
- distribution[offset].x = totarea;
- distribution[offset].y = __int_as_float(-i-1);
- distribution[offset].z = 1.0f;
- distribution[offset].w = scene->lights[i]->radius;
- totarea += lightarea;
+ if(!multi_light) {
+ float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
+
+ for(size_t i = 0; i < scene->lights.size(); i++, offset++) {
+ distribution[offset].x = totarea;
+ distribution[offset].y = __int_as_float(-i-1);
+ distribution[offset].z = 1.0f;
+ distribution[offset].w = scene->lights[i]->radius;
+ totarea += lightarea;
+ }
}
/* normalize cumulative distribution functions */
@@ -163,28 +171,40 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* update device */
KernelIntegrator *kintegrator = &dscene->data.integrator;
- kintegrator->use_emission = (totarea > 0.0f);
+ kintegrator->use_emission = (totarea > 0.0f) || (multi_light && num_lights);
if(kintegrator->use_emission) {
/* number of emissives */
- kintegrator->num_triangles = num_triangles;
- kintegrator->num_lights = num_lights;
- kintegrator->num_distribution = num_distribution;
+ kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
/* precompute pdfs */
kintegrator->pdf_triangles = 0.0f;
kintegrator->pdf_lights = 0.0f;
- if(trianglearea > 0.0f) {
- kintegrator->pdf_triangles = 1.0f/trianglearea;
+ if(multi_light) {
+ /* sample one of all triangles and all lights */
+ kintegrator->num_all_lights = num_lights;
+
+ if(trianglearea > 0.0f)
+ kintegrator->pdf_triangles = 1.0f/trianglearea;
if(num_lights)
- kintegrator->pdf_triangles *= 0.5f;
+ kintegrator->pdf_lights = 1.0f;
}
+ else {
+ /* sample one, with 0.5 probability of light or triangle */
+ kintegrator->num_all_lights = 0;
+
+ 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;
+ if(num_lights) {
+ kintegrator->pdf_lights = 1.0f/num_lights;
+ if(trianglearea > 0.0f)
+ kintegrator->pdf_lights *= 0.5f;
+ }
}
/* CDF */
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index b73013fc378..7a6ce547486 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -21,6 +21,7 @@
#include "device.h"
#include "shader.h"
+#include "light.h"
#include "mesh.h"
#include "object.h"
#include "scene.h"
@@ -250,6 +251,10 @@ void Mesh::tag_update(Scene *scene, bool rebuild)
scene->mesh_manager->need_update = true;
scene->object_manager->need_update = true;
+
+ foreach(uint sindex, used_shaders)
+ if(scene->shaders[sindex]->has_surface_emission)
+ scene->light_manager->need_update = true;
}
/* Mesh Manager */
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 0ff774bce59..f2030256814 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1024,7 +1024,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
compiler.add_node(NODE_CLOSURE_BSDF,
compiler.encode_uchar4(closure,
(param1)? param1->stack_offset: SVM_STACK_INVALID,
- (param2)? param2->stack_offset: SVM_STACK_INVALID),
+ (param2)? param2->stack_offset: SVM_STACK_INVALID,
+ compiler.closure_mix_weight_offset()),
__float_as_int((param1)? param1->value.x: 0.0f),
__float_as_int((param2)? param2->value.x: 0.0f));
}
@@ -1222,8 +1223,6 @@ EmissionNode::EmissionNode()
void EmissionNode::compile(SVMCompiler& compiler)
{
- compiler.add_node(NODE_CLOSURE_EMISSION, CLOSURE_EMISSION_ID);
-
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
@@ -1236,6 +1235,8 @@ void EmissionNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_EMISSION_SET_WEIGHT_TOTAL, color_in->value * strength_in->value.x);
else
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value * strength_in->value.x);
+
+ compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
}
void EmissionNode::compile(OSLCompiler& compiler)
@@ -1256,8 +1257,6 @@ BackgroundNode::BackgroundNode()
void BackgroundNode::compile(SVMCompiler& compiler)
{
- compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID);
-
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
@@ -1268,6 +1267,8 @@ void BackgroundNode::compile(SVMCompiler& compiler)
}
else
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value*strength_in->value.x);
+
+ compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID);
}
void BackgroundNode::compile(OSLCompiler& compiler)
@@ -1285,7 +1286,7 @@ HoldoutNode::HoldoutNode()
void HoldoutNode::compile(SVMCompiler& compiler)
{
- compiler.add_node(NODE_CLOSURE_HOLDOUT, CLOSURE_HOLDOUT_ID);
+ compiler.add_node(NODE_CLOSURE_HOLDOUT, compiler.closure_mix_weight_offset());
}
void HoldoutNode::compile(OSLCompiler& compiler)
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index fab051bde72..1059254d5c4 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -17,6 +17,7 @@
*/
#include "device.h"
+#include "light.h"
#include "mesh.h"
#include "object.h"
#include "scene.h"
@@ -83,8 +84,15 @@ void Object::apply_transform()
void Object::tag_update(Scene *scene)
{
- if(mesh && mesh->transform_applied)
- mesh->need_update = true;
+ if(mesh) {
+ if(mesh->transform_applied)
+ mesh->need_update = true;
+
+ foreach(uint sindex, mesh->used_shaders)
+ if(scene->shaders[sindex]->has_surface_emission)
+ scene->light_manager->need_update = true;
+ }
+
scene->mesh_manager->need_update = true;
scene->object_manager->need_update = true;
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 5fb687971ef..5eb8d51a816 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -35,7 +35,7 @@ Session::Session(const SessionParams& params_)
: params(params_),
tile_manager(params.progressive, params.passes, params.tile_size, params.min_size)
{
- device_use_gl = ((params.device_type == DEVICE_CUDA || params.device_type == DEVICE_OPENCL) && !params.background);
+ device_use_gl = ((params.device_type != DEVICE_CPU) && !params.background);
device = Device::create(params.device_type, params.background, params.threads);
buffers = new RenderBuffers(device);
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index 4d5cf434098..ca775939c09 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -58,7 +58,7 @@ public:
background = false;
output_path = "";
- progressive = false;
+ progressive = true;
passes = INT_MAX;
tile_size = 64;
min_size = 64;
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index da52eaecc18..c4188fda421 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -105,6 +105,7 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man
current_type = SHADER_TYPE_SURFACE;
current_shader = NULL;
background = false;
+ mix_weight_offset = SVM_STACK_INVALID;
}
int SVMCompiler::stack_size(ShaderSocketType type)
@@ -419,6 +420,84 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*> done, Stac
}
}
+void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset)
+{
+ /* todo: the weaks point here is that unlike the single closure sampling
+ we will evaluate all nodes even if they are used as input for closures
+ that are unused. it's not clear what would be the best way to skip such
+ nodes at runtime, especially if they are tangled up */
+
+ if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
+ ShaderInput *fin = node->input("Fac");
+ ShaderInput *cl1in = node->input("Closure1");
+ ShaderInput *cl2in = node->input("Closure2");
+
+ uint out1_offset = SVM_STACK_INVALID;
+ uint out2_offset = SVM_STACK_INVALID;
+
+ if(fin) {
+ /* mix closure */
+ set<ShaderNode*> dependencies;
+ find_dependencies(dependencies, done, fin);
+ generate_svm_nodes(dependencies, done);
+
+ stack_assign(fin);
+
+ if(cl1in->link)
+ out1_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
+ if(cl2in->link)
+ out2_offset = stack_find_offset(SHADER_SOCKET_FLOAT);
+
+ add_node(NODE_MIX_CLOSURE,
+ encode_uchar4(fin->stack_offset, in_offset, out1_offset, out2_offset));
+ }
+ else {
+ /* add closure */
+ out1_offset = in_offset;
+ out2_offset = in_offset;
+ }
+
+ if(cl1in->link) {
+ generate_multi_closure(cl1in->link->parent, done, out1_offset);
+
+ if(fin)
+ active_stack.users[out1_offset]--;
+ }
+
+ if(cl2in->link) {
+ generate_multi_closure(cl2in->link->parent, done, out2_offset);
+
+ if(fin)
+ active_stack.users[out2_offset]--;
+ }
+ }
+ else {
+ /* execute dependencies for closure */
+ foreach(ShaderInput *in, node->inputs) {
+ if(!node_skip_input(node, in) && in->link) {
+ set<ShaderNode*> dependencies;
+ find_dependencies(dependencies, done, in);
+ generate_svm_nodes(dependencies, done);
+ }
+ }
+
+ mix_weight_offset = in_offset;
+
+ /* compile closure itself */
+ node->compile(*this);
+ stack_clear_users(node, done);
+ stack_clear_temporary(node);
+
+ mix_weight_offset = SVM_STACK_INVALID;
+
+ if(node->name == ustring("emission"))
+ current_shader->has_surface_emission = true;
+
+ /* end node is added outside of this */
+ }
+}
+
+
void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{
/* Converting a shader graph into svm_nodes that can be executed
@@ -464,21 +543,35 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
}
if(clin->link) {
+ bool generate = false;
if(type == SHADER_TYPE_SURFACE) {
/* generate surface shader */
- generate_closure(clin->link->parent, set<ShaderNode*>(), Stack());
+ generate = true;
shader->has_surface = true;
}
else if(type == SHADER_TYPE_VOLUME) {
/* generate volume shader */
- generate_closure(clin->link->parent, set<ShaderNode*>(), Stack());
+ generate = true;
shader->has_volume = true;
}
else if(type == SHADER_TYPE_DISPLACEMENT) {
/* generate displacement shader */
- generate_closure(clin->link->parent, set<ShaderNode*>(), Stack());
+ generate = true;
shader->has_displacement = true;
}
+
+ if(generate) {
+ set<ShaderNode*> done;
+ bool multi_closure = false; /* __MULTI_CLOSURE__ */
+
+ if(multi_closure) {
+ generate_multi_closure(clin->link->parent, done, SVM_STACK_INVALID);
+ }
+ else {
+ Stack stack;
+ generate_closure(clin->link->parent, done, stack);
+ }
+ }
}
/* compile output node */
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index f76649e4a6f..05fb85b057f 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -24,6 +24,7 @@
#include "shader.h"
#include "util_set.h"
+#include "util_string.h"
CCL_NAMESPACE_BEGIN
@@ -65,6 +66,7 @@ public:
uint attribute(ustring name);
uint attribute(Attribute::Standard std);
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; }
@@ -75,6 +77,8 @@ public:
protected:
struct Stack {
+ Stack() { memset(users, 0, sizeof(users)); }
+
int users[SVM_STACK_SIZE];
};
@@ -88,6 +92,7 @@ protected:
void find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input);
void generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done);
void generate_closure(ShaderNode *node, set<ShaderNode*> done, Stack stack);
+ void generate_multi_closure(ShaderNode *node, set<ShaderNode*>& done, uint in_offset);
void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
@@ -96,6 +101,7 @@ protected:
Shader *current_shader;
Stack active_stack;
int max_stack_use;
+ uint mix_weight_offset;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index 450090c42f8..61f3af7aa10 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -96,7 +96,7 @@ void TileManager::set_tiles()
bool TileManager::done()
{
- return (state.pass+1 >= passes);
+ return (state.pass+1 >= passes && state.resolution == 1);
}
bool TileManager::next()
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index 90093e32d58..d3f739e19f6 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -109,11 +109,16 @@ string path_files_md5_hash(const string& dir)
return hash.get_hex();
}
-bool path_write_binary(const string& path, const vector<uint8_t>& binary)
+void path_create_directories(const string& path)
{
- /* write binary file from memory */
boost::filesystem::create_directories(path_dirname(path));
+}
+bool path_write_binary(const string& path, const vector<uint8_t>& binary)
+{
+ path_create_directories(path);
+
+ /* write binary file from memory */
FILE *f = fopen(path.c_str(), "wb");
if(!f)
diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h
index a91b91461fa..4a9d45ec594 100644
--- a/intern/cycles/util/util_path.h
+++ b/intern/cycles/util/util_path.h
@@ -42,6 +42,7 @@ string path_escape(const string& path);
bool path_exists(const string& path);
string path_files_md5_hash(const string& dir);
+void path_create_directories(const string& path);
bool path_write_binary(const string& path, const vector<uint8_t>& binary);
bool path_read_binary(const string& path, vector<uint8_t>& binary);