[Bf-blender-cvs] [ca8da1d] strand_gpu: Working interpolation code for strands.

Lukas Tönne noreply at git.blender.org
Tue Jul 5 09:57:21 CEST 2016


Commit: ca8da1d3039b95eeec11c6b6828cb09733f04639
Author: Lukas Tönne
Date:   Mon Jul 4 17:32:56 2016 +0200
Branches: strand_gpu
https://developer.blender.org/rBca8da1d3039b95eeec11c6b6828cb09733f04639

Working interpolation code for strands.

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

M	source/blender/blenkernel/intern/strands.c
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/intern/gpu_strands.c
A	source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
A	source/blender/gpu/shaders/gpu_shader_strand_geom.glsl
A	source/blender/gpu/shaders/gpu_shader_strand_vert.glsl

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

diff --git a/source/blender/blenkernel/intern/strands.c b/source/blender/blenkernel/intern/strands.c
index 53ed820..a4d6452 100644
--- a/source/blender/blenkernel/intern/strands.c
+++ b/source/blender/blenkernel/intern/strands.c
@@ -208,6 +208,44 @@ void BKE_strands_test_init(struct Strands *strands, struct DerivedMesh *scalp,
 	BLI_rng_free(rng);
 }
 
+BLI_INLINE void verify_root_weights(StrandRoot *root)
+{
+	const float *w = root->control_weights;
+	
+	BLI_assert(w[0] >= 0.0f && w[1] >= 0.0f && w[2] >= 0.0f && w[3] >= 0.0f);
+	float sum = w[0] + w[1] + w[2] + w[3];
+	float epsilon = 1.0e-2;
+	BLI_assert(sum > 1.0f - epsilon && sum < 1.0f + epsilon);
+	UNUSED_VARS(sum, epsilon);
+	
+	BLI_assert(w[0] >= w[1] && w[1] >= w[2] && w[2] >= w[3]);
+}
+
+static void sort_root_weights(StrandRoot *root)
+{
+	unsigned int *idx = root->control_index;
+	float *w = root->control_weights;
+
+#define ROOTSWAP(a, b) \
+	SWAP(unsigned int, idx[a], idx[b]); \
+	SWAP(float, w[a], w[b]);
+
+	for (int k = 0; k < 3; ++k) {
+		int maxi = k;
+		float maxw = w[k];
+		for (int i = k+1; i < 4; ++i) {
+			if (w[i] > maxw) {
+				maxi = i;
+				maxw = w[i];
+			}
+		}
+		if (maxi != k)
+			ROOTSWAP(k, maxi);
+	}
+	
+#undef ROOTSWAP
+}
+
 static void strands_calc_weights(const Strands *strands, struct DerivedMesh *scalp, StrandRoot *roots, int num_roots)
 {
 	float (*strandloc)[3] = MEM_mallocN(sizeof(float) * 3 * strands->totcurves, "strand locations");
@@ -250,14 +288,21 @@ static void strands_calc_weights(const Strands *strands, struct DerivedMesh *sca
 				float w[4];
 				interp_weights_face_v3(w, sloc[0], sloc[1], sloc[2], NULL, closest);
 				copy_v3_v3(root->control_weights, w);
+				/* float precisions issues can cause slightly negative weights */
+				CLAMP3(root->control_weights, 0.0f, 1.0f);
 			}
 			else if (found == 2) {
 				root->control_weights[1] = line_point_factor_v3(loc, sloc[0], sloc[1]);
 				root->control_weights[0] = 1.0f - root->control_weights[1];
+				/* float precisions issues can cause slightly negative weights */
+				CLAMP2(root->control_weights, 0.0f, 1.0f);
 			}
 			else if (found == 1) {
 				root->control_weights[0] = 1.0f;
 			}
+			
+			sort_root_weights(root);
+			verify_root_weights(root);
 		}
 	}
 	
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index c3cf5d3..b396202 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -81,6 +81,9 @@ set(SRC
 	shaders/gpu_shader_fx_depth_resolve.glsl
 	shaders/gpu_shader_smoke_frag.glsl
 	shaders/gpu_shader_smoke_vert.glsl
+	shaders/gpu_shader_strand_frag.glsl
+	shaders/gpu_shader_strand_geom.glsl
+	shaders/gpu_shader_strand_vert.glsl
 
 	GPU_basic_shader.h
 	GPU_buffers.h
@@ -122,6 +125,9 @@ data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_strand_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_strand_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_strand_vert.glsl SRC)
 
 if(WITH_GAMEENGINE)
 	add_definitions(-DWITH_GAMEENGINE)
