Cycles: internal changes that should have no effect on user level yet, added

shader flags for various purposes, and some code for light types other than
points.
This commit is contained in:
Brecht Van Lommel
2011-09-27 20:37:24 +00:00
parent 136d27b350
commit cdee3435c6
26 changed files with 513 additions and 230 deletions

View File

@@ -116,11 +116,23 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
@classmethod @classmethod
def register(cls): def register(cls):
bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles material settings") bpy.types.Material.cycles = PointerProperty(type=cls, name="Cycles Material Settings", description="Cycles material settings")
cls.sample_as_light = BoolProperty(name="Sample as Light", description="Use direct light sampling, to reduce noise for small or strong emitting materials", default=False)
cls.homogeneous_volume = BoolProperty(name="Homogeneous Volume", description="When using volume rendering, assume volume has the same density everywhere, for faster rendering", default=False)
@classmethod @classmethod
def unregister(cls): def unregister(cls):
del bpy.types.Material.cycles del bpy.types.Material.cycles
class CyclesLampSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
bpy.types.Lamp.cycles = PointerProperty(type=cls, name="Cycles Lamp Settings", description="Cycles lamp settings")
cls.cast_shadow = BoolProperty(name="Cast Shadow", description="Lamp casts shadows", default=True)
@classmethod
def unregister(cls):
del bpy.types.Lamp.cycles
class CyclesWorldSettings(bpy.types.PropertyGroup): class CyclesWorldSettings(bpy.types.PropertyGroup):
@classmethod @classmethod
def register(cls): def register(cls):
@@ -168,6 +180,7 @@ def register():
bpy.utils.register_class(CyclesRenderSettings) bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings) bpy.utils.register_class(CyclesCameraSettings)
bpy.utils.register_class(CyclesMaterialSettings) bpy.utils.register_class(CyclesMaterialSettings)
bpy.utils.register_class(CyclesLampSettings)
bpy.utils.register_class(CyclesWorldSettings) bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesVisibilitySettings) bpy.utils.register_class(CyclesVisibilitySettings)
bpy.utils.register_class(CyclesMeshSettings) bpy.utils.register_class(CyclesMeshSettings)
@@ -176,6 +189,7 @@ def unregister():
bpy.utils.unregister_class(CyclesRenderSettings) bpy.utils.unregister_class(CyclesRenderSettings)
bpy.utils.unregister_class(CyclesCameraSettings) bpy.utils.unregister_class(CyclesCameraSettings)
bpy.utils.unregister_class(CyclesMaterialSettings) bpy.utils.unregister_class(CyclesMaterialSettings)
bpy.utils.unregister_class(CyclesLampSettings)
bpy.utils.unregister_class(CyclesWorldSettings) bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings) bpy.utils.unregister_class(CyclesMeshSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings) bpy.utils.unregister_class(CyclesVisibilitySettings)

View File

@@ -360,7 +360,48 @@ def panel_node_draw(layout, id, output_type, input_name):
layout.template_node_view(ntree, node, input); layout.template_node_view(ntree, node, input);
class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
bl_label = "Surface" bl_label = "Lamp"
bl_context = "data"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return False
#return context.lamp and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
lamp = context.lamp
clamp = lamp.cycles
layout.prop(lamp, "type", expand=True)
split = layout.split()
col = split.column(align=True)
if lamp.type in ('POINT', 'SUN', 'SPOT'):
col.prop(lamp, "shadow_soft_size", text="Size")
elif lamp.type == 'AREA':
col.prop(lamp, "shape", text="")
sub = col.column(align=True)
if lamp.shape == 'SQUARE':
sub.prop(lamp, "size")
elif lamp.shape == 'RECTANGLE':
sub.prop(lamp, "size", text="Size X")
sub.prop(lamp, "size_y", text="Size Y")
col = split.column()
col.prop(clamp, "cast_shadow")
if lamp.type == 'SPOT':
layout.label(text="Not supported, interpreted as point lamp.")
elif lamp.type == 'HEMI':
layout.label(text="Not supported, interpreted as sun lamp.")
class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel):
bl_label = "Nodes"
bl_context = "data" bl_context = "data"
@classmethod @classmethod
@@ -399,8 +440,8 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
layout = self.layout layout = self.layout
layout.active = False layout.active = False
mat = context.world world = context.world
panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Volume') panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel): class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface" bl_label = "Surface"
@@ -429,8 +470,12 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
layout.active = False layout.active = False
mat = context.material mat = context.material
cmat = mat.cycles
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume') panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
layout.prop(cmat, "homogeneous_volume")
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel): class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
bl_label = "Displacement" bl_label = "Displacement"
bl_context = "material" bl_context = "material"
@@ -452,17 +497,22 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
# return context.material and CyclesButtonsPanel.poll(context)
return False return False
#return context.material and CyclesButtonsPanel.poll(context)
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
mat = context.material mat = context.material
cmat = mat.cycles
row = layout.row() split = layout.split()
row.label(text="Light Group:")
row.prop(mat, "light_group", text="") col = split.column()
col.prop(cmat, "sample_as_light")
col = split.column()
col.prop(cmat, "homogeneous_volume")
class CyclesTexture_PT_context(CyclesButtonsPanel, Panel): class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
bl_label = "" bl_label = ""

View File

@@ -88,11 +88,57 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
if(!light_map.sync(&light, b_ob, b_parent, key)) if(!light_map.sync(&light, b_ob, b_parent, key))
return; return;
BL::Lamp b_lamp(b_ob.data());
/* type */
#if 0
switch(b_lamp.type()) {
case BL::Lamp::type_POINT: {
BL::PointLamp b_point_lamp(b_lamp);
light->size = b_point_lamp.shadow_soft_size();
#endif
light->type = LIGHT_POINT;
#if 0
break;
}
case BL::Lamp::type_SPOT: {
BL::SpotLamp b_spot_lamp(b_lamp);
light->size = b_spot_lamp.shadow_soft_size();
light->type = LIGHT_POINT;
break;
}
case BL::Lamp::type_HEMI: {
light->type = LIGHT_DISTANT;
light->size = 0.0f;
break;
}
case BL::Lamp::type_SUN: {
BL::SunLamp b_sun_lamp(b_lamp);
light->size = b_sun_lamp.shadow_soft_size();
light->type = LIGHT_DISTANT;
break;
}
case BL::Lamp::type_AREA: {
BL::AreaLamp b_area_lamp(b_lamp);
light->size = 1.0f;
light->axisu = make_float3(tfm.x.x, tfm.y.x, tfm.z.x);
light->axisv = make_float3(tfm.x.y, tfm.y.y, tfm.z.y);
light->sizeu = b_area_lamp.size();
if(b_area_lamp.shape() == BL::AreaLamp::shape_RECTANGLE)
light->sizev = b_area_lamp.size_y();
else
light->sizev = light->sizeu;
light->type = LIGHT_AREA;
break;
}
}
#endif
/* location */ /* location */
light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w); light->co = make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
light->dir = make_float3(tfm.x.z, tfm.y.z, tfm.z.z);
/* shader */ /* shader */
BL::Lamp b_lamp(b_ob.data());
vector<uint> used_shaders; vector<uint> used_shaders;
find_shader(b_lamp, used_shaders); find_shader(b_lamp, used_shaders);
@@ -102,6 +148,10 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
light->shader = used_shaders[0]; light->shader = used_shaders[0];
/* shadow */
//PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
//light->cast_shadow = get_boolean(clamp, "cast_shadow");
/* tag */ /* tag */
light->tag_update(scene); light->tag_update(scene);
} }

