Fix #111588: Cycles: Vector displacement with adaptive subdiv breaks normal #112987
|
@ -30,6 +30,10 @@ ccl_device_noinline void svm_node_enter_bump_eval(KernelGlobals kg,
|
|||
|
||||
sd->P = P;
|
||||
sd->dP = differential_make_compact(dP);
|
||||
|
||||
/* Save the full differential, the compact form isn't enough for svm_node_set_bump. */
|
||||
stack_store_float3(stack, offset + 4, dP.dx);
|
||||
stack_store_float3(stack, offset + 7, dP.dy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@ ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
|||
ccl_private float *stack,
|
||||
uint4 node)
|
||||
{
|
||||
uint out_offset, bump_state_offset, dummy;
|
||||
svm_unpack_node_uchar4(node.w, &out_offset, &bump_state_offset, &dummy, &dummy);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
IF_KERNEL_NODES_FEATURE(BUMP)
|
||||
{
|
||||
|
@ -25,7 +28,16 @@ ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
|||
float3 normal_in = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
|
||||
sd->N;
|
||||
|
||||
differential3 dP = differential_from_compact(sd->Ng, sd->dP);
|
||||
/* If we have saved bump state, read the full differential from there.
|
||||
* Just using the compact form in those cases leads to incorrect normals (see #111588). */
|
||||
differential3 dP;
|
||||
if (bump_state_offset == SVM_STACK_INVALID) {
|
||||
dP = differential_from_compact(sd->Ng, sd->dP);
|
||||
}
|
||||
else {
|
||||
dP.dx = stack_load_float3(stack, bump_state_offset + 4);
|
||||
dP.dy = stack_load_float3(stack, bump_state_offset + 7);
|
||||
}
|
||||
|
||||
if (use_object_space) {
|
||||
object_inverse_normal_transform(kg, sd, &normal_in);
|
||||
|
@ -72,10 +84,10 @@ ccl_device_noinline void svm_node_set_bump(KernelGlobals kg,
|
|||
object_normal_transform(kg, sd, &normal_out);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, node.w, normal_out);
|
||||
stack_store_float3(stack, out_offset, normal_out);
|
||||
}
|
||||
else {
|
||||
stack_store_float3(stack, node.w, zero_float3());
|
||||
stack_store_float3(stack, out_offset, zero_float3());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ CCL_NAMESPACE_BEGIN
|
|||
/* SVM stack offsets with this value indicate that it's not on the stack */
|
||||
#define SVM_STACK_INVALID 255
|
||||
|
||||
#define SVM_BUMP_EVAL_STATE_SIZE 4
|
||||
#define SVM_BUMP_EVAL_STATE_SIZE 10
|
||||
|
||||
/* Nodes */
|
||||
|
||||
|
|
|
@ -6726,16 +6726,17 @@ void BumpNode::compile(SVMCompiler &compiler)
|
|||
ShaderOutput *normal_out = output("Normal");
|
||||
|
||||
/* pack all parameters in the node */
|
||||
compiler.add_node(NODE_SET_BUMP,
|
||||
compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
|
||||
compiler.stack_assign(distance_in),
|
||||
invert,
|
||||
use_object_space),
|
||||
compiler.encode_uchar4(compiler.stack_assign(center_in),
|
||||
compiler.stack_assign(dx_in),
|
||||
compiler.stack_assign(dy_in),
|
||||
compiler.stack_assign(strength_in)),
|
||||
compiler.stack_assign(normal_out));
|
||||
compiler.add_node(
|
||||
NODE_SET_BUMP,
|
||||
compiler.encode_uchar4(compiler.stack_assign_if_linked(normal_in),
|
||||
compiler.stack_assign(distance_in),
|
||||
invert,
|
||||
use_object_space),
|
||||
compiler.encode_uchar4(compiler.stack_assign(center_in),
|
||||
compiler.stack_assign(dx_in),
|
||||
compiler.stack_assign(dy_in),
|
||||
compiler.stack_assign(strength_in)),
|
||||
compiler.encode_uchar4(compiler.stack_assign(normal_out), compiler.get_bump_state_offset()));
|
||||
}
|
||||
|
||||
void BumpNode::compile(OSLCompiler &compiler)
|
||||
|
|
|
@ -163,6 +163,7 @@ SVMCompiler::SVMCompiler(Scene *scene) : scene(scene)
|
|||
current_graph = NULL;
|
||||
background = false;
|
||||
mix_weight_offset = SVM_STACK_INVALID;
|
||||
bump_state_offset = SVM_STACK_INVALID;
|
||||
compile_failed = false;
|
||||
|
||||
/* This struct has one entry for every node, in order of ShaderNodeType definition. */
|
||||
|
@ -784,9 +785,8 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
}
|
||||
|
||||
/* for the bump shader we need add a node to store the shader state */
|
||||
bool need_bump_state = (type == SHADER_TYPE_BUMP) &&
|
||||
(shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
int bump_state_offset = SVM_STACK_INVALID;
|
||||
const bool need_bump_state = (type == SHADER_TYPE_BUMP) &&
|
||||
(shader->get_displacement_method() == DISPLACE_BOTH);
|
||||
if (need_bump_state) {
|
||||
bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
|
||||
add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
|
||||
|
@ -846,6 +846,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
|||
/* add node to restore state after bump shader has finished */
|
||||
if (need_bump_state) {
|
||||
add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
|
||||
bump_state_offset = SVM_STACK_INVALID;
|
||||
}
|
||||
|
||||
/* if compile failed, generate empty shader */
|
||||
|
|
|
@ -106,6 +106,10 @@ class SVMCompiler {
|
|||
{
|
||||
return mix_weight_offset;
|
||||
}
|
||||
uint get_bump_state_offset()
|
||||
{
|
||||
return bump_state_offset;
|
||||
}
|
||||
|
||||
ShaderType output_type()
|
||||
{
|
||||
|
@ -222,6 +226,7 @@ class SVMCompiler {
|
|||
Stack active_stack;
|
||||
int max_stack_use;
|
||||
uint mix_weight_offset;
|
||||
uint bump_state_offset;
|
||||
bool compile_failed;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue