[Bf-blender-cvs] [f770bc4] master: Cycles: Implement watertight ray/triangle intersection

Sergey Sharybin noreply at git.blender.org
Wed Dec 24 22:56:21 CET 2014


Commit: f770bc4757a2b471d5aaee048359096c1c79a6b2
Author: Sergey Sharybin
Date:   Mon Dec 15 21:18:01 2014 +0500
Branches: master
https://developer.blender.org/rBf770bc4757a2b471d5aaee048359096c1c79a6b2

Cycles: Implement watertight ray/triangle intersection

Using this paper: Sven Woop, Watertight Ray/Triangle Intersection

  http://jcgt.org/published/0002/01/05/paper.pdf

This change is expected to address quite reasonable amount of reports from the
bug tracker, plus it might help reducing the noise in some scenes.

Unfortunately, it's currently about 7% slower than the previous solution with
pre-computed triangle plane equations, but maybe with some smart tweaks to the
code (tests reshuffle, using SIMD in a nice way or so) we can avoid the speed
regression.

But perhaps smartest thing to do here would be to change single triangle / ray
intersection with multiple triangles / ray intersections. That's how Embree does
this and it's watertight single ray intersection is not any faster that this.

Currently only triangle intersection is modified accordingly to the paper, in
the future we would also want to modify the node / ray intersection.

Reviewers: brecht, juicyfruit

Subscribers: dingto, ton

Differential Revision: https://developer.blender.org/D819

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

M	intern/cycles/bvh/bvh.cpp
M	intern/cycles/bvh/bvh.h
M	intern/cycles/kernel/geom/geom_bvh_shadow.h
M	intern/cycles/kernel/geom/geom_bvh_subsurface.h
M	intern/cycles/kernel/geom/geom_bvh_traversal.h
M	intern/cycles/kernel/geom/geom_bvh_volume.h
M	intern/cycles/kernel/geom/geom_triangle.h
M	intern/cycles/kernel/geom/geom_triangle_intersect.h
M	intern/cycles/util/util_math.h

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

diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 3f14c0d..8b1759e 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -275,68 +275,13 @@ void BVH::pack_triangle(int idx, float4 woop[3])
 	float3 v1 = vpos[vidx[1]];
 	float3 v2 = vpos[vidx[2]];
 
