* Fix missing update when editing objects with emission materials.
* Fix preview pass rendering set to 1 not showing full resolution.
* Fix CUDA runtime compiling failing due to missing cache directory.
* Use settings from first render layer for visibility and material override.

And a bunch of incomplete and still disabled code mostly related to closure
sampling.
This commit is contained in:
Brecht Van Lommel
2011-09-12 13:13:56 +00:00
parent c40492205b
commit ebc653463d
43 changed files with 1239 additions and 712 deletions

View File

@@ -207,11 +207,10 @@ option(WITH_API_INSTALL "Copy API header files into the blender install fold
# Cycles # Cycles
option(WITH_CYCLES "Enable Cycles Render Engine" ON) option(WITH_CYCLES "Enable Cycles Render Engine" ON)
OPTION(WITH_CYCLES_OSL "Build with Open Shading Language support" OFF) 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_BLENDER "Build Blender Python extension" ON)
OPTION(WITH_CYCLES_PARTIO "Build with Partio point cloud support (unfinished)" OFF) 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_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) OPTION(WITH_CYCLES_TEST "Build cycles test application" OFF)
# disable for now, but plan to support on all platforms eventually # disable for now, but plan to support on all platforms eventually

View File

@@ -41,10 +41,6 @@ if(WITH_CYCLES_NETWORK)
add_definitions(-DWITH_NETWORK) add_definitions(-DWITH_NETWORK)
endif() endif()
if(WITH_CYCLES_MULTI)
add_definitions(-DWITH_MULTI)
endif()
if(WITH_CYCLES_CUDA) if(WITH_CYCLES_CUDA)
add_definitions(-DWITH_CUDA_BINARIES) add_definitions(-DWITH_CUDA_BINARIES)
endif() endif()
@@ -59,6 +55,7 @@ endif()
add_definitions(-DWITH_OPENCL) add_definitions(-DWITH_OPENCL)
add_definitions(-DWITH_CUDA) add_definitions(-DWITH_CUDA)
add_definitions(-DWITH_MULTI)
include_directories( include_directories(
${BOOST_INCLUDE_DIR} ${BOOST_INCLUDE_DIR}

View File

@@ -140,6 +140,42 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(cscene, "debug_bvh_type", text="") sub.prop(cscene, "debug_bvh_type", text="")
sub.prop(cscene, "debug_use_spatial_splits") 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): class Cycles_PT_post_processing(CyclesButtonsPanel, Panel):
bl_label = "Post Processing" bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'} bl_options = {'DEFAULT_CLOSED'}

View File

@@ -223,8 +223,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
vector<uint> used_shaders; vector<uint> used_shaders;
BL::Object::material_slots_iterator slot; BL::Object::material_slots_iterator slot;
for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
find_shader(slot->material(), used_shaders); 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) if(used_shaders.size() == 0)
used_shaders.push_back(scene->default_surface); used_shaders.push_back(scene->default_surface);

View File

@@ -108,7 +108,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
/* Object */ /* 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 */ /* light is handled separately */
if(object_is_light(b_ob)) { 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->name = b_ob.name();
object->tfm = tfm; 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) if(b_parent.ptr.data != b_ob.ptr.data)
object->visibility &= object_ray_visibility(b_parent); 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) void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
{ {
/* layer data */ /* layer data */
uint layer; uint scene_layer = render_layer.scene_layer;
uint layer = render_layer.layer;
if(b_v3d)
layer = get_layer(b_v3d.layers());
else
layer = get_layer(b_scene.layers());
/* prepare for sync */ /* prepare for sync */
light_map.pre_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) { 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(); 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()) { if(b_ob->is_duplicator()) {
/* dupli objects */ /* dupli objects */
object_create_duplilist(*b_ob, b_scene); 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) { for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) {
Transform tfm = get_transform(b_dup->matrix()); 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++; b_index++;
} }
@@ -185,7 +187,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d)
else { else {
/* object itself */ /* object itself */
Transform tfm = get_transform(b_ob->matrix_world()); 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);
} }
} }
} }

View File

@@ -118,6 +118,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d)
{ {
sync_integrator(); sync_integrator();
sync_film(); sync_film();
sync_render_layer(b_v3d);
sync_shaders(); sync_shaders();
sync_objects(b_v3d); sync_objects(b_v3d);
} }
@@ -172,6 +173,29 @@ void BlenderSync::sync_film()
filter->tag_update(scene); 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 */ /* Scene Parameters */
SceneParams BlenderSync::get_scene_params(BL::Scene b_scene) SceneParams BlenderSync::get_scene_params(BL::Scene b_scene)

View File

@@ -72,11 +72,12 @@ private:
void sync_integrator(); void sync_integrator();
void sync_view(); void sync_view();
void sync_world(); void sync_world();
void sync_render_layer(BL::SpaceView3D b_v3d);
void sync_shaders(); void sync_shaders();
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
Mesh *sync_mesh(BL::Object b_ob, bool object_updated); 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); void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
/* util */ /* util */
@@ -99,6 +100,17 @@ private:
Scene *scene; Scene *scene;
bool preview; 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 CCL_NAMESPACE_END

View File

@@ -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) 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) 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); glPixelZoom((float)width/(float)w, (float)height/(float)h);
glRasterPos2f(0, y); 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); glRasterPos2f(0.0f, 0.0f);
glPixelZoom(1.0f, 1.0f); glPixelZoom(1.0f, 1.0f);

View File

@@ -232,11 +232,16 @@ public:
double starttime = time_dt(); double starttime = time_dt();
printf("Compiling CUDA kernel ...\n"); 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 " 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", "-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()); 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 */ /* verify if compilation succeeded */
if(!path_exists(cubin)) { if(!path_exists(cubin)) {
@@ -708,9 +713,13 @@ public:
cuda_push_context(); 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); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pmem.cuPBO);
glBindTexture(GL_TEXTURE_2D, pmem.cuTexId); 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); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
@@ -729,11 +738,11 @@ public:
glTexCoord2f(0.0f, 0.0f); glTexCoord2f(0.0f, 0.0f);
glVertex2f(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); 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); 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); glVertex2f(0.0f, (float)height);
glEnd(); glEnd();

View File

@@ -47,9 +47,6 @@ public:
MultiDevice(bool background_) MultiDevice(bool background_)
: unique_ptr(1) : unique_ptr(1)
{ {
/* enforce background for now */
background = true;
Device *device; Device *device;
/* add CPU device */ /* add CPU device */
@@ -125,6 +122,15 @@ public:
return desc.str(); 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) void mem_alloc(device_memory& mem, MemoryType type)
{ {
foreach(SubDevice& sub, devices) { foreach(SubDevice& sub, devices) {
@@ -219,12 +225,26 @@ public:
void pixels_alloc(device_memory& mem) 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) 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) void pixels_copy_from(device_memory& mem, int y, int w, int h)
@@ -248,14 +268,16 @@ public:
{ {
device_ptr tmp = rgba.device_pointer; device_ptr tmp = rgba.device_pointer;
int i = 0, sub_h = h/devices.size(); int i = 0, sub_h = h/devices.size();
int sub_height = height/devices.size();
foreach(SubDevice& sub, devices) { foreach(SubDevice& sub, devices) {
int sy = y + i*sub_h; int sy = y + i*sub_h;
int sh = (i == (int)devices.size() - 1)? h - sub_h*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 */ /* adjust math for w/width */
rgba.device_pointer = sub.ptr_map[tmp]; 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++; i++;
} }

View File

@@ -46,20 +46,29 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
return eval; return eval;
} }
__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, float randt, float rando, __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
float randu, float randv, Ray *ray, float3 *eval) float randt, float rando, float randu, float randv, Ray *ray, float3 *eval)
{ {
/* sample a position on a light */
LightSample ls; 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 */ /* compute incoming direction and distance */
float t; float t;
float3 omega_in = normalize_len(ls.P - sd->P, &t); float3 omega_in = normalize_len(ls.P - sd->P, &t);
/* compute pdf */ /* compute pdf */
float pdf = light_pdf(kg, &ls, -omega_in, t); float pdf = light_sample_pdf(kg, &ls, -omega_in, t);
/* evaluate closure */ /* evaluate closure */
*eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -omega_in); *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) if(is_zero(*eval) || pdf == 0.0f)
return false; return false;
/* todo: use visbility flag to skip lights */
/* evaluate BSDF at shading point */ /* evaluate BSDF at shading point */
float bsdf_pdf; float bsdf_pdf;
float3 bsdf_eval = shader_bsdf_eval(kg, sd, omega_in, &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; *eval *= 0.25f;
} }
/* setup ray */ #if 0
ray->P = ray_offset(sd->P, sd->Ng); /* todo: implement this in light */
ray->D = ray_offset(ls.P, ls.Ng) - ray->P; bool no_shadow = true;
ray->D = normalize_len(ray->D, &ray->t);
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; return true;
} }

View File

@@ -20,7 +20,7 @@
#ifdef __KERNEL_CPU__ #ifdef __KERNEL_CPU__
#ifdef WITH_OSL #ifdef __OSL__
#include "osl_globals.h" #include "osl_globals.h"
#endif #endif
@@ -43,7 +43,7 @@ typedef struct KernelGlobals {
KernelData __data; KernelData __data;
#ifdef WITH_OSL #ifdef __OSL__
/* On the CPU, we also have the OSL globals here. Most data structures are shared /* 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. */ with SVM, the difference is in the shaders and object/mesh attributes. */
OSLGlobals osl; OSLGlobals osl;

View File

@@ -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; float pdf;
@@ -141,5 +141,15 @@ __device float light_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
return pdf; 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 CCL_NAMESPACE_END

View File

@@ -162,6 +162,86 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
return average(throughput); 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) __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
{ {
/* initialize */ /* initialize */
@@ -247,13 +327,22 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
Ray light_ray; Ray light_ray;
float3 light_L; 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)) { for(; i < kernel_data.integrator.num_all_lights; i++) {
/* trace shadow ray */ #else
if(!scene_intersect(kg, &light_ray, PATH_RAY_SHADOW, &isect)) const int i = -1;
L += throughput*light_L; #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 #endif

View File

@@ -26,14 +26,19 @@
* *
*/ */
#ifdef __OSL__
#include "osl_shader.h"
#else
#include "svm/bsdf.h" #include "svm/bsdf.h"
#include "svm/emissive.h" #include "svm/emissive.h"
#include "svm/volume.h" #include "svm/volume.h"
#include "svm/svm_bsdf.h" #include "svm/svm_bsdf.h"
#include "svm/svm.h" #include "svm/svm.h"
#ifdef WITH_OSL
#include "osl_shader.h"
#endif #endif
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
@@ -270,96 +275,201 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
/* BSDF */ /* BSDF */
__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, #ifdef __MULTI_CLOSURE__
float randu, float randv, float3 *eval,
float3 *omega_in, differential3 *domega_in, float *pdf) __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(CLOSURE_IS_BSDF(sc->type)) {
if(kg->osl.use) float bsdf_pdf = 0.0f;
label = OSLShader::bsdf_sample(sd, randu, randv, *eval, *omega_in, *domega_in, *pdf); #ifdef __OSL__
else float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf);
#else
float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
#endif #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, __device float3 shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
const float3 omega_in, float *pdf) 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
}
__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; *pdf = 0.0f;
#ifdef __OSL__
#ifdef WITH_OSL label = OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
if(kg->osl.use) #else
eval = OSLShader::bsdf_eval(sd, omega_in, *pdf); label = svm_bsdf_sample(sd, sc, randu, randv, eval, omega_in, domega_in, pdf);
else
#endif #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) __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
{ {
#ifdef WITH_OSL #ifndef __OSL__
if(!kg->osl.use) #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 #endif
svm_bsdf_blur(sd, roughness);
} }
__device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *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
}
/* Emission */ /* Emission */
__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
{ {
#ifdef WITH_OSL #ifdef __MULTI_CLOSURE__
if(kg->osl.use) { float3 eval = make_float3(0.0f, 0.0f, 0.0f);
return OSLShader::emissive_eval(sd);
}
else
#endif
{
return svm_emissive_eval(sd);
}
}
__device void shader_emissive_sample(KernelGlobals *kg, ShaderData *sd, for(int i = 0; i < sd->num_closure; i++) {
float randu, float randv, float3 *eval, float3 *I, float *pdf) ShaderClosure *sc = &sd->closure[i];
{
#ifdef WITH_OSL if(CLOSURE_IS_EMISSION(sc->type)) {
if(kg->osl.use) { #ifdef __OSL__
OSLShader::emissive_sample(sd, randu, randv, eval, I, pdf); eval += OSLShader::emissive_eval(sd)*sc->weight;
} #else
else eval += svm_emissive_eval(sd, sc)*sc->weight;
#endif #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 */ /* Holdout */
__device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd) __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
{ {
#ifdef WITH_OSL #ifdef __MULTI_CLOSURE__
if(kg->osl.use) { float3 weight = make_float3(0.0f, 0.0f, 0.0f);
return OSLShader::holdout_eval(sd);
for(int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_HOLDOUT(sc->type))
weight += sc->weight;
} }
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 #endif
{
#ifdef __SVM__
if(sd->svm_closure == CLOSURE_HOLDOUT_ID)
return make_float3(1.0f, 1.0f, 1.0f);
else
#endif
return make_float3(0.0f, 0.0f, 0.0f);
}
} }
/* Surface Evaluation */ /* Surface Evaluation */
@@ -367,54 +477,54 @@ __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
__device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
float randb, int path_flag) float randb, int path_flag)
{ {
#ifdef WITH_OSL #ifdef __OSL__
if(kg->osl.use) { OSLShader::eval_surface(kg, sd, randb, path_flag);
OSLShader::eval_surface(kg, sd, randb, path_flag);
}
else
#endif
{
#ifdef __SVM__
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
#else #else
bsdf_diffuse_setup(sd, sd->N);
sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f); #ifdef __SVM__
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
#else
bsdf_diffuse_setup(sd, &sd->closure);
sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f);
#endif #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 #endif
}
} }
/* Background Evaluation */ /* Background Evaluation */
__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
{ {
#ifdef WITH_OSL #ifdef __OSL__
if(kg->osl.use) { return OSLShader::eval_background(kg, sd, path_flag);
return OSLShader::eval_background(kg, sd, path_flag);
}
else
#endif
{
#ifdef __SVM__
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
#else #else
sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
#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 #endif
return sd->svm_closure_weight; #else
} return make_float3(0.8f, 0.8f, 0.8f);
#endif
#endif
} }
/* Volume */ /* 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, __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
float3 omega_in, float3 omega_out) float3 omega_in, float3 omega_out)
{ {
#ifdef WITH_OSL #ifdef __MULTI_CLOSURE__
if(kg->osl.use) { float3 eval = make_float3(0.0f, 0.0f, 0.0f);
OSLShader::volume_eval_phase(sd, omega_in, omega_out);
} for(int i = 0; i< sd->num_closure; i++) {
else 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 #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 */ /* 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, __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
float randb, int path_flag) float randb, int path_flag)
{ {
#ifdef WITH_OSL
if(kg->osl.use) {
OSLShader::eval_volume(kg, sd, randb, path_flag);
}
else
#endif
{
#ifdef __SVM__ #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 #endif
}
} }
/* Displacement Evaluation */ /* Displacement Evaluation */
@@ -456,27 +572,21 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd) __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
{ {
/* this will modify sd->P */ /* this will modify sd->P */
#ifdef WITH_OSL
if(kg->osl.use) {
OSLShader::eval_displacement(kg, sd);
}
else
#endif
{
#ifdef __SVM__ #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 #endif
}
} }
/* Free ShaderData */ /* Free ShaderData */
__device void shader_release(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd)
{ {
#ifdef WITH_OSL #ifdef __OSL__
if(kg->osl.use) OSLShader::release(kg, sd);
OSLShader::release(kg, sd);
#endif #endif
} }

