diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2017-08-03 10:11:48 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2017-08-03 10:11:48 +0300 |
commit | e34ba9fb7a91ef9be9109eaae5242cd4b3d7a22c (patch) | |
tree | a4a7dc27c038dcd6d67bc4e1c20b06740c97658a /source/blender/draw | |
parent | c92457a87ab0866111f2cdc8ad1e6b1777465675 (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/blender/draw')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 64 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/hair_lib.glsl | 40 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_strands.c | 25 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_hair.c | 59 |
6 files changed, 132 insertions, 67 deletions
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); +} |