Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-08-12 12:33:21 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-08-12 12:33:21 +0300
commitf854fefa1796429907c2574ba414335eb5519714 (patch)
treece6c9132972336c2c8e0db3ed383f4bd38a82112
parentb60dcd85f9182117d097a54b667264f9acb8ccf2 (diff)
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.
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl3
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c54
-rw-r--r--source/blender/draw/intern/draw_hair.c6
-rw-r--r--source/blender/draw/intern/draw_hair_private.h4
-rw-r--r--source/blender/draw/modes/shaders/common_hair_lib.glsl70
5 files changed, 92 insertions, 45 deletions
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
@@ -6,13 +6,6 @@
**/
/**
- * 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.
* 2 - Polystrip Hair: Correct width, flat if camera is parallel.
@@ -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 <= 0) {
+ if (interp_segment <= 0) {
/* root points. Need to reconstruct previous data. */
data0 = data1 * 2.0 - data2;
}
- if (id + 1 >= strand_segments) {
+ if (interp_segment + 1 >= strand_segments) {
/* tip points. Need to reconstruct next data. */
data3 = data2 * 2.0 - data1;
}
@@ -105,11 +106,6 @@ void hair_get_interp_attribs(out vec4 data0, out vec4 data1, out vec4 data2, out
**/
#ifndef HAIR_PHASE_SUBDIV
-int hair_get_strand_id(void)
-{
- return gl_VertexID / (hairStrandsRes * hairThicknessRes);
-}
-
int hair_get_base_id(void)
{
return gl_VertexID / hairThicknessRes;
@@ -165,25 +161,25 @@ void hair_get_pos_tan_binor_time(
vec2 hair_get_customdata_vec2(const samplerBuffer cd_buf)
{
- int id = hair_get_strand_id();
- return texelFetch(cd_buf, id).rg;
+ int strand_index = hair_get_strand_id();
+ return texelFetch(cd_buf, strand_index).rg;
}
vec3 hair_get_customdata_vec3(const samplerBuffer cd_buf)
{
- int id = hair_get_strand_id();
- return texelFetch(cd_buf, id).rgb;
+ int strand_index = hair_get_strand_id();
+ return texelFetch(cd_buf, strand_index).rgb;
}
vec4 hair_get_customdata_vec4(const samplerBuffer cd_buf)
{
- int id = hair_get_strand_id();
- return texelFetch(cd_buf, id).rgba;
+ int strand_index = hair_get_strand_id();
+ return texelFetch(cd_buf, strand_index).rgba;
}
-vec3 hair_get_strand_pos(void)
+vec3 hair_get_strand_pos()
{
- int id = hair_get_strand_id() * hairStrandsRes;
+ int id = hair_get_base_id();
return texelFetch(hairPointBuffer, id).point_position;
}