View File

@@ -34,6 +34,9 @@ CCL_NAMESPACE_BEGIN
#define __BACKGROUND__ #define __BACKGROUND__
#define __CAUSTICS_TRICKS__ #define __CAUSTICS_TRICKS__
#define __VISIBILITY_FLAG__ #define __VISIBILITY_FLAG__
#define __RAY_DIFFERENTIALS__
#define __CAMERA_CLIPPING__
#define __INTERSECTION_REFINE__
#ifndef __KERNEL_OPENCL__ #ifndef __KERNEL_OPENCL__
#define __SVM__ #define __SVM__
@@ -42,9 +45,13 @@ CCL_NAMESPACE_BEGIN
#define __HOLDOUT__ #define __HOLDOUT__
#endif #endif
#define __RAY_DIFFERENTIALS__ #ifdef __KERNEL_CPU__
#define __CAMERA_CLIPPING__ //#define __MULTI_CLOSURE__
#define __INTERSECTION_REFINE__ //#define __MULTI_LIGHT__
//#define __TRANSPARENT_SHADOWS__
//#define __OSL__
#endif
//#define __SOBOL_FULL_SCREEN__ //#define __SOBOL_FULL_SCREEN__
//#define __MODIFY_TP__ //#define __MODIFY_TP__
//#define __QBVH__ //#define __QBVH__
@@ -179,20 +186,27 @@ typedef enum AttributeElement {
ATTR_ELEMENT_NONE ATTR_ELEMENT_NONE
} AttributeElement; } AttributeElement;
/* OSL data */ /* Closure data */
#if !defined(__KERNEL_GPU__) && defined(WITH_OSL) #define MAX_CLOSURE 8
#define MAX_OSL_CLOSURE 8 typedef struct ShaderClosure {
ClosureType type;
struct FlatClosure {
void *prim;
float3 weight; float3 weight;
float sample_weight;
};
#ifdef __MULTI_CLOSURE__
float sample_weight;
#endif #endif
#ifdef __OSL__
void *prim;
#else
float data0;
float data1;
#endif
} ShaderClosure;
/* Shader Data /* Shader Data
* *
* Main shader state at a point on the surface or in a volume. All coordinates * 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; float3 dPdu, dPdv;
#endif #endif
/* SVM closure data. we always sample a single closure, to get fixed #ifdef __MULTI_CLOSURE__
* memory usage, svm_closure_data contains closure parameters. */ /* Closure data, we store a fixed array of closures */
ClosureType svm_closure; ShaderClosure closure[MAX_CLOSURE];
float3 svm_closure_weight; int num_closure;
float svm_closure_data0; float randb_closure;
float svm_closure_data1; #else
/* Closure data, with a single sampled closure for low memory usage */
#if !defined(__KERNEL_GPU__) && defined(WITH_OSL) ShaderClosure closure;
/* OSL closure data and context. we store all closures flattened into #endif
* 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 __OSL__
/* OSL context */
void *osl_ctx; void *osl_ctx;
#endif #endif
} ShaderData; } ShaderData;
@@ -352,11 +350,11 @@ typedef struct KernelSunSky {
typedef struct KernelIntegrator { typedef struct KernelIntegrator {
/* emission */ /* emission */
int use_emission; int use_emission;
int num_triangles;
int num_distribution; int num_distribution;
int num_lights; int num_all_lights;
float pdf_triangles; float pdf_triangles;
float pdf_lights; float pdf_lights;
float pdf_pad;
/* bounces */ /* bounces */
int min_bounce; int min_bounce;

View File

@@ -119,13 +119,13 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if(prim) { if(prim) {
FlatClosure flat; ShaderClosure sc;
flat.prim = prim; sc.prim = prim;
flat.weight = weight; sc.weight = weight;
switch(prim->category()) { switch(prim->category()) {
case ClosurePrimitive::BSDF: { case ClosurePrimitive::BSDF: {
if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE) if(sd->num_closure == MAX_CLOSURE)
return; return;
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim; 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_weight = fabsf(average(weight))*albedo;
float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight; 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; sd->osl_closure.bsdf_sample_sum = sample_sum;
/* scattering flags */ /* scattering flags */
@@ -152,29 +153,35 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->flag |= SD_BSDF; sd->flag |= SD_BSDF;
/* add */ /* add */
sd->osl_closure.bsdf[sd->osl_closure.num_bsdf++] = flat; sd->closure[sd->num_closure++] = sc;
break; break;
} }
case ClosurePrimitive::Emissive: { case ClosurePrimitive::Emissive: {
if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE) if(sd->num_closure == MAX_CLOSURE)
return; return;
/* sample weight */ /* sample weight */
float sample_weight = fabsf(average(weight)); float sample_weight = fabsf(average(weight));
float sample_sum = sd->osl_closure.emissive_sample_sum + sample_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; sd->osl_closure.emissive_sample_sum = sample_sum;
/* flag */ /* flag */
sd->flag |= SD_EMISSION; sd->flag |= SD_EMISSION;
sd->osl_closure.emissive[sd->osl_closure.num_emissive++] = flat; sd->closure[sd->num_closure++] = sc;
break; break;
} }
case ClosurePrimitive::Holdout: 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->flag |= SD_HOLDOUT;
sd->closure[sd->num_closure++] = sc;
break; break;
case ClosurePrimitive::BSSRDF: case ClosurePrimitive::BSSRDF:
case ClosurePrimitive::Debug: 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); ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
/* flatten closure tree */ /* flatten closure tree */
sd->osl_closure.bsdf_sample_sum = 0.0f; sd->num_closure = 0;
sd->osl_closure.emissive_sample_sum = 0.0f; sd->randb_closure = randb;
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;
if(globals->Ci) { if(globals->Ci) {
bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics; 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(); OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data();
if(prim) { if(prim) {
FlatClosure flat; ShaderClosure sc;
flat.prim = prim; sc.prim = prim;
flat.weight = weight; sc.weight = weight;
switch(prim->category()) { switch(prim->category()) {
case ClosurePrimitive::Volume: { case ClosurePrimitive::Volume: {
if(sd->osl_closure.num_bsdf == MAX_OSL_CLOSURE) if(sd->num_closure == MAX_CLOSURE)
return; return;
/* sample weight */ /* sample weight */
float sample_weight = fabsf(average(weight)); float sample_weight = fabsf(average(weight));
float sample_sum = sd->osl_closure.volume_sample_sum + sample_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; sd->osl_closure.volume_sample_sum = sample_sum;
/* add */ /* add */
sd->osl_closure.volume[sd->osl_closure.num_volume++] = flat; sd->closure[sd->num_closure++] = sc;
break; break;
} }
case ClosurePrimitive::Holdout: case ClosurePrimitive::Holdout:
@@ -389,183 +393,76 @@ void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
/* BSDF Closure */ /* 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; int label = LABEL_NONE;
float r = sd->osl_closure.randb*sd->osl_closure.bsdf_sample_sum;
float sample_sum = 0.0f;
pdf = 0.0f; pdf = 0.0f;
if(sd->osl_closure.bsdf_sample_sum == 0.0f) /* sample BSDF closure */
return LABEL_NONE; ustring ulabel;
/* find a closure to sample */ ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
for(int i = 0; i < sd->osl_closure.num_bsdf; i++) { TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
const FlatClosure *flat = &sd->osl_closure.bsdf[i]; randu, randv,
sample_sum += flat->sample_weight; TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
pdf, TO_COLOR3(eval));
if(r > sample_sum) /* convert OSL label */
continue; if(ulabel == OSL::Labels::REFLECT)
label = LABEL_REFLECT;
else if(ulabel == OSL::Labels::TRANSMIT)
label = LABEL_TRANSMIT;
else
return LABEL_NONE; /* sampling failed */
/* sample BSDF closure */ /* convert scattering to our bitflag label */
sample_bsdf = (OSL::BSDFClosure*)flat->prim; ustring uscattering = sample_bsdf->scattering();
ustring ulabel;
ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng), if(uscattering == OSL::Labels::DIFFUSE)
TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), label |= LABEL_DIFFUSE;
randu, randv, else if(uscattering == OSL::Labels::GLOSSY)
TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy), label |= LABEL_GLOSSY;
pdf, TO_COLOR3(eval)); else if(uscattering == OSL::Labels::SINGULAR)
label |= LABEL_SINGULAR;
/* convert OSL label */ else
if(ulabel == OSL::Labels::REFLECT) label |= LABEL_TRANSPARENT;
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);
return label; 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); OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim;
OSL::Color3 bsdf_eval;
pdf = 0.0f; if(dot(sd->Ng, omega_in) >= 0.0f)
bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
for(int i = 0; i < sd->osl_closure.num_bsdf; i++) { else
const FlatClosure *flat = &sd->osl_closure.bsdf[i]; bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)flat->prim;
OSL::Color3 bsdf_eval; return TO_FLOAT3(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;
return eval;
} }
/* Emissive Closure */ /* 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); OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)sc->prim;
OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
for(int i = 0; i < sd->osl_closure.num_emissive; i++) { eval += TO_FLOAT3(emissive_eval);
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;
}
return 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 */ /* Volume Closure */
float3 OSLShader::volume_eval_phase(const ShaderData *sd, const float3 omega_in, const float3 omega_out) float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
{ {
float3 eval = make_float3(0.0f, 0.0f, 0.0f); OSL::VolumeClosure *volume = (OSL::VolumeClosure*)sc->prim;
OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
for(int i = 0; i < sd->osl_closure.num_volume; i++) { return TO_FLOAT3(volume_eval)*sc->weight;
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)
{
return sd->osl_closure.holdout_weight;
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -46,6 +46,7 @@ namespace OSL = ::OSL;
class OSLRenderServices; class OSLRenderServices;
class Scene; class Scene;
class ShaderClosure;
class ShaderData; class ShaderData;
class differential3; class differential3;
class KernelGlobals; class KernelGlobals;
@@ -66,15 +67,16 @@ public:
static void eval_displacement(KernelGlobals *kg, ShaderData *sd); static void eval_displacement(KernelGlobals *kg, ShaderData *sd);
/* sample & eval */ /* 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); 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 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
static float3 emissive_eval(const ShaderData *sd); const float3& omega_in, float& pdf);
static void emissive_sample(const ShaderData *sd, float randu, float randv,
float3 *eval, float3 *I, float *pdf); static float3 emissive_eval(const ShaderData *sd, const ShaderClosure *sc);
static float3 volume_eval_phase(const ShaderData *sd, const float3 omega_in,
const float3 omega_out); static float3 volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc,
static float3 holdout_eval(const ShaderData *sd); const float3 omega_in, const float3 omega_out);
/* release */ /* release */
static void release(KernelGlobals *kg, const ShaderData *sd); static void release(KernelGlobals *kg, const ShaderData *sd);

View File

@@ -40,24 +40,24 @@ typedef struct BsdfAshikhminVelvetClosure {
float m_invsigma2; float m_invsigma2;
} BsdfAshikhminVelvetClosure; } 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); sigma = fmaxf(sigma, 0.01f);
float m_invsigma2 = 1.0f/(sigma * sigma); 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->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; float3 m_N = sd->N;
float cosNO = dot(m_N, I); 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); 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); 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; 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; float3 m_N = sd->N;
// we are viewing the surface from above - send a ray out with uniform // we are viewing the surface from above - send a ray out with uniform

View File

@@ -41,17 +41,17 @@ typedef struct BsdfDiffuseClosure {
//float3 m_N; //float3 m_N;
} BsdfDiffuseClosure; } 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; 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; 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); 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); 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; 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; float3 m_N = sd->N;
@@ -99,22 +99,22 @@ typedef struct BsdfTranslucentClosure {
//float3 m_N; //float3 m_N;
} BsdfTranslucentClosure; } 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; 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); 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; 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); 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; 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; float3 m_N = sd->N;

