[Bf-blender-cvs] [328f8dc21c0] blender2.8: DRW: Add new GPU hair system.

Clément Foucault noreply at git.blender.org
Wed May 30 12:25:33 CEST 2018


Commit: 328f8dc21c0e8a7e3da14f6578fb84a811f80b89
Author: Clément Foucault
Date:   Tue May 29 12:11:03 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB328f8dc21c0e8a7e3da14f6578fb84a811f80b89

DRW: Add new GPU hair system.

This new system use transform feedback to compute subdivided hair points
position. For now no smoothing is done between input points.

This new system decouple the strands data (uv, mcol) with the points
position, requiring less update work if only simulation is running.

In the future, we can have compute shader do the work of the feedback
transform pass since it's really what it's meant to. Also we could generate
the child particles during this pass, releasing some CPU time.

draw_hair.c has been created to handle all of the Shading group creations
as well as subdivision shaders.

We store one final batch per settings combination because multiple viewport
or render could use the same particle system with a different subdivision
count or hair shape type.

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/intern/draw_cache_impl_particles.c
M	source/blender/draw/intern/draw_common.h
A	source/blender/draw/intern/draw_hair.c
A	source/blender/draw/intern/draw_hair_private.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/intern/draw_manager_data.c
A	source/blender/draw/modes/shaders/common_hair_lib.glsl
A	source/blender/draw/modes/shaders/common_hair_refine_vert.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 965faa7ba53..96dd9356109 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -63,6 +63,7 @@ set(SRC
 	intern/draw_cache_impl_particles.c
 	intern/draw_common.c
 	intern/draw_debug.c
+	intern/draw_hair.c
 	intern/draw_instance_data.c
 	intern/draw_manager.c
 	intern/draw_manager_data.c
@@ -123,6 +124,7 @@ set(SRC
 	intern/draw_cache_impl.h
 	intern/draw_common.h
 	intern/draw_debug.h
+	intern/draw_hair_private.h
 	intern/draw_instance_data.h
 	intern/draw_manager.h
 	intern/draw_manager_text.h
@@ -234,6 +236,8 @@ data_to_c_simple(engines/workbench/shaders/workbench_shadow_debug_frag.glsl SRC)
 data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC)
 
 data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
+data_to_c_simple(modes/shaders/common_hair_lib.glsl SRC)
+data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC)
 data_to_c_simple(modes/shaders/common_view_lib.glsl SRC)
 data_to_c_simple(modes/shaders/common_fxaa_lib.glsl SRC)
 data_to_c_simple(modes/shaders/common_fullscreen_vert.glsl SRC)
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c
index c89ea67a39c..26b2efffc86 100644
--- a/source/blender/draw/intern/draw_cache_impl_particles.c
+++ b/source/blender/draw/intern/draw_cache_impl_particles.c
@@ -42,6 +42,7 @@
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_particle_types.h"
+#include "DNA_customdata_types.h"
 
 #include "BKE_mesh.h"
 #include "BKE_particle.h"
@@ -54,6 +55,7 @@
 #include "DEG_depsgraph_query.h"
 
 #include "draw_cache_impl.h"  /* own include */
+#include "draw_hair_private.h"
 
 static void particle_batch_cache_clear(ParticleSystem *psys);
 
@@ -67,14 +69,6 @@ typedef struct ParticlePointCache {
 	int point_count;
 } ParticlePointCache;
 