View File

@@ -587,6 +587,11 @@ void BlenderSync::sync_materials()
graph->connect(closure->output("BSDF"), out->input("Surface")); graph->connect(closure->output("BSDF"), out->input("Surface"));
} }
/* settings */
PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
//shader->sample_as_light = get_boolean(cmat, "sample_as_light");
shader->homogeneous_volume = get_boolean(cmat, "homogeneous_volume");
shader->set_graph(graph); shader->set_graph(graph);
shader->tag_update(scene); shader->tag_update(scene);
} }

View File

@@ -83,12 +83,17 @@ bool BlenderSync::sync_recalc()
object_map.set_recalc(*b_ob); object_map.set_recalc(*b_ob);
light_map.set_recalc(*b_ob); light_map.set_recalc(*b_ob);
} }
if(object_is_mesh(*b_ob)) { if(object_is_mesh(*b_ob)) {
if(b_ob->recalc_data() || b_ob->data().recalc()) { if(b_ob->recalc_data() || b_ob->data().recalc()) {
BL::ID key = object_is_modified(*b_ob)? *b_ob: b_ob->data(); BL::ID key = object_is_modified(*b_ob)? *b_ob: b_ob->data();
mesh_map.set_recalc(key); mesh_map.set_recalc(key);
} }
} }
else if(object_is_light(*b_ob)) {
if(b_ob->recalc_data() || b_ob->data().recalc())
light_map.set_recalc(*b_ob);
}
} }
BL::BlendData::meshes_iterator b_mesh; BL::BlendData::meshes_iterator b_mesh;

View File