View File

@@ -43,34 +43,34 @@ typedef struct BsdfMicrofacetGGXClosure {
float m_eta; float m_eta;
} BsdfMicrofacetGGXClosure; } 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_ag = clamp(ag, 1e-5f, 1.0f);
float m_eta = eta; float m_eta = eta;
sd->svm_closure_data0 = m_ag; sc->data0 = m_ag;
sd->svm_closure_data1 = m_eta; sc->data1 = m_eta;
if(refractive) if(refractive)
sd->svm_closure = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
else 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; 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); 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_ag = sc->data0;
//float m_eta = sd->svm_closure_data1; //float m_eta = sc->data1;
int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sd->N;
if(m_refractive) return make_float3 (0, 0, 0); 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); 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_ag = sc->data0;
float m_eta = sd->svm_closure_data1; float m_eta = sc->data1;
int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sd->N;
if(!m_refractive) return make_float3 (0, 0, 0); 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); 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; 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_ag = sc->data0;
float m_eta = sd->svm_closure_data1; float m_eta = sc->data1;
int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sd->N;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);
@@ -268,34 +268,34 @@ typedef struct BsdfMicrofacetBeckmannClosure {
float m_eta; float m_eta;
} BsdfMicrofacetBeckmannClosure; } 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_ab = clamp(ab, 1e-5f, 1.0f);
float m_eta = eta; float m_eta = eta;
sd->svm_closure_data0 = m_ab; sc->data0 = m_ab;
sd->svm_closure_data1 = m_eta; sc->data1 = m_eta;
if(refractive) if(refractive)
sd->svm_closure = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
else 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; 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); 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_ab = sc->data0;
//float m_eta = sd->svm_closure_data1; //float m_eta = sc->data1;
int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sd->N;
if(m_refractive) return make_float3 (0, 0, 0); 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); 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_ab = sc->data0;
float m_eta = sd->svm_closure_data1; float m_eta = sc->data1;
int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sd->N;
if(!m_refractive) return make_float3 (0, 0, 0); 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); 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; 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_ab = sc->data0;
float m_eta = sd->svm_closure_data1; float m_eta = sc->data1;
int m_refractive = sd->svm_closure == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID; int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
float3 m_N = sd->N; float3 m_N = sd->N;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);