-typedef struct ParticleHairCache {
-	Gwn_VertBuf *pos;
-	Gwn_IndexBuf *indices;
-	Gwn_Batch *hairs;
-	int elems_count;
-	int point_count;
-} ParticleHairCache;
-
 typedef struct ParticleBatchCache {
 	/* Object mode strands for hair and points for particle,
 	 * strands for paths when in edit mode.
@@ -169,6 +163,30 @@ static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
 
 static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
 {
+	/* TODO more granular update tagging. */
+	GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
+	DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex);
+
+	GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf);
+	DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex);
+
+	for (int i = 0; i < MAX_MTFACE; ++i) {
+		GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]);
+		DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]);
+	}
+	for (int i = 0; i < MAX_MCOL; ++i) {
+		GWN_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]);
+		DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]);
+	}
+	for (int i = 0; i < MAX_HAIR_SUBDIV; ++i) {
+		GWN_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf);
+		DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex);
+		for (int j = 0; j < MAX_THICKRES - 1; ++j) {
+			GWN_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]);
+		}
+	}
+
+	/* "Normal" legacy hairs */
 	GWN_BATCH_DISCARD_SAFE(hair_cache->hairs);
 	GWN_VERTBUF_DISCARD_SAFE(hair_cache->pos);
 	GWN_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
@@ -185,6 +203,7 @@ static void particle_batch_cache_clear(ParticleSystem *psys)
 	particle_batch_cache_clear_hair(&cache->hair);
 
 	particle_batch_cache_clear_hair(&cache->edit_hair);
+
 	GWN_BATCH_DISCARD_SAFE(cache->edit_inner_points);
 	GWN_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
 	GWN_BATCH_DISCARD_SAFE(cache->edit_tip_points);
@@ -204,6 +223,7 @@ static void count_cache_segment_keys(ParticleCacheKey **pathcache,
 	for (int i = 0; i < num_path_cache_keys; i++) {
 		ParticleCacheKey *path = pathcache[i];
 		if (path->segments > 0) {
+			hair_cache->strands_count++;
 			hair_cache->elems_count += path->segments + 2;
 			hair_cache->point_count += path->segments + 1;
 		}
@@ -214,10 +234,12 @@ static void ensure_seg_pt_count(PTCacheEdit *edit,
                                 ParticleSystem *psys,
                                 ParticleHairCache *hair_cache)
 {
-	if (hair_cache->pos != NULL && hair_cache->indices != NULL) {
+	if ((hair_cache->pos != NULL && hair_cache->indices != NULL) ||
+		(hair_cache->proc_point_buf != NULL)) {
 		return;
 	}
 
+	hair_cache->strands_count = 0;
 	hair_cache->elems_count = 0;
 	hair_cache->point_count = 0;
 
@@ -237,6 +259,14 @@ static void ensure_seg_pt_count(PTCacheEdit *edit,
 	}
 }
 
+static void particle_pack_mcol(MCol *mcol, unsigned short r_scol[3])
+{
+	/* Convert to linear ushort and swizzle */
+	r_scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
+	r_scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
+	r_scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
+}
+
 /* Used by parent particles and simple children. */
 static void particle_calculate_parent_uvs(ParticleSystem *psys,
                                           ParticleSystemModifierData *psmd,
@@ -270,6 +300,38 @@ static void particle_calculate_parent_uvs(ParticleSystem *psys,
 	}
 }
 
+static void particle_calculate_parent_mcol(ParticleSystem *psys,
+                                           ParticleSystemModifierData *psmd,
+                                           const int num_uv_layers,
+                                           const int parent_index,
+                                           /*const*/ MCol **mcols,
+                                           MCol *r_mcol)
+{
+	if (psmd == NULL) {
+		return;
+	}
+	const int emit_from = psmd->psys->part->from;
+	if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+		return;
+	}
+	ParticleData *particle = &psys->particles[parent_index];
+	int num = particle->num_dmcache;
+	if (num == DMCACHE_NOTFOUND) {
+		if (particle->num < psmd->mesh_final->totface) {
+			num = particle->num;
+		}
+	}
+	if (num != DMCACHE_NOTFOUND) {
+		MFace *mface = &psmd->mesh_final->mface[num];
+		for (int j = 0; j < num_uv_layers; j++) {
+			psys_interpolate_mcol(mcols[j] + num,
+			                      mface->v4,
+			                      particle->fuv,
+			                      &r_mcol[j]);
+		}
+	}
+}
+
 /* Used by interpolated children. */
 static void particle_interpolate_children_uvs(ParticleSystem *psys,
                                               ParticleSystemModifierData *psmd,
@@ -290,8 +352,37 @@ static void particle_interpolate_children_uvs(ParticleSystem *psys,
 	if (num != DMCACHE_NOTFOUND) {
 		MFace *mface = &psmd->mesh_final->mface[num];
 		for (int j = 0; j < num_uv_layers; j++) {
-			psys_interpolate_uvs(
-			        mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]);
+			psys_interpolate_uvs(mtfaces[j] + num,
+			                     mface->v4,
+			                     particle->fuv,
+			                     r_uv[j]);
+		}
+	}
+}
+
+static void particle_interpolate_children_mcol(ParticleSystem *psys,
+                                               ParticleSystemModifierData *psmd,
+                                               const int num_col_layers,
+                                               const int child_index,
+                                               /*const*/ MCol **mcols,
+                                               MCol *r_mcol)
+{
+	if (psmd == NULL) {
+		return;
+	}
+	const int emit_from = psmd->psys->part->from;
+	if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+		return;
+	}
+	ChildParticle *particle = &psys->child[child_index];
+	int num = particle->num;
+	if (num != DMCACHE_NOTFOUND) {
+		MFace *mface = &psmd->mesh_final->mface[num];
+		for (int j = 0; j < num_col_layers; j++) {
+			psys_interpolate_mcol(mcols[j] + num,
+			                      mface->v4,
+			                      particle->fuv,
+			                      &r_mcol[j]);
 		}
 	}
 }
@@ -342,6 +433,52 @@ static void particle_calculate_uvs(ParticleSystem *psys,
 	}
 }
 