@@ -73,82 +73,17 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height) void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height)
{ {
if(strcmp(name, "__bvh_nodes") == 0) { if(0) {
kg->__bvh_nodes.data = (float4*)mem;
kg->__bvh_nodes.width = width;
} }
else if(strcmp(name, "__objects") == 0) {
kg->__objects.data = (float4*)mem; #define KERNEL_TEX(type, ttype, tname) \
kg->__objects.width = width; else if(strcmp(name, #tname) == 0) { \
} kg->tname.data = (type*)mem; \
else if(strcmp(name, "__tri_normal") == 0) { kg->tname.width = width; \
kg->__tri_normal.data = (float4*)mem;
kg->__tri_normal.width = width;
}
else if(strcmp(name, "__tri_woop") == 0) {
kg->__tri_woop.data = (float4*)mem;
kg->__tri_woop.width = width;
}
else if(strcmp(name, "__prim_visibility") == 0) {
kg->__prim_visibility.data = (uint*)mem;
kg->__prim_visibility.width = width;
}
else if(strcmp(name, "__prim_index") == 0) {
kg->__prim_index.data = (uint*)mem;
kg->__prim_index.width = width;
}
else if(strcmp(name, "__prim_object") == 0) {
kg->__prim_object.data = (uint*)mem;
kg->__prim_object.width = width;
}
else if(strcmp(name, "__object_node") == 0) {
kg->__object_node.data = (uint*)mem;
kg->__object_node.width = width;
}
else if(strcmp(name, "__tri_vnormal") == 0) {
kg->__tri_vnormal.data = (float4*)mem;
kg->__tri_vnormal.width = width;
}
else if(strcmp(name, "__tri_vindex") == 0) {
kg->__tri_vindex.data = (float4*)mem;
kg->__tri_vindex.width = width;
}
else if(strcmp(name, "__tri_verts") == 0) {
kg->__tri_verts.data = (float4*)mem;
kg->__tri_verts.width = width;
}
else if(strcmp(name, "__light_distribution") == 0) {
kg->__light_distribution.data = (float4*)mem;
kg->__light_distribution.width = width;
}
else if(strcmp(name, "__light_point") == 0) {
kg->__light_point.data = (float4*)mem;
kg->__light_point.width = width;
}
else if(strcmp(name, "__svm_nodes") == 0) {
kg->__svm_nodes.data = (uint4*)mem;
kg->__svm_nodes.width = width;
}
else if(strcmp(name, "__filter_table") == 0) {
kg->__filter_table.data = (float*)mem;
kg->__filter_table.width = width;
}
else if(strcmp(name, "__sobol_directions") == 0) {
kg->__sobol_directions.data = (uint*)mem;
kg->__sobol_directions.width = width;
}
else if(strcmp(name, "__attributes_map") == 0) {
kg->__attributes_map.data = (uint4*)mem;
kg->__attributes_map.width = width;
}
else if(strcmp(name, "__attributes_float") == 0) {
kg->__attributes_float.data = (float*)mem;
kg->__attributes_float.width = width;
}
else if(strcmp(name, "__attributes_float3") == 0) {
kg->__attributes_float3.data = (float4*)mem;
kg->__attributes_float3.width = width;
} }
#define KERNEL_IMAGE_TEX(type, ttype, tname)
#include "kernel_textures.h"
else if(strstr(name, "__tex_image")) { else if(strstr(name, "__tex_image")) {
texture_image_uchar4 *tex = NULL; texture_image_uchar4 *tex = NULL;
int id = atoi(name + strlen("__tex_image_")); int id = atoi(name + strlen("__tex_image_"));

View File

@@ -63,15 +63,11 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
light_sample(kg, randt, randu, randv, sd->P, &ls); 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 */ /* compute pdf */
float pdf = light_sample_pdf(kg, &ls, -omega_in, t); float pdf = light_sample_pdf(kg, &ls, -ls.D, ls.t);
/* evaluate closure */ /* evaluate closure */
*eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -omega_in); *eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D);
if(is_zero(*eval) || pdf == 0.0f) if(is_zero(*eval) || pdf == 0.0f)
return false; return false;
@@ -80,7 +76,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
/* evaluate BSDF at shading point */ /* evaluate BSDF at shading point */
float bsdf_pdf; float bsdf_pdf;
float3 bsdf_eval = shader_bsdf_eval(kg, sd, omega_in, &bsdf_pdf); float3 bsdf_eval = shader_bsdf_eval(kg, sd, ls.D, &bsdf_pdf);
*eval *= bsdf_eval/pdf; *eval *= bsdf_eval/pdf;
@@ -92,29 +88,34 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
float mis_weight = power_heuristic(pdf, bsdf_pdf); float mis_weight = power_heuristic(pdf, bsdf_pdf);
*eval *= mis_weight; *eval *= mis_weight;
} }
else { else if(!(ls.shader & SHADER_AREA_LIGHT)) {
/* ensure point light works in Watts, this should be handled /* ensure point light works in Watts, this should be handled
* elsewhere but for now together with the diffuse emission * elsewhere but for now together with the diffuse emission
* closure it works out to the right value */ * closure it works out to the right value */
*eval *= 0.25f; *eval *= 0.25f;
/* XXX verify with other light types */
} }
#if 0 if(ls.shader & SHADER_CAST_SHADOW) {
/* todo: implement this in light */
bool no_shadow = true;
if(no_shadow) {
ray->t = 0.0f;
}
else {
#endif
/* setup ray */ /* setup ray */
ray->P = ray_offset(sd->P, sd->Ng); 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(ls.t == FLT_MAX) {
#if 0 /* distant light */
ray->D = ls.D;
ray->t = ls.t;
}
else {
/* other lights, avoid self-intersection */
ray->D = ray_offset(ls.P, ls.Ng) - ray->P;
ray->D = normalize_len(ray->D, &ray->t);
}
}
else {
/* signal to not cast shadow ray */
ray->t = 0.0f;
} }
#endif
return true; return true;
} }
@@ -126,7 +127,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
/* evaluate emissive closure */ /* evaluate emissive closure */
float3 L = shader_emissive_eval(kg, sd); float3 L = shader_emissive_eval(kg, sd);
if(!(path_flag & PATH_RAY_SINGULAR)) { if(!(path_flag & PATH_RAY_SINGULAR) && (sd->flag & SD_SAMPLE_AS_LIGHT)) {
/* multiple importance sampling */ /* multiple importance sampling */
float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t); float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
float mis_weight = power_heuristic(bsdf_pdf, pdf); float mis_weight = power_heuristic(bsdf_pdf, pdf);

View File

@@ -20,30 +20,112 @@ CCL_NAMESPACE_BEGIN
typedef struct LightSample { typedef struct LightSample {
float3 P; float3 P;
float3 D;
float3 Ng; float3 Ng;
float t;
int object; int object;
int prim; int prim;
int shader; int shader;
float weight;
} LightSample; } LightSample;
/* Point Light */ /* Regular Light */
__device void point_light_sample(KernelGlobals *kg, int point, __device float3 disk_light_sample(float3 v, float randu, float randv)
{
float3 ru, rv;
make_orthonormals(v, &ru, &rv);
to_unit_disk(&randu, &randv);
return ru*randu + rv*randv;
}
__device float3 distant_light_sample(float3 D, float size, float randu, float randv)
{
return normalize(D + disk_light_sample(D, randu, randv)*size);
}
__device float3 sphere_light_sample(float3 P, float3 center, float size, float randu, float randv)
{
return disk_light_sample(normalize(P - center), randu, randv)*size;
}
__device float3 area_light_sample(float3 axisu, float3 axisv, float randu, float randv)
{
randu = randu - 0.5f;
randv = randv - 0.5f;
return axisu*randu + axisv*randv;
}
__device void regular_light_sample(KernelGlobals *kg, int point,
float randu, float randv, float3 P, LightSample *ls) float randu, float randv, float3 P, LightSample *ls)
{ {
float4 f = kernel_tex_fetch(__light_point, point); float4 data0 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 0);
float4 data1 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 1);
ls->P = make_float3(f.x, f.y, f.z); LightType type = (LightType)__float_as_int(data0.x);
ls->Ng = normalize(ls->P - P);
ls->shader = __float_as_int(f.w); if(type == LIGHT_DISTANT) {
/* distant light */
float3 D = make_float3(data0.y, data0.z, data0.w);
float size = data1.y;
if(size > 0.0f)
D = distant_light_sample(D, size, randu, randv);
ls->P = D;
ls->Ng = -D;
ls->D = D;
ls->t = FLT_MAX;
}
else {
ls->P = make_float3(data0.y, data0.z, data0.w);
if(type == LIGHT_POINT) {
float size = data1.y;
/* sphere light */
if(size > 0.0f)
ls->P += sphere_light_sample(P, ls->P, size, randu, randv);
ls->Ng = normalize(P - ls->P);
}
else {
/* area light */
float4 data2 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 2);
float4 data3 = kernel_tex_fetch(__light_data, point*LIGHT_SIZE + 3);
float3 axisu = make_float3(data1.y, data1.z, data2.w);
float3 axisv = make_float3(data2.y, data2.z, data2.w);
float3 D = make_float3(data3.y, data3.z, data3.w);
ls->P += area_light_sample(axisu, axisv, randu, randv);
ls->Ng = D;
}
ls->t = 0.0f;
}
ls->shader = __float_as_int(data1.x);
ls->object = ~0; ls->object = ~0;
ls->prim = ~0; ls->prim = ~0;
} }
__device float point_light_pdf(KernelGlobals *kg, float t) __device float regular_light_pdf(KernelGlobals *kg,
const float3 Ng, const float3 I, float t)
{ {
return t*t*kernel_data.integrator.pdf_lights; float pdf = kernel_data.integrator.pdf_lights;
if(t == FLT_MAX)
return pdf;
float cos_pi = fabsf(dot(Ng, I));
if(cos_pi == 0.0f)
return 0.0f;
return t*t*pdf/cos_pi;
} }
/* Triangle Light */ /* Triangle Light */
@@ -56,6 +138,7 @@ __device void triangle_light_sample(KernelGlobals *kg, int prim, int object,
ls->Ng = triangle_normal_MT(kg, prim, &ls->shader); ls->Ng = triangle_normal_MT(kg, prim, &ls->shader);
ls->object = object; ls->object = object;
ls->prim = prim; ls->prim = prim;
ls->t = 0.0f;
#ifdef __INSTANCING__ #ifdef __INSTANCING__
/* instance transform */ /* instance transform */
@@ -117,7 +200,6 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
/* fetch light data */ /* fetch light data */
float4 l = kernel_tex_fetch(__light_distribution, index); float4 l = kernel_tex_fetch(__light_distribution, index);
int prim = __float_as_int(l.y); int prim = __float_as_int(l.y);
ls->weight = l.z;
if(prim >= 0) { if(prim >= 0) {
int object = __float_as_int(l.w); int object = __float_as_int(l.w);
@@ -125,8 +207,12 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
} }
else { else {
int point = -prim-1; int point = -prim-1;
point_light_sample(kg, point, randu, randv, P, ls); regular_light_sample(kg, point, randu, randv, P, ls);
} }
/* compute incoming direction and distance */
if(ls->t != FLT_MAX)
ls->D = normalize_len(ls->P - P, &ls->t);
} }
__device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t) __device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
@@ -136,19 +222,19 @@ __device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, fl
if(ls->prim != ~0) if(ls->prim != ~0)
pdf = triangle_light_pdf(kg, ls->Ng, I, t); pdf = triangle_light_pdf(kg, ls->Ng, I, t);
else else
pdf = point_light_pdf(kg, t); pdf = regular_light_pdf(kg, ls->Ng, I, t);
return pdf; return pdf;
} }
__device void light_select(KernelGlobals *kg, int index, float randu, float randv, float3 P, LightSample *ls) __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); regular_light_sample(kg, index, randu, randv, P, ls);
} }
__device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t) __device float light_select_pdf(KernelGlobals *kg, LightSample *ls, float3 I, float t)
{ {
return point_light_pdf(kg, t); return regular_light_pdf(kg, ls->Ng, I, t);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -67,17 +67,6 @@ __device void to_unit_disk(float *x, float *y)
*y = r * sinf(phi); *y = r * sinf(phi);
} }
__device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
{
if(N.x != N.y || N.x != N.z)
*a = make_float3(N.z-N.y, N.x-N.z, N.y-N.x); //(1,1,1)x N
else
*a = make_float3(N.z-N.y, N.x+N.z, -N.y-N.x); //(-1,1,1)x N
*a = normalize(*a);
*b = cross(N, *a);
}
__device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b) __device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b)
{ {
*b = cross(N, T); *b = cross(N, T);

View File

@@ -162,19 +162,6 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
return average(throughput); return average(throughput);
} }
#ifdef __TRANSPARENT_SHADOWS__
__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
{
int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 Ns = kernel_tex_fetch(__tri_normal, prim);
int shader = __float_as_int(Ns.w);
/* todo: add shader flag to check this */
return true;
}
#endif
__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L) __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L)
{ {
if(ray->t == 0.0f) if(ray->t == 0.0f)
@@ -229,12 +216,10 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
throughput *= shader_bsdf_transparency(kg, &sd); throughput *= shader_bsdf_transparency(kg, &sd);
ray->P = ray_offset(sd.P, -sd.Ng); ray->P = ray_offset(sd.P, -sd.Ng);
ray->t = len(Pend - ray->P); ray->t = (ray->t == FLT_MAX)? FLT_MAX: len(Pend - ray->P);
bounce++; bounce++;
} }
return true;
} }
} }
#endif #endif
@@ -298,10 +283,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
#ifdef __EMISSION__ #ifdef __EMISSION__
/* emission */ /* emission */
if(kernel_data.integrator.use_emission) { if(sd.flag & SD_EMISSION)
if(sd.flag & SD_EMISSION) L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
}
#endif #endif
/* path termination. this is a strange place to put the termination, it's /* path termination. this is a strange place to put the termination, it's
@@ -316,7 +299,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
throughput /= probability; throughput /= probability;
#ifdef __EMISSION__ #ifdef __EMISSION__
if(kernel_data.integrator.use_emission) { if(kernel_data.integrator.use_direct_light) {
/* sample illumination from lights to find path contribution */ /* sample illumination from lights to find path contribution */
if(sd.flag & SD_BSDF_HAS_EVAL) { if(sd.flag & SD_BSDF_HAS_EVAL) {
float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT); float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);

