Cycles: Replace object index hack with actual checks for SD_TRANSFORM_APPLIED

Using ones complement for detecting if transform has been applied was confusing
and led to several bugs. With this proper checks are made.

Also added a few transforms where they were missing, mostly affecting baking
and displacement when `P` is used in the shader (previously `P` was in the
wrong space for these shaders)

Also removed `TIME_INVALID` as this may have resulted in incorrect
transforms in some cases.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D2192
This commit is contained in:
Mai Lavelle
2016-09-02 21:37:17 -04:00
parent 92a2c49aab
commit 013b46d6bd
14 changed files with 61 additions and 44 deletions

View File

@@ -681,8 +681,7 @@ void BlenderSession::bake(BL::Object& b_object,
} }
} }
/* when used, non-instanced convention: object = ~object */ int object = object_index;
int object = ~object_index;
BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels); BakeData *bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);

View File

@@ -564,6 +564,15 @@ ccl_device_inline void bvh_instance_motion_pop_factor(KernelGlobals *kg,
*/ */
#ifdef __KERNEL_OPENCL__ #ifdef __KERNEL_OPENCL__
ccl_device_inline void object_position_transform_addrspace(KernelGlobals *kg,
const ShaderData *sd,
ccl_addr_space float3 *P)
{
float3 private_P = *P;
object_position_transform(kg, sd, &private_P);
*P = private_P;
}
ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg, ccl_device_inline void object_dir_transform_addrspace(KernelGlobals *kg,
const ShaderData *sd, const ShaderData *sd,
ccl_addr_space float3 *D) ccl_addr_space float3 *D)
@@ -584,9 +593,11 @@ ccl_device_inline void object_normal_transform_addrspace(KernelGlobals *kg,
#endif #endif
#ifndef __KERNEL_OPENCL__ #ifndef __KERNEL_OPENCL__
# define object_position_transform_auto object_position_transform
# define object_dir_transform_auto object_dir_transform # define object_dir_transform_auto object_dir_transform
# define object_normal_transform_auto object_normal_transform # define object_normal_transform_auto object_normal_transform
#else #else
# define object_position_transform_auto object_position_transform_addrspace
# define object_dir_transform_auto object_dir_transform_addrspace # define object_dir_transform_auto object_dir_transform_addrspace
# define object_normal_transform_auto object_normal_transform_addrspace # define object_normal_transform_auto object_normal_transform_addrspace
#endif #endif

View File

@@ -52,8 +52,8 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int
float t = 1.0f - u - v; float t = 1.0f - u - v;
*P = (u*v0 + v*v1 + t*v2); *P = (u*v0 + v*v1 + t*v2);
/* get object flags, instance-aware */ /* get object flags */
int object_flag = kernel_tex_fetch(__object_flag, object >= 0 ? object : ~object); int object_flag = kernel_tex_fetch(__object_flag, object);
/* compute normal */ /* compute normal */
if(object_flag & SD_NEGATIVE_SCALE_APPLIED) if(object_flag & SD_NEGATIVE_SCALE_APPLIED)

View File

@@ -41,7 +41,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
ray.D = -sd->Ng; ray.D = -sd->Ng;
ray.t = FLT_MAX; ray.t = FLT_MAX;
#ifdef __CAMERA_MOTION__ #ifdef __CAMERA_MOTION__
ray.time = TIME_INVALID; ray.time = 0.5f;
#endif #endif
/* init radiance */ /* init radiance */
@@ -313,15 +313,14 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader); triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
/* dummy initilizations copied from SHADER_EVAL_DISPLACE */
float3 I = Ng;
float t = 1.0f;
float time = TIME_INVALID;
/* light passes */ /* light passes */
PathRadiance L; PathRadiance L;
shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time); shader_setup_from_sample(kg, &sd,
P, Ng, Ng,
shader, object, prim,
u, v, 1.0f, 0.5f,
!(kernel_tex_fetch(__object_flag, object) & SD_TRANSFORM_APPLIED));
sd.I = sd.N; sd.I = sd.N;
/* update differentials */ /* update differentials */
@@ -525,6 +524,8 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg,
float3 P = sd.P; float3 P = sd.P;
shader_eval_displacement(kg, &sd, &state, SHADER_CONTEXT_MAIN); shader_eval_displacement(kg, &sd, &state, SHADER_CONTEXT_MAIN);
out = sd.P - P; out = sd.P - P;
object_inverse_dir_transform(kg, &sd, &out);
} }
else { // SHADER_EVAL_BACKGROUND else { // SHADER_EVAL_BACKGROUND
/* setup ray */ /* setup ray */

View File

@@ -321,7 +321,7 @@ ccl_device_inline void camera_sample(KernelGlobals *kg,
#ifdef __CAMERA_MOTION__ #ifdef __CAMERA_MOTION__
/* motion blur */ /* motion blur */
if(kernel_data.cam.shuttertime == -1.0f) { if(kernel_data.cam.shuttertime == -1.0f) {
ray->time = TIME_INVALID; ray->time = 0.5f;
} }
else { else {
/* TODO(sergey): Such lookup is unneeded when there's rolling shutter /* TODO(sergey): Such lookup is unneeded when there's rolling shutter

View File

@@ -56,7 +56,10 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
} }
else else
{ {
shader_setup_from_sample(kg, emission_sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, ls->u, ls->v, t, time); shader_setup_from_sample(kg, emission_sd,
ls->P, ls->Ng, I,
ls->shader, ls->object, ls->prim,
ls->u, ls->v, t, time, false);
ls->Ng = ccl_fetch(emission_sd, Ng); ls->Ng = ccl_fetch(emission_sd, Ng);

View File

@@ -747,7 +747,7 @@ ccl_device void object_transform_light_sample(KernelGlobals *kg, LightSample *ls
{ {
#ifdef __INSTANCING__ #ifdef __INSTANCING__
/* instance transform */ /* instance transform */
if(object >= 0) { if(!(kernel_tex_fetch(__object_flag, object) & SD_TRANSFORM_APPLIED)) {
# ifdef __OBJECT_MOTION__ # ifdef __OBJECT_MOTION__
Transform itfm; Transform itfm;
Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm); Transform tfm = object_fetch_transform_motion_test(kg, object, time, &itfm);

View File

@@ -241,7 +241,8 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
const float3 I, const float3 I,
int shader, int object, int prim, int shader, int object, int prim,
float u, float v, float t, float u, float v, float t,
float time) float time,
bool object_space)
{ {
/* vectors */ /* vectors */
ccl_fetch(sd, P) = P; ccl_fetch(sd, P) = P;
@@ -263,20 +264,6 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
#endif #endif
ccl_fetch(sd, ray_length) = t; ccl_fetch(sd, ray_length) = t;
/* detect instancing, for non-instanced the object index is -object-1 */
#ifdef __INSTANCING__
bool instanced = false;
if(ccl_fetch(sd, prim) != PRIM_NONE) {
if(ccl_fetch(sd, object) >= 0)
instanced = true;
else
#endif
ccl_fetch(sd, object) = ~ccl_fetch(sd, object);
#ifdef __INSTANCING__
}
#endif
ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2); ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*2);
if(ccl_fetch(sd, object) != OBJECT_NONE) { if(ccl_fetch(sd, object) != OBJECT_NONE) {
ccl_fetch(sd, flag) |= kernel_tex_fetch(__object_flag, ccl_fetch(sd, object)); ccl_fetch(sd, flag) |= kernel_tex_fetch(__object_flag, ccl_fetch(sd, object));
@@ -290,14 +277,23 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
} }
#endif #endif
/* transform into world space */
if(object_space) {
object_position_transform_auto(kg, sd, &ccl_fetch(sd, P));
object_normal_transform_auto(kg, sd, &ccl_fetch(sd, Ng));
ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, I));
}
if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) { if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
/* smooth normal */ /* smooth normal */
if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) { if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v)); ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
#ifdef __INSTANCING__ #ifdef __INSTANCING__
if(instanced) if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) {
object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N)); object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
}
#endif #endif
} }
@@ -306,7 +302,7 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv)); triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
# ifdef __INSTANCING__ # ifdef __INSTANCING__
if(instanced) { if(!(ccl_fetch(sd, flag) & SD_TRANSFORM_APPLIED)) {
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu)); object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv)); object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
} }
@@ -357,9 +353,11 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
/* force smooth shading for displacement */ /* force smooth shading for displacement */
shader |= SHADER_SMOOTH_NORMAL; shader |= SHADER_SMOOTH_NORMAL;
/* watch out: no instance transform currently */ shader_setup_from_sample(kg, sd,
P, Ng, I,
shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v, 0.0f, TIME_INVALID); shader, object, prim,
u, v, 0.0f, 0.5f,
!(kernel_tex_fetch(__object_flag, object) & SD_TRANSFORM_APPLIED));
} }
/* ShaderData setup from ray into background */ /* ShaderData setup from ray into background */

View File

@@ -42,7 +42,6 @@ CCL_NAMESPACE_BEGIN
#define RAMP_TABLE_SIZE 256 #define RAMP_TABLE_SIZE 256
#define SHUTTER_TABLE_SIZE 256 #define SHUTTER_TABLE_SIZE 256
#define PARTICLE_SIZE 5 #define PARTICLE_SIZE 5
#define TIME_INVALID FLT_MAX
#define BSSRDF_MIN_RADIUS 1e-8f #define BSSRDF_MIN_RADIUS 1e-8f
#define BSSRDF_MAX_HITS 4 #define BSSRDF_MAX_HITS 4

View File

@@ -18,6 +18,8 @@
displacement node_output_displacement(float Displacement = 0.0) displacement node_output_displacement(float Displacement = 0.0)
{ {
P += N * Displacement * 0.1; /* todo: get rid of this factor */ vector dP = normalize(transform("object", N));
dP *= Displacement * 0.1; /* todo: get rid of this factor */
P += transform("object", "world", dP);
} }

View File

@@ -261,7 +261,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z); svm_node_geometry_bump_dy(kg, sd, stack, node.y, node.z);
break; break;
case NODE_SET_DISPLACEMENT: case NODE_SET_DISPLACEMENT:
svm_node_set_displacement(sd, stack, node.y); svm_node_set_displacement(kg, sd, stack, node.y);
break; break;
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */ # endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
# ifdef __TEXTURES__ # ifdef __TEXTURES__

