diff options
author | Mai Lavelle <mai.lavelle@gmail.com> | 2016-08-14 18:44:25 +0300 |
---|---|---|
committer | Mai Lavelle <mai.lavelle@gmail.com> | 2016-09-02 05:45:49 +0300 |
commit | e7ea1ae78c84904864c17248b1b22b1e6c11acc9 (patch) | |
tree | 58c4396ef99d11be64d3421bdbd049e67d076075 /intern/cycles/kernel/osl | |
parent | 62aecbdac19aca49270a11cd0d835f22d31cad72 (diff) |
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
Diffstat (limited to 'intern/cycles/kernel/osl')
-rw-r--r-- | intern/cycles/kernel/osl/osl_globals.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_services.cpp | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_services.h | 1 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_shader.cpp | 41 |
4 files changed, 44 insertions, 0 deletions
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 8353c4e434b..65cb7ecc6b4 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -54,6 +54,7 @@ struct OSLGlobals { vector<OSL::ShaderGroupRef> surface_state; vector<OSL::ShaderGroupRef> volume_state; vector<OSL::ShaderGroupRef> displacement_state; + vector<OSL::ShaderGroupRef> bump_state; OSL::ShaderGroupRef background_state; /* attributes */ diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 422af32ee79..f61a9ec0fb1 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -93,6 +93,7 @@ ustring OSLRenderServices::u_geom_numpolyvertices("geom:numpolyvertices"); ustring OSLRenderServices::u_geom_trianglevertices("geom:trianglevertices"); ustring OSLRenderServices::u_geom_polyvertices("geom:polyvertices"); ustring OSLRenderServices::u_geom_name("geom:name"); +ustring OSLRenderServices::u_geom_undisplaced("geom:undisplaced"); ustring OSLRenderServices::u_is_smooth("geom:is_smooth"); #ifdef __HAIR__ ustring OSLRenderServices::u_is_curve("geom:is_curve"); diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index 2701abb483c..0f2e02c62b0 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -158,6 +158,7 @@ public: static ustring u_geom_trianglevertices; static ustring u_geom_polyvertices; static ustring u_geom_name; + static ustring u_geom_undisplaced; static ustring u_is_smooth; static ustring u_is_curve; static ustring u_curve_thickness; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 20dd167708c..681ea3c1794 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -184,6 +184,47 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; + /* automatic bump shader */ + if(kg->osl->bump_state[shader]) { + /* save state */ + float3 P = sd->P; + float3 dPdx = sd->dP.dx; + float3 dPdy = sd->dP.dy; + + /* set state as if undisplaced */ + if(sd->flag & SD_HAS_DISPLACEMENT) { + float data[9]; + bool found = kg->osl->services->get_attribute(sd, true, OSLRenderServices::u_empty, TypeDesc::TypeVector, + OSLRenderServices::u_geom_undisplaced, data); + assert(found); + + memcpy(&sd->P, data, sizeof(float)*3); + memcpy(&sd->dP.dx, data+3, sizeof(float)*3); + memcpy(&sd->dP.dy, data+6, sizeof(float)*3); + + object_position_transform(kg, sd, &sd->P); + object_dir_transform(kg, sd, &sd->dP.dx); + object_dir_transform(kg, sd, &sd->dP.dy); + + globals->P = TO_VEC3(sd->P); + globals->dPdx = TO_VEC3(sd->dP.dx); + globals->dPdy = TO_VEC3(sd->dP.dy); + } + + /* execute bump shader */ + ss->execute(octx, *(kg->osl->bump_state[shader]), *globals); + + /* reset state */ + sd->P = P; + sd->dP.dx = dPdx; + sd->dP.dy = dPdy; + + globals->P = TO_VEC3(P); + globals->dPdx = TO_VEC3(dPdx); + globals->dPdy = TO_VEC3(dPdy); + } + + /* surface shader */ if(kg->osl->surface_state[shader]) { ss->execute(octx, *(kg->osl->surface_state[shader]), *globals); } |