View File

@@ -41,34 +41,34 @@ typedef struct BsdfReflectionClosure {
//float3 m_N; //float3 m_N;
} BsdfReflectionClosure; } 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; 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); 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); 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; 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; float3 m_N = sd->N;
// only one direction is possible // only one direction is possible

View File

@@ -41,36 +41,36 @@ typedef struct BsdfRefractionClosure {
float m_eta; float m_eta;
} BsdfRefractionClosure; } 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; 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); 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); 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; 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 m_N = sd->N;
float3 R, T; float3 R, T;

View File

@@ -35,32 +35,32 @@
CCL_NAMESPACE_BEGIN 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; 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); 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); 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; 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 // only one direction is possible
*omega_in = -sd->I; *omega_in = -sd->I;

View File

@@ -44,28 +44,28 @@ typedef struct BsdfWardClosure {
float m_ay; float m_ay;
} BsdfWardClosure; } 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_ax = clamp(ax, 1e-5f, 1.0f);
float m_ay = clamp(ay, 1e-5f, 1.0f); float m_ay = clamp(ay, 1e-5f, 1.0f);
sd->svm_closure_data0 = m_ax; sc->data0 = m_ax;
sd->svm_closure_data1 = m_ay; 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; 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); sc->data0 = fmaxf(roughness, sc->data0);
sd->svm_closure_data1 = fmaxf(roughness, sd->svm_closure_data1); 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_ax = sc->data0;
float m_ay = sd->svm_closure_data1; float m_ay = sc->data1;
float3 m_N = sd->N; float3 m_N = sd->N;
float3 m_T = normalize(sd->dPdu); 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); 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); 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; 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_ax = sc->data0;
float m_ay = sd->svm_closure_data1; float m_ay = sc->data1;
float3 m_N = sd->N; float3 m_N = sd->N;
float3 m_T = normalize(sd->dPdu); float3 m_T = normalize(sd->dPdu);

View File

@@ -42,26 +42,26 @@ typedef struct BsdfWestinBackscatterClosure {
float m_invroughness; float m_invroughness;
} BsdfWestinBackscatterClosure; } 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); roughness = clamp(roughness, 1e-5f, 1.0f);
float m_invroughness = 1.0f/roughness; 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->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); 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; float3 m_N = sd->N;
// pdf is implicitly 0 (no indirect sampling) // 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); 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); 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; 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; float3 m_N = sd->N;
float cosNO = dot(m_N, sd->I); float cosNO = dot(m_N, sd->I);
@@ -137,20 +137,20 @@ typedef struct BsdfWestinSheenClosure {
float m_edginess; float m_edginess;
} BsdfWestinSheenClosure; } 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->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; float3 m_N = sd->N;
// pdf is implicitly 0 (no indirect sampling) // 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); 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); 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; 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; float3 m_N = sd->N;
// we are viewing the surface from the right side - send a ray out with cosine // we are viewing the surface from the right side - send a ray out with cosine

View File