diff --git a/source/blender/gpu/intern/gpu_strands.c b/source/blender/gpu/intern/gpu_strands.c
index c6f0c72..5126124 100644
--- a/source/blender/gpu/intern/gpu_strands.c
+++ b/source/blender/gpu/intern/gpu_strands.c
@@ -67,88 +67,9 @@ struct GPUStrandsShader {
 	char *vertexcode;
 };
 
-const char *vertex_shader = STRINGIFY(
-	in uvec4 control_index;
-	in vec4 control_weight;
-	
-	out uvec4 v_control_index;
-	out vec4 v_control_weight;
-
-	out vec3 vColor;
-	
-	void main()
-	{
-//		vec4 co = gl_ModelViewMatrix * gl_Vertex;
-//		gl_Position = gl_ProjectionMatrix * co;
-		gl_Position = gl_Vertex;
-		
-		v_control_index = control_index;
-		v_control_weight = control_weight;
-		vColor = vec3(float(control_index.x)/float(10), 0.0, 0.0);
-	}
-);
-
-const char *geometry_shader = STRINGIFY(
-	layout(points) in;
-	layout(line_strip, max_vertices = 64) out;
-	
-	in vec3 vColor[];
-	
-	in uvec4 v_control_index[];
-	in vec4 v_control_weight[];
-
-	out vec3 fColor;
-
-	uniform isamplerBuffer control_curves;
-	uniform samplerBuffer control_points;
-	
-	void main()
-	{
-		vec4 root = gl_in[0].gl_Position;
-		
-		int index0 = int(v_control_index[0].x);
-		ivec4 curve0 = texelFetch(control_curves, index0);
-		int vert_begin0 = int(curve0.x);
-		int num_verts0 = int(curve0.y);
-		vec4 root0 = texelFetch(control_points, vert_begin0);
-		vec4 offset0 = root - root0;
-		
-//		fColor = vColor[0];
-		fColor = vec3(float(num_verts0)/float(10), 0.0, 0.0);
-		
-		gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * root;
-		EmitVertex();
-		
-//		gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * (root + vec4(0.1, 0.0, 0.0, 0.0));
-//		gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * (root + vec4(float(index0 % 10 + 1) * 0.01, 0.0, 0.0, 0.0));
-//		gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(index0, 0.0, 0.0, 1.0);
-//		gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(v_control_weight[0].xyz, 1.0);
-//		EmitVertex();
-		
-		gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * root0;
-		EmitVertex();
-		
-/*		for (int i = 1; i < num_verts; ++i) {
-			vec4 loc = texelFetch(control_points, vert_begin + i);
-			
-			gl_Position = vec4((loc + offset).xyz, 1.0);
-			EmitVertex();
-		}*/
-		
-	    EndPrimitive();
-	}
-);
-	
-	const char *fragment_shader = STRINGIFY(
-		in vec3 fColor;
-		
-		out vec4 outColor;
-		
-		void main()
-		{
-			outColor = vec4(fColor, 1.0);
-		}
-	);
+extern char datatoc_gpu_shader_strand_frag_glsl[];
+extern char datatoc_gpu_shader_strand_geom_glsl[];
+extern char datatoc_gpu_shader_strand_vert_glsl[];
 
 static char *codegen_vertex(void)
 {
@@ -162,7 +83,7 @@ static char *codegen_vertex(void)
 	
 	return code;
 #else
-	return BLI_strdup(vertex_shader);
+	return BLI_strdup(datatoc_gpu_shader_strand_vert_glsl);
 #endif
 }
 
@@ -178,7 +99,7 @@ static char *codegen_geometry(void)
 	
 	return code;
 #else
-	return BLI_strdup(geometry_shader);
+	return BLI_strdup(datatoc_gpu_shader_strand_geom_glsl);
 #endif
 }
 
@@ -194,7 +115,7 @@ static char *codegen_fragment(void)
 	
 	return code;
 #else
-	return BLI_strdup(fragment_shader);
+	return BLI_strdup(datatoc_gpu_shader_strand_frag_glsl);
 #endif
 }
 