View File

@@ -60,7 +60,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->N = Ng; sd->N = Ng;
sd->I = -ray->D; sd->I = -ray->D;
sd->shader = shader; sd->shader = shader;
sd->flag = 0;
/* triangle */ /* triangle */
#ifdef __INSTANCING__ #ifdef __INSTANCING__
@@ -73,10 +72,10 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#endif #endif
/* smooth normal */ /* smooth normal */
if(sd->shader < 0) { if(sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
sd->shader = -sd->shader;
} sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
#ifdef __DPDU__ #ifdef __DPDU__
/* dPdu/dPdv */ /* dPdu/dPdv */
@@ -103,7 +102,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
if(backfacing) { if(backfacing) {
sd->flag = SD_BACKFACING; sd->flag |= SD_BACKFACING;
sd->Ng = -sd->Ng; sd->Ng = -sd->Ng;
sd->N = -sd->N; sd->N = -sd->N;
#ifdef __DPDU__ #ifdef __DPDU__
@@ -132,7 +131,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
sd->Ng = Ng; sd->Ng = Ng;
sd->I = I; sd->I = I;
sd->shader = shader; sd->shader = shader;
sd->flag = 0;
/* primitive */ /* primitive */
#ifdef __INSTANCING__ #ifdef __INSTANCING__
@@ -159,9 +157,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif #endif
/* smooth normal */ /* smooth normal */
if(sd->shader < 0) { if(sd->shader & SHADER_SMOOTH_NORMAL) {
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
sd->shader = -sd->shader;
#ifdef __INSTANCING__ #ifdef __INSTANCING__
if(instanced) if(instanced)
@@ -169,6 +166,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif #endif
} }
sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
#ifdef __DPDU__ #ifdef __DPDU__
/* dPdu/dPdv */ /* dPdu/dPdv */
if(sd->prim == ~0) { if(sd->prim == ~0) {
@@ -192,7 +191,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
bool backfacing = (dot(sd->Ng, sd->I) < 0.0f); bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
if(backfacing) { if(backfacing) {
sd->flag = SD_BACKFACING; sd->flag |= SD_BACKFACING;
sd->Ng = -sd->Ng; sd->Ng = -sd->Ng;
sd->N = -sd->N; sd->N = -sd->N;
#ifdef __DPDU__ #ifdef __DPDU__
@@ -245,7 +244,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
sd->Ng = -sd->P; sd->Ng = -sd->P;
sd->I = -sd->P; sd->I = -sd->P;
sd->shader = kernel_data.background.shader; sd->shader = kernel_data.background.shader;
sd->flag = 0; sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
#ifdef __INSTANCING__ #ifdef __INSTANCING__
sd->object = ~0; sd->object = ~0;
@@ -410,7 +409,7 @@ __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
for(int i = 0; i< sd->num_closure; i++) { for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i]; ShaderClosure *sc = &sd->closure[i];
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // XXX osl if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
eval += sc->weight; eval += sc->weight;
} }
@@ -428,8 +427,9 @@ __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
{ {
float3 eval;
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
float3 eval = make_float3(0.0f, 0.0f, 0.0f); eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i < sd->num_closure; i++) { for(int i = 0; i < sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i]; ShaderClosure *sc = &sd->closure[i];
@@ -442,11 +442,11 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
#endif #endif
} }
} }
#else
eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
#endif
return eval; return eval;
#else
return svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
#endif
} }
/* Holdout */ /* Holdout */
@@ -581,6 +581,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
#endif #endif
} }
/* Transparent Shadows */
#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);
int flag = kernel_tex_fetch(__shader_flag, shader & SHADER_MASK);
return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
}
#endif
/* Free ShaderData */ /* Free ShaderData */
__device void shader_release(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd)

View File

@@ -32,10 +32,11 @@ KERNEL_TEX(float4, texture_float4, __attributes_float3)
/* lights */ /* lights */
KERNEL_TEX(float4, texture_float4, __light_distribution) KERNEL_TEX(float4, texture_float4, __light_distribution)
KERNEL_TEX(float4, texture_float4, __light_point) KERNEL_TEX(float4, texture_float4, __light_data)
/* shaders */ /* shaders */
KERNEL_TEX(uint4, texture_uint4, __svm_nodes) KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
KERNEL_TEX(uint, texture_uint, __shader_flag)
/* camera/film */ /* camera/film */
KERNEL_TEX(float, texture_float, __filter_table) KERNEL_TEX(float, texture_float, __filter_table)

View File

@@ -26,6 +26,7 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
#define OBJECT_SIZE 16 #define OBJECT_SIZE 16
#define LIGHT_SIZE 4
#define __SOBOL__ #define __SOBOL__
#define __INSTANCING__ #define __INSTANCING__
@@ -43,12 +44,12 @@ CCL_NAMESPACE_BEGIN
#define __EMISSION__ #define __EMISSION__
#define __TEXTURES__ #define __TEXTURES__
#define __HOLDOUT__ #define __HOLDOUT__
//#define __MULTI_CLOSURE__
//#define __TRANSPARENT_SHADOWS__
//#define __MULTI_LIGHT__
#endif #endif
#ifdef __KERNEL_CPU__ #ifdef __KERNEL_CPU__
//#define __MULTI_CLOSURE__
//#define __MULTI_LIGHT__
//#define __TRANSPARENT_SHADOWS__
//#define __OSL__ //#define __OSL__
#endif #endif
@@ -79,6 +80,7 @@ enum PathTraceDimension {
/* these flag values correspond exactly to OSL defaults, so be careful not to /* these flag values correspond exactly to OSL defaults, so be careful not to
* change this, or if you do, set the "raytypes" shading system attribute with * change this, or if you do, set the "raytypes" shading system attribute with
* your own new ray types and bitflag values */ * your own new ray types and bitflag values */
enum PathRayFlag { enum PathRayFlag {
PATH_RAY_CAMERA = 1, PATH_RAY_CAMERA = 1,
PATH_RAY_SHADOW = 2, PATH_RAY_SHADOW = 2,
@@ -92,28 +94,6 @@ enum PathRayFlag {
PATH_RAY_ALL = (1|2|4|8|16|32|64|128) PATH_RAY_ALL = (1|2|4|8|16|32|64|128)
}; };
/* Bidirectional Path Tracing */
enum BidirTraceDimension {
BRNG_FILTER_U = 0,
BRNG_FILTER_V = 1,
BRNG_LENS_U = 2,
BRNG_LENS_V = 3,
BRNG_LIGHT_U = 4,
BRNG_LIGHT_V = 5,
BRNG_LIGHT = 6,
BRNG_LIGHT_F = 7,
BRNG_EMISSIVE_U = 8,
BRNG_EMISSIVE_V = 9,
BRNG_BASE_NUM = 10,
BRNG_BSDF_U = 0,
BRNG_BSDF_V = 1,
BRNG_BSDF = 2,
BRNG_TERMINATE = 3,
BRNG_BOUNCE_NUM = 4
};
/* Closure Label */ /* Closure Label */
typedef enum ClosureLabel { typedef enum ClosureLabel {
@@ -132,16 +112,23 @@ typedef enum ClosureLabel {
LABEL_STOP = 2048 LABEL_STOP = 2048
} ClosureLabel; } ClosureLabel;
/* Ray Type */ /* Shader Flag */
typedef enum RayType { typedef enum ShaderFlag {
RayTypeCamera = 1, SHADER_SMOOTH_NORMAL = (1 << 31),
RayTypeShadow = 2, SHADER_CAST_SHADOW = (1 << 30),
RayTypeReflection = 4, SHADER_AREA_LIGHT = (1 << 29),
RayTypeRefraction = 8,
RayTypeDiffuse = 16, SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT)
RayTypeGlossy = 32 } ShaderFlag;
} RayType;
/* Light Type */
typedef enum LightType {
LIGHT_POINT,
LIGHT_DISTANT,
LIGHT_AREA
} LightType;
/* Differential */ /* Differential */
@@ -213,13 +200,20 @@ typedef struct ShaderClosure {
* are in world space. */ * are in world space. */
enum ShaderDataFlag { enum ShaderDataFlag {
/* runtime flags */
SD_BACKFACING = 1, /* backside of surface? */ SD_BACKFACING = 1, /* backside of surface? */
SD_EMISSION = 2, /* have emissive closure? */ SD_EMISSION = 2, /* have emissive closure? */
SD_BSDF = 4, /* have bsdf closure? */ SD_BSDF = 4, /* have bsdf closure? */
SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */ SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */ SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
SD_HOLDOUT = 32, /* have holdout closure? */ SD_HOLDOUT = 32, /* have holdout closure? */
SD_VOLUME = 64 /* have volume closure? */ SD_VOLUME = 64, /* have volume closure? */
/* shader flags */
SD_SAMPLE_AS_LIGHT = 128, /* direct light sample */
SD_HAS_SURFACE_TRANSPARENT = 256, /* has surface transparency */
SD_HAS_VOLUME = 512, /* has volume shader */
SD_HOMOGENEOUS_VOLUME = 1024 /* has homogeneous volume */
}; };
typedef struct ShaderData { typedef struct ShaderData {
@@ -351,7 +345,7 @@ typedef struct KernelSunSky {
typedef struct KernelIntegrator { typedef struct KernelIntegrator {
/* emission */ /* emission */
int use_emission; int use_direct_light;
int num_distribution; int num_distribution;
int num_all_lights; int num_all_lights;
float pdf_triangles; float pdf_triangles;

View File

@@ -216,8 +216,10 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
shaderdata_to_shaderglobals(kg, sd, path_flag, globals); shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
/* execute shader for this point */ /* execute shader for this point */
if(kg->osl.surface_state[sd->shader]) int shader = sd->shader & SHADER_MASK;
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
if(kg->osl.surface_state[shader])
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals);
/* flatten closure tree */ /* flatten closure tree */
sd->num_closure = 0; sd->num_closure = 0;
@@ -351,7 +353,10 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
shaderdata_to_shaderglobals(kg, sd, path_flag, globals); shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
/* execute shader */ /* execute shader */
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[sd->shader]), *globals); int shader = sd->shader & SHADER_MASK;
if(kg->osl.volume_state[shader])
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals);
/* retrieve resulting closures */ /* retrieve resulting closures */
sd->osl_closure.volume_sample_sum = 0.0f; sd->osl_closure.volume_sample_sum = 0.0f;
@@ -377,7 +382,10 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
shaderdata_to_shaderglobals(kg, sd, 0, globals); shaderdata_to_shaderglobals(kg, sd, 0, globals);
/* execute shader */ /* execute shader */
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[sd->shader]), *globals); int shader = sd->shader & SHADER_MASK;
if(kg->osl.displacement_state[shader])
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals);
/* get back position */ /* get back position */
sd->P = TO_FLOAT3(globals->P); sd->P = TO_FLOAT3(globals->P);

View File

@@ -152,7 +152,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
{ {
float stack[SVM_STACK_SIZE]; float stack[SVM_STACK_SIZE];
float closure_weight = 1.0f; float closure_weight = 1.0f;
int offset = sd->shader; int offset = sd->shader & SHADER_MASK;
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
sd->num_closure = 0; sd->num_closure = 0;

View File

@@ -90,6 +90,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf); eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break; break;
#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID: case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf); eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break; break;
@@ -124,6 +125,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_WESTIN_SHEEN_ID: case CLOSURE_BSDF_WESTIN_SHEEN_ID:
eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf); eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break; break;
#endif
default: default:
eval = make_float3(0.0f, 0.0f, 0.0f); eval = make_float3(0.0f, 0.0f, 0.0f);
break; break;
@@ -134,6 +136,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf); eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break; break;
#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID: case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf); eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break; break;
@@ -168,6 +171,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_WESTIN_SHEEN_ID: case CLOSURE_BSDF_WESTIN_SHEEN_ID:
eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf); eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break; break;
#endif
default: default:
eval = make_float3(0.0f, 0.0f, 0.0f); eval = make_float3(0.0f, 0.0f, 0.0f);
break; break;
@@ -183,6 +187,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_DIFFUSE_ID: case CLOSURE_BSDF_DIFFUSE_ID:
bsdf_diffuse_blur(sc, roughness); bsdf_diffuse_blur(sc, roughness);
break; break;
#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID: case CLOSURE_BSDF_TRANSLUCENT_ID:
bsdf_translucent_blur(sc, roughness); bsdf_translucent_blur(sc, roughness);
break; break;
@@ -217,6 +222,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_WESTIN_SHEEN_ID: case CLOSURE_BSDF_WESTIN_SHEEN_ID:
bsdf_westin_sheen_blur(sc, roughness); bsdf_westin_sheen_blur(sc, roughness);
break; break;
#endif
default: default:
break; break;
} }

