Cycles microdisplacement: Improved automatic bump mapping
Object coordinates can now be used in the displacement shader and will give correct results, where as before bump mapping was calculated from the displace positions and resulted in incorrect shading. This works by evaluating the shader in two parts, first bump then surface, and setting the shader state to match what it would be if the surface was undisplaced for the bump shader evaluation. Currently only `P` is set as if undisplaced, but other shader variables could be set as well, such as `I` or `time`. Since these aren't set to anything meaningful for displacement I left them out of this patch, we can decide what to do with them separately. Reviewed By: brecht Differential Revision: https://developer.blender.org/D2156
This commit is contained in:
@@ -146,9 +146,8 @@ int SVMCompiler::stack_size(SocketType::Type type)
|
||||
return size;
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_find_offset(SocketType::Type type)
|
||||
int SVMCompiler::stack_find_offset(int size)
|
||||
{
|
||||
int size = stack_size(type);
|
||||
int offset = -1;
|
||||
|
||||
/* find free space in stack & mark as used */
|
||||
@@ -175,6 +174,11 @@ int SVMCompiler::stack_find_offset(SocketType::Type type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SVMCompiler::stack_find_offset(SocketType::Type type)
|
||||
{
|
||||
return stack_find_offset(stack_size(type));
|
||||
}
|
||||
|
||||
void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
|
||||
{
|
||||
int size = stack_size(type);
|
||||
@@ -647,6 +651,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
||||
case SHADER_TYPE_DISPLACEMENT:
|
||||
clin = node->input("Displacement");
|
||||
break;
|
||||
case SHADER_TYPE_BUMP:
|
||||
clin = node->input("Normal");
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@@ -663,6 +670,13 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
||||
output->stack_offset = SVM_STACK_INVALID;
|
||||
}
|
||||
|
||||
/* for the bump shader we need add a node to store the shader state */
|
||||
int bump_state_offset = SVM_STACK_INVALID;
|
||||
if(type == SHADER_TYPE_BUMP) {
|
||||
bump_state_offset = stack_find_offset(SVM_BUMP_EVAL_STATE_SIZE);
|
||||
add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
|
||||
}
|
||||
|
||||
if(shader->used) {
|
||||
if(clin->link) {
|
||||
bool generate = false;
|
||||
@@ -680,6 +694,9 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
||||
generate = true;
|
||||
shader->has_displacement = true;
|
||||
break;
|
||||
case SHADER_TYPE_BUMP: /* generate bump shader */
|
||||
generate = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -696,13 +713,21 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
||||
node->compile(*this);
|
||||
}
|
||||
|
||||
/* add node to restore state after bump shader has finished */
|
||||
if(type == SHADER_TYPE_BUMP) {
|
||||
add_node(NODE_LEAVE_BUMP_EVAL, bump_state_offset);
|
||||
}
|
||||
|
||||
/* if compile failed, generate empty shader */
|
||||
if(compile_failed) {
|
||||
svm_nodes.clear();
|
||||
compile_failed = false;
|
||||
}
|
||||
|
||||
add_node(NODE_END, 0, 0, 0);
|
||||
/* for bump shaders we fall thru to the surface shader, but if this is any other kind of shader it ends here */
|
||||
if(type != SHADER_TYPE_BUMP) {
|
||||
add_node(NODE_END, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void SVMCompiler::compile(Scene *scene,
|
||||
@@ -752,17 +777,22 @@ void SVMCompiler::compile(Scene *scene,
|
||||
shader->has_object_dependency = false;
|
||||
shader->has_integrator_dependency = false;
|
||||
|
||||
/* generate surface shader */
|
||||
if(shader->displacement_method == DISPLACE_TRUE || !shader->graph_bump) {
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
||||
/* generate bump shader */
|
||||
if(shader->displacement_method != DISPLACE_TRUE && shader->graph_bump) {
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
|
||||
compile_type(shader, shader->graph_bump, SHADER_TYPE_BUMP);
|
||||
global_svm_nodes[index].y = global_svm_nodes.size();
|
||||
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
|
||||
}
|
||||
else {
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
|
||||
compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
|
||||
global_svm_nodes[index].y = global_svm_nodes.size();
|
||||
|
||||
/* generate surface shader */
|
||||
{
|
||||
scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
||||
/* only set jump offset if there's no bump shader, as the bump shader will fall thru to this one if it exists */
|
||||
if(shader->displacement_method == DISPLACE_TRUE || !shader->graph_bump) {
|
||||
global_svm_nodes[index].y = global_svm_nodes.size();
|
||||
}
|
||||
global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user