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:
@@ -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);
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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)
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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__
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user