Code refactor: rename subsurface to local traversal, for reuse.
This commit is contained in:
parent
d0af56fe3b
commit
f79f386731
|
@ -139,6 +139,9 @@ public:
|
|||
/* Denoising features. */
|
||||
bool use_denoising;
|
||||
|
||||
/* Use raytracing in shaders. */
|
||||
bool use_shader_raytrace;
|
||||
|
||||
DeviceRequestedFeatures()
|
||||
{
|
||||
/* TODO(sergey): Find more meaningful defaults. */
|
||||
|
@ -158,6 +161,7 @@ public:
|
|||
use_shadow_tricks = false;
|
||||
use_principled = false;
|
||||
use_denoising = false;
|
||||
use_shader_raytrace = false;
|
||||
}
|
||||
|
||||
bool modified(const DeviceRequestedFeatures& requested_features)
|
||||
|
@ -177,7 +181,8 @@ public:
|
|||
use_transparent == requested_features.use_transparent &&
|
||||
use_shadow_tricks == requested_features.use_shadow_tricks &&
|
||||
use_principled == requested_features.use_principled &&
|
||||
use_denoising == requested_features.use_denoising);
|
||||
use_denoising == requested_features.use_denoising &&
|
||||
use_shader_raytrace == requested_features.use_shader_raytrace);
|
||||
}
|
||||
|
||||
/* Convert the requested features structure to a build options,
|
||||
|
@ -230,6 +235,9 @@ public:
|
|||
if(!use_denoising) {
|
||||
build_options += " -D__NO_DENOISING__";
|
||||
}
|
||||
if(!use_shader_raytrace) {
|
||||
build_options += " -D__NO_SHADER_RAYTRACE__";
|
||||
}
|
||||
return build_options;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -65,14 +65,14 @@ set(SRC_BVH_HEADERS
|
|||
bvh/bvh.h
|
||||
bvh/bvh_nodes.h
|
||||
bvh/bvh_shadow_all.h
|
||||
bvh/bvh_subsurface.h
|
||||
bvh/bvh_local.h
|
||||
bvh/bvh_traversal.h
|
||||
bvh/bvh_types.h
|
||||
bvh/bvh_volume.h
|
||||
bvh/bvh_volume_all.h
|
||||
bvh/qbvh_nodes.h
|
||||
bvh/qbvh_shadow_all.h
|
||||
bvh/qbvh_subsurface.h
|
||||
bvh/qbvh_local.h
|
||||
bvh/qbvh_traversal.h
|
||||
bvh/qbvh_volume.h
|
||||
bvh/qbvh_volume_all.h
|
||||
|
|
|
@ -68,17 +68,17 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
/* Subsurface scattering BVH traversal */
|
||||
|
||||
#if defined(__SUBSURFACE__)
|
||||
# define BVH_FUNCTION_NAME bvh_intersect_subsurface
|
||||
#if defined(__BVH_LOCAL__)
|
||||
# define BVH_FUNCTION_NAME bvh_intersect_local
|
||||
# define BVH_FUNCTION_FEATURES BVH_HAIR
|
||||
# include "kernel/bvh/bvh_subsurface.h"
|
||||
# include "kernel/bvh/bvh_local.h"
|
||||
|
||||
# if defined(__OBJECT_MOTION__)
|
||||
# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
|
||||
# define BVH_FUNCTION_NAME bvh_intersect_local_motion
|
||||
# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
|
||||
# include "kernel/bvh/bvh_subsurface.h"
|
||||
# include "kernel/bvh/bvh_local.h"
|
||||
# endif
|
||||
#endif /* __SUBSURFACE__ */
|
||||
#endif /* __BVH_LOCAL__ */
|
||||
|
||||
/* Volume BVH traversal */
|
||||
|
||||
|
@ -201,31 +201,31 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
|
|||
#endif /* __KERNEL_CPU__ */
|
||||
}
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
#ifdef __BVH_LOCAL__
|
||||
/* Note: ray is passed by value to work around a possible CUDA compiler bug. */
|
||||
ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
|
||||
const Ray ray,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
int subsurface_object,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
ccl_device_intersect void scene_intersect_local(KernelGlobals *kg,
|
||||
const Ray ray,
|
||||
LocalIntersection *local_isect,
|
||||
int local_object,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
{
|
||||
#ifdef __OBJECT_MOTION__
|
||||
if(kernel_data.bvh.have_motion) {
|
||||
return bvh_intersect_subsurface_motion(kg,
|
||||
&ray,
|
||||
ss_isect,
|
||||
subsurface_object,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
return bvh_intersect_local_motion(kg,
|
||||
&ray,
|
||||
local_isect,
|
||||
local_object,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
#endif /* __OBJECT_MOTION__ */
|
||||
return bvh_intersect_subsurface(kg,
|
||||
&ray,
|
||||
ss_isect,
|
||||
subsurface_object,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
return bvh_intersect_local(kg,
|
||||
&ray,
|
||||
local_isect,
|
||||
local_object,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
#ifdef __QBVH__
|
||||
# include "kernel/bvh/qbvh_subsurface.h"
|
||||
# include "kernel/bvh/qbvh_local.h"
|
||||
#endif
|
||||
|
||||
#if BVH_FEATURE(BVH_HAIR)
|
||||
|
@ -27,9 +27,10 @@
|
|||
# define NODE_INTERSECT bvh_aligned_node_intersect
|
||||
#endif
|
||||
|
||||
/* This is a template BVH traversal function for subsurface scattering, where
|
||||
* various features can be enabled/disabled. This way we can compile optimized
|
||||
* versions for each case without new features slowing things down.
|
||||
/* This is a template BVH traversal function for finding local intersections
|
||||
* around the shading point, for subsurface scattering and bevel. We disable
|
||||
* various features for performance, and for instanced objects avoid traversing
|
||||
* other parts of the scene.
|
||||
*
|
||||
* BVH_MOTION: motion blur rendering
|
||||
*
|
||||
|
@ -42,8 +43,8 @@ ccl_device_inline
|
|||
#endif
|
||||
void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
||||
const Ray *ray,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
int subsurface_object,
|
||||
LocalIntersection *local_isect,
|
||||
int local_object,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
{
|
||||
|
@ -60,7 +61,7 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
|
||||
/* traversal variables in registers */
|
||||
int stack_ptr = 0;
|
||||
int node_addr = kernel_tex_fetch(__object_node, subsurface_object);
|
||||
int node_addr = kernel_tex_fetch(__object_node, local_object);
|
||||
|
||||
/* ray parameters in registers */
|
||||
float3 P = ray->P;
|
||||
|
@ -69,14 +70,14 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
int object = OBJECT_NONE;
|
||||
float isect_t = ray->t;
|
||||
|
||||
ss_isect->num_hits = 0;
|
||||
local_isect->num_hits = 0;
|
||||
|
||||
const int object_flag = kernel_tex_fetch(__object_flag, subsurface_object);
|
||||
const int object_flag = kernel_tex_fetch(__object_flag, local_object);
|
||||
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
Transform ob_itfm;
|
||||
isect_t = bvh_instance_motion_push(kg,
|
||||
subsurface_object,
|
||||
local_object,
|
||||
ray,
|
||||
&P,
|
||||
&dir,
|
||||
|
@ -84,9 +85,9 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
isect_t,
|
||||
&ob_itfm);
|
||||
#else
|
||||
isect_t = bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, isect_t);
|
||||
isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
|
||||
#endif
|
||||
object = subsurface_object;
|
||||
object = local_object;
|
||||
}
|
||||
|
||||
#if defined(__KERNEL_SSE2__)
|
||||
|
@ -193,15 +194,16 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
/* intersect ray against primitive */
|
||||
for(; prim_addr < prim_addr2; prim_addr++) {
|
||||
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
|
||||
triangle_intersect_subsurface(kg,
|
||||
ss_isect,
|
||||
P,
|
||||
dir,
|
||||
object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
triangle_intersect_local(kg,
|
||||
local_isect,
|
||||
P,
|
||||
dir,
|
||||
object,
|
||||
local_object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -210,16 +212,17 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
/* intersect ray against primitive */
|
||||
for(; prim_addr < prim_addr2; prim_addr++) {
|
||||
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
|
||||
motion_triangle_intersect_subsurface(kg,
|
||||
ss_isect,
|
||||
P,
|
||||
dir,
|
||||
ray->time,
|
||||
object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
motion_triangle_intersect_local(kg,
|
||||
local_isect,
|
||||
P,
|
||||
dir,
|
||||
ray->time,
|
||||
object,
|
||||
local_object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -235,8 +238,8 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
|
|||
|
||||
ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
|
||||
const Ray *ray,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
int subsurface_object,
|
||||
LocalIntersection *local_isect,
|
||||
int local_object,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
{
|
||||
|
@ -244,8 +247,8 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
|
|||
if(kernel_data.bvh.use_qbvh) {
|
||||
return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
|
||||
ray,
|
||||
ss_isect,
|
||||
subsurface_object,
|
||||
local_isect,
|
||||
local_object,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
|
@ -255,8 +258,8 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
|
|||
kernel_assert(kernel_data.bvh.use_qbvh == false);
|
||||
return BVH_FUNCTION_FULL_NAME(BVH)(kg,
|
||||
ray,
|
||||
ss_isect,
|
||||
subsurface_object,
|
||||
local_isect,
|
||||
local_object,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
|
@ -14,9 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This is a template BVH traversal function for subsurface scattering, where
|
||||
* various features can be enabled/disabled. This way we can compile optimized
|
||||
* versions for each case without new features slowing things down.
|
||||
/* This is a template BVH traversal function for finding local intersections
|
||||
* around the shading point, for subsurface scattering and bevel. We disable
|
||||
* various features for performance, and for instanced objects avoid traversing
|
||||
* other parts of the scene.
|
||||
*
|
||||
* BVH_MOTION: motion blur rendering
|
||||
*
|
||||
|
@ -30,8 +31,8 @@
|
|||
|
||||
ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
||||
const Ray *ray,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
int subsurface_object,
|
||||
LocalIntersection *local_isect,
|
||||
int local_object,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
{
|
||||
|
@ -49,7 +50,7 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
|||
|
||||
/* Traversal variables in registers. */
|
||||
int stack_ptr = 0;
|
||||
int node_addr = kernel_tex_fetch(__object_node, subsurface_object);
|
||||
int node_addr = kernel_tex_fetch(__object_node, local_object);
|
||||
|
||||
/* Ray parameters in registers. */
|
||||
float3 P = ray->P;
|
||||
|
@ -58,14 +59,14 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
|||
int object = OBJECT_NONE;
|
||||
float isect_t = ray->t;
|
||||
|
||||
ss_isect->num_hits = 0;
|
||||
local_isect->num_hits = 0;
|
||||
|
||||
const int object_flag = kernel_tex_fetch(__object_flag, subsurface_object);
|
||||
const int object_flag = kernel_tex_fetch(__object_flag, local_object);
|
||||
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
|
||||
#if BVH_FEATURE(BVH_MOTION)
|
||||
Transform ob_itfm;
|
||||
isect_t = bvh_instance_motion_push(kg,
|
||||
subsurface_object,
|
||||
local_object,
|
||||
ray,
|
||||
&P,
|
||||
&dir,
|
||||
|
@ -73,9 +74,9 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
|||
isect_t,
|
||||
&ob_itfm);
|
||||
#else
|
||||
isect_t = bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, isect_t);
|
||||
isect_t = bvh_instance_push(kg, local_object, ray, &P, &dir, &idir, isect_t);
|
||||
#endif
|
||||
object = subsurface_object;
|
||||
object = local_object;
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_SSE41__
|
||||
|
@ -249,15 +250,16 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
|||
/* Intersect ray against primitive, */
|
||||
for(; prim_addr < prim_addr2; prim_addr++) {
|
||||
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
|
||||
triangle_intersect_subsurface(kg,
|
||||
ss_isect,
|
||||
P,
|
||||
dir,
|
||||
object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
triangle_intersect_local(kg,
|
||||
local_isect,
|
||||
P,
|
||||
dir,
|
||||
object,
|
||||
local_object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -266,16 +268,17 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|
|||
/* Intersect ray against primitive. */
|
||||
for(; prim_addr < prim_addr2; prim_addr++) {
|
||||
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
|
||||
motion_triangle_intersect_subsurface(kg,
|
||||
ss_isect,
|
||||
P,
|
||||
dir,
|
||||
ray->time,
|
||||
object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
motion_triangle_intersect_local(kg,
|
||||
local_isect,
|
||||
P,
|
||||
dir,
|
||||
ray->time,
|
||||
object,
|
||||
local_object,
|
||||
prim_addr,
|
||||
isect_t,
|
||||
lcg_state,
|
||||
max_hits);
|
||||
}
|
||||
break;
|
||||
}
|
|
@ -97,17 +97,17 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg,
|
|||
* for instancing.
|
||||
*/
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
#ifdef __BVH_LOCAL__
|
||||
# if defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86))
|
||||
ccl_device_noinline
|
||||
# else
|
||||
ccl_device_inline
|
||||
# endif
|
||||
float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
const Intersection *isect,
|
||||
const Ray *ray,
|
||||
float3 verts[3])
|
||||
float3 motion_triangle_refine_local(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
const Intersection *isect,
|
||||
const Ray *ray,
|
||||
float3 verts[3])
|
||||
{
|
||||
float3 P = ray->P;
|
||||
float3 D = ray->D;
|
||||
|
@ -159,7 +159,7 @@ float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
|
|||
return P + D*t;
|
||||
# endif /* __INTERSECTION_REFINE__ */
|
||||
}
|
||||
#endif /* __SUBSURFACE__ */
|
||||
#endif /* __BVH_LOCAL__ */
|
||||
|
||||
|
||||
/* Ray intersection. We simply compute the vertex positions at the given ray
|
||||
|
@ -215,31 +215,37 @@ ccl_device_inline bool motion_triangle_intersect(
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Special ray intersection routines for subsurface scattering. In that case we
|
||||
/* Special ray intersection routines for local intersections. In that case we
|
||||
* only want to intersect with primitives in the same object, and if case of
|
||||
* multiple hits we pick a single random primitive as the intersection point.
|
||||
*/
|
||||
#ifdef __SUBSURFACE__
|
||||
ccl_device_inline void motion_triangle_intersect_subsurface(
|
||||
#ifdef __BVH_LOCAL__
|
||||
ccl_device_inline void motion_triangle_intersect_local(
|
||||
KernelGlobals *kg,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
LocalIntersection *local_isect,
|
||||
float3 P,
|
||||
float3 dir,
|
||||
float time,
|
||||
int object,
|
||||
int local_object,
|
||||
int prim_addr,
|
||||
float tmax,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
{
|
||||
/* Only intersect with matching object, for instanced objects we
|
||||
* already know we are only intersecting the right object. */
|
||||
if(object == OBJECT_NONE) {
|
||||
if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Primitive index for vertex location lookup. */
|
||||
int prim = kernel_tex_fetch(__prim_index, prim_addr);
|
||||
int fobject = (object == OBJECT_NONE)
|
||||
? kernel_tex_fetch(__prim_object, prim_addr)
|
||||
: object;
|
||||
/* Get vertex locations for intersection. */
|
||||
float3 verts[3];
|
||||
motion_triangle_vertices(kg, fobject, prim, time, verts);
|
||||
motion_triangle_vertices(kg, local_object, prim, time, verts);
|
||||
/* Ray-triangle intersection, unoptimized. */
|
||||
float t, u, v;
|
||||
if(ray_triangle_intersect(P,
|
||||
|
@ -252,27 +258,27 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
|
|||
#endif
|
||||
&u, &v, &t))
|
||||
{
|
||||
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
|
||||
if(ss_isect->hits[i].t == t) {
|
||||
for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
|
||||
if(local_isect->hits[i].t == t) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ss_isect->num_hits++;
|
||||
local_isect->num_hits++;
|
||||
int hit;
|
||||
if(ss_isect->num_hits <= max_hits) {
|
||||
hit = ss_isect->num_hits - 1;
|
||||
if(local_isect->num_hits <= max_hits) {
|
||||
hit = local_isect->num_hits - 1;
|
||||
}
|
||||
else {
|
||||
/* Reservoir sampling: if we are at the maximum number of
|
||||
* hits, randomly replace element or skip it.
|
||||
*/
|
||||
hit = lcg_step_uint(lcg_state) % ss_isect->num_hits;
|
||||
hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
|
||||
|
||||
if(hit >= max_hits)
|
||||
return;
|
||||
}
|
||||
/* Record intersection. */
|
||||
Intersection *isect = &ss_isect->hits[hit];
|
||||
Intersection *isect = &local_isect->hits[hit];
|
||||
isect->t = t;
|
||||
isect->u = u;
|
||||
isect->v = v;
|
||||
|
@ -280,10 +286,10 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
|
|||
isect->object = object;
|
||||
isect->type = PRIMITIVE_MOTION_TRIANGLE;
|
||||
/* Record geometric normal. */
|
||||
ss_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
|
||||
local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
|
||||
verts[2] - verts[0]));
|
||||
}
|
||||
}
|
||||
#endif /* __SUBSURFACE__ */
|
||||
#endif /* __BVH_LOCAL__ */
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -36,7 +36,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
|
|||
ShaderData *sd, const
|
||||
Intersection *isect,
|
||||
const Ray *ray,
|
||||
bool subsurface)
|
||||
bool is_local)
|
||||
{
|
||||
/* Get shader. */
|
||||
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
|
||||
|
@ -66,16 +66,16 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
|
|||
verts[1] = (1.0f - t)*verts[1] + t*next_verts[1];
|
||||
verts[2] = (1.0f - t)*verts[2] + t*next_verts[2];
|
||||
/* Compute refined position. */
|
||||
#ifdef __SUBSURFACE__
|
||||
if(subsurface) {
|
||||
sd->P = motion_triangle_refine_subsurface(kg,
|
||||
sd,
|
||||
isect,
|
||||
ray,
|
||||
verts);
|
||||
#ifdef __BVH_LOCAL__
|
||||
if(is_local) {
|
||||
sd->P = motion_triangle_refine_local(kg,
|
||||
sd,
|
||||
isect,
|
||||
ray,
|
||||
verts);
|
||||
}
|
||||
else
|
||||
#endif /* __SUBSURFACE__*/
|
||||
#endif /* __BVH_LOCAL__*/
|
||||
{
|
||||
sd->P = motion_triangle_refine(kg, sd, isect, ray, verts);
|
||||
}
|
||||
|
|
|
@ -70,23 +70,32 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Special ray intersection routines for subsurface scattering. In that case we
|
||||
/* Special ray intersection routines for local intersection. In that case we
|
||||
* only want to intersect with primitives in the same object, and if case of
|
||||
* multiple hits we pick a single random primitive as the intersection point.
|
||||
*/
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
ccl_device_inline void triangle_intersect_subsurface(
|
||||
#ifdef __BVH_LOCAL__
|
||||
ccl_device_inline void triangle_intersect_local(
|
||||
KernelGlobals *kg,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
LocalIntersection *local_isect,
|
||||
float3 P,
|
||||
float3 dir,
|
||||
int object,
|
||||
int local_object,
|
||||
int prim_addr,
|
||||
float tmax,
|
||||
uint *lcg_state,
|
||||
int max_hits)
|
||||
{
|
||||
/* Only intersect with matching object, for instanced objects we
|
||||
* already know we are only intersecting the right object. */
|
||||
if(object == OBJECT_NONE) {
|
||||
if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
|
||||
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
|
||||
const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex];
|
||||
|
@ -109,29 +118,29 @@ ccl_device_inline void triangle_intersect_subsurface(
|
|||
return;
|
||||
}
|
||||
|
||||
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
|
||||
if(ss_isect->hits[i].t == t) {
|
||||
for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
|
||||
if(local_isect->hits[i].t == t) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ss_isect->num_hits++;
|
||||
local_isect->num_hits++;
|
||||
int hit;
|
||||
|
||||
if(ss_isect->num_hits <= max_hits) {
|
||||
hit = ss_isect->num_hits - 1;
|
||||
if(local_isect->num_hits <= max_hits) {
|
||||
hit = local_isect->num_hits - 1;
|
||||
}
|
||||
else {
|
||||
/* reservoir sampling: if we are at the maximum number of
|
||||
* hits, randomly replace element or skip it */
|
||||
hit = lcg_step_uint(lcg_state) % ss_isect->num_hits;
|
||||
hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
|
||||
|
||||
if(hit >= max_hits)
|
||||
return;
|
||||
}
|
||||
|
||||
/* record intersection */
|
||||
Intersection *isect = &ss_isect->hits[hit];
|
||||
Intersection *isect = &local_isect->hits[hit];
|
||||
isect->prim = prim_addr;
|
||||
isect->object = object;
|
||||
isect->type = PRIMITIVE_TRIANGLE;
|
||||
|
@ -145,9 +154,9 @@ ccl_device_inline void triangle_intersect_subsurface(
|
|||
tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)),
|
||||
tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
|
||||
#endif
|
||||
ss_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
|
||||
local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
|
||||
}
|
||||
#endif /* __SUBSURFACE__ */
|
||||
#endif /* __BVH_LOCAL__ */
|
||||
|
||||
/* Refine triangle intersection to more precise hit point. For rays that travel
|
||||
* far the precision is often not so good, this reintersects the primitive from
|
||||
|
@ -226,10 +235,10 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
|
|||
/* Same as above, except that isect->t is assumed to be in object space for
|
||||
* instancing.
|
||||
*/
|
||||
ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
const Intersection *isect,
|
||||
const Ray *ray)
|
||||
ccl_device_inline float3 triangle_refine_local(KernelGlobals *kg,
|
||||
ShaderData *sd,
|
||||
const Intersection *isect,
|
||||
const Ray *ray)
|
||||
{
|
||||
float3 P = ray->P;
|
||||
float3 D = ray->D;
|
||||
|
|
|
@ -340,7 +340,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
|
|||
/* do subsurface scatter step with copy of shader data, this will
|
||||
* replace the BSSRDF with a diffuse BSDF closure */
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
SubsurfaceIntersection ss_isect;
|
||||
LocalIntersection ss_isect;
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_branched_rng_2D(kg, bssrdf_rng_hash, state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
|
||||
int num_hits = subsurface_scatter_multi_intersect(kg,
|
||||
|
|
|
@ -47,7 +47,7 @@ bool kernel_path_subsurface_scatter(
|
|||
|
||||
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
|
||||
|
||||
SubsurfaceIntersection ss_isect;
|
||||
LocalIntersection ss_isect;
|
||||
int num_hits = subsurface_scatter_multi_intersect(kg,
|
||||
&ss_isect,
|
||||
sd,
|
||||
|
|
|
@ -181,7 +181,7 @@ void shader_setup_from_subsurface(
|
|||
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
|
||||
|
||||
/* static triangle */
|
||||
sd->P = triangle_refine_subsurface(kg, sd, isect, ray);
|
||||
sd->P = triangle_refine_local(kg, sd, isect, ray);
|
||||
sd->Ng = Ng;
|
||||
sd->N = Ng;
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
|
|||
*/
|
||||
ccl_device_inline int subsurface_scatter_multi_intersect(
|
||||
KernelGlobals *kg,
|
||||
SubsurfaceIntersection *ss_isect,
|
||||
LocalIntersection *ss_isect,
|
||||
ShaderData *sd,
|
||||
const ShaderClosure *sc,
|
||||
uint *lcg_state,
|
||||
|
@ -240,22 +240,22 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
|
|||
|
||||
/* intersect with the same object. if multiple intersections are found it
|
||||
* will use at most BSSRDF_MAX_HITS hits, a random subset of all hits */
|
||||
scene_intersect_subsurface(kg,
|
||||
*ray,
|
||||
ss_isect,
|
||||
sd->object,
|
||||
lcg_state,
|
||||
BSSRDF_MAX_HITS);
|
||||
scene_intersect_local(kg,
|
||||
*ray,
|
||||
ss_isect,
|
||||
sd->object,
|
||||
lcg_state,
|
||||
BSSRDF_MAX_HITS);
|
||||
int num_eval_hits = min(ss_isect->num_hits, BSSRDF_MAX_HITS);
|
||||
|
||||
for(int hit = 0; hit < num_eval_hits; hit++) {
|
||||
/* Quickly retrieve P and Ng without setting up ShaderData. */
|
||||
float3 hit_P;
|
||||
if(sd->type & PRIMITIVE_TRIANGLE) {
|
||||
hit_P = triangle_refine_subsurface(kg,
|
||||
sd,
|
||||
&ss_isect->hits[hit],
|
||||
ray);
|
||||
hit_P = triangle_refine_local(kg,
|
||||
sd,
|
||||
&ss_isect->hits[hit],
|
||||
ray);
|
||||
}
|
||||
#ifdef __OBJECT_MOTION__
|
||||
else if(sd->type & PRIMITIVE_MOTION_TRIANGLE) {
|
||||
|
@ -266,11 +266,11 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
|
|||
kernel_tex_fetch(__prim_index, ss_isect->hits[hit].prim),
|
||||
sd->time,
|
||||
verts);
|
||||
hit_P = motion_triangle_refine_subsurface(kg,
|
||||
sd,
|
||||
&ss_isect->hits[hit],
|
||||
ray,
|
||||
verts);
|
||||
hit_P = motion_triangle_refine_local(kg,
|
||||
sd,
|
||||
&ss_isect->hits[hit],
|
||||
ray,
|
||||
verts);
|
||||
}
|
||||
#endif /* __OBJECT_MOTION__ */
|
||||
else {
|
||||
|
@ -313,7 +313,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
|
|||
|
||||
ccl_device_noinline void subsurface_scatter_multi_setup(
|
||||
KernelGlobals *kg,
|
||||
SubsurfaceIntersection* ss_isect,
|
||||
LocalIntersection* ss_isect,
|
||||
int hit,
|
||||
ShaderData *sd,
|
||||
ccl_addr_space PathState *state,
|
||||
|
@ -403,8 +403,8 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, ccl_a
|
|||
|
||||
/* intersect with the same object. if multiple intersections are
|
||||
* found it will randomly pick one of them */
|
||||
SubsurfaceIntersection ss_isect;
|
||||
scene_intersect_subsurface(kg, ray, &ss_isect, sd->object, lcg_state, 1);
|
||||
LocalIntersection ss_isect;
|
||||
scene_intersect_local(kg, ray, &ss_isect, sd->object, lcg_state, 1);
|
||||
|
||||
/* evaluate bssrdf */
|
||||
if(ss_isect.num_hits > 0) {
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* constants */
|
||||
/* Constants */
|
||||
#define OBJECT_SIZE 12
|
||||
#define OBJECT_VECTOR_SIZE 6
|
||||
#define LIGHT_SIZE 11
|
||||
|
@ -46,6 +46,7 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
#define BSSRDF_MIN_RADIUS 1e-8f
|
||||
#define BSSRDF_MAX_HITS 4
|
||||
#define LOCAL_MAX_HITS 4
|
||||
|
||||
#define BECKMANN_TABLE_SIZE 256
|
||||
|
||||
|
@ -56,6 +57,7 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
#define VOLUME_STACK_SIZE 16
|
||||
|
||||
/* Split kernel constants */
|
||||
#define WORK_POOL_SIZE_GPU 64
|
||||
#define WORK_POOL_SIZE_CPU 1
|
||||
#ifdef __KERNEL_GPU__
|
||||
|
@ -76,7 +78,7 @@ CCL_NAMESPACE_BEGIN
|
|||
#endif
|
||||
|
||||
|
||||
/* device capabilities */
|
||||
/* Device capabilities */
|
||||
#ifdef __KERNEL_CPU__
|
||||
# ifdef __KERNEL_SSE2__
|
||||
# define __QBVH__
|
||||
|
@ -161,7 +163,7 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
#endif /* __KERNEL_OPENCL__ */
|
||||
|
||||
/* kernel features */
|
||||
/* Kernel features */
|
||||
#define __SOBOL__
|
||||
#define __INSTANCING__
|
||||
#define __DPDU__
|
||||
|
@ -175,8 +177,8 @@ CCL_NAMESPACE_BEGIN
|
|||
#define __CLAMP_SAMPLE__
|
||||
#define __PATCH_EVAL__
|
||||
#define __SHADOW_TRICKS__
|
||||
|
||||
#define __DENOISING_FEATURES__
|
||||
#define __SHADER_RAYTRACE__
|
||||
|
||||
#ifdef __KERNEL_SHADING__
|
||||
# define __SVM__
|
||||
|
@ -199,10 +201,6 @@ CCL_NAMESPACE_BEGIN
|
|||
# define __BAKING__
|
||||
#endif
|
||||
|
||||
#ifdef WITH_CYCLES_DEBUG
|
||||
# define __KERNEL_DEBUG__
|
||||
#endif
|
||||
|
||||
/* Scene-based selective features compilation. */
|
||||
#ifdef __NO_CAMERA_MOTION__
|
||||
# undef __CAMERA_MOTION__
|
||||
|
@ -241,6 +239,18 @@ CCL_NAMESPACE_BEGIN
|
|||
#ifdef __NO_DENOISING__
|
||||
# undef __DENOISING_FEATURES__
|
||||
#endif
|
||||
#ifdef __NO_SHADER_RAYTRACE__
|
||||
# undef __SHADER_RAYTRACE__
|
||||
#endif
|
||||
|
||||
/* Features that enable others */
|
||||
#ifdef WITH_CYCLES_DEBUG
|
||||
# define __KERNEL_DEBUG__
|
||||
#endif
|
||||
|
||||
#if defined(__SUBSURFACE__) || defined(__SHADER_RAYTRACE__)
|
||||
# define __BVH_LOCAL__
|
||||
#endif
|
||||
|
||||
/* Shader Evaluation */
|
||||
|
||||
|
@ -1048,17 +1058,17 @@ typedef struct PathState {
|
|||
#endif
|
||||
} PathState;
|
||||
|
||||
/* Subsurface */
|
||||
|
||||
/* Struct to gather multiple SSS hits. */
|
||||
typedef struct SubsurfaceIntersection {
|
||||
/* Struct to gather multiple nearby intersections. */
|
||||
typedef struct LocalIntersection {
|
||||
Ray ray;
|
||||
float3 weight[BSSRDF_MAX_HITS];
|
||||
float3 weight[LOCAL_MAX_HITS];
|
||||
|
||||
int num_hits;
|
||||
struct Intersection hits[BSSRDF_MAX_HITS];
|
||||
float3 Ng[BSSRDF_MAX_HITS];
|
||||
} SubsurfaceIntersection;
|
||||
struct Intersection hits[LOCAL_MAX_HITS];
|
||||
float3 Ng[LOCAL_MAX_HITS];
|
||||
} LocalIntersection;
|
||||
|
||||
/* Subsurface */
|
||||
|
||||
/* Struct to gather SSS indirect rays and delay tracing them. */
|
||||
typedef struct SubsurfaceIndirectRays {
|
||||
|
@ -1070,6 +1080,7 @@ typedef struct SubsurfaceIndirectRays {
|
|||
float3 throughputs[BSSRDF_MAX_HITS];
|
||||
struct PathRadianceState L_state[BSSRDF_MAX_HITS];
|
||||
} SubsurfaceIndirectRays;
|
||||
static_assert(BSSRDF_MAX_HITS <= LOCAL_MAX_HITS, "BSSRDF hits too high.");
|
||||
|
||||
/* Constant Kernel Data
|
||||
*
|
||||
|
|
|
@ -67,7 +67,7 @@ typedef ccl_global struct SplitBranchedState {
|
|||
int num_hits;
|
||||
|
||||
uint lcg_state;
|
||||
SubsurfaceIntersection ss_isect;
|
||||
LocalIntersection ss_isect;
|
||||
|
||||
# ifdef __VOLUME__
|
||||
VolumeStack volume_stack[VOLUME_STACK_SIZE];
|
||||
|
|
|
@ -61,7 +61,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
|
|||
/* do subsurface scatter step with copy of shader data, this will
|
||||
* replace the BSSRDF with a diffuse BSDF closure */
|
||||
for(int j = branched_state->ss_next_sample; j < num_samples; j++) {
|
||||
ccl_global SubsurfaceIntersection *ss_isect = &branched_state->ss_isect;
|
||||
ccl_global LocalIntersection *ss_isect = &branched_state->ss_isect;
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_branched_rng_2D(kg,
|
||||
bssrdf_rng_hash,
|
||||
|
@ -75,7 +75,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
|
|||
/* intersection is expensive so avoid doing multiple times for the same input */
|
||||
if(branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) {
|
||||
uint lcg_state = branched_state->lcg_state;
|
||||
SubsurfaceIntersection ss_isect_private;
|
||||
LocalIntersection ss_isect_private;
|
||||
|
||||
branched_state->num_hits = subsurface_scatter_multi_intersect(kg,
|
||||
&ss_isect_private,
|
||||
|
@ -102,7 +102,7 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it
|
|||
*bssrdf_sd = *sd; /* note: copy happens each iteration of inner loop, this is
|
||||
* important as the indirect path will write into bssrdf_sd */
|
||||
|
||||
SubsurfaceIntersection ss_isect_private = *ss_isect;
|
||||
LocalIntersection ss_isect_private = *ss_isect;
|
||||
subsurface_scatter_multi_setup(kg,
|
||||
&ss_isect_private,
|
||||
hit,
|
||||
|
|
|
@ -157,6 +157,7 @@ public:
|
|||
virtual bool has_object_dependency() { return false; }
|
||||
virtual bool has_integrator_dependency() { return false; }
|
||||
virtual bool has_volume_support() { return false; }
|
||||
virtual bool has_raytrace() { return false; }
|
||||
vector<ShaderInput*> inputs;
|
||||
vector<ShaderOutput*> outputs;
|
||||
|
||||
|
|
|
@ -592,6 +592,9 @@ void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
|
|||
if(node->has_surface_transparent()) {
|
||||
requested_features->use_transparent = true;
|
||||
}
|
||||
if(node->has_raytrace()) {
|
||||
requested_features->use_shader_raytrace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue