[Bf-blender-cvs] [f854fefa179] tmp_hair_curves: Separate buffer texture for hair index for each vertex.

Lukas Tönne noreply at git.blender.org
Sun Aug 12 11:35:32 CEST 2018


Commit: f854fefa1796429907c2574ba414335eb5519714
Author: Lukas Tönne
Date:   Sun Aug 12 10:33:21 2018 +0100
Branches: tmp_hair_curves
https://developer.blender.org/rBf854fefa1796429907c2574ba414335eb5519714

Separate buffer texture for hair index for each vertex.

This is needed for allowing variable length hair strands, where the hair index can not
simply be calculated from the vertex index based on a fixed-length strand.

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

M	source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
M	source/blender/draw/intern/draw_cache_impl_particles.c
M	source/blender/draw/intern/draw_hair.c
M	source/blender/draw/intern/draw_hair_private.h
M	source/blender/draw/modes/shaders/common_hair_lib.glsl

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

diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
index 66b529fcf5e..dfc45c8d04c 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
@@ -23,6 +23,8 @@ out vec3 normal_viewport;
 out vec2 uv_interp;
 #endif
 
+out int DEBUG;
+
 /* From http://libnoise.sourceforge.net/noisegen/index.html */
 float integer_noise(int n)
 {
@@ -34,6 +36,7 @@ float integer_noise(int n)
 void main()
 {
 #ifdef HAIR_SHADER
+	DEBUG = hair_get_strand_id();
 #  ifdef V3D_SHADING_TEXTURE_COLOR
 	vec2 uv = hair_get_customdata_vec2(u);
 #  endif
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index 0d29debfae1..da360f89051 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -743,13 +743,23 @@ static void ensure_seg_pt_final_count(
 	final_cache->elems_len = (points_per_curve * thickness_res + 1) * final_cache->strands_len;
 }
 
+#define USE_POSITION_HAIR_INDEX
+
 static void particle_batch_cache_ensure_procedural_final_points(
+        const ParticleSystem *psys,
         ParticleHairCache *cache,
         int subdiv)
 {
+
 	/* Same format as point_tex. */
+#ifdef USE_POSITION_HAIR_INDEX
+	static Gwn_VertFormat format = { 0 };
+	GWN_vertformat_clear(&format);
+	uint pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+#else
 	Gwn_VertFormat format = { 0 };
 	GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
+#endif
 
 	cache->final[subdiv].proc_point_buf = GWN_vertbuf_create_with_format(&format);
 
@@ -757,12 +767,53 @@ static void particle_batch_cache_ensure_procedural_final_points(
 	/* Thoses are points! not line segments. */
 	GWN_vertbuf_data_alloc(cache->final[subdiv].proc_point_buf, cache->final[subdiv].point_len);
 
+#ifdef USE_POSITION_HAIR_INDEX
+	Gwn_VertBufRaw data_step;
+	GWN_vertbuf_attr_get_raw_data(cache->final[subdiv].proc_point_buf, pos_id, &data_step);
+	const int points_per_curve = (1 << (psys->part->draw_step + subdiv)) + 1;
+	for (int i = 0; i < cache->final[subdiv].strands_len; i++) {
+		for (int j = 0; j < points_per_curve; ++j) {
+			uint *data = (uint *)GWN_vertbuf_raw_step(&data_step);
+			*data = (uint)i;
+		}
+	}
+#endif
+
 	/* Create vbo immediatly to bind to texture buffer. */
 	GWN_vertbuf_use(cache->final[subdiv].proc_point_buf);
 
 	cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_point_buf);
 }
 
+static void particle_batch_cache_ensure_procedural_final_hair_index(
+        const ParticleSystem *psys,
+        ParticleHairCache *cache,
+        int subdiv)
+{
+	/* Same format as point_tex. */
+	Gwn_VertFormat format = { 0 };
+	uint hair_index_id = GWN_vertformat_attr_add(&format, "hair_index", GWN_COMP_U32, 1, GWN_FETCH_INT);
+
+	cache->final[subdiv].proc_hair_index_buf = GWN_vertbuf_create_with_format(&format);
+
+	GWN_vertbuf_data_alloc(cache->final[subdiv].proc_hair_index_buf, cache->final[subdiv].point_len);
+
+	Gwn_VertBufRaw data_step;
+	GWN_vertbuf_attr_get_raw_data(cache->final[subdiv].proc_hair_index_buf, hair_index_id, &data_step);
+	const int points_per_curve = (1 << (psys->part->draw_step + subdiv)) + 1;
+	for (int i = 0; i < cache->final[subdiv].strands_len; i++) {
+		for (int j = 0; j < points_per_curve; ++j) {
+			uint *data = (uint *)GWN_vertbuf_raw_step(&data_step);
+			*data = (uint)i;
+		}
+	}
+
+	/* Create vbo immediatly to bind to texture buffer. */
+	GWN_vertbuf_use(cache->final[subdiv].proc_hair_index_buf);
+
+	cache->final[subdiv].hair_index_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_hair_index_buf);
+}
+
 static void particle_batch_cache_ensure_procedural_strand_data(
         PTCacheEdit *edit,
         ParticleSystem *psys,
@@ -1565,7 +1616,8 @@ bool particles_ensure_procedural_data(
 	/* Refreshed only on subdiv count change. */
 	if ((*r_hair_cache)->final[subdiv].proc_point_buf == NULL) {
 		ensure_seg_pt_final_count(psys, &cache->hair, subdiv, thickness_res);
-		particle_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv);
+		particle_batch_cache_ensure_procedural_final_points(psys, &cache->hair, subdiv);
+		particle_batch_cache_ensure_procedural_final_hair_index(psys, &cache->hair, subdiv);
 		need_ft_update = true;
 	}
 	if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) {
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index e291aabe5a3..7406e7a0645 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -158,11 +158,8 @@ static DRWShadingGroup *drw_shgroup_create_particle_hair_procedural_ex(
 		}
 	}
 
-	// XXX HACK! soon to be removed in favor of per-strand res values (need the static for setting a uniform)
-	static int strands_res;
-	strands_res = (1 << (part->draw_step + subdiv)) + 1;
 	DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
-	DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &strands_res, 1);
+	DRW_shgroup_uniform_texture(shgrp, "hairIndexBuffer", hair_cache->final[subdiv].hair_index_tex);
 	DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
 	DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1);
 	DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f);