-	float3 r0 = v0 - v2;
-	float3 r1 = v1 - v2;
-	float3 r2 = cross(r0, r1);
-
-	if(is_zero(r0) || is_zero(r1) || is_zero(r2)) {
-		/* degenerate */
-		woop[0] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-		woop[1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-		woop[2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
-	}
-	else {
-		Transform t = make_transform(
-			r0.x, r1.x, r2.x, v2.x,
-			r0.y, r1.y, r2.y, v2.y,
-			r0.z, r1.z, r2.z, v2.z,
-			0.0f, 0.0f, 0.0f, 1.0f);
-
-		t = transform_inverse(t);
-
-		woop[0] = make_float4(t.z.x, t.z.y, t.z.z, -t.z.w);
-		woop[1] = make_float4(t.x.x, t.x.y, t.x.z, t.x.w);
-		woop[2] = make_float4(t.y.x, t.y.y, t.y.z, t.y.w);
-	}
+	woop[0] = float3_to_float4(v0);
+	woop[1] = float3_to_float4(v1);
+	woop[2] = float3_to_float4(v2);
 }
 
 /* Curves*/
 
-void BVH::pack_curve_segment(int idx, float4 woop[3])
-{
-	int tob = pack.prim_object[idx];
-	const Mesh *mesh = objects[tob]->mesh;
-	int tidx = pack.prim_index[idx];
-	int segment = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[idx]);
-	int k0 = mesh->curves[tidx].first_key + segment;
-	int k1 = mesh->curves[tidx].first_key + segment + 1;
-	float3 v0 = float4_to_float3(mesh->curve_keys[k0]);
-	float3 v1 = float4_to_float3(mesh->curve_keys[k1]);
-
-	float3 d0 = v1 - v0;
-	float l =  len(d0);
-	
-	/*Plan
-	*Transform tfm = make_transform(
-	*	location <3>    , l,
-	*	extra curve data <3>    , StrID,
-	*	nextkey, flags/tip?,    0, 0);
-	*/
-	float3 tg0 = make_float3(1.0f, 0.0f, 0.0f);
-	float3 tg1 = make_float3(1.0f, 0.0f, 0.0f);
-	
-	Transform tfm = make_transform(
-		tg0.x, tg0.y, tg0.z, l,
-		tg1.x, tg1.y, tg1.z, 0,
-		0, 0, 0, 0,
-		0, 0, 0, 1);
-
-	woop[0] = tfm.x;
-	woop[1] = tfm.y;
-	woop[2] = tfm.z;
-
-}
-
 void BVH::pack_primitives()
 {
 	int nsize = TRI_NODE_SIZE;
@@ -351,9 +296,7 @@ void BVH::pack_primitives()
 		if(pack.prim_index[i] != -1) {
 			float4 woop[3];
 
-			if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
-				pack_curve_segment(i, woop);
-			else
+			if(pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE)
 				pack_triangle(i, woop);
 			
 			memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index ef4575a..a4a1270 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -106,7 +106,6 @@ protected:
 	/* triangles and strands*/
 	void pack_primitives();
 	void pack_triangle(int idx, float4 woop[3]);
-	void pack_curve_segment(int idx, float4 woop[3]);
 
 	/* merge instance BVH's */
 	void pack_instances(size_t nodes_size);
diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h
index 9704b0a..db7c564 100644
--- a/intern/cycles/kernel/geom/geom_bvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h
@@ -81,6 +81,9 @@ ccl_device bool BVH_FUNCTION_NAME
 	gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
 #endif
 
+	IsectPrecalc isect_precalc;
+	triangle_intersect_precalc(dir, &isect_precalc);
+
 	/* traversal loop */
 	do {
 		do {
@@ -214,7 +217,7 @@ ccl_device bool BVH_FUNCTION_NAME
 
 						switch(type & PRIMITIVE_ALL) {
 							case PRIMITIVE_TRIANGLE: {
-								hit = triangle_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
+								hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
 								break;
 							}
 #if FEATURE(BVH_MOTION)
@@ -295,6 +298,7 @@ ccl_device bool BVH_FUNCTION_NAME
 					bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
 #endif
 
+					triangle_intersect_precalc(dir, &isect_precalc);
 					num_hits_in_instance = 0;
 
 #if defined(__KERNEL_SSE2__)
@@ -330,6 +334,8 @@ ccl_device bool BVH_FUNCTION_NAME
 				bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
 #endif
 
+				triangle_intersect_precalc(dir, &isect_precalc);
+
 				/* scale isect->t to adjust for instancing */
 				for(int i = 0; i < num_hits_in_instance; i++)
 					(isect_array-i-1)->t *= t_fac;
@@ -342,6 +348,7 @@ ccl_device bool BVH_FUNCTION_NAME
 #else
 				bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
 #endif
+				triangle_intersect_precalc(dir, &isect_precalc);
 			}
 
 #if defined(__KERNEL_SSE2__)
diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
index e5cb60f..756130b 100644
--- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
@@ -77,6 +77,9 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
 	gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
 #endif
 
+	IsectPrecalc isect_precalc;
+	triangle_intersect_precalc(dir, &isect_precalc);
+
 	/* traversal loop */
 	do {
 		do
@@ -202,7 +205,7 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
 
 						switch(type & PRIMITIVE_ALL) {
 							case PRIMITIVE_TRIANGLE: {
-								triangle_intersect_subsurface(kg, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
+								triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
 								break;
 							}
 #if FEATURE(BVH_MOTION)
@@ -228,6 +231,7 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
 #else
 						bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
 #endif
+						triangle_intersect_precalc(dir, &isect_precalc);
 
 #if defined(__KERNEL_SSE2__)
 						Psplat[0] = ssef(P.x);
@@ -265,6 +269,8 @@ ccl_device uint BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersectio
 			bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect_t);
 #endif
 
+			triangle_intersect_precalc(dir, &isect_precalc);
+
 #if defined(__KERNEL_SSE2__)
 			Psplat[0] = ssef(P.x);
 			Psplat[1] = ssef(P.y);
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index 1d053ba..7be22c0 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -89,6 +89,9 @@ ccl_device bool BVH_FUNCTION_NAME
 	gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
 #endif
 
+	IsectPrecalc isect_precalc;
+	triangle_intersect_precalc(dir, &isect_precalc);
+
 	/* traversal loop */
 	do {
 		do {
@@ -257,7 +260,7 @@ ccl_device bool BVH_FUNCTION_NAME
 
 						switch(type & PRIMITIVE_ALL) {
 							case PRIMITIVE_TRIANGLE: {
-								hit = triangle_intersect(kg, isect, P, dir, visibility, object, primAddr);
+								hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
 								break;
 							}
 #if FEATURE(BVH_MOTION)
@@ -312,6 +315,7 @@ ccl_device bool BVH_FUNCTION_NAME
 #else
 					bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
 #endif
+					triangle_intersect_precalc(dir, &isect_precalc);
 
 #if defined(__KERNEL_SSE2__)
 					Psplat[0] = ssef(P.x);
@@ -342,6 +346,7 @@ ccl_device bool BVH_FUNCTION_NAME
 #else
 			bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
 #endif
+			triangle_intersect_precalc(dir, &isect_precalc);
 
 #if defined(__KERNEL_SSE2__)
 			Psplat[0] = ssef(P.x);
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h
index 58dda7b..7d6b9bd 100644
--- a/intern/cycles/kernel/geom/geom_bvh_volume.h
+++ b/intern/cycles/kernel/geom/geom_bvh_volume.h
@@ -83,6 +83,9 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
 	gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
 #endif
 
+	IsectPrecalc isect_precalc;
+	triangle_intersect_precalc(dir, &isect_precalc);
+
 	/* traversal loop */
 	do {
 		do {
@@ -209,7 +212,7 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
 
 						switch(type & PRIMITIVE_ALL) {
 							case PRIMITIVE_TRIANGLE: {
-								triangle_intersect(kg, isect, P, dir, visibility, object, primAddr);
+								triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
 								break;
 							}
 #if FEATURE(BVH_MOTION)
@@ -248,6 +251,8 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
 						bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
 #endif
 
+						triangle_intersect_precalc(dir, &isect_precalc);
+
 #if defined(__KERNEL_SSE2__)
 						Psplat[0] = ssef(P.x);
 						Psplat[1] = ssef(P.y);
@@ -285,6 +290,8 @@ ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg,
 			bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
 #endif
 
+			triangle_intersect_precalc(dir, &isect_precalc);
+
 #if defined(__KERNEL_SSE2__)
 			Psplat[0] = ssef(P.x);
 			Psplat[1] = ssef(P.y);
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 0390804..dd39286 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -17,7 +17,9 @@
 
 /* Triangle Primitive
  *
- * Basic triangle with 3 vertices is used to represent mesh surfaces. */
+ * Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH
+ * ray intersection we use a precomputed triangle storage to accelerate
+ * intersection at the cost of more memory usage */
 
 CCL_NAMESPACE_BEGIN
 
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index b965bdd..4bb60ca 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -1,6 +1,5 @@
 /*
- * Adapted from code Copyright 2009-2010 NVIDIA Corporation
- * Modifications Copyright 2011, Blender Foundation.
+ * Copyright 2014, Blender Foundation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,122 +14,270 @@
  * limitations under the License.
 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list