@@ -42,23 +42,6 @@ __device float3 emissive_eval(const float3 Ng, const float3 I)
return make_float3(res, res, res); 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, /// Return the probability distribution function in the direction I,
/// given the parameters and the light's surface normal. This MUST match /// given the parameters and the light's surface normal. This MUST match
/// the PDF computed by sample(). /// 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; return (cosNO > 0.0f)? M_1_PI_F: 0.0f;
} }
__device float3 svm_emissive_eval(ShaderData *sd) __device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc)
{ {
return sd->svm_closure_weight*emissive_eval(sd->Ng, sd->I); return emissive_eval(sd->Ng, sd->I);
}
__device void svm_emissive_sample(ShaderData *sd, float randu, float randv, float3 *eval, float3 *I, float *pdf)
{
*eval = sd->svm_closure_weight;
emissive_sample(sd->Ng, randu, randv, I, pdf);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -47,14 +47,14 @@ CCL_NAMESPACE_BEGIN
/* Stack */ /* 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); kernel_assert(a+2 < SVM_STACK_SIZE);
return make_float3(stack[a+0], stack[a+1], stack[a+2]); 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); 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; 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); kernel_assert(a < SVM_STACK_SIZE);
return stack[a]; 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); 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); kernel_assert(a < SVM_STACK_SIZE);
stack[a] = f; stack[a] = f;
} }
__device bool stack_valid(uint a) __device_inline bool stack_valid(uint a)
{ {
return a != (uint)SVM_STACK_INVALID; return a != (uint)SVM_STACK_INVALID;
} }
/* Reading Nodes */ /* 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); uint4 node = kernel_tex_fetch(__svm_nodes, *offset);
(*offset)++; (*offset)++;
return node; 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); 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)); 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; 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(x) *x = (i & 0xFF);
if(y) *y = ((i >> 8) & 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; float closure_weight = 1.0f;
int offset = sd->shader; int offset = sd->shader;
sd->svm_closure = NBUILTIN_CLOSURES; #ifdef __MULTI_CLOSURE__
sd->svm_closure_weight = make_float3(0.0f, 0.0f, 0.0f); sd->num_closure = 0;
sd->randb_closure = randb;
#else
sd->closure.type = NBUILTIN_CLOSURES;
#endif
while(1) { while(1) {
uint4 node = read_node(kg, &offset); uint4 node = read_node(kg, &offset);
@@ -169,16 +173,16 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
break; break;
} }
case NODE_CLOSURE_BSDF: case NODE_CLOSURE_BSDF:
svm_node_closure_bsdf(sd, stack, node, randb); svm_node_closure_bsdf(kg, sd, stack, node, randb, path_flag);
break; break;
case NODE_CLOSURE_EMISSION: case NODE_CLOSURE_EMISSION:
svm_node_closure_emission(sd); svm_node_closure_emission(sd, stack, node);
break; break;
case NODE_CLOSURE_BACKGROUND: case NODE_CLOSURE_BACKGROUND:
svm_node_closure_background(sd); svm_node_closure_background(sd, node);
break; break;
case NODE_CLOSURE_HOLDOUT: case NODE_CLOSURE_HOLDOUT:
svm_node_closure_holdout(sd); svm_node_closure_holdout(sd, stack, node);
break; break;
case NODE_CLOSURE_SET_WEIGHT: case NODE_CLOSURE_SET_WEIGHT:
svm_node_closure_set_weight(sd, node.y, node.z, node.w); 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); svm_node_emission_weight(kg, sd, stack, node);
break; break;
case NODE_MIX_CLOSURE: 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; break;
case NODE_ADD_CLOSURE: case NODE_ADD_CLOSURE:
svm_node_add_closure(sd, stack, node.y, node.z, &offset, &randb, &closure_weight); 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; break;
case NODE_END: case NODE_END:
default: default:
sd->svm_closure_weight *= closure_weight; #ifndef __MULTI_CLOSURE__
sd->closure.weight *= closure_weight;
#endif
return; return;
} }
} }

View File

@@ -29,48 +29,48 @@
CCL_NAMESPACE_BEGIN 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; int label;
switch(sd->svm_closure) { switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID: 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; break;
#ifdef __SVM__ #ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID: 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; break;
case CLOSURE_BSDF_REFLECTION_ID: 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; break;
case CLOSURE_BSDF_REFRACTION_ID: 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; break;
case CLOSURE_BSDF_TRANSPARENT_ID: 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; break;
case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_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; break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_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; break;
#ifdef __DPDU__ #ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID: 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; break;
#endif #endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: 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; break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: 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; break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID: 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; break;
#endif #endif
default: default:
@@ -78,53 +78,51 @@ __device int svm_bsdf_sample(const ShaderData *sd, float randu, float randv, flo
break; break;
} }
*eval *= sd->svm_closure_weight;
return label; 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; float3 eval;
if(dot(sd->Ng, omega_in) >= 0.0f) { if(dot(sd->Ng, omega_in) >= 0.0f) {
switch(sd->svm_closure) { switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID: 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; break;
case CLOSURE_BSDF_TRANSLUCENT_ID: 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; break;
case CLOSURE_BSDF_REFLECTION_ID: 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; break;
case CLOSURE_BSDF_REFRACTION_ID: 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; break;
case CLOSURE_BSDF_TRANSPARENT_ID: 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; break;
case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_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; break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_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; break;
#ifdef __DPDU__ #ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID: 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; break;
#endif #endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: 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; break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: 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; break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID: 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; break;
default: default:
eval = make_float3(0.0f, 0.0f, 0.0f); 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 { else {
switch(sd->svm_closure) { switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID: 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; break;
case CLOSURE_BSDF_TRANSLUCENT_ID: 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; break;
case CLOSURE_BSDF_REFLECTION_ID: 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; break;
case CLOSURE_BSDF_REFRACTION_ID: 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; break;
case CLOSURE_BSDF_TRANSPARENT_ID: 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; break;
case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_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; break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_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; break;
#ifdef __DPDU__ #ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID: 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; break;
#endif #endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: 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; break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: 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; break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID: 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; break;
default: default:
eval = make_float3(0.0f, 0.0f, 0.0f); 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; 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: case CLOSURE_BSDF_DIFFUSE_ID:
bsdf_diffuse_blur(sd, roughness); bsdf_diffuse_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_TRANSLUCENT_ID: case CLOSURE_BSDF_TRANSLUCENT_ID:
bsdf_translucent_blur(sd, roughness); bsdf_translucent_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_REFLECTION_ID: case CLOSURE_BSDF_REFLECTION_ID:
bsdf_reflection_blur(sd, roughness); bsdf_reflection_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_REFRACTION_ID: case CLOSURE_BSDF_REFRACTION_ID:
bsdf_refraction_blur(sd, roughness); bsdf_refraction_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_TRANSPARENT_ID: case CLOSURE_BSDF_TRANSPARENT_ID:
bsdf_transparent_blur(sd, roughness); bsdf_transparent_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
bsdf_microfacet_ggx_blur(sd, roughness); bsdf_microfacet_ggx_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
bsdf_microfacet_beckmann_blur(sd, roughness); bsdf_microfacet_beckmann_blur(sc, roughness);
break; break;
#ifdef __DPDU__ #ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID: case CLOSURE_BSDF_WARD_ID:
bsdf_ward_blur(sd, roughness); bsdf_ward_blur(sc, roughness);
break; break;
#endif #endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
bsdf_ashikhmin_velvet_blur(sd, roughness); bsdf_ashikhmin_velvet_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID:
bsdf_westin_backscatter_blur(sd, roughness); bsdf_westin_backscatter_blur(sc, roughness);
break; break;
case CLOSURE_BSDF_WESTIN_SHEEN_ID: case CLOSURE_BSDF_WESTIN_SHEEN_ID:
bsdf_westin_sheen_blur(sd, roughness); bsdf_westin_sheen_blur(sc, roughness);
break; break;
default: default:
break; break;

View File

@@ -20,28 +20,92 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */ /* 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; 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); 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 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); float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w);
switch(type) { switch(type) {
case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_DIFFUSE_ID: {
bsdf_diffuse_setup(sd, sd->N); ShaderClosure *sc = svm_node_closure_get(sd);
svm_node_closure_set_mix_weight(sc, mix_weight);
bsdf_diffuse_setup(sd, sc);
break; 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; 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; break;
}
case CLOSURE_BSDF_REFLECTION_ID: case CLOSURE_BSDF_REFLECTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ID: case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_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 */ /* index of refraction */
float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f); float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f);
eta = 1.0f/eta; eta = 1.0f/eta;
@@ -49,26 +113,22 @@ __device void svm_node_closure_bsdf(ShaderData *sd, float *stack, uint4 node, fl
/* fresnel */ /* fresnel */
float cosNO = dot(sd->N, sd->I); float cosNO = dot(sd->N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta); float fresnel = fresnel_dielectric_cos(cosNO, eta);
float roughness = param1;
sd->svm_closure_weight *= fresnel; sc->weight *= fresnel;
/* setup bsdf */ /* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID) { svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
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);
}
break; break;
} }
case CLOSURE_BSDF_REFRACTION_ID: case CLOSURE_BSDF_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_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 */ /* index of refraction */
float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f); float eta = clamp(1.0f-param2, 1e-5f, 1.0f - 1e-5f);
eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta; 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 */ /* fresnel */
float cosNO = dot(sd->N, sd->I); float cosNO = dot(sd->N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta); 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; break;
} }
#ifdef __DPDU__ #ifdef __DPDU__
case CLOSURE_BSDF_WARD_ID: { 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_u = param1;
float roughness_v = param2; 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; break;
} }
#endif #endif
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
ShaderClosure *sc = svm_node_closure_get(sd);
svm_node_closure_set_mix_weight(sc, mix_weight);
/* sigma */ /* sigma */
float sigma = clamp(param1, 0.0f, 1.0f); 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 cosNO = dot(sd->N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta); 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; break;
} }
default: 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; 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; sd->flag |= SD_HOLDOUT;
} }
/* Closure Nodes */ /* 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) __device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
{ {
sd->svm_closure_weight.x = __int_as_float(r); float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
sd->svm_closure_weight.y = __int_as_float(g); svm_node_closure_store_weight(sd, weight);
sd->svm_closure_weight.z = __int_as_float(b);
} }
__device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b) __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); float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b));
sd->svm_closure_weight.y = __int_as_float(g);
sd->svm_closure_weight.z = __int_as_float(b);
if(sd->object != ~0) 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) __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) __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 strength_offset = node.z;
uint total_power = node.w; 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) 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, __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)
{ {
float weight = stack_load_float(stack, weight_offset); #ifdef __MULTI_CLOSURE__
weight = clamp(weight, 0.0f, 1.0f); /* 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);
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. /* 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 closure 1 starts on the next node, for closure 2 the start is at an
offset from the current node, so we jump */ 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) { if(*randb < weight) {
*offset += node_jump; *offset += node_jump;
*randb = *randb/weight; *randb = *randb/weight;
} }
else else
*randb = (*randb - weight)/(1.0f - weight); *randb = (*randb - weight)/(1.0f - weight);
#endif
} }
__device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused, __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused,
uint node_jump, int *offset, float *randb, float *closure_weight) 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 /* 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 is not going to be great, for that we'd need to evaluate the weights
of the two closures being added */ of the two closures being added */
float weight = 0.5f;
if(*randb < weight) { if(*randb < weight) {
*offset += node_jump; *offset += node_jump;
*randb = *randb/weight; *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); *randb = (*randb - weight)/(1.0f - weight);
*closure_weight *= 2.0f; *closure_weight *= 2.0f;
#endif
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -258,6 +258,7 @@ typedef enum ShaderType {
/* Closure */ /* Closure */
typedef enum ClosureType { typedef enum ClosureType {
CLOSURE_BSDF_ID,
CLOSURE_BSDF_DIFFUSE_ID, CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_TRANSLUCENT_ID, CLOSURE_BSDF_TRANSLUCENT_ID,
CLOSURE_BSDF_REFLECTION_ID, CLOSURE_BSDF_REFLECTION_ID,
@@ -272,16 +273,25 @@ typedef enum ClosureType {
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_WESTIN_SHEEN_ID, CLOSURE_BSDF_WESTIN_SHEEN_ID,
CLOSURE_BSSRDF_CUBIC_ID, CLOSURE_BSSRDF_CUBIC_ID,
CLOSURE_EMISSION_ID, CLOSURE_EMISSION_ID,
CLOSURE_DEBUG_ID, CLOSURE_DEBUG_ID,
CLOSURE_BACKGROUND_ID, CLOSURE_BACKGROUND_ID,
CLOSURE_HOLDOUT_ID, CLOSURE_HOLDOUT_ID,
CLOSURE_SUBSURFACE_ID, CLOSURE_SUBSURFACE_ID,
CLOSURE_VOLUME_ID,
NBUILTIN_CLOSURES NBUILTIN_CLOSURES
} ClosureType; } 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 CCL_NAMESPACE_END
#endif /* __SVM_TYPES_H__ */ #endif /* __SVM_TYPES_H__ */

View File

@@ -34,7 +34,7 @@ CCL_NAMESPACE_BEGIN
/* VOLUME CLOSURE */ /* 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); return make_float3(1.0f, 1.0f, 1.0f);
} }

View File

@@ -55,6 +55,9 @@ LightManager::~LightManager()
void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) 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 */ /* count */
size_t num_lights = scene->lights.size(); size_t num_lights = scene->lights.size();
size_t num_triangles = 0; 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 */ /* emission area */
float4 *distribution = dscene->light_distribution.resize(num_distribution + 1); 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; float trianglearea = totarea;
/* point lights */ /* point lights */
float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f; 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++) { for(size_t i = 0; i < scene->lights.size(); i++, offset++) {
distribution[offset].x = totarea; distribution[offset].x = totarea;
distribution[offset].y = __int_as_float(-i-1); distribution[offset].y = __int_as_float(-i-1);
distribution[offset].z = 1.0f; distribution[offset].z = 1.0f;
distribution[offset].w = scene->lights[i]->radius; distribution[offset].w = scene->lights[i]->radius;
totarea += lightarea; totarea += lightarea;
}
} }
/* normalize cumulative distribution functions */ /* normalize cumulative distribution functions */
@@ -163,28 +171,40 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* update device */ /* update device */
KernelIntegrator *kintegrator = &dscene->data.integrator; 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) { if(kintegrator->use_emission) {
/* number of emissives */ /* number of emissives */
kintegrator->num_triangles = num_triangles; kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
kintegrator->num_lights = num_lights;
kintegrator->num_distribution = num_distribution;
/* precompute pdfs */ /* precompute pdfs */
kintegrator->pdf_triangles = 0.0f; kintegrator->pdf_triangles = 0.0f;
kintegrator->pdf_lights = 0.0f; kintegrator->pdf_lights = 0.0f;
if(trianglearea > 0.0f) { if(multi_light) {
kintegrator->pdf_triangles = 1.0f/trianglearea; /* sample one of all triangles and all lights */
if(num_lights) kintegrator->num_all_lights = num_lights;
kintegrator->pdf_triangles *= 0.5f;
}
if(num_lights) {
kintegrator->pdf_lights = 1.0f/num_lights;
if(trianglearea > 0.0f) if(trianglearea > 0.0f)
kintegrator->pdf_lights *= 0.5f; kintegrator->pdf_triangles = 1.0f/trianglearea;
if(num_lights)
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;
}
} }
/* CDF */ /* CDF */

View File

@@ -21,6 +21,7 @@
#include "device.h" #include "device.h"
#include "shader.h" #include "shader.h"
#include "light.h"
#include "mesh.h" #include "mesh.h"
#include "object.h" #include "object.h"
#include "scene.h" #include "scene.h"
@@ -250,6 +251,10 @@ void Mesh::tag_update(Scene *scene, bool rebuild)
scene->mesh_manager->need_update = true; scene->mesh_manager->need_update = true;
scene->object_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 */ /* Mesh Manager */

View File

@@ -1024,7 +1024,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
compiler.add_node(NODE_CLOSURE_BSDF, compiler.add_node(NODE_CLOSURE_BSDF,
compiler.encode_uchar4(closure, compiler.encode_uchar4(closure,
(param1)? param1->stack_offset: SVM_STACK_INVALID, (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((param1)? param1->value.x: 0.0f),
__float_as_int((param2)? param2->value.x: 0.0f)); __float_as_int((param2)? param2->value.x: 0.0f));
} }
@@ -1222,8 +1223,6 @@ EmissionNode::EmissionNode()
void EmissionNode::compile(SVMCompiler& compiler) void EmissionNode::compile(SVMCompiler& compiler)
{ {
compiler.add_node(NODE_CLOSURE_EMISSION, CLOSURE_EMISSION_ID);
ShaderInput *color_in = input("Color"); ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength"); 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); compiler.add_node(NODE_EMISSION_SET_WEIGHT_TOTAL, color_in->value * strength_in->value.x);
else else
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value * strength_in->value.x); 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) void EmissionNode::compile(OSLCompiler& compiler)
@@ -1256,8 +1257,6 @@ BackgroundNode::BackgroundNode()
void BackgroundNode::compile(SVMCompiler& compiler) void BackgroundNode::compile(SVMCompiler& compiler)
{ {
compiler.add_node(NODE_CLOSURE_BACKGROUND, CLOSURE_BACKGROUND_ID);
ShaderInput *color_in = input("Color"); ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength"); ShaderInput *strength_in = input("Strength");
@@ -1268,6 +1267,8 @@ void BackgroundNode::compile(SVMCompiler& compiler)
} }
else else
compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value*strength_in->value.x); 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) void BackgroundNode::compile(OSLCompiler& compiler)
@@ -1285,7 +1286,7 @@ HoldoutNode::HoldoutNode()
void HoldoutNode::compile(SVMCompiler& compiler) 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) void HoldoutNode::compile(OSLCompiler& compiler)