@@ -178,7 +175,6 @@ static DRWShadingGroup *drw_shgroup_create_particle_hair_procedural_ex(
 		                                                                  hair_cache->final[subdiv].proc_point_buf);
 		DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", hair_cache->point_tex);
 		DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", hair_cache->strand_tex);
-		DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &strands_res, 1);
 		DRW_shgroup_call_procedural_points_add(tf_shgrp, hair_cache->final[subdiv].point_len, NULL);
 	}
 
diff --git a/source/blender/draw/intern/draw_hair_private.h b/source/blender/draw/intern/draw_hair_private.h
index 2182b1477ab..e035131b4d7 100644
--- a/source/blender/draw/intern/draw_hair_private.h
+++ b/source/blender/draw/intern/draw_hair_private.h
@@ -46,8 +46,8 @@ typedef struct ParticleHairFinalCache {
 	Gwn_VertBuf *proc_point_buf;
 	GPUTexture *proc_tex;
 
-//	Gwn_VertBuf *proc_strand_buf; /* Infos of control points strands (segment count and base index) */
-//	GPUTexture *strand_tex;
+	Gwn_VertBuf *proc_hair_index_buf; /* Hair strand index for each vertex */
+	GPUTexture *hair_index_tex;
 
 	/* Just contains a huge index buffer used to draw the final hair. */
 	Gwn_Batch *proc_hairs[MAX_THICKRES];
diff --git a/source/blender/draw/modes/shaders/common_hair_lib.glsl b/source/blender/draw/modes/shaders/common_hair_lib.glsl
index 552690ba972..75e58adf374 100644
--- a/source/blender/draw/modes/shaders/common_hair_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_hair_lib.glsl
@@ -5,13 +5,6 @@
  * of data the CPU has to precompute and transfert for each update.
  **/
 
-/**
- * hairStrandsRes: Number of points per hair strand.
- * 2 - no subdivision
- * 3+ - 1 or more interpolated points per hair.
- **/
-uniform int hairStrandsRes = 8;
-
 /**
  * hairThicknessRes : Subdiv around the hair.
  * 1 - Wire Hair: Only one pixel thick, independant of view distance.
@@ -33,6 +26,7 @@ uniform samplerBuffer hairPointBuffer; /* RGBA32F */
 
 /* -- Per strands data -- */
 uniform usamplerBuffer hairStrandBuffer; /* R32UI */
+uniform usamplerBuffer hairIndexBuffer; /* R32UI */
 
 /* Not used, use one buffer per uv layer */
 //uniform samplerBuffer hairUVBuffer; /* RG32F */
@@ -49,6 +43,13 @@ void unpack_strand_data(uint data, out int strand_offset, out int strand_segment
 #endif
 }
 
+int hair_get_strand_id(void)
+{
+	//return gl_VertexID / (hairStrandsRes * hairThicknessRes);
+	uint strand_index = texelFetch(hairIndexBuffer, gl_VertexID).x;
+	return int(strand_index);
+}
+
 /* -- Subdivision stage -- */
 /**
  * We use a transform feedback to preprocess the strands and add more subdivision to it.
@@ -59,40 +60,40 @@ void unpack_strand_data(uint data, out int strand_offset, out int strand_segment
  **/
 
 #ifdef HAIR_PHASE_SUBDIV
-int hair_get_base_id(float local_time, int strand_segments, out float interp_time)
+/**
+ * Calculate segment and local time for interpolation
+ */
+void hair_get_interp_time(float local_time, int strand_segments, out int interp_segment, out float interp_time)
 {
 	float time_per_strand_seg = 1.0 / float(strand_segments);
 
 	float ratio = local_time / time_per_strand_seg;
+	interp_segment = int(ratio);
 	interp_time = fract(ratio);
-
-	return int(ratio);
 }
 
 void hair_get_interp_attribs(out vec4 data0, out vec4 data1, out vec4 data2, out vec4 data3, out float interp_time)
 {
-	float local_time = float(gl_VertexID % hairStrandsRes) / float(hairStrandsRes - 1);
-
-	int hair_id = gl_VertexID / hairStrandsRes;
-	uint strand_data = texelFetch(hairStrandBuffer, hair_id).x;
-
+	int strand_index = hair_get_strand_id();
+	uint strand_data = texelFetch(hairStrandBuffer, strand_index).x;
 	int strand_offset, strand_segments;
 	unpack_strand_data(strand_data, strand_offset, strand_segments);
 
-	int id = hair_get_base_id(local_time, strand_segments, interp_time);
+	float local_time = float(gl_VertexID - strand_offset) / float(strand_segments);
+	int interp_segment;
+	hair_get_interp_time(local_time, strand_segments, interp_segment, interp_time);
+	int interp_point = interp_segment + strand_offset;
 
-	int ofs_id = id + strand_offset;
+	data0 = texelFetch(hairPointBuffer, interp_point - 1);
+	data1 = texelFetch(hairPointBuffer, interp_point);
+	data2 = texelFetch(hairPointBuffer, interp_point + 1);
+	data3 = texelFetch(hairPointBuffer, interp_point + 2);
 
-	data0 = texelFetch(hairPointBuffer, ofs_id - 1);
-	data1 = texelFetch(hairPointBuffer, ofs_id);
-	data2 = texelFetch(hairPointBuffer, ofs_id + 1);
-	data3 = texelFetch(hairPointBuffer, ofs_id + 2);
-
-	if (id

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list