[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