[Bf-blender-cvs] [dd84acf305e] cycles_embree: Cycles: Embree support for ribbon line segments and subsurface scattering

Stefan Werner noreply at git.blender.org
Sun Nov 26 23:11:08 CET 2017


Commit: dd84acf305e2d28468469bd4b8148016bf83430e
Author: Stefan Werner
Date:   Wed Jun 7 15:05:35 2017 +0200
Branches: cycles_embree
https://developer.blender.org/rBdd84acf305e2d28468469bd4b8148016bf83430e

Cycles: Embree support for ribbon line segments and subsurface scattering

===================================================================

M	intern/cycles/bvh/bvh_embree.cpp
M	intern/cycles/bvh/bvh_embree.h
M	intern/cycles/device/device_cpu.cpp
M	intern/cycles/kernel/bvh/bvh.h
M	intern/cycles/kernel/bvh/bvh_embree_traversal.h

===================================================================

diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp
index 331657d270a..37fffc28977 100644
--- a/intern/cycles/bvh/bvh_embree.cpp
+++ b/intern/cycles/bvh/bvh_embree.cpp
@@ -24,18 +24,100 @@
 #include "util/util_foreach.h"
 
 #include "embree2/rtcore_geometry.h"
+
+/* kernel includes are necessary so that the filter function for embree can access the packed BVH */
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/split/kernel_split_data_types.h"
+#include "kernel/kernel_globals.h"
+#include "kernel/kernel_random.h"
 #include "kernel/bvh/bvh_embree_traversal.h"
 
 #include "xmmintrin.h"
 #include "pmmintrin.h"
 
-// #define EMBREE_CURVES
 #define EMBREE_SHARED_MEM 1
 
 CCL_NAMESPACE_BEGIN
 
-void cclFilterFunc(void* userDataPtr, RTCRay& ray)
+/* This gets called by embree at every valid ray/object intersection.
+ * Things like recording subsurface or shadow hits for later evaluation
+ * as well as filtering for volume objects happen here.
+ * Cycles' own BVH does that directly inside the traversal calls.
+ */
+
+void cclFilterFunc(void* userDataPtr, RTCRay& ray_)
 {
+	CCLRay &ray = (CCLRay&)ray_;
+	KernelGlobals *kg = ray.kg;
+
+	if(ray.type == CCLRay::RAY_REGULAR) {
+		return;
+	}
+	else if(ray.type == CCLRay::RAY_SHADOW_ALL) {
+		// append the intersection to the end of the array
+		if(ray.num_hits < ray.max_hits) {
+			Intersection *isect = &ray.isect_s[ray.num_hits];
+			ray.num_hits++;
+			ray.isect_to_ccl(isect);
+			int prim = kernel_tex_fetch(__prim_index, isect->prim);
+			int shader = 0;
+			if(kernel_tex_fetch(__prim_type, isect->prim) & PRIMITIVE_ALL_TRIANGLE)
+			{
+				shader = kernel_tex_fetch(__tri_shader, prim);
+			}
+			else {
+				float4 str = kernel_tex_fetch(__curves, prim);
+				shader = __float_as_int(str.z);
+			}
+			int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*SHADER_SIZE);
+			/* if no transparent shadows, all light is blocked */
+			if(flag & SD_HAS_TRANSPARENT_SHADOW) {
+				/* this tells embree to continue tracing */
+				ray.geomID = RTC_INVALID_GEOMETRY_ID;
+			}
+		}
+		return;
+	}
+	else if(ray.type == CCLRay::RAY_SSS) {
+		/* see triangle_intersect_subsurface() for the native equivalent */
+		for(int i = min(ray.max_hits, ray.ss_isect->num_hits) - 1; i >= 0; --i) {
+			if(ray.ss_isect->hits[i].t == ray.tfar) {
+				/* this tells embree to continue tracing */
+				ray.geomID = RTC_INVALID_GEOMETRY_ID;
+				return;
+			}
+		}
+
+		ray.ss_isect->num_hits++;
+		int hit;
+
+		if(ray.ss_isect->num_hits <= ray.max_hits) {
+			hit = ray.ss_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(ray.lcg_state) % ray.ss_isect->num_hits;
+
+			if(hit >= ray.max_hits) {
+				/* this tells embree to continue tracing */
+				ray.geomID = RTC_INVALID_GEOMETRY_ID;
+				return;
+			}
+		}
+		/* record intersection */
+		ray.isect_to_ccl(&ray.ss_isect->hits[hit]);
+		ray.ss_isect->Ng[hit].x = -ray.Ng[0];
+		ray.ss_isect->Ng[hit].y = -ray.Ng[1];
+		ray.ss_isect->Ng[hit].z = -ray.Ng[2];
+		ray.ss_isect->Ng[hit] = normalize(ray.ss_isect->Ng[hit]);
+		/* this tells embree to continue tracing */
+		ray.geomID = RTC_INVALID_GEOMETRY_ID;
+		return;
+	} else if(ray.type == CCLRay::RAY_VOLUME_ALL) {
+		return;
+	}
+
 	return;
 }
 
