Cycles: always perform backface culling for curve, remove option

The hair BSDFs are already designed to assume this, and disabling backface
culling would break them in some cases.

Ref T73778

Depends on D8009

Maniphest Tasks: T73778

Differential Revision: https://developer.blender.org/D8010
This commit is contained in:
Brecht Van Lommel
2020-06-10 18:34:18 +02:00
parent c7d940278b
commit fed101a7be
9 changed files with 69 additions and 101 deletions

View File

@@ -1236,11 +1236,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
items=enum_curve_shape, items=enum_curve_shape,
default='THICK', default='THICK',
) )
cull_backfacing: BoolProperty(
name="Cull Back-faces",
description="Do not test the back-face of each hair",
default=True,
)
use_curves: BoolProperty( use_curves: BoolProperty(
name="Use Cycles Hair Rendering", name="Use Cycles Hair Rendering",
description="Activate Cycles hair rendering for particle system", description="Activate Cycles hair rendering for particle system",

View File

@@ -409,8 +409,6 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
if ccscene.shape == 'RIBBONS': if ccscene.shape == 'RIBBONS':
# TODO: use for embree # TODO: use for embree
col.prop(ccscene, "subdivisions", text="Curve subdivisions") col.prop(ccscene, "subdivisions", text="Curve subdivisions")
else:
col.prop(ccscene, "cull_backfacing", text="Cull back-faces")
class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel): class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):

View File

@@ -519,7 +519,6 @@ void BlenderSync::sync_curve_settings(BL::Depsgraph &b_depsgraph)
curve_system_manager->curve_shape = (CurveShapeType)get_enum( curve_system_manager->curve_shape = (CurveShapeType)get_enum(
csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK); csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
curve_system_manager->subdivisions = get_int(csscene, "subdivisions"); curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
curve_system_manager->use_backfacing = !get_boolean(csscene, "cull_backfacing");
if (curve_system_manager->modified_mesh(prev_curve_system_manager)) { if (curve_system_manager->modified_mesh(prev_curve_system_manager)) {
BL::Depsgraph::objects_iterator b_ob; BL::Depsgraph::objects_iterator b_ob;

View File

@@ -67,29 +67,9 @@ static_assert(Object::MAX_MOTION_STEPS == Geometry::MAX_MOTION_STEPS,
* as well as filtering for volume objects happen here. * as well as filtering for volume objects happen here.
* Cycles' own BVH does that directly inside the traversal calls. * Cycles' own BVH does that directly inside the traversal calls.
*/ */
static void rtc_filter_func(const RTCFilterFunctionNArguments *args)
{
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1);
const RTCRay *ray = (RTCRay *)args->ray;
const RTCHit *hit = (RTCHit *)args->hit;
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
KernelGlobals *kg = ctx->kg;
/* Check if there is backfacing hair to ignore. */
if (IS_HAIR(hit->geomID) && !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) &&
!(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
*args->valid = 0;
return;
}
}
}
static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
{ {
/* Current implementation in Cycles assumes only single-ray intersection queries. */
assert(args->N == 1); assert(args->N == 1);
const RTCRay *ray = (RTCRay *)args->ray; const RTCRay *ray = (RTCRay *)args->ray;
@@ -97,16 +77,6 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
KernelGlobals *kg = ctx->kg; KernelGlobals *kg = ctx->kg;
/* For all ray types: Check if there is backfacing hair to ignore */
if (IS_HAIR(hit->geomID) && !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) &&
!(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) {
if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
*args->valid = 0;
return;
}
}
switch (ctx->type) { switch (ctx->type) {
case CCLIntersectContext::RAY_SHADOW_ALL: { case CCLIntersectContext::RAY_SHADOW_ALL: {
/* Append the intersection to the end of the array. */ /* Append the intersection to the end of the array. */
@@ -168,7 +138,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
} }
/* Ignore curves. */ /* Ignore curves. */
if (hit->geomID & 1) { if (IS_HAIR(hit->geomID)) {
/* This tells Embree to continue tracing. */ /* This tells Embree to continue tracing. */
*args->valid = 0; *args->valid = 0;
break; break;
@@ -249,6 +219,34 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args)
} }
} }
static void rtc_filter_func_thick_curve(const RTCFilterFunctionNArguments *args)
{
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
/* Always ignore backfacing intersections. */
if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
*args->valid = 0;
return;
}
}
static void rtc_filter_occluded_func_thick_curve(const RTCFilterFunctionNArguments *args)
{
const RTCRay *ray = (RTCRay *)args->ray;
RTCHit *hit = (RTCHit *)args->hit;
/* Always ignore backfacing intersections. */
if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z),
make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) {
*args->valid = 0;
return;
}
rtc_filter_occluded_func(args);
}
static size_t unaccounted_mem = 0; static size_t unaccounted_mem = 0;
static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bool) static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bool)
@@ -652,7 +650,6 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
} }
rtcSetGeometryUserData(geom_id, (void *)prim_offset); rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func);
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
@@ -825,8 +822,13 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
update_curve_vertex_buffer(geom_id, hair); update_curve_vertex_buffer(geom_id, hair);
rtcSetGeometryUserData(geom_id, (void *)prim_offset); rtcSetGeometryUserData(geom_id, (void *)prim_offset);
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func); if (use_ribbons) {
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
}
else {
rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_thick_curve);
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_thick_curve);
}
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
rtcCommitGeometry(geom_id); rtcCommitGeometry(geom_id);

