Fix #31168: cycles mask layer should only affect objects for camera rays.

Fix: texture coordinate normal output was not correct, still changed under
object transform.
This commit is contained in:
Brecht Van Lommel 2012-05-02 09:33:45 +00:00
parent 5d4fd04f05
commit 1e2afcddd3
16 changed files with 99 additions and 55 deletions

@ -198,11 +198,11 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
/* Sync */
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
{
/* test if we can instance or if the object is modified */
BL::ID b_ob_data = b_ob.data();
BL::ID key = (object_is_modified(b_ob) || holdout)? b_ob: b_ob_data;
BL::ID key = (object_is_modified(b_ob))? b_ob: b_ob_data;
BL::Material material_override = render_layer.material_override;
/* find shader indices */
@ -212,18 +212,14 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool holdout, bool object_updated)
for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) {
BL::Material material_override = render_layer.material_override;
if(holdout)
find_shader(PointerRNA_NULL, used_shaders, scene->default_holdout);
else if(material_override)
if(material_override)
find_shader(material_override, used_shaders, scene->default_surface);
else
find_shader(slot->material(), used_shaders, scene->default_surface);
}
if(used_shaders.size() == 0) {
if(holdout)
used_shaders.push_back(scene->default_holdout);
else if(material_override)
if(material_override)
find_shader(material_override, used_shaders, scene->default_surface);
else
used_shaders.push_back(scene->default_surface);

@ -232,11 +232,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
if(object_map.sync(&object, b_ob, b_parent, key))
object_updated = true;
/* holdout? */
bool holdout = (layer_flag & render_layer.holdout_layer) != 0;
bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
/* mesh sync */
object->mesh = sync_mesh(b_ob, holdout, object_updated);
object->mesh = sync_mesh(b_ob, object_updated);
if(use_holdout != object->use_holdout) {
object->use_holdout = use_holdout;
scene->object_manager->tag_update(scene);
}
/* object sync */
if(object_updated || (object->mesh && object->mesh->need_update)) {

@ -79,7 +79,7 @@ private:
void sync_shaders();
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
Mesh *sync_mesh(BL::Object b_ob, bool holdout, bool object_updated);
Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion);
void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
void sync_background_light();

@ -64,7 +64,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float
Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __MOTION__
if(ray->time != TIME_INVALID)
if(kernel_data.cam.have_motion)
transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
#endif
@ -107,7 +107,7 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa
Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __MOTION__
if(ray->time != TIME_INVALID)
if(kernel_data.cam.have_motion)
transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
#endif
@ -147,7 +147,7 @@ __device void camera_sample_environment(KernelGlobals *kg, float raster_x, float
Transform cameratoworld = kernel_data.cam.cameratoworld;
#ifdef __MOTION__
if(ray->time != TIME_INVALID)
if(kernel_data.cam.have_motion)
transform_motion_interpolate(&cameratoworld, &kernel_data.cam.motion, ray->time);
#endif

@ -32,34 +32,28 @@ __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object,
#ifdef __MOTION__
/* if we do motion blur */
if(time != TIME_INVALID) {
int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE;
float4 have_motion = kernel_tex_fetch(__objects, offset + 0);
if(sd->flag & SD_OBJECT_MOTION) {
/* fetch motion transforms */
MotionTransform motion;
/* if this object have motion */
if(have_motion.x != FLT_MAX) {
/* fetch motion transforms */
MotionTransform motion;
motion.pre.x = have_motion;
motion.pre.y = kernel_tex_fetch(__objects, offset + 1);
motion.pre.z = kernel_tex_fetch(__objects, offset + 2);
motion.pre.w = kernel_tex_fetch(__objects, offset + 3);
motion.pre.x = have_motion;
motion.pre.y = kernel_tex_fetch(__objects, offset + 1);
motion.pre.z = kernel_tex_fetch(__objects, offset + 2);
motion.pre.w = kernel_tex_fetch(__objects, offset + 3);
motion.post.x = kernel_tex_fetch(__objects, offset + 4);
motion.post.y = kernel_tex_fetch(__objects, offset + 5);
motion.post.z = kernel_tex_fetch(__objects, offset + 6);
motion.post.w = kernel_tex_fetch(__objects, offset + 7);
motion.post.x = kernel_tex_fetch(__objects, offset + 4);
motion.post.y = kernel_tex_fetch(__objects, offset + 5);
motion.post.z = kernel_tex_fetch(__objects, offset + 6);
motion.post.w = kernel_tex_fetch(__objects, offset + 7);
/* interpolate (todo: do only once per object) */
transform_motion_interpolate(&tfm, &motion, time);
/* interpolate (todo: do only once per object) */
transform_motion_interpolate(&tfm, &motion, time);
/* invert */
if(type == OBJECT_INVERSE_TRANSFORM)
tfm = transform_quick_inverse(tfm);
/* invert */
if(type == OBJECT_INVERSE_TRANSFORM)
tfm = transform_quick_inverse(tfm);
return tfm;
}
return tfm;
}
#endif
@ -83,6 +77,16 @@ __device_inline void object_position_transform(KernelGlobals *kg, ShaderData *sd
#endif
}
__device_inline void object_inverse_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N)
{
#ifdef __MOTION__
*N = normalize(transform_direction_transposed(&sd->ob_tfm, *N));
#else
Transform tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
#endif
}
__device_inline void object_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N)
{
#ifdef __MOTION__

@ -277,12 +277,21 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
/* holdout */
#ifdef __HOLDOUT__
if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) {
float3 holdout_weight = shader_holdout_eval(kg, &sd);
if((sd.flag & (SD_HOLDOUT|SD_HOLDOUT_MASK)) && (state.flag & PATH_RAY_CAMERA)) {
if(kernel_data.background.transparent) {
float3 holdout_weight;
if(sd.flag & SD_HOLDOUT_MASK)
holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
else
shader_holdout_eval(kg, &sd);
if(kernel_data.background.transparent)
/* any throughput is ok, should all be identical here */
L_transparent += average(holdout_weight*throughput);
}
if(sd.flag & SD_HOLDOUT_MASK)
break;
}
#endif

@ -83,6 +83,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
#ifdef __DPDU__
/* dPdu/dPdv */
@ -177,6 +178,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
}
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
sd->flag |= kernel_tex_fetch(__object_flag, sd->object);
#ifdef __DPDU__
/* dPdu/dPdv */

@ -39,6 +39,7 @@ KERNEL_TEX(float2, texture_float2, __light_background_conditional_cdf)
/* shaders */
KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
KERNEL_TEX(uint, texture_uint, __shader_flag)
KERNEL_TEX(uint, texture_uint, __object_flag)
/* camera/film */
KERNEL_TEX(float, texture_float, __filter_table)

@ -38,7 +38,7 @@ CCL_NAMESPACE_BEGIN
/* device capabilities */
#ifdef __KERNEL_CPU__
#define __KERNEL_SHADING__
#define __KERNEL_ADV_SHADING__
//#define __KERNEL_ADV_SHADING__
#endif
#ifdef __KERNEL_CUDA__
@ -370,7 +370,11 @@ enum ShaderDataFlag {
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 */
SD_HOMOGENEOUS_VOLUME = 1024, /* has homogeneous volume */
/* object flags */
SD_HOLDOUT_MASK = 2048, /* holdout for camera rays */
SD_OBJECT_MOTION = 4096 /* has object motion blur */
};
typedef struct ShaderData {
@ -463,7 +467,7 @@ typedef struct KernelCamera {
/* motion blur */
float shuttertime;
float pad;
int have_motion;
/* clipping */
float nearclip;

@ -43,7 +43,7 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
case NODE_TEXCO_NORMAL: {
if(sd->object != ~0) {
data = sd->N;
object_normal_transform(kg, sd, &data);
object_inverse_normal_transform(kg, sd, &data);
}
else
data = sd->N;
@ -97,7 +97,7 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
case NODE_TEXCO_NORMAL: {
if(sd->object != ~0) {
data = sd->N;
object_normal_transform(kg, sd, &data);
object_inverse_normal_transform(kg, sd, &data);
}
else
data = sd->N;
@ -154,7 +154,7 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
case NODE_TEXCO_NORMAL: {
if(sd->object != ~0) {
data = sd->N;
object_normal_transform(kg, sd, &data);
object_inverse_normal_transform(kg, sd, &data);
}
else
data = sd->N;

@ -149,6 +149,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
/* camera motion */
Scene::MotionType need_motion = scene->need_motion();
kcam->have_motion = 0;
if(need_motion == Scene::MOTION_PASS) {
if(use_motion) {
@ -162,7 +163,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
}
else if(need_motion == Scene::MOTION_BLUR) {
/* todo: exact camera position will not be hit this way */
transform_motion_decompose(&kcam->motion, &motion);
if(use_motion) {
transform_motion_decompose(&kcam->motion, &motion);
kcam->have_motion = 1;
}
}
/* depth of field */

@ -41,6 +41,7 @@ Object::Object()
motion.pre = transform_identity();
motion.post = transform_identity();
use_motion = false;
use_holdout = false;
}
Object::~Object()
@ -143,12 +144,14 @@ ObjectManager::~ObjectManager()
void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
uint *object_flag = dscene->object_flag.resize(OBJECT_SIZE*scene->objects.size());
int i = 0;
map<Mesh*, float> surface_area_map;
Scene::MotionType need_motion = scene->need_motion();
foreach(Object *ob, scene->objects) {
Mesh *mesh = ob->mesh;
uint flag = 0;
/* compute transformations */
Transform tfm = ob->tfm;
@ -219,6 +222,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
transform_motion_decompose(&decomp, &ob->motion);
memcpy(&objects[offset+8], &decomp, sizeof(float4)*8);
flag |= SD_OBJECT_MOTION;
}
else {
float4 no_motion = make_float4(FLT_MAX);
@ -226,12 +230,18 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
}
}
/* object flag */
if(ob->use_holdout)
flag |= SD_HOLDOUT_MASK;
object_flag[i] = flag;
i++;
if(progress.get_cancel()) return;
}
device->tex_alloc("__objects", dscene->objects);
device->tex_alloc("__object_flag", dscene->object_flag);
}
void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@ -266,6 +276,9 @@ void ObjectManager::device_free(Device *device, DeviceScene *dscene)
{
device->tex_free(dscene->objects);
dscene->objects.clear();
device->tex_free(dscene->object_flag);
dscene->object_flag.clear();
}
void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress)

@ -46,6 +46,7 @@ public:
uint visibility;
MotionTransform motion;
bool use_motion;
bool use_holdout;
Object();
~Object();

@ -85,6 +85,7 @@ public:
/* shaders */
device_vector<uint4> svm_nodes;
device_vector<uint> shader_flag;
device_vector<uint> object_flag;
/* filter */
device_vector<float> filter_table;

@ -436,6 +436,11 @@ __device_inline float len(const float3 a)
return sqrtf(dot(a, a));
}
__device_inline float len_squared(const float3 a)
{
return dot(a, a);
}
#ifndef __KERNEL_OPENCL__
__device_inline float3 normalize(const float3 a)

@ -255,12 +255,12 @@ __device_inline bool transform_uniform_scale(const Transform& tfm, float& scale)
Transform ttfm = transform_transpose(tfm);
float eps = 1e-7f;
float sx = len(float4_to_float3(tfm.x));
float sy = len(float4_to_float3(tfm.y));
float sz = len(float4_to_float3(tfm.z));
float stx = len(float4_to_float3(ttfm.x));
float sty = len(float4_to_float3(ttfm.y));
float stz = len(float4_to_float3(ttfm.z));
float sx = len_squared(float4_to_float3(tfm.x));
float sy = len_squared(float4_to_float3(tfm.y));
float sz = len_squared(float4_to_float3(tfm.z));
float stx = len_squared(float4_to_float3(ttfm.x));
float sty = len_squared(float4_to_float3(ttfm.y));
float stz = len_squared(float4_to_float3(ttfm.z));
if(fabsf(sx - sy) < eps && fabsf(sx - sz) < eps &&
fabsf(sx - stx) < eps && fabsf(sx - sty) < eps &&