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

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

View File

@@ -116,11 +116,23 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
@classmethod
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)

View File

@@ -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 = ""

View File

@@ -88,11 +88,57 @@ void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob,
if(!light_map.sync(&light, b_ob, b_parent, key))
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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -73,82 +73,17 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height)
{
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_"));

View File

@@ -63,15 +63,11 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
light_sample(kg, randt, randu, randv, sd->P, &ls);
}
/* 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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;

View File

@@ -216,8 +216,10 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
/* 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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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);

View File

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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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__ */