+static void particle_calculate_mcol(ParticleSystem *psys,
+                                    ParticleSystemModifierData *psmd,
+                                    const bool is_simple,
+                                    const int num_col_layers,
+                                    const int parent_index,
+                                    const int child_index,
+                                    /*const*/ MCol **mcols,
+                                    MCol **r_parent_mcol,
+                                    MCol **r_mcol)
+{
+	if (psmd == NULL) {
+		return;
+	}
+	if (is_simple) {
+		if (r_parent_mcol[parent_index] != NULL) {
+			*r_mcol = r_parent_mcol[parent_index];
+		}
+		else {
+			*r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol");
+		}
+	}
+	else {
+		*r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol");
+	}
+	if (child_index == -1) {
+		/* Calculate MCols for parent particles. */
+		if (is_simple) {
+			r_parent_mcol[parent_index] = *r_mcol;
+		}
+		particle_calculate_parent_mcol(
+		        psys, psmd, num_col_layers, parent_index, mcols, *r_mcol);
+	}
+	else {
+		/* Calculate MCols for child particles. */
+		if (!is_simple) {
+			particle_interpolate_children_mcol(
+			        psys, psmd, num_col_layers, child_index, mcols, *r_mcol);
+		}
+		else if (!r_parent_mcol[psys->child[child_index].parent]) {
+			r_parent_mcol[psys->child[child_index].parent] = *r_mcol;
+			particle_calculate_parent_mcol(
+			        psys, psmd, num_col_layers, parent_index, mcols, *r_mcol);
+		}
+	}
+}
+
 /* Will return last filled index. */
 typedef enum ParticleSource {
 	PARTICLE_SOURCE_PARENT,
@@ -356,9 +493,13 @@ static int particle_batch_cache_fill_segments(
         const int start_index,
         const int num_path_keys,
         const int num_uv_layers,
+        const int num_col_layers,
         /*const*/ MTFace **mtfaces,
+        /*const*/ MCol **mcols,
         uint *uv_id,
+        uint *col_id,
         float (***r_parent_uvs)[2],
+        MCol ***r_parent_mcol,
         Gwn

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list