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:
authorClément Foucault <foucault.clem@gmail.com>2018-05-29 13:11:03 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-05-30 13:25:20 +0300
commit328f8dc21c0e8a7e3da14f6578fb84a811f80b89 (patch)
tree6d7cbe0cb0bc0fee859bff5c73f98dbf9109b6f8 /source/blender/draw/intern/draw_hair.c
parent2faef3473c061e34a03668905c8d81672a72dd38 (diff)
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.
Diffstat (limited to 'source/blender/draw/intern/draw_hair.c')
-rw-r--r--source/blender/draw/intern/draw_hair.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
new file mode 100644
index 00000000000..c292415d38c
--- /dev/null
+++ b/source/blender/draw/intern/draw_hair.c
@@ -0,0 +1,167 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_hair.c
+ * \ingroup draw
+ *
+ * \brief Contains procedural GPU hair drawing methods.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_string_utils.h"
+
+#include "DNA_mesh_types.h"
+#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"
+#include "BKE_pointcache.h"
+
+#include "ED_particle.h"
+
+#include "GPU_batch.h"
+#include "GPU_shader.h"
+
+#include "draw_hair_private.h"
+
+typedef enum ParticleRefineShader {
+ PART_REFINE_CATMULL_ROM = 0,
+ PART_REFINE_MAX_SHADER,
+} ParticleRefineShader;
+
+static GPUShader *g_refine_shaders[PART_REFINE_MAX_SHADER] = {NULL};
+
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_common_hair_refine_vert_glsl[];
+
+static GPUShader *hair_refine_shader_get(ParticleRefineShader 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);
+
+ const char *var_names[1] = {"outData"};
+
+ 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);
+
+ MEM_freeN(vert_with_lib);
+
+ return g_refine_shaders[sh];
+}
+
+static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(
+ Object *object, ParticleSystem *psys, ModifierData *md,
+ DRWPass *hair_pass, DRWPass *tf_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;
+
+ 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 {
+ 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; 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; 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]);
+ }
+ }
+
+ 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_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_ct = hair_cache->final[subdiv].strands_res * hair_cache->strands_count;
+ GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM);
+ DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create(tf_shader, tf_pass,
+ hair_cache->final[subdiv].proc_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", &hair_cache->final[subdiv].strands_res, 1);
+ DRW_shgroup_call_procedural_points_add(tf_shgrp, final_points_ct, NULL);
+ }
+
+ return shgrp;
+}
+
+DRWShadingGroup *DRW_shgroup_hair_create(
+ Object *object, ParticleSystem *psys, ModifierData *md,
+ DRWPass *hair_pass, DRWPass *tf_pass,
+ GPUShader *shader)
+{
+ return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, tf_pass, NULL, shader);
+}
+
+DRWShadingGroup *DRW_shgroup_material_hair_create(
+ Object *object, ParticleSystem *psys, ModifierData *md,
+ DRWPass *hair_pass, DRWPass *tf_pass,
+ struct GPUMaterial *material)
+{
+ return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, tf_pass, material, NULL);
+}
+
+void DRW_hair_free(void)
+{
+ for (int i = 0; i < PART_REFINE_MAX_SHADER; ++i) {
+ DRW_SHADER_FREE_SAFE(g_refine_shaders[i]);
+ }
+} \ No newline at end of file