Cycles: internal refactoring to make thick/ribbon curve separate primitives

Also removing the curve system manager which only stored a few curve intersection
settings. These are all changes towards making shape and subdivision settings
per-object instead of per-scene, but there is more work to do here.

Ref T73778

Depends on D8013

Maniphest Tasks: T73778

Differential Revision: https://developer.blender.org/D8014
This commit is contained in:
Brecht Van Lommel 2020-06-10 19:07:07 +02:00
parent 207338bb58
commit 2c41c8e94f
Notes: blender-bot 2023-02-14 07:47:59 +01:00
Referenced by issue #73778, Cycles: Embree improvements
26 changed files with 119 additions and 239 deletions

View File

@ -1225,11 +1225,6 @@ class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
items=enum_curve_shape,
default='RIBBONS',
)
use_curves: BoolProperty(
name="Use Cycles Hair Rendering",
description="Activate Cycles hair rendering for particle system",
default=True,
)
subdivisions: IntProperty(
name="Subdivisions",
description="Number of subdivisions used in Cardinal curve intersection (power of 2)",

View File

@ -387,13 +387,6 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
bl_label = "Hair"
bl_options = {'DEFAULT_CLOSED'}
def draw_header(self, context):
layout = self.layout
scene = context.scene
ccscene = scene.cycles_curves
layout.prop(ccscene, "use_curves", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
@ -402,8 +395,6 @@ class CYCLES_RENDER_PT_hair(CyclesButtonsPanel, Panel):
scene = context.scene
ccscene = scene.cycles_curves
layout.active = ccscene.use_curves
col = layout.column()
col.prop(ccscene, "shape", text="Shape")
if ccscene.shape == 'RIBBONS':

View File

@ -507,42 +507,6 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int
/* Hair Curve Sync */
void BlenderSync::sync_curve_settings(BL::Depsgraph &b_depsgraph)
{
PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
CurveSystemManager *curve_system_manager = scene->curve_system_manager;
CurveSystemManager prev_curve_system_manager = *curve_system_manager;
curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
curve_system_manager->curve_shape = (CurveShapeType)get_enum(
csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
if (curve_system_manager->modified_mesh(prev_curve_system_manager)) {
BL::Depsgraph::objects_iterator b_ob;
for (b_depsgraph.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
if (object_is_mesh(*b_ob)) {
BL::Object::particle_systems_iterator b_psys;
for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end();
++b_psys) {
if ((b_psys->settings().render_type() == BL::ParticleSettings::render_type_PATH) &&
(b_psys->settings().type() == BL::ParticleSettings::type_HAIR)) {
BL::ID key = BKE_object_is_modified(*b_ob) ? *b_ob : b_ob->data();
geometry_map.set_recalc(key);
object_map.set_recalc(*b_ob);
}
}
}
}
}
if (curve_system_manager->modified(prev_curve_system_manager))
curve_system_manager->tag_update(scene);
}
bool BlenderSync::object_has_particle_hair(BL::Object b_ob)
{
/* Test if the object has a particle modifier with hair. */
@ -867,7 +831,7 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph,
hair->clear();
hair->used_shaders = used_shaders;
if (view_layer.use_hair && scene->curve_system_manager->use_curves) {
if (view_layer.use_hair) {
#ifdef WITH_NEW_OBJECT_TYPES
if (b_ob.type() == BL::Object::type_HAIR) {
/* Hair object. */

View File

@ -212,7 +212,6 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
sync_film(b_v3d);
sync_shaders(b_depsgraph, b_v3d);
sync_images();
sync_curve_settings(b_depsgraph);
geometry_synced.clear(); /* use for objects and motion sync */
@ -732,6 +731,11 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background)
params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
params.hair_subdivisions = get_int(csscene, "subdivisions");
params.hair_shape = (CurveShapeType)get_enum(
csscene, "shape", CURVE_NUM_SHAPE_TYPES, CURVE_THICK);
if (background && params.shadingsystem != SHADINGSYSTEM_OSL)
params.persistent_data = r.use_persistent_data();
else

View File

@ -159,7 +159,6 @@ class BlenderSync {
void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_particle_hair(
Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_curve_settings(BL::Depsgraph &b_depsgraph);
bool object_has_particle_hair(BL::Object b_ob);
/* Camera */

View File

@ -159,6 +159,13 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
if (hair->has_motion_blur()) {
curve_attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
}
const PrimitiveType primitive_type =
(curve_attr_mP != NULL) ?
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
PRIMITIVE_MOTION_CURVE_THICK) :
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK);
const size_t num_curves = hair->num_curves();
for (uint j = 0; j < num_curves; j++) {
const Hair::Curve curve = hair->get_curve(j);
@ -169,7 +176,7 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
BoundBox bounds = BoundBox::empty;
curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds);
if (bounds.valid()) {
int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k);
int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k);
references.push_back(BVHReference(bounds, j, i, packed_type));
root.grow(bounds);
center.grow(bounds.center2());
@ -190,7 +197,7 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
curve.bounds_grow(k, key_steps + step * num_keys, curve_radius, bounds);
}
if (bounds.valid()) {
int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k);
int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k);
references.push_back(BVHReference(bounds, j, i, packed_type));
root.grow(bounds);
center.grow(bounds.center2());
@ -246,7 +253,7 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox &center, Hair *hair
bounds.grow(curr_bounds);
if (bounds.valid()) {
const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1;
int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k);
int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k);
references.push_back(BVHReference(bounds, j, i, packed_type, prev_time, curr_time));
root.grow(bounds);
center.grow(bounds.center2());
@ -537,14 +544,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range,
for (int i = 0; i < size; i++) {
const BVHReference &ref = references[range.start() + i];
if (ref.prim_type() & PRIMITIVE_CURVE)
num_curves++;
if (ref.prim_type() & PRIMITIVE_MOTION_CURVE)
num_motion_curves++;
else if (ref.prim_type() & PRIMITIVE_TRIANGLE)
num_triangles++;
else if (ref.prim_type() & PRIMITIVE_MOTION_TRIANGLE)
num_motion_triangles++;
if (ref.prim_type() & PRIMITIVE_ALL_CURVE) {
if (ref.prim_type() & PRIMITIVE_ALL_MOTION) {
num_motion_curves++;
}
else {
num_curves++;
}
}
else if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
if (ref.prim_type() & PRIMITIVE_ALL_MOTION) {
num_motion_triangles++;
}
else {
num_triangles++;
}
}
}
return (num_triangles <= params.max_triangle_leaf_size) &&

