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
path: root/source
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2017-08-03 10:11:48 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2017-08-03 10:11:48 +0300
commite34ba9fb7a91ef9be9109eaae5242cd4b3d7a22c (patch)
treea4a7dc27c038dcd6d67bc4e1c20b06740c97658a /source
parentc92457a87ab0866111f2cdc8ad1e6b1777465675 (diff)
Use a 2D texture for the hair interpolation data instead of 1D for larger number of hairs.
It turns out that 1D textures have the same size limit on their 1 axis as 2D textures. This limits the potential number of hair dramatically, even though the actual size of the texture is very small. Using a 2D texture and wrapping the index avoids this problem.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_editstrands.h9
-rw-r--r--source/blender/blenkernel/BKE_hair.h6
-rw-r--r--source/blender/blenkernel/intern/editstrands.c18
-rw-r--r--source/blender/blenkernel/intern/hair.c80
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c64
-rw-r--r--source/blender/draw/engines/eevee/shaders/hair_lib.glsl40
-rw-r--r--source/blender/draw/intern/draw_cache_impl_strands.c25
-rw-r--r--source/blender/draw/intern/draw_common.h10
-rw-r--r--source/blender/draw/intern/draw_hair.c59
10 files changed, 193 insertions, 119 deletions
diff --git a/source/blender/blenkernel/BKE_editstrands.h b/source/blender/blenkernel/BKE_editstrands.h
index 9199668fb9e..e5858160f65 100644
--- a/source/blender/blenkernel/BKE_editstrands.h
+++ b/source/blender/blenkernel/BKE_editstrands.h
@@ -85,10 +85,11 @@ bool BKE_editstrands_hair_ensure(struct BMEditStrands *es);
void BKE_editstrands_hair_free(struct BMEditStrands *es);
int* BKE_editstrands_hair_get_fiber_lengths(struct BMEditStrands *es);
-void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, void **texbuffer, int *r_size,
- int *strand_map_start,
- int *strand_vertex_start,
- int *fiber_start);
+void BKE_editstrands_hair_get_texture_buffer_size(struct BMEditStrands *es, int *r_size,
+ int *r_strand_map_start,
+ int *r_strand_vertex_start,
+ int *r_fiber_start);
+void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, void *texbuffer);
/* === Constraints === */
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 4169a3b6f16..5eafc14e66f 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -68,9 +68,11 @@ struct HairFiber* BKE_hair_fibers_create(const struct StrandsView *strands,
int* BKE_hair_get_fiber_lengths(const struct HairFiber *fibers, int totfibers,
const struct StrandsView *strands);
+void BKE_hair_get_texture_buffer_size(const struct StrandsView *strands, int totfibers,
+ int *r_size, int *r_strand_map_start,
+ int *r_strand_vertex_start, int *r_fiber_start);
void BKE_hair_get_texture_buffer(const struct StrandsView *strands, struct DerivedMesh *scalp,
const struct HairFiber *fibers, int totfibers,
- void **r_texbuffer, int *r_size, int *r_strand_map_start,
- int *r_strand_vertex_start, int *r_fiber_start);
+ void *texbuffer);
#endif
diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index 16e47aabf91..0fe286a5d3a 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -239,14 +239,20 @@ int* BKE_editstrands_hair_get_fiber_lengths(BMEditStrands *es)
return BKE_hair_get_fiber_lengths(es->hair_fibers, es->hair_totfibers, &strands.base);
}
-void BKE_editstrands_hair_get_texture_buffer(BMEditStrands *es, void **r_texbuffer, int *r_size,
- int *r_strand_map_start,
- int *r_strand_vertex_start,
- int *r_fiber_start)
+void BKE_editstrands_hair_get_texture_buffer_size(BMEditStrands *es, int *r_size,
+ int *r_strand_map_start,
+ int *r_strand_vertex_start,
+ int *r_fiber_start)
{
EditStrandsView strands = editstrands_get_view(es);
- BKE_hair_get_texture_buffer(&strands.base, es->root_dm, es->hair_fibers, es->hair_totfibers,
- r_texbuffer, r_size, r_strand_map_start, r_strand_vertex_start, r_fiber_start);
+ BKE_hair_get_texture_buffer_size(&strands.base, es->hair_totfibers,
+ r_size, r_strand_map_start, r_strand_vertex_start, r_fiber_start);
+}
+
+void BKE_editstrands_hair_get_texture_buffer(BMEditStrands *es, void *texbuffer)
+{
+ EditStrandsView strands = editstrands_get_view(es);
+ BKE_hair_get_texture_buffer(&strands.base, es->root_dm, es->hair_fibers, es->hair_totfibers, texbuffer);
}
/* === Constraints === */
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 838956ea843..59677a25bc1 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -374,60 +374,60 @@ static void hair_get_fiber_buffer(const HairFiber *fibers, int totfibers, Derive
}
}
+void BKE_hair_get_texture_buffer_size(const StrandsView *strands, int totfibers,
+ int *r_size, int *r_strand_map_start,
+ int *r_strand_vertex_start, int *r_fiber_start)
+{
+ const int totstrands = strands->get_num_strands(strands);
+ const int totverts = strands->get_num_verts(strands);
+ *r_strand_map_start = 0;
+ *r_strand_vertex_start = *r_strand_map_start + totstrands * sizeof(HairStrandMapTextureBuffer);
+ *r_fiber_start = *r_strand_vertex_start + totverts * sizeof(HairStrandVertexTextureBuffer);
+ *r_size = *r_fiber_start + totfibers * sizeof(HairFiberTextureBuffer);
+}
+
void BKE_hair_get_texture_buffer(const StrandsView *strands, DerivedMesh *scalp,
const HairFiber *fibers, int totfibers,
- void **r_texbuffer, int *r_size, int *r_strand_map_start,
- int *r_strand_vertex_start, int *r_fiber_start)
+ void *buffer)
{
const int totstrands = strands->get_num_strands(strands);
const int totverts = strands->get_num_verts(strands);
const int strand_map_start = 0;
const int strand_vertex_start = strand_map_start + totstrands * sizeof(HairStrandMapTextureBuffer);
const int fiber_start = strand_vertex_start + totverts * sizeof(HairStrandVertexTextureBuffer);
- const int size = fiber_start + totfibers * sizeof(HairFiberTextureBuffer);
- void *buffer = MEM_mallocN(size, "hair texture buffer");
+ int *lengths = MEM_mallocN(sizeof(int) * totstrands, "strand lengths");
+ MeshSample *roots = MEM_mallocN(sizeof(MeshSample) * totstrands, "strand roots");
+ float (*positions)[3] = MEM_mallocN(sizeof(float[3]) * totverts, "strand vertex positions");
- {
- int *lengths = MEM_mallocN(sizeof(int) * totstrands, "strand lengths");
- MeshSample *roots = MEM_mallocN(sizeof(MeshSample) * totstrands, "strand roots");
- float (*positions)[3] = MEM_mallocN(sizeof(float[3]) * totverts, "strand vertex positions");
-
- strands->get_strand_lengths(strands, lengths);
- strands->get_strand_roots(strands, roots);
- strands->get_strand_vertices(strands, positions);
+ strands->get_strand_lengths(strands, lengths);
+ strands->get_strand_roots(strands, roots);
+ strands->get_strand_vertices(strands, positions);
+
+ HairStrandMapTextureBuffer *smap = (HairStrandMapTextureBuffer*)((char*)buffer + strand_map_start);
+ HairStrandVertexTextureBuffer *svert = (HairStrandVertexTextureBuffer*)((char*)buffer + strand_vertex_start);
+ unsigned int vertex_start = 0;
+ for (int i = 0; i < totstrands; ++i) {
+ const unsigned int len = lengths[i];
+ smap->vertex_start = vertex_start;
+ smap->vertex_count = len;
- HairStrandMapTextureBuffer *smap = (HairStrandMapTextureBuffer*)((char*)buffer + strand_map_start);
- HairStrandVertexTextureBuffer *svert = (HairStrandVertexTextureBuffer*)((char*)buffer + strand_vertex_start);
- unsigned int vertex_start = 0;
- for (int i = 0; i < totstrands; ++i) {
- const unsigned int len = lengths[i];
- smap->vertex_start = vertex_start;
- smap->vertex_count = len;
-
- {
- float pos[3];
- float matrix[3][3];
- BKE_mesh_sample_eval(scalp, &roots[i], pos, matrix[2], matrix[0]);
- cross_v3_v3v3(matrix[1], matrix[2], matrix[0]);
- hair_strand_calc_verts(positions + vertex_start, len, matrix, svert);
- }
-
- vertex_start += len;
- ++smap;
- svert += len;
+ {
+ float pos[3];
+ float matrix[3][3];
+ BKE_mesh_sample_eval(scalp, &roots[i], pos, matrix[2], matrix[0]);
+ cross_v3_v3v3(matrix[1], matrix[2], matrix[0]);
+ hair_strand_calc_verts(positions + vertex_start, len, matrix, svert);
}
- MEM_freeN(lengths);
- MEM_freeN(roots);
- MEM_freeN(positions);
+ vertex_start += len;
+ ++smap;
+ svert += len;
}
- hair_get_fiber_buffer(fibers, totfibers, scalp, (HairFiberTextureBuffer*)((char*)buffer + fiber_start));
+ MEM_freeN(lengths);
+ MEM_freeN(roots);
+ MEM_freeN(positions);
- *r_strand_map_start = strand_map_start;
- *r_strand_vertex_start = strand_vertex_start;
- *r_fiber_start = fiber_start;
- *r_texbuffer = buffer;
- *r_size = size;
+ hair_get_fiber_buffer(fibers, totfibers, scalp, (HairFiberTextureBuffer*)((char*)buffer + fiber_start));
}
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index b4527361615..1fada0e6f93 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -62,6 +62,7 @@ set(SRC
intern/draw_cache_impl_particles.c
intern/draw_cache_impl_strands.c
intern/draw_common.c
+ intern/draw_hair.c
intern/draw_manager.c
intern/draw_manager_text.c
intern/draw_view.c
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 1c937cac92e..a50b5b62e62 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -196,7 +196,7 @@ static char *eevee_get_defines(int options)
BLI_dynstr_appendf(ds, "#define HAIR_SHADER\n");
}
if ((options & VAR_MAT_HAIR_FIBERS) != 0) {
- BLI_dynstr_appendf(ds, "#define HAIR_SHADER_FIBERS\n");
+ BLI_dynstr_append(ds, DRW_hair_shader_defines());
}
if ((options & VAR_MAT_PROBE) != 0) {
BLI_dynstr_appendf(ds, "#define PROBE_CAPTURE\n");
@@ -381,12 +381,15 @@ void EEVEE_materials_init(EEVEE_StorageList *stl)
"#define CLIP_PLANES\n");
e_data.default_prepass_hair_fiber_sh = DRW_shader_create(
- hair_fiber_vert_str, NULL, datatoc_prepass_frag_glsl,
- "#define HAIR_SHADER\n#define HAIR_SHADER_FIBERS\n");
+ hair_fiber_vert_str, NULL, datatoc_prepass_frag_glsl, DRW_hair_shader_defines());
- e_data.default_prepass_hair_fiber_clip_sh = DRW_shader_create(
- hair_fiber_vert_str, NULL, datatoc_prepass_frag_glsl,
- "#define HAIR_SHADER\n#define HAIR_SHADER_FIBERS\n#define CLIP_PLANES\n");
+ {
+ char defines[256];
+ BLI_snprintf(defines, sizeof(defines), "#define CLIP_PLANES\n%s",
+ DRW_hair_shader_defines());
+ e_data.default_prepass_hair_fiber_clip_sh = DRW_shader_create(
+ hair_fiber_vert_str, NULL, datatoc_prepass_frag_glsl, defines);
+ }
MEM_freeN(frag_str);
MEM_freeN(hair_fiber_vert_str);
@@ -1122,11 +1125,8 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
bool use_fibers = false;
float mat[4][4];
struct Gwn_Batch *hair_geom = NULL;
+ const DRWHairFiberTextureBuffer *fiber_buffer = NULL;
GPUTexture **fiber_texture = NULL;
- const float *ribbon_width = NULL;
- const int *strand_map_start = NULL;
- const int *strand_vertex_start = NULL;
- const int *fiber_start = NULL;
if (ob->mode & OB_MODE_HAIR_EDIT) {
BMEditStrands *edit = psys->hairedit;
@@ -1136,16 +1136,12 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
use_fibers = true;
copy_m4_m4(mat, ob->obmat);
- const DRWHairFiberTextureBuffer *buffer = NULL;
- hair_geom = DRW_cache_editstrands_get_hair_fibers(edit, true, &buffer);
+ hair_geom = DRW_cache_editstrands_get_hair_fibers(edit, true, &fiber_buffer);
+
if (!edit->texture) {
- edit->texture = DRW_texture_create_1D(buffer->size, DRW_TEX_RG_32, 0, buffer->data);
+ edit->texture = DRW_texture_create_2D(fiber_buffer->width, fiber_buffer->height,
+ DRW_TEX_RG_32, 0, fiber_buffer->data);
}
-
- ribbon_width = &tsettings->hair_draw_size;
- strand_map_start = &buffer->strand_map_start;
- strand_vertex_start = &buffer->strand_vertex_start;
- fiber_start = &buffer->fiber_start;
fiber_texture = (GPUTexture **)(&edit->texture);
}
}
@@ -1169,24 +1165,13 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
DRW_shgroup_call_add(stl->g_data->depth_shgrp_clip, hair_geom, mat);
}
else {
- DRWShadingGroup *depth_shgrp = stl->g_data->depth_shgrp_hair_fibers;
- DRWShadingGroup *depth_clip_shgrp = stl->g_data->depth_shgrp_hair_fibers_clip;
- DRW_shgroup_call_add(depth_shgrp, hair_geom, mat);
- DRW_shgroup_call_add(depth_clip_shgrp, hair_geom, mat);
-
- DRW_shgroup_uniform_vec2(depth_shgrp, "viewport_size", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_vec2(depth_clip_shgrp, "viewport_size", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_float(depth_shgrp, "ribbon_width", ribbon_width, 1);
- DRW_shgroup_uniform_float(depth_clip_shgrp, "ribbon_width", ribbon_width, 1);
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp_hair_fibers, hair_geom, mat);
+ DRW_hair_shader_uniforms(stl->g_data->depth_shgrp_hair_fibers, scene,
+ fiber_texture, fiber_buffer);
- DRW_shgroup_uniform_buffer(depth_shgrp, "strand_data", fiber_texture);
- DRW_shgroup_uniform_buffer(depth_clip_shgrp, "strand_data", fiber_texture);
- DRW_shgroup_uniform_int(depth_shgrp, "strand_map_start", strand_map_start, 1);
- DRW_shgroup_uniform_int(depth_clip_shgrp, "strand_map_start", strand_map_start, 1);
- DRW_shgroup_uniform_int(depth_shgrp, "strand_vertex_start", strand_vertex_start, 1);
- DRW_shgroup_uniform_int(depth_clip_shgrp, "strand_vertex_start", strand_vertex_start, 1);
- DRW_shgroup_uniform_int(depth_shgrp, "fiber_start", fiber_start, 1);
- DRW_shgroup_uniform_int(depth_clip_shgrp, "fiber_start", fiber_start, 1);
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp_hair_fibers_clip, hair_geom, mat);
+ DRW_hair_shader_uniforms(stl->g_data->depth_shgrp_hair_fibers_clip, scene,
+ fiber_texture, fiber_buffer);
}
DRWShadingGroup *shgrp = BLI_ghash_lookup(material_hash, (const void *)ma);
@@ -1233,13 +1218,8 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
DRW_shgroup_call_add(shgrp, hair_geom, mat);
if (use_fibers) {
- DRW_shgroup_uniform_vec2(shgrp, "viewport_size", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_float(shgrp, "ribbon_width", ribbon_width, 1);
-
- DRW_shgroup_uniform_buffer(shgrp, "strand_data", fiber_texture);
- DRW_shgroup_uniform_int(shgrp, "strand_map_start", strand_map_start, 1);
- DRW_shgroup_uniform_int(shgrp, "strand_vertex_start", strand_vertex_start, 1);
- DRW_shgroup_uniform_int(shgrp, "fiber_start", fiber_start, 1);
+ DRW_hair_shader_uniforms(shgrp, scene,
+ fiber_texture, fiber_buffer);
}
}
}
diff --git a/source/blender/draw/engines/eevee/shaders/hair_lib.glsl b/source/blender/draw/engines/eevee/shaders/hair_lib.glsl
index 430fee1bc2c..4cbf69e1074 100644
--- a/source/blender/draw/engines/eevee/shaders/hair_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/hair_lib.glsl
@@ -1,8 +1,8 @@
-#ifdef HAIR_SHADER
+#ifdef HAIR_SHADER_FIBERS
#define FIBER_RIBBON
-uniform sampler1D strand_data;
+uniform sampler2D strand_data;
uniform int strand_map_start;
uniform int strand_vertex_start;
uniform int fiber_start;
@@ -13,6 +13,12 @@ uniform vec2 viewport_size;
#define INDEX_INVALID -1
+vec2 read_texdata(int offset)
+{
+ ivec2 offset2 = ivec2(offset % HAIR_SHADER_TEX_WIDTH, offset / HAIR_SHADER_TEX_WIDTH);
+ return texelFetch(strand_data, offset2, 0).rg;
+}
+
mat3 mat3_from_vectors(vec3 nor, vec3 tang)
{
tang = normalize(tang);
@@ -23,7 +29,7 @@ mat3 mat3_from_vectors(vec3 nor, vec3 tang)
void get_strand_data(int index, out int start, out int count)
{
int offset = strand_map_start + index;
- vec4 a = texelFetch(strand_data, offset, 0);
+ vec2 a = read_texdata(offset);
start = floatBitsToInt(a.r);
count = floatBitsToInt(a.g);
@@ -32,11 +38,11 @@ void get_strand_data(int index, out int start, out int count)
void get_strand_vertex(int index, out vec3 co, out vec3 nor, out vec3 tang)
{
int offset = strand_vertex_start + index * 5;
- vec4 a = texelFetch(strand_data, offset, 0);
- vec4 b = texelFetch(strand_data, offset + 1, 0);
- vec4 c = texelFetch(strand_data, offset + 2, 0);
- vec4 d = texelFetch(strand_data, offset + 3, 0);
- vec4 e = texelFetch(strand_data, offset + 4, 0);
+ vec2 a = read_texdata(offset);
+ vec2 b = read_texdata(offset + 1);
+ vec2 c = read_texdata(offset + 2);
+ vec2 d = read_texdata(offset + 3);
+ vec2 e = read_texdata(offset + 4);
co = vec3(a.rg, b.r);
nor = vec3(b.g, c.rg);
@@ -46,8 +52,8 @@ void get_strand_vertex(int index, out vec3 co, out vec3 nor, out vec3 tang)
void get_strand_root(int index, out vec3 co)
{
int offset = strand_vertex_start + index * 5;
- vec4 a = texelFetch(strand_data, offset, 0);
- vec4 b = texelFetch(strand_data, offset + 1, 0);
+ vec2 a = read_texdata(offset);
+ vec2 b = read_texdata(offset + 1);
co = vec3(a.rg, b.r);
}
@@ -55,12 +61,12 @@ void get_strand_root(int index, out vec3 co)
void get_fiber_data(int fiber_index, out ivec4 parent_index, out vec4 parent_weight, out vec3 pos)
{
int offset = fiber_start + fiber_index * 6;
- vec4 a = texelFetch(strand_data, offset, 0);
- vec4 b = texelFetch(strand_data, offset + 1, 0);
- vec4 c = texelFetch(strand_data, offset + 2, 0);
- vec4 d = texelFetch(strand_data, offset + 3, 0);
- vec4 e = texelFetch(strand_data, offset + 4, 0);
- vec4 f = texelFetch(strand_data, offset + 5, 0);
+ vec2 a = read_texdata(offset);
+ vec2 b = read_texdata(offset + 1);
+ vec2 c = read_texdata(offset + 2);
+ vec2 d = read_texdata(offset + 3);
+ vec2 e = read_texdata(offset + 4);
+ vec2 f = read_texdata(offset + 5);
parent_index = ivec4(floatBitsToInt(a.rg), floatBitsToInt(b.rg));
parent_weight = vec4(c.rg, d.rg);
@@ -168,4 +174,4 @@ void hair_fiber_get_vertex(int fiber_index, float curve_param, mat4 ModelViewMat
#endif
}
-#endif /*HAIR_SHADER*/
+#endif /*HAIR_SHADER_FIBERS*/
diff --git a/source/blender/draw/intern/draw_cache_impl_strands.c b/source/blender/draw/intern/draw_cache_impl_strands.c
index bf3f8b02365..2d57d7e20ac 100644
--- a/source/blender/draw/intern/draw_cache_impl_strands.c
+++ b/source/blender/draw/intern/draw_cache_impl_strands.c
@@ -40,6 +40,7 @@
#include "BKE_editstrands.h"
#include "GPU_batch.h"
+#include "GPU_extensions.h"
#include "GPU_texture.h"
#include "draw_common.h"
@@ -163,7 +164,8 @@ static void editstrands_batch_cache_clear_hair(BMEditStrands *es)
buffer->fiber_start = 0;
buffer->strand_map_start = 0;
buffer->strand_vertex_start = 0;
- buffer->size = 0;
+ buffer->width = 0;
+ buffer->height = 0;
}
}
}
@@ -447,17 +449,26 @@ static void editstrands_batch_cache_ensure_hair_fibers(BMEditStrands *es, Strand
static void editstrands_batch_cache_ensure_hair_fiber_texbuffer(BMEditStrands *es, StrandsBatchCache *cache, bool UNUSED(use_ribbons))
{
DRWHairFiberTextureBuffer *buffer = &cache->hair.texbuffer;
+ static const int elemsize = 8;
+ const int width = GPU_max_texture_size();
+ const int align = width * elemsize;
- void *data;
// Offsets in bytes
int b_size, b_strand_map_start, b_strand_vertex_start, b_fiber_start;
- BKE_editstrands_hair_get_texture_buffer(es, &data, &b_size,
- &b_strand_map_start, &b_strand_vertex_start, &b_fiber_start);
+ BKE_editstrands_hair_get_texture_buffer_size(es, &b_size,
+ &b_strand_map_start, &b_strand_vertex_start, &b_fiber_start);
+ // Pad for alignment
+ b_size += align - b_size % align;
- buffer->data = data;
// Convert to element size as texture offsets
- static const int elemsize = 8;
- buffer->size = b_size / elemsize;
+ const int size = b_size / elemsize;
+ const int height = size / width;
+
+ buffer->data = MEM_mallocN(b_size, "hair fiber texture buffer");
+ BKE_editstrands_hair_get_texture_buffer(es, buffer->data);
+
+ buffer->width = width;
+ buffer->height = height;
buffer->strand_map_start = b_strand_map_start / elemsize;
buffer->strand_vertex_start = b_strand_vertex_start / elemsize;
buffer->fiber_start = b_fiber_start / elemsize;
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index b7b591da918..c9f3629dc18 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -29,7 +29,9 @@
struct DRWPass;
struct DRWShadingGroup;
struct Gwn_Batch;
+struct GPUTexture;
struct Object;
+struct Scene;
struct SceneLayer;
/* Used as ubo but colors can be directly referenced as well */
@@ -134,7 +136,13 @@ typedef struct DRWHairFiberTextureBuffer {
int strand_map_start;
int strand_vertex_start;
int fiber_start;
- int size;
+ int width;
+ int height;
} DRWHairFiberTextureBuffer;
+const char* DRW_hair_shader_defines(void);
+
+void DRW_hair_shader_uniforms(struct DRWShadingGroup *shgrp, struct Scene *scene,
+ struct GPUTexture **fibertex, const struct DRWHairFiberTextureBuffer *texbuffer);
+
#endif /* __DRAW_COMMON_H__ */
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
new file mode 100644
index 00000000000..0a357518381
--- /dev/null
+++ b/source/blender/draw/intern/draw_hair.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_hair.c
+ * \ingroup draw
+ */
+
+#include "DNA_scene_types.h"
+
+#include "DRW_render.h"
+
+#include "BLI_utildefines.h"
+
+#include "GPU_extensions.h"
+#include "GPU_texture.h"
+
+#include "draw_common.h"
+
+const char* DRW_hair_shader_defines(void)
+{
+ static char str[256];
+
+ BLI_snprintf(str, sizeof(str), "#define HAIR_SHADER_FIBERS\n#define HAIR_SHADER_TEX_WIDTH %d\n",
+ GPU_max_texture_size());
+
+ return str;
+}
+
+void DRW_hair_shader_uniforms(DRWShadingGroup *shgrp, Scene *scene,
+ GPUTexture **fibertex, const DRWHairFiberTextureBuffer *texbuffer)
+{
+ const HairEditSettings *tsettings = &scene->toolsettings->hair_edit;
+
+ DRW_shgroup_uniform_vec2(shgrp, "viewport_size", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_float(shgrp, "ribbon_width", &tsettings->hair_draw_size, 1);
+
+ DRW_shgroup_uniform_buffer(shgrp, "strand_data", fibertex);
+ DRW_shgroup_uniform_int(shgrp, "strand_map_start", &texbuffer->strand_map_start, 1);
+ DRW_shgroup_uniform_int(shgrp, "strand_vertex_start", &texbuffer->strand_vertex_start, 1);
+ DRW_shgroup_uniform_int(shgrp, "fiber_start", &texbuffer->fiber_start, 1);
+}