diff --git a/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl b/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
new file mode 100644
index 0000000..164320b
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_strand_frag.glsl
@@ -0,0 +1,8 @@
+in vec3 fColor;
+
+out vec4 outColor;
+
+void main()
+{
+	outColor = vec4(fColor, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl b/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl
new file mode 100644
index 0000000..295f2f5
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_strand_geom.glsl
@@ -0,0 +1,166 @@
+// Define which one is the outer loop.
+// TODO Have to determine which variant is better
+//#define LOOP_CURVES
+#define LOOP_VERTS
+
+#define MAX_CURVE_VERTS 64
+
+layout(points) in;
+layout(line_strip, max_vertices = MAX_CURVE_VERTS) out;
+
+in vec3 vColor[];
+
+in uvec4 v_control_index[];
+in vec4 v_control_weight[];
+
+out vec3 fColor;
+
+uniform usamplerBuffer control_curves;
+uniform samplerBuffer control_points;
+
+bool is_valid_index(uint index)
+{
+	return index < uint(0xFFFFFFFF);
+}
+
+void emit_vertex(in vec4 loc)
+{
+	gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(loc.xyz, 1.0);
+	EmitVertex();
+}
+
+void main()
+{
+	fColor = vColor[0];
+	
+	vec4 root = gl_in[0].gl_Position;
+	
+	emit_vertex(root);
+	
+	
+	int index[4] = int[4](int(v_control_index[0].x),
+	                      int(v_control_index[0].y),
+	                      int(v_control_index[0].z),
+	                      int(v_control_index[0].w));
+	bool valid[4] = bool[4](is_valid_index(v_control_index[0].x),
+		                    is_valid_index(v_control_index[0].y),
+		                    is_valid_index(v_control_index[0].z),
+		                    is_valid_index(v_control_index[0].w));
+	float weight[4] = float[4](v_control_weight[0].x,
+	                           v_control_weight[0].y,
+	                           v_control_weight[0].z,
+	                           v_control_weight[0].w);
+
+	int cvert_begin[4];
+	int num_cverts[4];
+	float fnum_verts = 0.0;
+	vec4 croot[4];
+	vec4 offset[4];
+	for (int k = 0; k < 4; ++k) {
+		uvec4 curve = texelFetch(control_curves, index[k]);
+		cvert_begin[k] = int(curve.x);
+		num_cverts[k] = int(curve.y);
+		
+		fnum_verts += weight[k] * float(num_cverts[k]);
+		
+		croot[k] = texelFetch(control_points, cvert_begin[k]);
+		offset[k] = root - croot[k];
+	}
+#ifdef LOOP_CURVES
+	int num_verts = clamp(int(ceil(fnum_verts)), 2, MAX_CURVE_VERTS);
+#else
+	int num_verts = max(int(ceil(fnum_verts)), 2);
+#endif
+#if 1
+#else
+	/* XXX DEBUGGING!! */
+	num_verts = max(2, num_cverts[0]);
+	valid[0] = true;
+	valid[1] = false;
+	valid[2] = false;
+	valid[3] = false;
+#endif
+
+#ifdef LOOP_VERTS
+	float dt[4];
+	for (int k = 0; k < 4; ++k) {
+		dt[k] = float(num_cverts[k] - 1) / float(num_verts - 1);
+	}
+#endif
+
+	fColor = vec3(0.0, 1.0, 0.0);
+	emit_vertex(root);
+
+#ifdef LOOP_VERTS
+	float t[4] = float[4](dt[0], dt[1], dt[2], dt[3]);
+	for (int i = 1; i < num_verts; ++i) {
+		vec4 loc = vec4(0.0, 0.0, 0.0, 1.0);
+
+		for (int k = 0; k < 4; ++k) {
+			if (!valid[k])
+				continue;
+
+#if 0
+			int ci0 = clamp(int(t[k]), 0, num_cverts[k] - 1);
+			int ci1 = ci0 + 1;
+			float lambda = t[k] - floor(t[k]);
+			/* XXX could use texture filtering to do this for us? */
+			vec4 cloc0 = texelFetch(control_points, cvert_begin[k] + ci0);
+			vec4 cloc1 = texelFetch(control_points, cvert_begin[k] + ci1);
+			vec4 cloc = mix(cloc0, cloc1, lambda) + offset[k];
+#else
+			/* XXX DEBUGGING!! */
+			int ci0 = clamp(int(t[k]), 0, num_cverts[k] - 1);
+			vec4 cloc0 = texelFetch(control_points, cvert_begin[k] + ci0);
+			vec4 cloc = cloc0 + offset[k];
+#endif
+			
+#if 1
+			loc += weight[k] * cloc;
+#else
+			/* XXX DEB

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list