View File

@ -324,7 +324,6 @@ BVHEmbree::BVHEmbree(const BVHParams &params_,
stats(NULL),
curve_subdivisions(params.curve_subdivisions),
build_quality(RTC_BUILD_QUALITY_REFIT),
use_ribbons(params.curve_flags & CURVE_KN_RIBBONS),
dynamic_scene(true)
{
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
@ -771,6 +770,12 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
}
const size_t num_motion_steps = min(num_geometry_motion_steps, RTC_MAX_TIME_STEP_COUNT);
const PrimitiveType primitive_type =
(num_motion_steps > 1) ?
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
PRIMITIVE_MOTION_CURVE_THICK) :
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK);
assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
const size_t num_curves = hair->num_curves();
@ -791,11 +796,12 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
size_t prim_tri_index_size = pack.prim_index.size();
pack.prim_tri_index.resize(prim_tri_index_size + num_segments);
enum RTCGeometryType type = (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE :
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
enum RTCGeometryType type = (hair->curve_shape == CURVE_RIBBON ?
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE :
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type);
rtcSetGeometryTessellationRate(geom_id, curve_subdivisions);
rtcSetGeometryTessellationRate(geom_id, curve_subdivisions + 1);
unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);
size_t rtc_index = 0;
@ -807,8 +813,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
rtc_indices[rtc_index] += j * 2;
/* Cycles specific data. */
pack.prim_object[prim_object_size + rtc_index] = i;
pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(
num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k));
pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(primitive_type, k));
pack.prim_index[prim_index_size + rtc_index] = j;
pack.prim_tri_index[prim_tri_index_size + rtc_index] = rtc_index;
@ -822,7 +827,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
update_curve_vertex_buffer(geom_id, hair);
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
if (use_ribbons) {
if (hair->curve_shape == CURVE_RIBBON) {
rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func);
}
else {

View File

@ -81,7 +81,7 @@ class BVHEmbree : public BVH {
vector<RTCScene> delayed_delete_scenes;
int curve_subdivisions;
enum RTCBuildQuality build_quality;
bool use_ribbons, dynamic_scene;
bool dynamic_scene;
};
CCL_NAMESPACE_END

View File

@ -77,9 +77,12 @@ void BVHOptiX::pack_blas()
// 'pack.prim_time' is only used in geom_curve_intersect.h
// It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH
uint type = PRIMITIVE_CURVE;
if (hair->use_motion_blur && hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION))
type = PRIMITIVE_MOTION_CURVE;
uint type = (hair->use_motion_blur &&
hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) ?
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
PRIMITIVE_MOTION_CURVE_THICK) :
((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON :
PRIMITIVE_CURVE_THICK);
for (size_t j = 0; j < num_curves; ++j) {
const Hair::Curve curve = hair->get_curve(j);

View File

@ -89,7 +89,6 @@ class BVHParams {
int bvh_type;
/* These are needed for Embree. */
int curve_flags;
int curve_subdivisions;
/* fixed parameters */
@ -122,7 +121,6 @@ class BVHParams {
bvh_type = 0;
curve_flags = 0;
curve_subdivisions = 4;
}

View File

@ -68,7 +68,8 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali
const Object *object = objects_[ref.prim_object()];
const int packed_type = ref.prim_type();
const int type = (packed_type & PRIMITIVE_ALL);
if (type & PRIMITIVE_CURVE) {
/* No motion blur curves here, we can't fit them to aligned boxes well. */
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) {
const int curve_index = ref.prim_index();
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
const Hair *hair = static_cast<const Hair *>(object->geometry);
@ -93,7 +94,8 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim,
const Object *object = objects_[prim.prim_object()];
const int packed_type = prim.prim_type();
const int type = (packed_type & PRIMITIVE_ALL);
if (type & PRIMITIVE_CURVE) {
/* No motion blur curves here, we can't fit them to aligned boxes well. */
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) {
const int curve_index = prim.prim_index();
const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type);
const Hair *hair = static_cast<const Hair *>(object->geometry);

View File

@ -158,8 +158,10 @@ ccl_device_inline
}
#endif
#if BVH_FEATURE(BVH_HAIR)
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
case PRIMITIVE_CURVE_THICK:
case PRIMITIVE_MOTION_CURVE_THICK:
case PRIMITIVE_CURVE_RIBBON:
case PRIMITIVE_MOTION_CURVE_RIBBON: {
const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
hit = curve_intersect(
kg, isect_array, P, dir, visibility, object, prim_addr, ray->time, curve_type);

View File

@ -164,13 +164,15 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
}
#endif /* BVH_FEATURE(BVH_MOTION) */
#if BVH_FEATURE(BVH_HAIR)
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
case PRIMITIVE_CURVE_THICK:
case PRIMITIVE_MOTION_CURVE_THICK:
case PRIMITIVE_CURVE_RIBBON:
case PRIMITIVE_MOTION_CURVE_RIBBON: {
for (; prim_addr < prim_addr2; prim_addr++) {
BVH_DEBUG_NEXT_INTERSECTION();
const uint curve_type = kernel_tex_fetch(__prim_type, prim_addr);
kernel_assert((curve_type & PRIMITIVE_ALL) == (type & PRIMITIVE_ALL));
bool hit = curve_intersect(
const bool hit = curve_intersect(
kg, isect, P, dir, visibility, object, prim_addr, ray->time, curve_type);
if (hit) {
/* shadow ray early termination */

View File

@ -213,7 +213,9 @@ ccl_device int bsdf_principled_hair_setup(ShaderData *sd, PrincipledHairBSDF *bs
/* TODO: we convert this value to a cosine later and discard the sign, so
* we could probably save some operations. */
float h = dot(cross(sd->Ng, X), Z);
float h = (sd->type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_MOTION_CURVE_RIBBON)) ?
-sd->v :
dot(cross(sd->Ng, X), Z);
kernel_assert(fabsf(h) < 1.0f + 1e-4f);
kernel_assert(isfinite3_safe(Y));

View File

@ -211,7 +211,7 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
float4 P_curve[2];
if (sd->type & PRIMITIVE_CURVE) {
if (!(sd->type & PRIMITIVE_ALL_MOTION)) {
P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
}

View File

@ -627,10 +627,10 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
float time,
int type)
{
const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
const bool is_motion = (type & PRIMITIVE_ALL_MOTION);
# ifndef __KERNEL_OPTIX__ /* See OptiX motion flag OPTIX_MOTION_FLAG_[START|END]_VANISH */
if (!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
if (is_motion && kernel_data.bvh.use_bvh_steps) {
const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
if (time < prim_time.x || time > prim_time.y) {
return false;
@ -650,7 +650,7 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
int kb = min(k1 + 1, __float_as_int(v00.x) + __float_as_int(v00.y) - 1);
float4 curve[4];
if (is_curve_primitive) {
if (!is_motion) {
curve[0] = kernel_tex_fetch(__curve_keys, ka);
curve[1] = kernel_tex_fetch(__curve_keys, k0);
curve[2] = kernel_tex_fetch(__curve_keys, k1);
@ -667,10 +667,9 @@ ccl_device_forceinline bool curve_intersect(KernelGlobals *kg,
}
# endif
const bool use_ribbon = (kernel_data.curve.curveflags & CURVE_KN_RIBBONS) != 0;
if (use_ribbon) {
if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_MOTION_CURVE_RIBBON)) {
/* todo: adaptive number of subdivisions could help performance here. */
const int subdivisions = kernel_data.curve.subdivisions;
const int subdivisions = kernel_data.bvh.curve_subdivisions;
if (ribbon_intersect(P, dir, isect->t, subdivisions, curve, isect)) {
isect->prim = curveAddr;
isect->object = object;
@ -724,7 +723,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals *kg,
float4 P_curve[4];
if (sd->type & PRIMITIVE_CURVE) {
if (!(sd->type & PRIMITIVE_ALL_MOTION)) {
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
@ -742,7 +741,7 @@ ccl_device_inline void curve_shader_setup(KernelGlobals *kg,
const float4 dPdu4 = catmull_rom_basis_derivative(P_curve, isect->u);
const float3 dPdu = float4_to_float3(dPdu4);
if (kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
if (sd->type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_MOTION_CURVE_RIBBON)) {
/* Rounded smooth normals for ribbons, to approximate thick curve shape. */
const float3 tangent = normalize(dPdu);
const float3 bitangent = normalize(cross(tangent, -D));

View File

@ -691,27 +691,38 @@ typedef enum PrimitiveType {
PRIMITIVE_NONE = 0,
PRIMITIVE_TRIANGLE = (1 << 0),
PRIMITIVE_MOTION_TRIANGLE = (1 << 1),
PRIMITIVE_CURVE = (1 << 2),
PRIMITIVE_MOTION_CURVE = (1 << 3),
PRIMITIVE_CURVE_THICK = (1 << 2),
PRIMITIVE_MOTION_CURVE_THICK = (1 << 3),
PRIMITIVE_CURVE_RIBBON = (1 << 4),
PRIMITIVE_MOTION_CURVE_RIBBON = (1 << 5),
/* Lamp primitive is not included below on purpose,
* since it is no real traceable primitive.
*/
PRIMITIVE_LAMP = (1 << 4),
PRIMITIVE_LAMP = (1 << 6),
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE | PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE | PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE | PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE_THICK | PRIMITIVE_MOTION_CURVE_THICK |
PRIMITIVE_CURVE_RIBBON | PRIMITIVE_MOTION_CURVE_RIBBON),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE | PRIMITIVE_MOTION_CURVE_THICK |
PRIMITIVE_MOTION_CURVE_RIBBON),
PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE | PRIMITIVE_ALL_CURVE),
/* Total number of different traceable primitives.
* NOTE: This is an actual value, not a bitflag.
*/
PRIMITIVE_NUM_TOTAL = 4,
PRIMITIVE_NUM_TOTAL = 6,
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << PRIMITIVE_NUM_TOTAL) | (type))
#define PRIMITIVE_UNPACK_SEGMENT(type) (type >> PRIMITIVE_NUM_TOTAL)
typedef enum CurveShapeType {
CURVE_RIBBON = 0,
CURVE_THICK = 1,
CURVE_NUM_SHAPE_TYPES,
} CurveShapeType;
/* Attributes */
typedef enum AttributePrimitive {
@ -1400,7 +1411,7 @@ typedef struct KernelBVH {
int have_curves;
int bvh_layout;
int use_bvh_steps;
int pad;
int curve_subdivisions;
/* Custom BVH */
#ifdef __KERNEL_OPTIX__
@ -1418,19 +1429,6 @@ typedef struct KernelBVH {
} KernelBVH;
static_assert_align(KernelBVH, 16);
typedef enum CurveFlag {
/* runtime flags */
CURVE_KN_RIBBONS = 1, /* use flat curve ribbons */
} CurveFlag;
typedef struct KernelCurves {
int curveflags;
int subdivisions;
int pad1, pad2;
} KernelCurves;
static_assert_align(KernelCurves, 16);
typedef struct KernelTables {
int beckmann_offset;
int pad1, pad2, pad3;
@ -1451,7 +1449,6 @@ typedef struct KernelData {
KernelBackground background;
KernelIntegrator integrator;
KernelBVH bvh;
KernelCurves curve;
KernelTables tables;
KernelBake bake;
} KernelData;

View File

@ -76,76 +76,4 @@ void curvebounds(float *lower, float *upper, float3 *p, int dim)
*lower = min(*lower, min(exa, exb));
}
/* Hair System Manager */
CurveSystemManager::CurveSystemManager()
{
curve_shape = CURVE_THICK;
subdivisions = 3;
use_curves = true;
need_update = true;
need_mesh_update = false;
}
CurveSystemManager::~CurveSystemManager()
{
}
void CurveSystemManager::device_update(Device *device,
DeviceScene *dscene,
Scene * /*scene*/,
Progress &progress)
{
if (!need_update)
return;
device_free(device, dscene);
progress.set_status("Updating Hair settings", "Copying Hair settings to device");
KernelCurves *kcurve = &dscene->data.curve;
kcurve->curveflags = 0;
if (use_curves) {
if (curve_shape == CURVE_RIBBON) {
kcurve->curveflags |= CURVE_KN_RIBBONS;
}
/* Matching the tesselation rate limit in Embree. */
kcurve->subdivisions = clamp(1 << subdivisions, 1, 16);
}
if (progress.get_cancel())
return;
need_update = false;
}
void CurveSystemManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
bool CurveSystemManager::modified(const CurveSystemManager &CurveSystemManager)
{
return !(use_curves == CurveSystemManager.use_curves &&
subdivisions == CurveSystemManager.subdivisions);
}
bool CurveSystemManager::modified_mesh(const CurveSystemManager &CurveSystemManager)
{
return !(use_curves == CurveSystemManager.use_curves);
}
void CurveSystemManager::tag_update(Scene * /*scene*/)
{
need_update = true;
}
void CurveSystemManager::tag_update_mesh()
{
need_mesh_update = true;
}
CCL_NAMESPACE_END

View File

@ -20,6 +20,8 @@
#include "util/util_array.h"
#include "util/util_types.h"
#include "render/hair.h"
CCL_NAMESPACE_BEGIN
class Device;
@ -29,13 +31,6 @@ class Scene;
void curvebounds(float *lower, float *upper, float3 *p, int dim);
typedef enum CurveShapeType {
CURVE_RIBBON = 0,
CURVE_THICK = 1,
CURVE_NUM_SHAPE_TYPES,
} CurveShapeType;
class ParticleCurveData {
public:
@ -61,30 +56,6 @@ class ParticleCurveData {
array<float> curvekey_time;
};
/* HairSystem Manager */
class CurveSystemManager {
public:
CurveShapeType curve_shape;
int subdivisions;
bool use_curves;
bool need_update;
bool need_mesh_update;
CurveSystemManager();
~CurveSystemManager();
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
void device_free(Device *device, DeviceScene *dscene);
bool modified(const CurveSystemManager &CurveSystemManager);
bool modified_mesh(const CurveSystemManager &CurveSystemManager);
void tag_update(Scene *scene);
void tag_update_mesh();
};
CCL_NAMESPACE_END
#endif /* __CURVES_H__ */

View File

@ -211,8 +211,7 @@ void Geometry::compute_bvh(
bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
bparams.num_motion_curve_steps = params->num_bvh_time_steps;
bparams.bvh_type = params->bvh_type;
bparams.curve_flags = dscene->data.curve.curveflags;
bparams.curve_subdivisions = dscene->data.curve.subdivisions;
bparams.curve_subdivisions = params->curve_subdivisions();
delete bvh;
bvh = BVH::create(bparams, geometry, objects);
@ -1026,8 +1025,7 @@ void GeometryManager::device_update_bvh(Device *device,
bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
bparams.bvh_type = scene->params.bvh_type;
bparams.curve_flags = dscene->data.curve.curveflags;
bparams.curve_subdivisions = dscene->data.curve.subdivisions;
bparams.curve_subdivisions = scene->params.curve_subdivisions();
VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
@ -1103,6 +1101,7 @@ void GeometryManager::device_update_bvh(Device *device,
dscene->data.bvh.root = pack.root_index;
dscene->data.bvh.bvh_layout = bparams.bvh_layout;
dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
dscene->data.bvh.curve_subdivisions = scene->params.curve_subdivisions();
bvh->copy_to_device(progress, dscene);
@ -1145,6 +1144,12 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
create_volume_mesh(mesh, progress);
}
}
if (geom->type == Geometry::HAIR) {
/* Set curve shape, still a global scene setting for now. */
Hair *hair = static_cast<Hair *>(geom);
hair->curve_shape = scene->params.hair_shape;
}
}
need_flags_update = false;

View File

@ -294,6 +294,7 @@ NODE_DEFINE(Hair)
Hair::Hair() : Geometry(node_type, Geometry::HAIR)
{
curvekey_offset = 0;
curve_shape = CURVE_RIBBON;
}
Hair::~Hair()

View File

@ -96,6 +96,7 @@ class Hair : public Geometry {
/* BVH */
size_t curvekey_offset;
CurveShapeType curve_shape;
/* Constructor/Destructor */
Hair();

View File

@ -219,7 +219,6 @@ void Object::tag_update(Scene *scene)
}
scene->camera->need_flags_update = true;
scene->curve_system_manager->need_update = true;
scene->geometry_manager->need_update = true;
scene->object_manager->need_update = true;
}
@ -844,7 +843,6 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P
void ObjectManager::tag_update(Scene *scene)
{
need_update = true;
scene->curve_system_manager->need_update = true;
scene->geometry_manager->need_update = true;
scene->light_manager->need_update = true;
}

View File

@ -108,7 +108,6 @@ Scene::Scene(const SceneParams &params_, Device *device)
integrator = new Integrator();
image_manager = new ImageManager(device->info);
particle_system_manager = new ParticleSystemManager();
curve_system_manager = new CurveSystemManager();
bake_manager = new BakeManager();
/* OSL only works on the CPU */
@ -156,7 +155,6 @@ void Scene::free_memory(bool final)
light_manager->device_free(device, &dscene);
particle_system_manager->device_free(device, &dscene);
curve_system_manager->device_free(device, &dscene);
bake_manager->device_free(device, &dscene);
@ -180,7 +178,6 @@ void Scene::free_memory(bool final)
delete shader_manager;
delete light_manager;
delete particle_system_manager;
delete curve_system_manager;
delete image_manager;
delete bake_manager;
}
@ -230,12 +227,6 @@ void Scene::device_update(Device *device_, Progress &progress)
progress.set_status("Updating Objects");
object_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error())
return;
progress.set_status("Updating Hair Systems");
curve_system_manager->device_update(device, &dscene, this, progress);
if (progress.get_cancel() || device->have_error())
return;
@ -369,8 +360,7 @@ bool Scene::need_data_update()
return (background->need_update || image_manager->need_update || object_manager->need_update ||
geometry_manager->need_update || light_manager->need_update ||
lookup_tables->need_update || integrator->need_update || shader_manager->need_update ||
particle_system_manager->need_update || curve_system_manager->need_update ||
bake_manager->need_update || film->need_update);
particle_system_manager->need_update || bake_manager->need_update || film->need_update);
}
bool Scene::need_reset()
@ -393,7 +383,6 @@ void Scene::reset()
geometry_manager->tag_update(this);
light_manager->tag_update(this);
particle_system_manager->tag_update(this);
curve_system_manager->tag_update(this);
}
void Scene::device_free()

View File

@ -168,6 +168,8 @@ class SceneParams {
bool use_bvh_spatial_split;
bool use_bvh_unaligned_nodes;
int num_bvh_time_steps;
int hair_subdivisions;
CurveShapeType hair_shape;
bool persistent_data;
int texture_limit;
@ -181,6 +183,8 @@ class SceneParams {
use_bvh_spatial_split = false;
use_bvh_unaligned_nodes = true;
num_bvh_time_steps = 0;
hair_subdivisions = 3;
hair_shape = CURVE_RIBBON;
persistent_data = false;
texture_limit = 0;
background = true;
@ -193,8 +197,15 @@ class SceneParams {
use_bvh_spatial_split == params.use_bvh_spatial_split &&
use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes &&
num_bvh_time_steps == params.num_bvh_time_steps &&
hair_subdivisions == params.hair_subdivisions && hair_shape == params.hair_shape &&
persistent_data == params.persistent_data && texture_limit == params.texture_limit);
}
int curve_subdivisions()
{
/* Matching the tesselation rate limit in Embree. */
return clamp(1 << hair_subdivisions, 1, 16);
}
};
/* Scene */
@ -226,7 +237,6 @@ class Scene {
GeometryManager *geometry_manager;
ObjectManager *object_manager;
ParticleSystemManager *particle_system_manager;
CurveSystemManager *curve_system_manager;
BakeManager *bake_manager;
/* default shaders */

View File

@ -21,7 +21,6 @@
#include "render/bake.h"
#include "render/buffers.h"
#include "render/camera.h"
#include "render/curves.h"
#include "render/graph.h"
#include "render/integrator.h"
#include "render/light.h"
@ -774,7 +773,7 @@ DeviceRequestedFeatures Session::get_requested_device_features()
*/
bool use_motion = scene->need_motion() == Scene::MotionType::MOTION_BLUR;
requested_features.use_hair = false;
requested_features.use_hair_thick = (scene->curve_system_manager->curve_shape == CURVE_THICK);
requested_features.use_hair_thick = (scene->params.hair_shape == CURVE_THICK);
requested_features.use_object_motion = false;
requested_features.use_camera_motion = use_motion && scene->camera->use_motion();
foreach (Object *object, scene->objects) {