View File

@@ -32,8 +32,19 @@ CCL_NAMESPACE_BEGIN
Light::Light() Light::Light()
{ {
type = LIGHT_POINT;
co = make_float3(0.0f, 0.0f, 0.0f); co = make_float3(0.0f, 0.0f, 0.0f);
radius = 0.0f;
dir = make_float3(0.0f, 0.0f, 0.0f);
size = 0.0f;
axisu = make_float3(0.0f, 0.0f, 0.0f);
sizeu = 1.0f;
axisv = make_float3(0.0f, 0.0f, 0.0f);
sizev = 1.0f;
cast_shadow = true;
shader = 0; shader = 0;
} }
@@ -68,7 +79,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* skip if we have no emission shaders */ /* skip if we have no emission shaders */
foreach(uint sindex, mesh->used_shaders) { foreach(uint sindex, mesh->used_shaders) {
if(scene->shaders[sindex]->has_surface_emission) { Shader *shader = scene->shaders[sindex];
if(shader->sample_as_light && shader->has_surface_emission) {
have_emission = true; have_emission = true;
break; break;
} }
@@ -79,7 +92,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
for(size_t i = 0; i < mesh->triangles.size(); i++) { for(size_t i = 0; i < mesh->triangles.size(); i++) {
Shader *shader = scene->shaders[mesh->shader[i]]; Shader *shader = scene->shaders[mesh->shader[i]];
if(shader->has_surface_emission) if(shader->sample_as_light && shader->has_surface_emission)
num_triangles++; num_triangles++;
} }
} }
@@ -104,7 +117,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* skip if we have no emission shaders */ /* skip if we have no emission shaders */
foreach(uint sindex, mesh->used_shaders) { foreach(uint sindex, mesh->used_shaders) {
if(scene->shaders[sindex]->has_surface_emission) { Shader *shader = scene->shaders[sindex];
if(shader->sample_as_light && shader->has_surface_emission) {
have_emission = true; have_emission = true;
break; break;
} }
@@ -118,7 +133,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
for(size_t i = 0; i < mesh->triangles.size(); i++) { for(size_t i = 0; i < mesh->triangles.size(); i++) {
Shader *shader = scene->shaders[mesh->shader[i]]; Shader *shader = scene->shaders[mesh->shader[i]];
if(shader->has_surface_emission) { if(shader->sample_as_light && shader->has_surface_emission) {
distribution[offset].x = totarea; distribution[offset].x = totarea;
distribution[offset].y = __int_as_float(i + mesh->tri_offset); distribution[offset].y = __int_as_float(i + mesh->tri_offset);
distribution[offset].z = 1.0f; distribution[offset].z = 1.0f;
@@ -150,7 +165,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
distribution[offset].x = totarea; distribution[offset].x = totarea;
distribution[offset].y = __int_as_float(-i-1); distribution[offset].y = __int_as_float(-i-1);
distribution[offset].z = 1.0f; distribution[offset].z = 1.0f;
distribution[offset].w = scene->lights[i]->radius; distribution[offset].w = scene->lights[i]->size;
totarea += lightarea; totarea += lightarea;
} }
} }
@@ -171,9 +186,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* update device */ /* update device */
KernelIntegrator *kintegrator = &dscene->data.integrator; KernelIntegrator *kintegrator = &dscene->data.integrator;
kintegrator->use_emission = (totarea > 0.0f) || (multi_light && num_lights); kintegrator->use_direct_light = (totarea > 0.0f) || (multi_light && num_lights);
if(kintegrator->use_emission) { if(kintegrator->use_direct_light) {
/* number of emissives */ /* number of emissives */
kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0; kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
@@ -219,16 +234,45 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
if(scene->lights.size() == 0) if(scene->lights.size() == 0)
return; return;
float4 *light_point = dscene->light_point.resize(scene->lights.size()); float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
for(size_t i = 0; i < scene->lights.size(); i++) { for(size_t i = 0; i < scene->lights.size(); i++) {
float3 co = scene->lights[i]->co; Light *light = scene->lights[i];
float3 co = light->co;
float3 dir = normalize(light->dir);
int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader); int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
light_point[i] = make_float4(co.x, co.y, co.z, __int_as_float(shader_id)); if(!light->cast_shadow)
shader_id &= ~SHADER_CAST_SHADOW;
if(light->type == LIGHT_POINT) {
shader_id &= ~SHADER_AREA_LIGHT;
light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_DISTANT) {
shader_id &= ~SHADER_AREA_LIGHT;
light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
}
else if(light->type == LIGHT_AREA) {
float3 axisu = light->axisu*(light->sizeu*light->size);
float3 axisv = light->axisv*(light->sizev*light->size);
light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z);
light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z);
}
} }
device->tex_alloc("__light_point", dscene->light_point); device->tex_alloc("__light_data", dscene->light_data);
} }
void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -250,10 +294,10 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce
void LightManager::device_free(Device *device, DeviceScene *dscene) void LightManager::device_free(Device *device, DeviceScene *dscene)
{ {
device->tex_free(dscene->light_distribution); device->tex_free(dscene->light_distribution);
device->tex_free(dscene->light_point); device->tex_free(dscene->light_data);
dscene->light_distribution.clear(); dscene->light_distribution.clear();
dscene->light_point.clear(); dscene->light_data.clear();
} }
void LightManager::tag_update(Scene *scene) void LightManager::tag_update(Scene *scene)

