diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/draw/intern/draw_hair.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/draw/intern/draw_hair.c')
-rw-r--r-- | source/blender/draw/intern/draw_hair.c | 421 |
1 files changed, 215 insertions, 206 deletions
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 6c1e44ac8e7..b3081a44dfb 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -34,7 +34,6 @@ #include "BKE_anim.h" - #include "GPU_batch.h" #include "GPU_shader.h" @@ -45,16 +44,16 @@ #endif typedef enum ParticleRefineShader { - PART_REFINE_CATMULL_ROM = 0, - PART_REFINE_MAX_SHADER, + PART_REFINE_CATMULL_ROM = 0, + PART_REFINE_MAX_SHADER, } ParticleRefineShader; #ifndef USE_TRANSFORM_FEEDBACK typedef struct ParticleRefineCall { - struct ParticleRefineCall *next; - GPUVertBuf *vbo; - DRWShadingGroup *shgrp; - uint vert_len; + struct ParticleRefineCall *next; + GPUVertBuf *vbo; + DRWShadingGroup *shgrp; + uint vert_len; } ParticleRefineCall; static ParticleRefineCall *g_tf_calls = NULL; @@ -72,248 +71,258 @@ extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]; static GPUShader *hair_refine_shader_get(ParticleRefineShader sh) { - if (g_refine_shaders[sh]) { - return g_refine_shaders[sh]; - } + if (g_refine_shaders[sh]) { + return g_refine_shaders[sh]; + } - char *vert_with_lib = BLI_string_joinN(datatoc_common_hair_lib_glsl, datatoc_common_hair_refine_vert_glsl); + char *vert_with_lib = BLI_string_joinN(datatoc_common_hair_lib_glsl, + datatoc_common_hair_refine_vert_glsl); #ifdef USE_TRANSFORM_FEEDBACK - const char *var_names[1] = {"finalColor"}; - g_refine_shaders[sh] = DRW_shader_create_with_transform_feedback(vert_with_lib, NULL, "#define HAIR_PHASE_SUBDIV\n", - GPU_SHADER_TFB_POINTS, var_names, 1); + const char *var_names[1] = {"finalColor"}; + g_refine_shaders[sh] = DRW_shader_create_with_transform_feedback( + vert_with_lib, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1); #else - g_refine_shaders[sh] = DRW_shader_create( - vert_with_lib, NULL, - datatoc_gpu_shader_3D_smooth_color_frag_glsl, - "#define HAIR_PHASE_SUBDIV\n" - "#define TF_WORKAROUND\n"); + g_refine_shaders[sh] = DRW_shader_create(vert_with_lib, + NULL, + datatoc_gpu_shader_3D_smooth_color_frag_glsl, + "#define HAIR_PHASE_SUBDIV\n" + "#define TF_WORKAROUND\n"); #endif - MEM_freeN(vert_with_lib); + MEM_freeN(vert_with_lib); - return g_refine_shaders[sh]; + return g_refine_shaders[sh]; } void DRW_hair_init(void) { #ifdef USE_TRANSFORM_FEEDBACK - g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_TRANS_FEEDBACK); + g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_TRANS_FEEDBACK); #else - g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_POINT); + g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_POINT); #endif } typedef struct DRWHairInstanceData { - DrawData dd; + DrawData dd; - float mat[4][4]; + float mat[4][4]; } DRWHairInstanceData; -static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex( - Object *object, ParticleSystem *psys, ModifierData *md, - DRWPass *hair_pass, - struct GPUMaterial *gpu_mat, GPUShader *gpu_shader) +static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, + ParticleSystem *psys, + ModifierData *md, + DRWPass *hair_pass, + struct GPUMaterial *gpu_mat, + GPUShader *gpu_shader) { - /* TODO(fclem): Pass the scene as parameter */ - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - static float unit_mat[4][4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, - }; - float (*dupli_mat)[4]; - Object *dupli_parent = DRW_object_get_dupli_parent(object); - DupliObject *dupli_object = DRW_object_get_dupli(object); - - int subdiv = scene->r.hair_subdiv; - int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; - - ParticleHairCache *hair_cache; - ParticleSettings *part = psys->part; - bool need_ft_update = particles_ensure_procedural_data(object, psys, md, &hair_cache, subdiv, thickness_res); - - DRWShadingGroup *shgrp; - if (gpu_mat) { - shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass); - } - else if (gpu_shader) { - shgrp = DRW_shgroup_create(gpu_shader, hair_pass); - } - else { - shgrp = NULL; - BLI_assert(0); - } - - /* TODO optimize this. Only bind the ones GPUMaterial needs. */ - for (int i = 0; i < hair_cache->num_uv_layers; ++i) { - for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; ++n) { - DRW_shgroup_uniform_texture(shgrp, hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]); - } - } - for (int i = 0; i < hair_cache->num_col_layers; ++i) { - for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->col_layer_names[i][n][0] != '\0'; ++n) { - DRW_shgroup_uniform_texture(shgrp, hair_cache->col_layer_names[i][n], hair_cache->col_tex[i]); - } - } - - if ((dupli_parent != NULL) && (dupli_object != NULL)) { - DRWHairInstanceData *hair_inst_data = (DRWHairInstanceData *)DRW_drawdata_ensure( - &object->id, (DrawEngineType *)&drw_shgroup_create_hair_procedural_ex, - sizeof(DRWHairInstanceData), NULL, NULL); - dupli_mat = hair_inst_data->mat; - if (dupli_object->type & OB_DUPLICOLLECTION) { - copy_m4_m4(dupli_mat, dupli_parent->obmat); - } - else { - copy_m4_m4(dupli_mat, dupli_object->ob->obmat); - invert_m4(dupli_mat); - mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); - } - } - else { - dupli_mat = unit_mat; - } - - DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex); - DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); - DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res); - DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1); - DRW_shgroup_uniform_mat4(shgrp, "hairDupliMatrix", dupli_mat); - DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f); - DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f); - DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0); - /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling test. */ - DRW_shgroup_call_object_add_no_cull(shgrp, hair_cache->final[subdiv].proc_hairs[thickness_res - 1], object); - - /* Transform Feedback subdiv. */ - if (need_ft_update) { - int final_points_len = hair_cache->final[subdiv].strands_res * hair_cache->strands_len; - GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); + /* TODO(fclem): Pass the scene as parameter */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + static float unit_mat[4][4] = { + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, + }; + float(*dupli_mat)[4]; + Object *dupli_parent = DRW_object_get_dupli_parent(object); + DupliObject *dupli_object = DRW_object_get_dupli(object); + + int subdiv = scene->r.hair_subdiv; + int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2; + + ParticleHairCache *hair_cache; + ParticleSettings *part = psys->part; + bool need_ft_update = particles_ensure_procedural_data( + object, psys, md, &hair_cache, subdiv, thickness_res); + + DRWShadingGroup *shgrp; + if (gpu_mat) { + shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass); + } + else if (gpu_shader) { + shgrp = DRW_shgroup_create(gpu_shader, hair_pass); + } + else { + shgrp = NULL; + BLI_assert(0); + } + + /* TODO optimize this. Only bind the ones GPUMaterial needs. */ + for (int i = 0; i < hair_cache->num_uv_layers; ++i) { + for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; ++n) { + DRW_shgroup_uniform_texture(shgrp, hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]); + } + } + for (int i = 0; i < hair_cache->num_col_layers; ++i) { + for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->col_layer_names[i][n][0] != '\0'; ++n) { + DRW_shgroup_uniform_texture( + shgrp, hair_cache->col_layer_names[i][n], hair_cache->col_tex[i]); + } + } + + if ((dupli_parent != NULL) && (dupli_object != NULL)) { + DRWHairInstanceData *hair_inst_data = (DRWHairInstanceData *)DRW_drawdata_ensure( + &object->id, + (DrawEngineType *)&drw_shgroup_create_hair_procedural_ex, + sizeof(DRWHairInstanceData), + NULL, + NULL); + dupli_mat = hair_inst_data->mat; + if (dupli_object->type & OB_DUPLICOLLECTION) { + copy_m4_m4(dupli_mat, dupli_parent->obmat); + } + else { + copy_m4_m4(dupli_mat, dupli_object->ob->obmat); + invert_m4(dupli_mat); + mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat); + } + } + else { + dupli_mat = unit_mat; + } + + DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex); + DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); + DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res); + DRW_shgroup_uniform_float(shgrp, "hairRadShape", &part->shape, 1); + DRW_shgroup_uniform_mat4(shgrp, "hairDupliMatrix", dupli_mat); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", part->rad_root * part->rad_scale * 0.5f); + DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", part->rad_tip * part->rad_scale * 0.5f); + DRW_shgroup_uniform_bool_copy( + shgrp, "hairCloseTip", (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0); + /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass culling test. */ + DRW_shgroup_call_object_add_no_cull( + shgrp, hair_cache->final[subdiv].proc_hairs[thickness_res - 1], object); + + /* Transform Feedback subdiv. */ + if (need_ft_update) { + int final_points_len = hair_cache->final[subdiv].strands_res * hair_cache->strands_len; + GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); #ifdef USE_TRANSFORM_FEEDBACK - DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, g_tf_pass, - hair_cache->final[subdiv].proc_buf); + DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( + tf_shader, g_tf_pass, hair_cache->final[subdiv].proc_buf); #else - DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); - - ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); - pr_call->next = g_tf_calls; - pr_call->vbo = hair_cache->final[subdiv].proc_buf; - pr_call->shgrp = tf_shgrp; - pr_call->vert_len = final_points_len; - g_tf_calls = pr_call; - DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); - DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); - DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); + DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); + + ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); + pr_call->next = g_tf_calls; + pr_call->vbo = hair_cache->final[subdiv].proc_buf; + pr_call->shgrp = tf_shgrp; + pr_call->vert_len = final_points_len; + g_tf_calls = pr_call; + DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); + DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); + DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); #endif - 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_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex); - DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); - DRW_shgroup_call_procedural_points_add(tf_shgrp, final_points_len, NULL); - } + 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_texture(tf_shgrp, "hairStrandSegBuffer", hair_cache->strand_seg_tex); + DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1); + DRW_shgroup_call_procedural_points_add(tf_shgrp, final_points_len, NULL); + } - return shgrp; + return shgrp; } DRWShadingGroup *DRW_shgroup_hair_create( - Object *object, ParticleSystem *psys, ModifierData *md, - DRWPass *hair_pass, - GPUShader *shader) + Object *object, ParticleSystem *psys, ModifierData *md, DRWPass *hair_pass, GPUShader *shader) { - return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, shader); + return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, shader); } -DRWShadingGroup *DRW_shgroup_material_hair_create( - Object *object, ParticleSystem *psys, ModifierData *md, - DRWPass *hair_pass, - struct GPUMaterial *material) +DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object, + ParticleSystem *psys, + ModifierData *md, + DRWPass *hair_pass, + struct GPUMaterial *material) { - return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, material, NULL); + return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, material, NULL); } void DRW_hair_update(void) { #ifndef USE_TRANSFORM_FEEDBACK - /** - * Workaround to tranform feedback not working on mac. - * On some system it crashes (see T58489) and on some other it renders garbage (see T60171). - * - * So instead of using transform feedback we render to a texture, - * readback the result to system memory and reupload as VBO data. - * It is really not ideal performance wise, but it is the simplest - * and the most local workaround that still uses the power of the GPU. - */ - - if (g_tf_calls == NULL) { - return; - } - - /* Search ideal buffer size. */ - uint max_size = 0; - for (ParticleRefineCall *pr_call = g_tf_calls; pr_call; pr_call = pr_call->next) { - max_size = max_ii(max_size, pr_call->vert_len); - } - - /* Create target Texture / Framebuffer */ - /* Don't use max size as it can be really heavy and fail. - * Do chunks of maximum 2048 * 2048 hair points. */ - int width = 2048; - int height = min_ii(width, 1 + max_size / width); - GPUTexture *tex = DRW_texture_pool_query_2d(width, height, GPU_RGBA32F, (void *)DRW_hair_update); - g_tf_target_height = height; - g_tf_target_width = width; - - GPUFrameBuffer *fb = NULL; - GPU_framebuffer_ensure_config(&fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(tex), - }); - - float *data = MEM_mallocN(sizeof(float) * 4 * width * height, "tf fallback buffer"); - - GPU_framebuffer_bind(fb); - while (g_tf_calls != NULL) { - ParticleRefineCall *pr_call = g_tf_calls; - g_tf_calls = g_tf_calls->next; - - g_tf_id_offset = 0; - while (pr_call->vert_len > 0) { - int max_read_px_len = min_ii(width * height, pr_call->vert_len); - - DRW_draw_pass_subset(g_tf_pass, pr_call->shgrp, pr_call->shgrp); - /* Readback result to main memory. */ - GPU_framebuffer_read_color(fb, 0, 0, width, height, 4, 0, data); - /* Upload back to VBO. */ - GPU_vertbuf_use(pr_call->vbo); - glBufferSubData(GL_ARRAY_BUFFER, - sizeof(float) * 4 * g_tf_id_offset, - sizeof(float) * 4 * max_read_px_len, - data); - - g_tf_id_offset += max_read_px_len; - pr_call->vert_len -= max_read_px_len; - } - - MEM_freeN(pr_call); - } - - MEM_freeN(data); - GPU_framebuffer_free(fb); + /** + * Workaround to tranform feedback not working on mac. + * On some system it crashes (see T58489) and on some other it renders garbage (see T60171). + * + * So instead of using transform feedback we render to a texture, + * readback the result to system memory and reupload as VBO data. + * It is really not ideal performance wise, but it is the simplest + * and the most local workaround that still uses the power of the GPU. + */ + + if (g_tf_calls == NULL) { + return; + } + + /* Search ideal buffer size. */ + uint max_size = 0; + for (ParticleRefineCall *pr_call = g_tf_calls; pr_call; pr_call = pr_call->next) { + max_size = max_ii(max_size, pr_call->vert_len); + } + + /* Create target Texture / Framebuffer */ + /* Don't use max size as it can be really heavy and fail. + * Do chunks of maximum 2048 * 2048 hair points. */ + int width = 2048; + int height = min_ii(width, 1 + max_size / width); + GPUTexture *tex = DRW_texture_pool_query_2d(width, height, GPU_RGBA32F, (void *)DRW_hair_update); + g_tf_target_height = height; + g_tf_target_width = width; + + GPUFrameBuffer *fb = NULL; + GPU_framebuffer_ensure_config(&fb, + { + GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(tex), + }); + + float *data = MEM_mallocN(sizeof(float) * 4 * width * height, "tf fallback buffer"); + + GPU_framebuffer_bind(fb); + while (g_tf_calls != NULL) { + ParticleRefineCall *pr_call = g_tf_calls; + g_tf_calls = g_tf_calls->next; + + g_tf_id_offset = 0; + while (pr_call->vert_len > 0) { + int max_read_px_len = min_ii(width * height, pr_call->vert_len); + + DRW_draw_pass_subset(g_tf_pass, pr_call->shgrp, pr_call->shgrp); + /* Readback result to main memory. */ + GPU_framebuffer_read_color(fb, 0, 0, width, height, 4, 0, data); + /* Upload back to VBO. */ + GPU_vertbuf_use(pr_call->vbo); + glBufferSubData(GL_ARRAY_BUFFER, + sizeof(float) * 4 * g_tf_id_offset, + sizeof(float) * 4 * max_read_px_len, + data); + + g_tf_id_offset += max_read_px_len; + pr_call->vert_len -= max_read_px_len; + } + + MEM_freeN(pr_call); + } + + MEM_freeN(data); + GPU_framebuffer_free(fb); #else - /* TODO(fclem): replace by compute shader. */ - /* Just render using transform feedback. */ - DRW_draw_pass(g_tf_pass); + /* TODO(fclem): replace by compute shader. */ + /* Just render using transform feedback. */ + DRW_draw_pass(g_tf_pass); #endif } void DRW_hair_free(void) { - for (int i = 0; i < PART_REFINE_MAX_SHADER; ++i) { - DRW_SHADER_FREE_SAFE(g_refine_shaders[i]); - } + for (int i = 0; i < PART_REFINE_MAX_SHADER; ++i) { + DRW_SHADER_FREE_SAFE(g_refine_shaders[i]); + } } |