View File

@@ -82,8 +82,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
} }
else { else {
int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object; int fobject = (object == OBJECT_NONE) ? kernel_tex_fetch(__prim_object, curveAddr) : object;
motion_curve_keys_avx( motion_curve_keys_avx(kg, fobject, prim, time, ka, k0, k1, kb, &P_curve_0_1, &P_curve_2_3);
kg, fobject, prim, time, ka, k0, k1, kb, &P_curve_0_1, &P_curve_2_3);
} }
# else /* __KERNEL_AVX2__ */ # else /* __KERNEL_AVX2__ */
ssef P_curve[4]; ssef P_curve[4];
@@ -217,7 +216,6 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
float r_curr = max(r_st, r_en); float r_curr = max(r_st, r_en);
if ((flags & CURVE_KN_RIBBONS) || !(flags & CURVE_KN_BACKFACING))
epsilon = 2 * r_curr; epsilon = 2 * r_curr;
/* find bounds - this is slow for cubic curves */ /* find bounds - this is slow for cubic curves */
@@ -439,13 +437,6 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
if (dot(tg, dp_en) < 0) if (dot(tg, dp_en) < 0)
dp_en *= -1; dp_en *= -1;
if (flags & CURVE_KN_BACKFACING &&
(dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 ||
isect->t < t || t <= 0.0f)) {
correction = (-tb + rootd) * 0.5f * invcyla;
t = tcentre + correction;
}
if (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 || if (dot(dp_st, -p_st) + t * dp_st.z < 0 || dot(dp_en, p_en) - t * dp_en.z < 0 ||
isect->t < t || t <= 0.0f) { isect->t < t || t <= 0.0f) {
tree++; tree++;

View File

@@ -1428,8 +1428,7 @@ static_assert_align(KernelBVH, 16);
typedef enum CurveFlag { typedef enum CurveFlag {
/* runtime flags */ /* runtime flags */
CURVE_KN_BACKFACING = 1, /* backside of cylinder? */ CURVE_KN_RIBBONS = 1, /* use flat curve ribbons */
CURVE_KN_RIBBONS = 2, /* use flat curve ribbons */
} CurveFlag; } CurveFlag;
typedef struct KernelCurves { typedef struct KernelCurves {

View File

@@ -847,15 +847,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: { case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
float3 weight = sd->svm_closure_weight * mix_weight; float3 weight = sd->svm_closure_weight * mix_weight;
if (sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
/* todo: giving a fixed weight here will cause issues when
* mixing multiple BSDFS. energy will not be conserved and
* the throughput can blow up after multiple bounces. we
* better figure out a way to skip backfaces from rays
* spawned by transmission from the front */
bsdf_transparent_setup(sd, make_float3(1.0f, 1.0f, 1.0f), path_flag);
}
else {
HairBsdf *bsdf = (HairBsdf *)bsdf_alloc(sd, sizeof(HairBsdf), weight); HairBsdf *bsdf = (HairBsdf *)bsdf_alloc(sd, sizeof(HairBsdf), weight);
if (bsdf) { if (bsdf) {
@@ -881,7 +872,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
sd->flag |= bsdf_hair_transmission_setup(bsdf); sd->flag |= bsdf_hair_transmission_setup(bsdf);
} }
} }
}
break; break;
} }

View File

@@ -85,7 +85,6 @@ CurveSystemManager::CurveSystemManager()
subdivisions = 3; subdivisions = 3;
use_curves = true; use_curves = true;
use_backfacing = false;
need_update = true; need_update = true;
need_mesh_update = false; need_mesh_update = false;
@@ -115,9 +114,6 @@ void CurveSystemManager::device_update(Device *device,
if (curve_shape == CURVE_RIBBON) { if (curve_shape == CURVE_RIBBON) {
kcurve->curveflags |= CURVE_KN_RIBBONS; kcurve->curveflags |= CURVE_KN_RIBBONS;
} }
else if (use_backfacing) {
kcurve->curveflags |= CURVE_KN_BACKFACING;
}
kcurve->subdivisions = subdivisions; kcurve->subdivisions = subdivisions;
} }
@@ -134,8 +130,7 @@ void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene
bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager) bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager)
{ {
return !(use_backfacing == CurveSystemManager.use_backfacing && return !(use_curves == CurveSystemManager.use_curves &&
use_curves == CurveSystemManager.use_curves &&
subdivisions == CurveSystemManager.subdivisions); subdivisions == CurveSystemManager.subdivisions);
} }

View File

@@ -69,7 +69,6 @@ class CurveSystemManager {
int subdivisions; int subdivisions;
bool use_curves; bool use_curves;
bool use_backfacing;
bool need_update; bool need_update;
bool need_mesh_update; bool need_mesh_update;