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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2011-09-28 00:37:24 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2011-09-28 00:37:24 +0400
commitcdee3435c67abebb633cb09410c4a87d42ff61e3 (patch)
tree9647e36a3661caab918e7726a5971b58b444d403 /intern/cycles
parent136d27b350355232ebe4d0a13427777445334b05 (diff)
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.
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/blender/addon/properties.py14
-rw-r--r--intern/cycles/blender/addon/ui.py64
-rw-r--r--intern/cycles/blender/blender_object.cpp52
-rw-r--r--intern/cycles/blender/blender_shader.cpp5
-rw-r--r--intern/cycles/blender/blender_sync.cpp5
-rw-r--r--intern/cycles/kernel/kernel.cpp83
-rw-r--r--intern/cycles/kernel/kernel_emission.h43
-rw-r--r--intern/cycles/kernel/kernel_light.h114
-rw-r--r--intern/cycles/kernel/kernel_montecarlo.h11
-rw-r--r--intern/cycles/kernel/kernel_path.h25
-rw-r--r--intern/cycles/kernel/kernel_shader.h44
-rw-r--r--intern/cycles/kernel/kernel_textures.h3
-rw-r--r--intern/cycles/kernel/kernel_types.h66
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp16
-rw-r--r--intern/cycles/kernel/svm/svm.h2
-rw-r--r--intern/cycles/kernel/svm/svm_bsdf.h6
-rw-r--r--intern/cycles/render/light.cpp72
-rw-r--r--intern/cycles/render/light.h15
-rw-r--r--intern/cycles/render/nodes.cpp1
-rw-r--r--intern/cycles/render/object.cpp7
-rw-r--r--intern/cycles/render/osl.cpp9
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/render/shader.cpp49
-rw-r--r--intern/cycles/render/shader.h8
-rw-r--r--intern/cycles/render/svm.cpp11
-rw-r--r--intern/cycles/util/util_math.h13
26 files changed, 512 insertions, 229 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 89c2829175c..8d3f709cdef 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -116,11 +116,23 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
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
def unregister(cls):
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):
@classmethod
def register(cls):
@@ -168,6 +180,7 @@ def register():
bpy.utils.register_class(CyclesRenderSettings)
bpy.utils.register_class(CyclesCameraSettings)
bpy.utils.register_class(CyclesMaterialSettings)
+ bpy.utils.register_class(CyclesLampSettings)
bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesVisibilitySettings)
bpy.utils.register_class(CyclesMeshSettings)
@@ -176,6 +189,7 @@ def unregister():
bpy.utils.unregister_class(CyclesRenderSettings)
bpy.utils.unregister_class(CyclesCameraSettings)
bpy.utils.unregister_class(CyclesMaterialSettings)
+ bpy.utils.unregister_class(CyclesLampSettings)
bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index f9ebfdc0bb5..ca2f7e497df 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -360,7 +360,48 @@ def panel_node_draw(layout, id, output_type, input_name):
layout.template_node_view(ntree, node, input);
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"
@classmethod
@@ -399,8 +440,8 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
layout = self.layout
layout.active = False
- mat = context.world
- panel_node_draw(layout, mat, 'OUTPUT_WORLD', 'Volume')
+ world = context.world
+ panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
class CyclesMaterial_PT_surface(CyclesButtonsPanel, Panel):
bl_label = "Surface"
@@ -429,8 +470,12 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
layout.active = False
mat = context.material
+ cmat = mat.cycles
+
panel_node_draw(layout, mat, 'OUTPUT_MATERIAL', 'Volume')
+ layout.prop(cmat, "homogeneous_volume")
+
class CyclesMaterial_PT_displacement(CyclesButtonsPanel, Panel):
bl_label = "Displacement"
bl_context = "material"
@@ -452,17 +497,22 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- # return context.material and CyclesButtonsPanel.poll(context)
return False
+ #return context.material and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
mat = context.material
+ cmat = mat.cycles
+
+ split = layout.split()
- row = layout.row()
- 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):
bl_label = ""
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index e693efb2d7f..a4944a378e0 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -87,12 +87,58 @@ 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))
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 */
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 */
- BL::Lamp b_lamp(b_ob.data());
vector<uint> 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];
+ /* shadow */
+ //PointerRNA clamp = RNA_pointer_get(&b_lamp.ptr, "cycles");
+ //light->cast_shadow = get_boolean(clamp, "cast_shadow");
+
/* tag */
light->tag_update(scene);
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 3993efbce39..0c962e3c5f0 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -587,6 +587,11 @@ void BlenderSync::sync_materials()
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->tag_update(scene);
}
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 9bb7cb45e35..6f03cac315c 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -83,12 +83,17 @@ bool BlenderSync::sync_recalc()
object_map.set_recalc(*b_ob);
light_map.set_recalc(*b_ob);
}
+
if(object_is_mesh(*b_ob)) {
if(b_ob->recalc_data() || b_ob->data().recalc()) {
BL::ID key = object_is_modified(*b_ob)? *b_ob: b_ob->data();
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;
diff --git a/intern/cycles/kernel/kernel.cpp b/intern/cycles/kernel/kernel.cpp
index 7e5fa25c662..52a3852aa01 100644
--- a/intern/cycles/kernel/kernel.cpp
+++ b/intern/cycles/kernel/kernel.cpp
@@ -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)
{
- if(strcmp(name, "__bvh_nodes") == 0) {
- kg->__bvh_nodes.data = (float4*)mem;
- kg->__bvh_nodes.width = width;
+ if(0) {
}
- else if(strcmp(name, "__objects") == 0) {
- kg->__objects.data = (float4*)mem;
- kg->__objects.width = width;
- }
- else if(strcmp(name, "__tri_normal") == 0) {
- 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_TEX(type, ttype, tname) \
+ else if(strcmp(name, #tname) == 0) { \
+ kg->tname.data = (type*)mem; \
+ kg->tname.width = width; \
}
+#define KERNEL_IMAGE_TEX(type, ttype, tname)
+#include "kernel_textures.h"
+
else if(strstr(name, "__tex_image")) {
texture_image_uchar4 *tex = NULL;
int id = atoi(name + strlen("__tex_image_"));
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 58c9183e58a..13c48464088 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -63,15 +63,11 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
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_sample_pdf(kg, &ls, -omega_in, t);
+ float pdf = light_sample_pdf(kg, &ls, -ls.D, ls.t);
/* 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)
return false;
@@ -80,7 +76,7 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
/* evaluate BSDF at shading point */
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;
@@ -92,29 +88,34 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
float mis_weight = power_heuristic(pdf, bsdf_pdf);
*eval *= mis_weight;
}
- else {
+ else if(!(ls.shader & SHADER_AREA_LIGHT)) {
/* ensure point light works in Watts, this should be handled
* elsewhere but for now together with the diffuse emission
* closure it works out to the right value */
*eval *= 0.25f;
+
+ /* XXX verify with other light types */
}
-#if 0
- /* todo: implement this in light */
- bool no_shadow = true;
+ if(ls.shader & SHADER_CAST_SHADOW) {
+ /* setup ray */
+ ray->P = ray_offset(sd->P, sd->Ng);
- if(no_shadow) {
- ray->t = 0.0f;
+ if(ls.t == FLT_MAX) {
+ /* 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 {
-#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
+ /* signal to not cast shadow ray */
+ ray->t = 0.0f;
}
-#endif
return true;
}
@@ -126,7 +127,7 @@ __device float3 indirect_emission(KernelGlobals *kg, ShaderData *sd, float t, in
/* evaluate emissive closure */
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 */
float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
float mis_weight = power_heuristic(bsdf_pdf, pdf);
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 77e73e932ef..68d08a2655f 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -20,30 +20,112 @@ CCL_NAMESPACE_BEGIN
typedef struct LightSample {
float3 P;
+ float3 D;
float3 Ng;
+ float t;
int object;
int prim;
int shader;
- float weight;
} 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)
{
- 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);
+
+ LightType type = (LightType)__float_as_int(data0.x);
+
+ 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->P = make_float3(f.x, f.y, f.z);
- ls->Ng = normalize(ls->P - P);
- ls->shader = __float_as_int(f.w);
+ ls->shader = __float_as_int(data1.x);
ls->object = ~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 */
@@ -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->object = object;
ls->prim = prim;
+ ls->t = 0.0f;
#ifdef __INSTANCING__
/* instance transform */
@@ -117,7 +200,6 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
/* fetch light data */
float4 l = kernel_tex_fetch(__light_distribution, index);
int prim = __float_as_int(l.y);
- ls->weight = l.z;
if(prim >= 0) {
int object = __float_as_int(l.w);
@@ -125,8 +207,12 @@ __device void light_sample(KernelGlobals *kg, float randt, float randu, float ra
}
else {
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)
@@ -136,19 +222,19 @@ __device float light_sample_pdf(KernelGlobals *kg, LightSample *ls, float3 I, fl
if(ls->prim != ~0)
pdf = triangle_light_pdf(kg, ls->Ng, I, t);
else
- pdf = point_light_pdf(kg, t);
+ pdf = regular_light_pdf(kg, ls->Ng, I, 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);
+ regular_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);
+ return regular_light_pdf(kg, ls->Ng, I, t);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_montecarlo.h b/intern/cycles/kernel/kernel_montecarlo.h
index 5d9afb6418f..df291b66b23 100644
--- a/intern/cycles/kernel/kernel_montecarlo.h
+++ b/intern/cycles/kernel/kernel_montecarlo.h
@@ -67,17 +67,6 @@ __device void to_unit_disk(float *x, float *y)
*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)
{
*b = cross(N, T);
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index d6977c24c53..e438780b1c8 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -162,19 +162,6 @@ __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)
@@ -229,12 +216,10 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
throughput *= shader_bsdf_transparency(kg, &sd);
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++;
}
-
- return true;
}
}
#endif
@@ -298,10 +283,8 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
#ifdef __EMISSION__
/* emission */
- if(kernel_data.integrator.use_emission) {
- if(sd.flag & SD_EMISSION)
- L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
- }
+ if(sd.flag & SD_EMISSION)
+ L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
#endif
/* 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;
#ifdef __EMISSION__
- if(kernel_data.integrator.use_emission) {
+ if(kernel_data.integrator.use_direct_light) {
/* sample illumination from lights to find path contribution */
if(sd.flag & SD_BSDF_HAS_EVAL) {
float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 0cf2091590c..c1bcbb067b5 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -60,7 +60,6 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->N = Ng;
sd->I = -ray->D;
sd->shader = shader;
- sd->flag = 0;
/* triangle */
#ifdef __INSTANCING__
@@ -73,10 +72,10 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
#endif
/* 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->shader = -sd->shader;
- }
+
+ sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
#ifdef __DPDU__
/* 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);
if(backfacing) {
- sd->flag = SD_BACKFACING;
+ sd->flag |= SD_BACKFACING;
sd->Ng = -sd->Ng;
sd->N = -sd->N;
#ifdef __DPDU__
@@ -132,7 +131,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
sd->Ng = Ng;
sd->I = I;
sd->shader = shader;
- sd->flag = 0;
/* primitive */
#ifdef __INSTANCING__
@@ -159,9 +157,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif
/* 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->shader = -sd->shader;
#ifdef __INSTANCING__
if(instanced)
@@ -169,6 +166,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif
}
+ sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
+
#ifdef __DPDU__
/* dPdu/dPdv */
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);
if(backfacing) {
- sd->flag = SD_BACKFACING;
+ sd->flag |= SD_BACKFACING;
sd->Ng = -sd->Ng;
sd->N = -sd->N;
#ifdef __DPDU__
@@ -245,7 +244,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
sd->Ng = -sd->P;
sd->I = -sd->P;
sd->shader = kernel_data.background.shader;
- sd->flag = 0;
+ sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
#ifdef __INSTANCING__
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++) {
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;
}
@@ -428,8 +427,9 @@ __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
{
+ float3 eval;
#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++) {
ShaderClosure *sc = &sd->closure[i];
@@ -442,11 +442,11 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
#endif
}
}
-
- return eval;
#else
- return svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
+ eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
#endif
+
+ return eval;
}
/* Holdout */
@@ -581,6 +581,20 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
#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 */
__device void shader_release(KernelGlobals *kg, ShaderData *sd)
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 19635b2664c..2bfb1b3b88e 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -32,10 +32,11 @@ KERNEL_TEX(float4, texture_float4, __attributes_float3)
/* lights */
KERNEL_TEX(float4, texture_float4, __light_distribution)
-KERNEL_TEX(float4, texture_float4, __light_point)
+KERNEL_TEX(float4, texture_float4, __light_data)
/* shaders */
KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
+KERNEL_TEX(uint, texture_uint, __shader_flag)
/* camera/film */
KERNEL_TEX(float, texture_float, __filter_table)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index e09eaa8284c..bda037e88cc 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -26,6 +26,7 @@
CCL_NAMESPACE_BEGIN
#define OBJECT_SIZE 16
+#define LIGHT_SIZE 4
#define __SOBOL__
#define __INSTANCING__
@@ -43,12 +44,12 @@ CCL_NAMESPACE_BEGIN
#define __EMISSION__
#define __TEXTURES__
#define __HOLDOUT__
+//#define __MULTI_CLOSURE__
+//#define __TRANSPARENT_SHADOWS__
+//#define __MULTI_LIGHT__
#endif
#ifdef __KERNEL_CPU__
-//#define __MULTI_CLOSURE__
-//#define __MULTI_LIGHT__
-//#define __TRANSPARENT_SHADOWS__
//#define __OSL__
#endif
@@ -79,6 +80,7 @@ enum PathTraceDimension {
/* 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
* your own new ray types and bitflag values */
+
enum PathRayFlag {
PATH_RAY_CAMERA = 1,
PATH_RAY_SHADOW = 2,
@@ -92,28 +94,6 @@ enum PathRayFlag {
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 */
typedef enum ClosureLabel {
@@ -132,16 +112,23 @@ typedef enum ClosureLabel {
LABEL_STOP = 2048
} ClosureLabel;
-/* Ray Type */
+/* Shader Flag */
+
+typedef enum ShaderFlag {
+ SHADER_SMOOTH_NORMAL = (1 << 31),
+ SHADER_CAST_SHADOW = (1 << 30),
+ SHADER_AREA_LIGHT = (1 << 29),
-typedef enum RayType {
- RayTypeCamera = 1,
- RayTypeShadow = 2,
- RayTypeReflection = 4,
- RayTypeRefraction = 8,
- RayTypeDiffuse = 16,
- RayTypeGlossy = 32
-} RayType;
+ SHADER_MASK = ~(SHADER_SMOOTH_NORMAL|SHADER_CAST_SHADOW|SHADER_AREA_LIGHT)
+} ShaderFlag;
+
+/* Light Type */
+
+typedef enum LightType {
+ LIGHT_POINT,
+ LIGHT_DISTANT,
+ LIGHT_AREA
+} LightType;
/* Differential */
@@ -213,13 +200,20 @@ typedef struct ShaderClosure {
* are in world space. */
enum ShaderDataFlag {
+ /* runtime flags */
SD_BACKFACING = 1, /* backside of surface? */
SD_EMISSION = 2, /* have emissive closure? */
SD_BSDF = 4, /* have bsdf closure? */
SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
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 {
@@ -351,7 +345,7 @@ typedef struct KernelSunSky {
typedef struct KernelIntegrator {
/* emission */
- int use_emission;
+ int use_direct_light;
int num_distribution;
int num_all_lights;
float pdf_triangles;
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 3f0b1610181..18a8e974492 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -216,8 +216,10 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
/* execute shader for this point */
- if(kg->osl.surface_state[sd->shader])
- ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[sd->shader]), *globals);
+ int shader = sd->shader & SHADER_MASK;
+
+ if(kg->osl.surface_state[shader])
+ ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals);
/* flatten closure tree */
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);
/* 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 */
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);
/* 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 */
sd->P = TO_FLOAT3(globals->P);
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index bd5c07753ad..62e02f1a01a 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -152,7 +152,7 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
{
float stack[SVM_STACK_SIZE];
float closure_weight = 1.0f;
- int offset = sd->shader;
+ int offset = sd->shader & SHADER_MASK;
#ifdef __MULTI_CLOSURE__
sd->num_closure = 0;
diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h
index a1b39c6ca1e..411efc8be8f 100644
--- a/intern/cycles/kernel/svm/svm_bsdf.h
+++ b/intern/cycles/kernel/svm/svm_bsdf.h
@@ -90,6 +90,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
+#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
@@ -124,6 +125,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
eval = bsdf_westin_sheen_eval_reflect(sd, sc, sd->I, omega_in, pdf);
break;
+#endif
default:
eval = make_float3(0.0f, 0.0f, 0.0f);
break;
@@ -134,6 +136,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
+#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
@@ -168,6 +171,7 @@ __device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, con
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
eval = bsdf_westin_sheen_eval_transmit(sd, sc, sd->I, omega_in, pdf);
break;
+#endif
default:
eval = make_float3(0.0f, 0.0f, 0.0f);
break;
@@ -183,6 +187,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_DIFFUSE_ID:
bsdf_diffuse_blur(sc, roughness);
break;
+#ifdef __SVM__
case CLOSURE_BSDF_TRANSLUCENT_ID:
bsdf_translucent_blur(sc, roughness);
break;
@@ -217,6 +222,7 @@ __device void svm_bsdf_blur(ShaderClosure *sc, float roughness)
case CLOSURE_BSDF_WESTIN_SHEEN_ID:
bsdf_westin_sheen_blur(sc, roughness);
break;
+#endif
default:
break;
}
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index b13cab55404..74943fd0ff7 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -32,8 +32,19 @@ CCL_NAMESPACE_BEGIN
Light::Light()
{
+ type = LIGHT_POINT;
+
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;
}
@@ -68,7 +79,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* skip if we have no emission 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;
break;
}
@@ -79,7 +92,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
for(size_t i = 0; i < mesh->triangles.size(); i++) {
Shader *shader = scene->shaders[mesh->shader[i]];
- if(shader->has_surface_emission)
+ if(shader->sample_as_light && shader->has_surface_emission)
num_triangles++;
}
}
@@ -104,7 +117,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* skip if we have no emission 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;
break;
}
@@ -118,7 +133,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
for(size_t i = 0; i < mesh->triangles.size(); 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].y = __int_as_float(i + mesh->tri_offset);
distribution[offset].z = 1.0f;
@@ -150,7 +165,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
distribution[offset].x = totarea;
distribution[offset].y = __int_as_float(-i-1);
distribution[offset].z = 1.0f;
- distribution[offset].w = scene->lights[i]->radius;
+ distribution[offset].w = scene->lights[i]->size;
totarea += lightarea;
}
}
@@ -171,9 +186,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* update device */
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 */
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)
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++) {
- 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);
- 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)
@@ -250,10 +294,10 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce
void LightManager::device_free(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->light_distribution);
- device->tex_free(dscene->light_point);
+ device->tex_free(dscene->light_data);
dscene->light_distribution.clear();
- dscene->light_point.clear();
+ dscene->light_data.clear();
}
void LightManager::tag_update(Scene *scene)
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index dbc333260ee..19cbcb55386 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -19,6 +19,8 @@
#ifndef __LIGHT_H__
#define __LIGHT_H__
+#include "kernel_types.h"
+
#include "util_types.h"
#include "util_vector.h"
@@ -33,8 +35,19 @@ class Light {
public:
Light();
+ LightType type;
float3 co;
- float radius; /* not implemented yet */
+
+ float3 dir;
+ float size;
+
+ float3 axisu;
+ float sizeu;
+ float3 axisv;
+ float sizev;
+
+ bool cast_shadow;
+
int shader;
void tag_update(Scene *scene);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 4fd562b540c..9e7e2a8a81d 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1214,6 +1214,7 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler)
TransparentBsdfNode::TransparentBsdfNode()
{
+ name = "transparent";
closure = CLOSURE_BSDF_TRANSPARENT_ID;
}
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index fec1ab7f4c8..b91531ac462 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -88,9 +88,12 @@ void Object::tag_update(Scene *scene)
if(mesh->transform_applied)
mesh->need_update = true;
- foreach(uint sindex, mesh->used_shaders)
- if(scene->shaders[sindex]->has_surface_emission)
+ foreach(uint sindex, mesh->used_shaders) {
+ Shader *shader = scene->shaders[sindex];
+
+ if(shader->sample_as_light && shader->has_surface_emission)
scene->light_manager->need_update = true;
+ }
}
scene->mesh_manager->need_update = true;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 446cf72f5d6..b0173334c76 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -91,7 +91,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
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;
OSLCompiler compiler((void*)ss);
@@ -112,12 +112,16 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
/* set texture system */
scene->image_manager->set_osl_texture_system((void*)ts);
+
+ device_update_common(device, dscene, scene, progress);
}
void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
{
OSLGlobals *og = (OSLGlobals*)device->osl_memory();
+ device_free_common(device, dscene);
+
/* clear shader engine */
og->use = false;
og->ss = NULL;
@@ -340,6 +344,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
if(node->name == ustring("emission"))
current_shader->has_surface_emission = true;
+ if(node->name == ustring("transparent"))
+ current_shader->has_surface_transparent = true;
}
else
nodes_done = false;
@@ -403,6 +409,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
shader->has_surface = false;
shader->has_surface_emission = false;
+ shader->has_surface_transparent = false;
shader->has_volume = false;
shader->has_displacement = false;
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 93d8ebf1301..a969dd66c4c 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -77,10 +77,11 @@ public:
/* lights */
device_vector<float4> light_distribution;
- device_vector<float4> light_point;
+ device_vector<float4> light_data;
/* shaders */
device_vector<uint4> svm_nodes;
+ device_vector<uint> shader_flag;
/* filter */
device_vector<float> filter_table;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 548beaaecdd..6e827ec94bb 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -39,7 +39,11 @@ Shader::Shader()
graph = NULL;
graph_bump = NULL;
+ sample_as_light = true;
+ homogeneous_volume = false;
+
has_surface = false;
+ has_surface_transparent = false;
has_surface_emission = false;
has_volume = 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 new shader is emissive, a light manager update tag will be
* done in the shader manager device update. */
- if(has_surface_emission)
+ if(sample_as_light && has_surface_emission)
scene->light_manager->need_update = true;
/* 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 */
if(mesh && mesh->displacement_method != Mesh::DISPLACE_TRUE)
id += 1;
- /* stuff in smooth flag too */
+ /* smooth flag */
if(smooth)
- id= -id;
+ id |= SHADER_SMOOTH_NORMAL;
+
+ /* default flags */
+ id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
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)
{
Shader *shader;
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index cc8bc473a3f..45efa123ef6 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -56,6 +56,10 @@ public:
level setting, so we need to handle both */
ShaderGraph *graph_bump;
+ /* sampling */
+ bool sample_as_light;
+ bool homogeneous_volume;
+
/* synchronization */
bool need_update;
bool need_update_attributes;
@@ -63,6 +67,7 @@ public:
/* information about shader after compiling */
bool has_surface;
bool has_surface_emission;
+ bool has_surface_transparent;
bool has_volume;
bool has_displacement;
@@ -92,6 +97,9 @@ public:
virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 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 */
uint get_attribute_id(ustring name);
uint get_attribute_id(Attribute::Standard std);
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 8b527691bd9..a1687ae5e29 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -66,7 +66,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
assert(shader->graph);
- if(shader->has_surface_emission)
+ if(shader->sample_as_light && shader->has_surface_emission)
scene->light_manager->need_update = true;
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;
}
+ device_update_common(device, dscene, scene, progress);
+
need_update = false;
}
void SVMShaderManager::device_free(Device *device, DeviceScene *dscene)
{
+ device_free_common(device, dscene);
+
device->tex_free(dscene->svm_nodes);
dscene->svm_nodes.clear();
}
@@ -461,6 +465,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done)
if(node->name == ustring("emission"))
current_shader->has_surface_emission = true;
+ if(node->name == ustring("transparent"))
+ current_shader->has_surface_transparent = true;
/* 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"))
current_shader->has_surface_emission = true;
+ if(node->name == ustring("transparent"))
+ current_shader->has_surface_transparent = true;
/* 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_emission = false;
+ shader->has_surface_transparent = false;
shader->has_volume = false;
shader->has_displacement = false;
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index c0418b3d8fd..38e90f0b2b2 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -780,6 +780,19 @@ __device_inline float triangle_area(const float3 v1, const float3 v2, const floa
#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
#endif /* __UTIL_MATH_H__ */