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