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:
@@ -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)
|
||||
|
@@ -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
|
||||
|
||||
row = layout.row()
|
||||
row.label(text="Light Group:")
|
||||
row.prop(mat, "light_group", text="")
|
||||
split = layout.split()
|
||||
|
||||
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 = ""
|
||||
|
@@ -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))
|
||||
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);
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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_"));
|
||||
|
@@ -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(no_shadow) {
|
||||
ray->t = 0.0f;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
if(ls.shader & SHADER_CAST_SHADOW) {
|
||||
/* setup ray */
|
||||
ray->P = ray_offset(sd->P, sd->Ng);
|
||||
|
||||
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);
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* signal to not cast shadow ray */
|
||||
ray->t = 0.0f;
|
||||
}
|
||||
|
||||
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);
|
||||
|
@@ -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);
|
||||
|
||||
ls->P = make_float3(f.x, f.y, f.z);
|
||||
ls->Ng = normalize(ls->P - P);
|
||||
ls->shader = __float_as_int(f.w);
|
||||
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->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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
#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);
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
||||
#else
|
||||
eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
|
||||
#endif
|
||||
|
||||
return eval;
|
||||
#else
|
||||
return svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
@@ -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)
|
||||
|
@@ -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 RayType {
|
||||
RayTypeCamera = 1,
|
||||
RayTypeShadow = 2,
|
||||
RayTypeReflection = 4,
|
||||
RayTypeRefraction = 8,
|
||||
RayTypeDiffuse = 16,
|
||||
RayTypeGlossy = 32
|
||||
} RayType;
|
||||
typedef enum ShaderFlag {
|
||||
SHADER_SMOOTH_NORMAL = (1 << 31),
|
||||
SHADER_CAST_SHADOW = (1 << 30),
|
||||
SHADER_AREA_LIGHT = (1 << 29),
|
||||
|
||||
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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
|
@@ -1214,6 +1214,7 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler)
|
||||
|
||||
TransparentBsdfNode::TransparentBsdfNode()
|
||||
{
|
||||
name = "transparent";
|
||||
closure = CLOSURE_BSDF_TRANSPARENT_ID;
|
||||
}
|
||||
|
||||
|
@@ -88,10 +88,13 @@ 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;
|
||||
scene->object_manager->need_update = true;
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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__ */
|
||||
|
Reference in New Issue
Block a user