Fix #111588: Cycles: Vector displacement with adaptive subdiv breaks normal #112987

Merged
Lukas Stockner merged 1 commits from LukasStockner/blender:fix-111588 into blender-v4.0-release 2023-10-02 02:19:59 +02:00
6 changed files with 40 additions and 17 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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