View File

@@ -76,10 +76,18 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
/* Displacement Node */ /* Displacement Node */
ccl_device void svm_node_set_displacement(ShaderData *sd, float *stack, uint fac_offset) ccl_device void svm_node_set_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset)
{ {
float d = stack_load_float(stack, fac_offset); float d = stack_load_float(stack, fac_offset);
ccl_fetch(sd, P) += ccl_fetch(sd, N)*d*0.1f; /* todo: get rid of this factor */
float3 dP = ccl_fetch(sd, N);
object_inverse_normal_transform(kg, sd, &dP);
dP *= d*0.1f; /* todo: get rid of this factor */
object_dir_transform(kg, sd, &dP);
ccl_fetch(sd, P) += dP;
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -309,9 +309,6 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
int object_id = j; int object_id = j;
int shader_flag = 0; int shader_flag = 0;
if(transform_applied)
object_id = ~object_id;
if(!(object->visibility & PATH_RAY_DIFFUSE)) { if(!(object->visibility & PATH_RAY_DIFFUSE)) {
shader_flag |= SHADER_EXCLUDE_DIFFUSE; shader_flag |= SHADER_EXCLUDE_DIFFUSE;
use_light_visibility = true; use_light_visibility = true;

View File

@@ -86,8 +86,7 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
done[t.v[j]] = true; done[t.v[j]] = true;
/* set up object, primitive and barycentric coordinates */ /* set up object, primitive and barycentric coordinates */
/* when used, non-instanced convention: object = ~object */ int object = object_index;
int object = ~object_index;
int prim = mesh->tri_offset + i; int prim = mesh->tri_offset + i;
float u, v; float u, v;