@@ -106,30 +188,20 @@ void BVHEmbree::build(Progress& progress)
 	foreach(Object *ob, objects) {
 		unsigned geom_id;
 
-		size_t prim_index_offset = pack.prim_index.size();
 		if(params.top_level) {
 			if(!ob->is_traceable()) {
 				++i;
 				continue;
 			}
 			if(!ob->mesh->is_instanced())
-				geom_id = add_mesh(ob->mesh, i);
+				geom_id = add_object(ob, i);
 			else
 				geom_id = add_instance(ob, i);
 
 		}
 		else
-			geom_id = add_mesh(ob->mesh, i);
+			geom_id = add_object(ob, i);
 
-		if(geom_id != RTC_INVALID_GEOMETRY_ID) {
-			if(!ob->mesh->is_instanced()) {
-				rtcSetUserData(scene, geom_id, (void*)prim_index_offset);
-				rtcSetIntersectionFilterFunction(scene, geom_id, cclFilterFunc);
-			}
-			else {
-				rtcSetUserData(scene, geom_id, (void*)0);
-			}
-		}
 		i++;
 
 		if(progress.get_cancel()) return;
@@ -154,14 +226,25 @@ void BVHEmbree::build(Progress& progress)
 	pack_nodes(NULL);
 }
 
-unsigned BVHEmbree::add_mesh(Mesh *mesh, int i)
+unsigned BVHEmbree::add_object(Object *ob, int i)
 {
+	Mesh *mesh = ob->mesh;
 	unsigned geom_id = RTC_INVALID_GEOMETRY_ID;
 	if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE && mesh->num_triangles() > 0) {
+		size_t prim_offset = pack.prim_index.size();
 		geom_id = add_triangles(mesh, i);
+		rtcSetUserData(scene, geom_id, (void*)prim_offset);
+		rtcSetIntersectionFilterFunction(scene, geom_id, cclFilterFunc);
+		rtcSetOcclusionFilterFunction(scene, geom_id, cclFilterFunc);
+		rtcSetMask(scene, geom_id, ob->visibility);
 	}
 	if(params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) {
+		size_t prim_offset = pack.prim_index.size();
 		geom_id = add_curves(mesh, i);
+		rtcSetUserData(scene, geom_id, (void*)prim_offset);
+		rtcSetIntersectionFilterFunction(scene, geom_id, cclFilterFunc);
+		rtcSetOcclusionFilterFunction(scene, geom_id, cclFilterFunc);
+		rtcSetMask(scene, geom_id, ob->visibility);
 	}
 	return geom_id;
 }
@@ -185,6 +268,9 @@ unsigned BVHEmbree::add_instance(Object *ob, int i)
 		rtcSetTransform2(scene, geom_id, RTC_MATRIX_ROW_MAJOR, (const float*)&ob->tfm);
 	}
 
+	rtcSetUserData(scene, geom_id, (void*)0);
+	rtcSetMask(scene, geom_id, ob->visibility);
+
 	pack.prim_index.push_back_slow(-1);
 	pack.prim_object.push_back_slow(i);
 	pack.prim_type.push_back_slow(PRIMITIVE_NONE);
@@ -199,11 +285,13 @@ unsigned BVHEmbree::add_triangles(Mesh *mesh, int i)
 	size_t t_mid = 0;
 	if(mesh->has_motion_blur()) {
 		attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-		num_motion_steps = mesh->motion_steps;
-		t_mid = (num_motion_steps - 1) / 2;
-		if(num_motion_steps > RTC_MAX_TIME_STEPS) {
-			assert(0);
-			num_motion_steps = RTC_MAX_TIME_STEPS;
+		if(attr_mP) {
+			num_motion_steps = mesh->motion_steps;
+			t_mid = (num_motion_steps - 1) / 2;
+			if(num_motion_steps > RTC_MAX_TIME_STEPS) {
+				assert(0);
+				num_motion_steps = RTC_MAX_TIME_STEPS;
+			}
 		}
 	}
 
@@ -262,7 +350,7 @@ unsigned BVHEmbree::add_triangles(Mesh *mesh, int i)
 	pack.prim_tri_index.reserve(pack.prim_index.size() + num_triangles);
 	for(size_t j = 0; j < num_triangles; j++) {
 		pack.prim_object.push_back_reserved(i);
-		pack.prim_type.push_back_reserved(PRIMITIVE_TRIANGLE);
+		pack.prim_type.push_back_reserved(num_motion_steps > 1 ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE);
 		pack.prim_index.push_back_reserved(j);
 		pack.prim_tri_index.push_back_reserved(j);
 	}
@@ -272,14 +360,13 @@ unsigned BVHEmbree::add_triangles(Mesh *mesh, int i)
 
 unsigned BVHEmbree::add_curves(Mesh *mesh, int i)
 {
-#ifndef EMBREE_CURVES
-	return RTC_INVALID_GEOMETRY_ID;
-#endif
 	const Attribute *attr_mP = NULL;
 	size_t num_motion_steps = 1;
 	if(mesh->has_motion_blur()) {
-		attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-		num_motion_steps = mesh->motion_steps;
+		attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+		if(attr_mP) {
+			num_motion_steps = mesh->motion_steps;
+		}
 	}
 
 	const size_t num_curves = mesh->num_curves();
@@ -288,24 +375,42 @@ unsigned BVHEmbree::add_curves(Mesh *mesh, int i)
 		Mesh::Curve c = mesh->get_curve(j);
 		num_segments += c.num_segments();
 	}
+
 	const size_t num_keys = mesh->curve_keys.size();
-	unsigned geom_id = rtcNewBezierHairGeometry2(scene,
+	unsigned geom_id = rtcNewLineSegments2(scene,
 												 RTC_GEOMETRY_STATIC,
-												 num_curves,
+												 num_segments,
 												 num_keys,
 												 num_motion_steps,
 												 i*2+1);
 
+	/* Make room for Cycles specific data */
+	pack.prim_object.reserve(pack.prim_object.size() + num_segments);
+	pack.prim_type.reserve(pack.prim_type.size() + num_segments);
+	pack.prim_index.reserve(pack.prim_index.size() + num_segments);
+	pack.prim_tri_index.reserve(pack.prim_index.size() + num_segments);
+
+	/* Split the Cycles curves into embree curve segments, each with 4 CVs */
 	void* raw_buffer = rtcMapBuffer(scene, geom_id, RTC_INDEX_BUFFER);
 	unsigned *rtc_indices = (unsigned*) raw_buffer;
 	size_t rtc_index = 0;
 	for(size_t j = 0; j < num_curves; j++) {
 		Mesh::Curve c = mesh->get_curve(j);
-				rtc_indices[rtc_index] = max(c.first_key - 1,c.first_key);
-				rtc_index++;
+		for(size_t k = 0; k < c.num_segments(); k++) {
+			rtc_indices[rtc_index] = c.first_key + k;
+
+			/* Cycles specific data */
+			pack.prim_object.push_back_reserved(i);
+			pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k));
+			pack.prim_index.push_back_reserved(j);
+			pack.prim_tri_index.push_back_reserved(rtc_index);
+
+			rtc_index++;
+		}
 	}
 	rtcUnmapBuffer(scene, geom_id, RTC_INDEX_BUFFER);
 
+	/* Copy the CV data to embree */
 	int t_mid = (num_motion_steps - 1) / 2;
 	const float *curve_radius = &mesh->curve_radius[0];
 	for(int t = 0; t < num_motion_steps; t++) {
@@ -317,29 +422,25 @@ unsigned BVHEmbree::add_curves(Mesh *mesh, int i)
 			int t_ = (t > t_mid) ? (t - 1) : t;
 			verts = &attr_mP->data_float3()[t_ * num_keys];
 		}
-		raw_buffer = rtcMapBuffer(scene, geom_id, buffer_type);
-		float *rtc_verts = (float*) raw_buffer;
-		for(size_t j = 0; j < num_keys; j++) {
-			rtc_verts[0] = verts[j].x;
-			rtc_verts[1] = verts[j].y;
-			rtc_verts[2] = verts[j].z;
-			rtc_verts[3] = curve_radius[j];
-			rtc_verts += 4;
+
+#ifdef EMBREE_SHARED_MEM
+		if(t != t_mid) {
+			rtcSetBuffer(scene, geom_id, buffer_type, verts, 0, sizeof(float4));
+		} else {
+#endif
+			raw_buffer = rtcMapBuffer(scene, geom_id, buffer_type);
+			float *rtc_verts = (float*) raw_buffer;
+			for(size_t j = 0; j < num_keys; j++) {
+				rtc_verts[0] = verts[j].x;
+				rtc_verts[1] = verts[j].y;
+				rtc_verts[2] = verts[j].z;
+				rtc_verts[3] = curve_radius[j];
+				rtc_verts += 4;
+			}
+			rtcUnmapBuffer(scene, geom_id, buffer_type);
 		}
-		rtcUnmapBuffer(scene, geom_id, buffer_type);
 	}
 
-	pack.prim_object

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list