View File

@@ -17,6 +17,7 @@
*/ */
#include "device.h" #include "device.h"
#include "light.h"
#include "mesh.h" #include "mesh.h"
#include "object.h" #include "object.h"
#include "scene.h" #include "scene.h"
@@ -83,8 +84,15 @@ void Object::apply_transform()
void Object::tag_update(Scene *scene) void Object::tag_update(Scene *scene)
{ {
if(mesh && mesh->transform_applied) if(mesh) {
mesh->need_update = true; 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->mesh_manager->need_update = true;
scene->object_manager->need_update = true; scene->object_manager->need_update = true;
} }

View File

@@ -35,7 +35,7 @@ Session::Session(const SessionParams& params_)
: params(params_), : params(params_),
tile_manager(params.progressive, params.passes, params.tile_size, params.min_size) 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); device = Device::create(params.device_type, params.background, params.threads);
buffers = new RenderBuffers(device); buffers = new RenderBuffers(device);

View File

@@ -58,7 +58,7 @@ public:
background = false; background = false;
output_path = ""; output_path = "";
progressive = false; progressive = true;
passes = INT_MAX; passes = INT_MAX;
tile_size = 64; tile_size = 64;
min_size = 64; min_size = 64;

View File

@@ -105,6 +105,7 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man
current_type = SHADER_TYPE_SURFACE; current_type = SHADER_TYPE_SURFACE;
current_shader = NULL; current_shader = NULL;
background = false; background = false;
mix_weight_offset = SVM_STACK_INVALID;
} }
int SVMCompiler::stack_size(ShaderSocketType type) 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) void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
{ {
/* Converting a shader graph into svm_nodes that can be executed /* 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) { if(clin->link) {
bool generate = false;
if(type == SHADER_TYPE_SURFACE) { if(type == SHADER_TYPE_SURFACE) {
/* generate surface shader */ /* generate surface shader */
generate_closure(clin->link->parent, set<ShaderNode*>(), Stack()); generate = true;
shader->has_surface = true; shader->has_surface = true;
} }
else if(type == SHADER_TYPE_VOLUME) { else if(type == SHADER_TYPE_VOLUME) {
/* generate volume shader */ /* generate volume shader */
generate_closure(clin->link->parent, set<ShaderNode*>(), Stack()); generate = true;
shader->has_volume = true; shader->has_volume = true;
} }
else if(type == SHADER_TYPE_DISPLACEMENT) { else if(type == SHADER_TYPE_DISPLACEMENT) {
/* generate displacement shader */ /* generate displacement shader */
generate_closure(clin->link->parent, set<ShaderNode*>(), Stack()); generate = true;
shader->has_displacement = 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 */ /* compile output node */

View File

@@ -24,6 +24,7 @@
#include "shader.h" #include "shader.h"
#include "util_set.h" #include "util_set.h"
#include "util_string.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
@@ -65,6 +66,7 @@ public:
uint attribute(ustring name); uint attribute(ustring name);
uint attribute(Attribute::Standard std); uint attribute(Attribute::Standard std);
uint encode_uchar4(uint x, uint y = 0, uint z = 0, uint w = 0); 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; } ShaderType output_type() { return current_type; }
@@ -75,6 +77,8 @@ public:
protected: protected:
struct Stack { struct Stack {
Stack() { memset(users, 0, sizeof(users)); }
int users[SVM_STACK_SIZE]; int users[SVM_STACK_SIZE];
}; };
@@ -88,6 +92,7 @@ protected:
void find_dependencies(set<ShaderNode*>& dependencies, const set<ShaderNode*>& done, ShaderInput *input); 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_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done);
void generate_closure(ShaderNode *node, set<ShaderNode*> done, Stack stack); 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); void compile_type(Shader *shader, ShaderGraph *graph, ShaderType type);
@@ -96,6 +101,7 @@ protected:
Shader *current_shader; Shader *current_shader;
Stack active_stack; Stack active_stack;
int max_stack_use; int max_stack_use;
uint mix_weight_offset;
}; };
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -96,7 +96,7 @@ void TileManager::set_tiles()
bool TileManager::done() bool TileManager::done()
{ {
return (state.pass+1 >= passes); return (state.pass+1 >= passes && state.resolution == 1);
} }
bool TileManager::next() bool TileManager::next()

View File

@@ -109,11 +109,16 @@ string path_files_md5_hash(const string& dir)
return hash.get_hex(); return hash.get_hex();
} }
void path_create_directories(const string& path)
{
boost::filesystem::create_directories(path_dirname(path));
}
bool path_write_binary(const string& path, const vector<uint8_t>& binary) bool path_write_binary(const string& path, const vector<uint8_t>& binary)
{ {
/* write binary file from memory */ path_create_directories(path);
boost::filesystem::create_directories(path_dirname(path));
/* write binary file from memory */
FILE *f = fopen(path.c_str(), "wb"); FILE *f = fopen(path.c_str(), "wb");
if(!f) if(!f)

View File

@@ -42,6 +42,7 @@ string path_escape(const string& path);
bool path_exists(const string& path); bool path_exists(const string& path);
string path_files_md5_hash(const string& dir); 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_write_binary(const string& path, const vector<uint8_t>& binary);
bool path_read_binary(const string& path, vector<uint8_t>& binary); bool path_read_binary(const string& path, vector<uint8_t>& binary);