View File

@@ -19,6 +19,8 @@
#ifndef __LIGHT_H__ #ifndef __LIGHT_H__
#define __LIGHT_H__ #define __LIGHT_H__
#include "kernel_types.h"
#include "util_types.h" #include "util_types.h"
#include "util_vector.h" #include "util_vector.h"
@@ -33,8 +35,19 @@ class Light {
public: public:
Light(); Light();
LightType type;
float3 co; float3 co;
float radius; /* not implemented yet */
float3 dir;
float size;
float3 axisu;
float sizeu;
float3 axisv;
float sizev;
bool cast_shadow;
int shader; int shader;
void tag_update(Scene *scene); void tag_update(Scene *scene);

View File

@@ -1214,6 +1214,7 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler)
TransparentBsdfNode::TransparentBsdfNode() TransparentBsdfNode::TransparentBsdfNode()
{ {
name = "transparent";
closure = CLOSURE_BSDF_TRANSPARENT_ID; closure = CLOSURE_BSDF_TRANSPARENT_ID;
} }

View File

@@ -88,9 +88,12 @@ void Object::tag_update(Scene *scene)
if(mesh->transform_applied) if(mesh->transform_applied)
mesh->need_update = true; mesh->need_update = true;
foreach(uint sindex, mesh->used_shaders) foreach(uint sindex, mesh->used_shaders) {
if(scene->shaders[sindex]->has_surface_emission) Shader *shader = scene->shaders[sindex];
if(shader->sample_as_light && shader->has_surface_emission)
scene->light_manager->need_update = true; scene->light_manager->need_update = true;
}
} }
scene->mesh_manager->need_update = true; scene->mesh_manager->need_update = true;

View File

@@ -91,7 +91,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
if(progress.get_cancel()) return; if(progress.get_cancel()) return;
if(shader->has_surface_emission) if(shader->sample_as_light && shader->has_surface_emission)
scene->light_manager->need_update = true; scene->light_manager->need_update = true;
OSLCompiler compiler((void*)ss); OSLCompiler compiler((void*)ss);
@@ -112,12 +112,16 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
/* set texture system */ /* set texture system */
scene->image_manager->set_osl_texture_system((void*)ts); scene->image_manager->set_osl_texture_system((void*)ts);
device_update_common(device, dscene, scene, progress);
} }
void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
{ {
OSLGlobals *og = (OSLGlobals*)device->osl_memory(); OSLGlobals *og = (OSLGlobals*)device->osl_memory();
device_free_common(device, dscene);
/* clear shader engine */ /* clear shader engine */
og->use = false; og->use = false;
og->ss = NULL; og->ss = NULL;
@@ -340,6 +344,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
if(node->name == ustring("emission")) if(node->name == ustring("emission"))
current_shader->has_surface_emission = true; current_shader->has_surface_emission = true;
if(node->name == ustring("transparent"))
current_shader->has_surface_transparent = true;
} }
else else
nodes_done = false; nodes_done = false;
@@ -403,6 +409,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
shader->has_surface = false; shader->has_surface = false;
shader->has_surface_emission = false; shader->has_surface_emission = false;
shader->has_surface_transparent = false;
shader->has_volume = false; shader->has_volume = false;
shader->has_displacement = false; shader->has_displacement = false;

View File

@@ -77,10 +77,11 @@ public:
/* lights */ /* lights */
device_vector<float4> light_distribution; device_vector<float4> light_distribution;
device_vector<float4> light_point; device_vector<float4> light_data;
/* shaders */ /* shaders */
device_vector<uint4> svm_nodes; device_vector<uint4> svm_nodes;
device_vector<uint> shader_flag;
/* filter */ /* filter */
device_vector<float> filter_table; device_vector<float> filter_table;

View File

@@ -39,7 +39,11 @@ Shader::Shader()
graph = NULL; graph = NULL;
graph_bump = NULL; graph_bump = NULL;
sample_as_light = true;
homogeneous_volume = false;
has_surface = false; has_surface = false;
has_surface_transparent = false;
has_surface_emission = false; has_surface_emission = false;
has_volume = false; has_volume = false;
has_displacement = false; has_displacement = false;
@@ -72,7 +76,7 @@ void Shader::tag_update(Scene *scene)
/* if the shader previously was emissive, update light distribution, /* if the shader previously was emissive, update light distribution,
* if the new shader is emissive, a light manager update tag will be * if the new shader is emissive, a light manager update tag will be
* done in the shader manager device update. */ * done in the shader manager device update. */
if(has_surface_emission) if(sample_as_light && has_surface_emission)
scene->light_manager->need_update = true; scene->light_manager->need_update = true;
/* get requested attributes. this could be optimized by pruning unused /* get requested attributes. this could be optimized by pruning unused
@@ -146,13 +150,52 @@ int ShaderManager::get_shader_id(uint shader, Mesh *mesh, bool smooth)
/* index depends bump since this setting is not in the shader */ /* index depends bump since this setting is not in the shader */
if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE) if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
id += 1; id += 1;
/* stuff in smooth flag too */ /* smooth flag */
if(smooth) if(smooth)
id= -id; id |= SHADER_SMOOTH_NORMAL;
/* default flags */
id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
return id; return id;
} }
void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
device_free_common(device, dscene);
if(scene->shaders.size() == 0)
return;
uint shader_flag_size = scene->shaders.size()*2;
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
uint i = 0;
foreach(Shader *shader, scene->shaders) {
uint flag = 0;
if(shader->sample_as_light)
flag |= SD_SAMPLE_AS_LIGHT;
if(shader->has_surface_transparent)
flag |= SD_HAS_SURFACE_TRANSPARENT;
if(shader->has_volume)
flag |= SD_HAS_VOLUME;
if(shader->homogeneous_volume)
flag |= SD_HOMOGENEOUS_VOLUME;
shader_flag[i++] = flag;
shader_flag[i++] = flag;
}
device->tex_alloc("__shader_flag", dscene->shader_flag);
}
void ShaderManager::device_free_common(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->shader_flag);
dscene->shader_flag.clear();
}
void ShaderManager::add_default(Scene *scene) void ShaderManager::add_default(Scene *scene)
{ {
Shader *shader; Shader *shader;

View File

@@ -56,6 +56,10 @@ public:
level setting, so we need to handle both */ level setting, so we need to handle both */
ShaderGraph *graph_bump; ShaderGraph *graph_bump;
/* sampling */
bool sample_as_light;
bool homogeneous_volume;
/* synchronization */ /* synchronization */
bool need_update; bool need_update;
bool need_update_attributes; bool need_update_attributes;
@@ -63,6 +67,7 @@ public:
/* information about shader after compiling */ /* information about shader after compiling */
bool has_surface; bool has_surface;
bool has_surface_emission; bool has_surface_emission;
bool has_surface_transparent;
bool has_volume; bool has_volume;
bool has_displacement; bool has_displacement;
@@ -92,6 +97,9 @@ public:
virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0;
virtual void device_free(Device *device, DeviceScene *dscene) = 0; virtual void device_free(Device *device, DeviceScene *dscene) = 0;
void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free_common(Device *device, DeviceScene *dscene);
/* get globally unique id for a type of attribute */ /* get globally unique id for a type of attribute */
uint get_attribute_id(ustring name); uint get_attribute_id(ustring name);
uint get_attribute_id(Attribute::Standard std); uint get_attribute_id(Attribute::Standard std);

View File

@@ -66,7 +66,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
assert(shader->graph); assert(shader->graph);
if(shader->has_surface_emission) if(shader->sample_as_light && shader->has_surface_emission)
scene->light_manager->need_update = true; scene->light_manager->need_update = true;
SVMCompiler compiler(scene->shader_manager, scene->image_manager, SVMCompiler compiler(scene->shader_manager, scene->image_manager,
@@ -86,11 +86,15 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
shader->need_update = false; shader->need_update = false;
} }
device_update_common(device, dscene, scene, progress);
need_update = false; need_update = false;
} }
void SVMShaderManager::device_free(Device *device, DeviceScene *dscene) void SVMShaderManager::device_free(Device *device, DeviceScene *dscene)
{ {
device_free_common(device, dscene);
device->tex_free(dscene->svm_nodes); device->tex_free(dscene->svm_nodes);
dscene->svm_nodes.clear(); dscene->svm_nodes.clear();
} }
@@ -461,6 +465,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
if(node->name == ustring("emission")) if(node->name == ustring("emission"))
current_shader->has_surface_emission = true; current_shader->has_surface_emission = true;
if(node->name == ustring("transparent"))
current_shader->has_surface_transparent = true;
/* end node is added outside of this */ /* end node is added outside of this */
} }
@@ -538,6 +544,8 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don
if(node->name == ustring("emission")) if(node->name == ustring("emission"))
current_shader->has_surface_emission = true; current_shader->has_surface_emission = true;
if(node->name == ustring("transparent"))
current_shader->has_surface_transparent = true;
/* end node is added outside of this */ /* end node is added outside of this */
} }
@@ -641,6 +649,7 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in
shader->has_surface = false; shader->has_surface = false;
shader->has_surface_emission = false; shader->has_surface_emission = false;
shader->has_surface_transparent = false;
shader->has_volume = false; shader->has_volume = false;
shader->has_displacement = false; shader->has_displacement = false;

View File

@@ -780,6 +780,19 @@ __device_inline float triangle_area(const float3 v1, const float3 v2, const floa
#endif #endif
/* Orthonormal vectors */
__device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
{
if(N.x != N.y || N.x != N.z)
*a = make_float3(N.z-N.y, N.x-N.z, N.y-N.x); //(1,1,1)x N
else
*a = make_float3(N.z-N.y, N.x+N.z, -N.y-N.x); //(-1,1,1)x N
*a = normalize(*a);
*b = cross(N, *a);
}
CCL_NAMESPACE_END CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */ #endif /* __UTIL_MATH_H__ */