Blender  V2.93
draw_hair.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2017 by Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include "DRW_render.h"
27 
28 #include "BLI_string_utils.h"
29 #include "BLI_utildefines.h"
30 
31 #include "DNA_collection_types.h"
32 #include "DNA_customdata_types.h"
33 #include "DNA_modifier_types.h"
34 #include "DNA_particle_types.h"
35 
36 #include "BKE_duplilist.h"
37 
38 #include "GPU_batch.h"
39 #include "GPU_shader.h"
40 #include "GPU_vertex_buffer.h"
41 
42 #include "draw_hair_private.h"
43 
44 #ifndef __APPLE__
45 # define USE_TRANSFORM_FEEDBACK
46 #endif
47 
48 typedef enum ParticleRefineShader {
52 
53 #ifndef USE_TRANSFORM_FEEDBACK
54 typedef struct ParticleRefineCall {
55  struct ParticleRefineCall *next;
56  GPUVertBuf *vbo;
57  DRWShadingGroup *shgrp;
58  uint vert_len;
59 } ParticleRefineCall;
60 
61 static ParticleRefineCall *g_tf_calls = NULL;
62 static int g_tf_id_offset;
63 static int g_tf_target_width;
64 static int g_tf_target_height;
65 #endif
66 
70 static DRWPass *g_tf_pass; /* XXX can be a problem with multiple DRWManager in the future */
71 
72 extern char datatoc_common_hair_lib_glsl[];
75 
77 {
78  if (g_refine_shaders[sh]) {
79  return g_refine_shaders[sh];
80  }
81 
82  char *vert_with_lib = BLI_string_joinN(datatoc_common_hair_lib_glsl,
84 
85 #ifdef USE_TRANSFORM_FEEDBACK
86  const char *var_names[1] = {"finalColor"};
88  vert_with_lib, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1);
89 #else
90  g_refine_shaders[sh] = DRW_shader_create(vert_with_lib,
91  NULL,
93  "#define blender_srgb_to_framebuffer_space(a) a\n"
94  "#define HAIR_PHASE_SUBDIV\n"
95  "#define TF_WORKAROUND\n");
96 #endif
97 
98  MEM_freeN(vert_with_lib);
99 
100  return g_refine_shaders[sh];
101 }
102 
103 void DRW_hair_init(void)
104 {
105 #ifdef USE_TRANSFORM_FEEDBACK
106  g_tf_pass = DRW_pass_create("Update Hair Pass", 0);
107 #else
108  g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR);
109 #endif
110 
111  if (g_dummy_vbo == NULL) {
112  /* initialize vertex format */
113  GPUVertFormat format = {0};
115 
117 
118  const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f};
120  GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert);
121  /* Create vbo immediately to bind to texture buffer. */
123 
125  }
126 }
127 
129  Object *object, ParticleSystem *psys, ModifierData *md, int subdiv, int thickness_res)
130 {
131  bool update;
132  ParticleHairCache *cache;
133  if (psys) {
134  /* Old particle hair. */
135  update = particles_ensure_procedural_data(object, psys, md, &cache, subdiv, thickness_res);
136  }
137  else {
138  /* New hair object. */
139  update = hair_ensure_procedural_data(object, &cache, subdiv, thickness_res);
140  }
141 
142  if (update) {
143  int final_points_len = cache->final[subdiv].strands_res * cache->strands_len;
144  if (final_points_len > 0) {
146 
147 #ifdef USE_TRANSFORM_FEEDBACK
149  tf_shader, g_tf_pass, cache->final[subdiv].proc_buf);
150 #else
151  DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass);
152 
153  ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__);
154  pr_call->next = g_tf_calls;
155  pr_call->vbo = cache->final[subdiv].proc_buf;
156  pr_call->shgrp = tf_shgrp;
157  pr_call->vert_len = final_points_len;
158  g_tf_calls = pr_call;
159  DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1);
160  DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1);
161  DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1);
162 #endif
163 
164  DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", cache->point_tex);
165  DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", cache->strand_tex);
166  DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", cache->strand_seg_tex);
167  DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1);
168  DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len);
169  }
170  }
171  return cache;
172 }
173 
174 /* Note: Only valid after DRW_hair_update(). */
176 {
177  const DRWContextState *draw_ctx = DRW_context_state_get();
178  Scene *scene = draw_ctx->scene;
179 
180  int subdiv = scene->r.hair_subdiv;
181  int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
182 
183  ParticleHairCache *cache = drw_hair_particle_cache_get(object, psys, md, subdiv, thickness_res);
184 
185  return cache->final[subdiv].proc_buf;
186 }
187 
189  ParticleSystem *psys,
190  ModifierData *UNUSED(md),
191  float (*dupli_mat)[4])
192 {
193  Object *dupli_parent = DRW_object_get_dupli_parent(object);
194  DupliObject *dupli_object = DRW_object_get_dupli(object);
195 
196  if (psys) {
197  if ((dupli_parent != NULL) && (dupli_object != NULL)) {
198  if (dupli_object->type & OB_DUPLICOLLECTION) {
199  unit_m4(dupli_mat);
200  Collection *collection = dupli_parent->instance_collection;
201  if (collection != NULL) {
202  sub_v3_v3(dupli_mat[3], collection->instance_offset);
203  }
204  mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat);
205  }
206  else {
207  copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
208  invert_m4(dupli_mat);
209  mul_m4_m4m4(dupli_mat, object->obmat, dupli_mat);
210  }
211  }
212  else {
213  unit_m4(dupli_mat);
214  }
215  }
216  else {
217  /* New hair object. */
218  copy_m4_m4(dupli_mat, object->obmat);
219  }
220 }
221 
223  ParticleSystem *psys,
224  ModifierData *md,
225  DRWShadingGroup *shgrp_parent)
226 {
227  const DRWContextState *draw_ctx = DRW_context_state_get();
228  Scene *scene = draw_ctx->scene;
229  float dupli_mat[4][4];
230 
231  int subdiv = scene->r.hair_subdiv;
232  int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
233 
235  object, psys, md, subdiv, thickness_res);
236 
237  DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
238 
239  /* TODO optimize this. Only bind the ones GPUMaterial needs. */
240  for (int i = 0; i < hair_cache->num_uv_layers; i++) {
241  for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; n++) {
242  DRW_shgroup_uniform_texture(shgrp, hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]);
243  }
244  }
245  for (int i = 0; i < hair_cache->num_col_layers; i++) {
246  for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->col_layer_names[i][n][0] != '\0'; n++) {
248  shgrp, hair_cache->col_layer_names[i][n], hair_cache->col_tex[i]);
249  }
250  }
251 
252  /* Fix issue with certain driver not drawing anything if there is no texture bound to
253  * "ac", "au", "u" or "c". */
254  if (hair_cache->num_uv_layers == 0) {
257  }
258  if (hair_cache->num_col_layers == 0) {
261  }
262 
263  DRW_hair_duplimat_get(object, psys, md, dupli_mat);
264 
265  /* Get hair shape parameters. */
266  float hair_rad_shape, hair_rad_root, hair_rad_tip;
267  bool hair_close_tip;
268  if (psys) {
269  /* Old particle hair. */
270  ParticleSettings *part = psys->part;
271  hair_rad_shape = part->shape;
272  hair_rad_root = part->rad_root * part->rad_scale * 0.5f;
273  hair_rad_tip = part->rad_tip * part->rad_scale * 0.5f;
274  hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0;
275  }
276  else {
277  /* TODO: implement for new hair object. */
278  hair_rad_shape = 1.0f;
279  hair_rad_root = 0.005f;
280  hair_rad_tip = 0.0f;
281  hair_close_tip = true;
282  }
283 
284  DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", hair_cache->final[subdiv].proc_tex);
285  DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
286  DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
287  DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
288  DRW_shgroup_uniform_vec4_array_copy(shgrp, "hairDupliMatrix", dupli_mat, 4);
289  DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
290  DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
291  DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
292  /* TODO(fclem): Until we have a better way to cull the hair and render with orco, bypass
293  * culling test. */
294  GPUBatch *geom = hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
295  DRW_shgroup_call_no_cull(shgrp, geom, object);
296 
297  return shgrp;
298 }
299 
300 void DRW_hair_update(void)
301 {
302 #ifndef USE_TRANSFORM_FEEDBACK
313  if (g_tf_calls == NULL) {
314  return;
315  }
316 
317  /* Search ideal buffer size. */
318  uint max_size = 0;
319  for (ParticleRefineCall *pr_call = g_tf_calls; pr_call; pr_call = pr_call->next) {
320  max_size = max_ii(max_size, pr_call->vert_len);
321  }
322 
323  /* Create target Texture / Frame-buffer */
324  /* Don't use max size as it can be really heavy and fail.
325  * Do chunks of maximum 2048 * 2048 hair points. */
326  int width = 2048;
327  int height = min_ii(width, 1 + max_size / width);
329  g_tf_target_height = height;
330  g_tf_target_width = width;
331 
333  GPU_framebuffer_ensure_config(&fb,
334  {
335  GPU_ATTACHMENT_NONE,
336  GPU_ATTACHMENT_TEXTURE(tex),
337  });
338 
339  float *data = MEM_mallocN(sizeof(float[4]) * width * height, "tf fallback buffer");
340 
342  while (g_tf_calls != NULL) {
343  ParticleRefineCall *pr_call = g_tf_calls;
344  g_tf_calls = g_tf_calls->next;
345 
346  g_tf_id_offset = 0;
347  while (pr_call->vert_len > 0) {
348  int max_read_px_len = min_ii(width * height, pr_call->vert_len);
349 
350  DRW_draw_pass_subset(g_tf_pass, pr_call->shgrp, pr_call->shgrp);
351  /* Readback result to main memory. */
353  /* Upload back to VBO. */
354  GPU_vertbuf_use(pr_call->vbo);
355  GPU_vertbuf_update_sub(pr_call->vbo,
356  sizeof(float[4]) * g_tf_id_offset,
357  sizeof(float[4]) * max_read_px_len,
358  data);
359 
360  g_tf_id_offset += max_read_px_len;
361  pr_call->vert_len -= max_read_px_len;
362  }
363 
364  MEM_freeN(pr_call);
365  }
366 
367  MEM_freeN(data);
369 #else
370  /* TODO(fclem): replace by compute shader. */
371  /* Just render using transform feedback. */
373 #endif
374 }
375 
376 void DRW_hair_free(void)
377 {
378  for (int i = 0; i < PART_REFINE_MAX_SHADER; i++) {
380  }
381 
384 }
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1187
void unit_m4(float m[4][4])
Definition: rct.c:1140
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
MINLINE void sub_v3_v3(float r[3], const float a[3])
#define BLI_string_joinN(...)
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
Object groups, one object can be in many groups at once.
@ OB_DUPLICOLLECTION
@ PART_SHAPE_CLOSE_TIP
@ SCE_HAIR_SHAPE_STRAND
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
Definition: DRW_render.h:433
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:315
#define DRW_SHADER_FREE_SAFE(shader)
Definition: DRW_render.h:279
#define DRW_shader_create(vert, geom, frag, defines)
Definition: DRW_render.h:235
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:180
GPUBatch
Definition: GPU_batch.h:93
struct GPUFrameBuffer GPUFrameBuffer
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
struct GPUShader GPUShader
Definition: GPU_shader.h:33
@ GPU_SHADER_TFB_POINTS
Definition: GPU_shader.h:37
struct GPUTexture GPUTexture
Definition: GPU_texture.h:33
GPUTexture * GPU_texture_create_from_vertbuf(const char *name, struct GPUVertBuf *vert)
Definition: gpu_texture.cc:315
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:172
@ GPU_RGBA32F
Definition: GPU_texture.h:91
#define GPU_vertbuf_create_with_format(format)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
void GPU_vertbuf_update_sub(GPUVertBuf *verts, uint start, uint len, void *data)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_use(GPUVertBuf *)
void GPU_vertbuf_attr_fill(GPUVertBuf *, uint a_idx, const void *data)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Scene scene
bool hair_ensure_procedural_data(Object *object, ParticleHairCache **r_hair_cache, int subdiv, int thickness_res)
bool particles_ensure_procedural_data(Object *object, ParticleSystem *psys, ModifierData *md, ParticleHairCache **r_hair_cache, int subdiv, int thickness_res)
char datatoc_gpu_shader_3D_smooth_color_frag_glsl[]
DRWShadingGroup * DRW_shgroup_hair_create_sub(Object *object, ParticleSystem *psys, ModifierData *md, DRWShadingGroup *shgrp_parent)
Definition: draw_hair.c:222
static GPUShader * hair_refine_shader_get(ParticleRefineShader sh)
Definition: draw_hair.c:76
static GPUTexture * g_dummy_texture
Definition: draw_hair.c:68
void DRW_hair_update(void)
Definition: draw_hair.c:300
static GPUVertBuf * g_dummy_vbo
Definition: draw_hair.c:67
static ParticleHairCache * drw_hair_particle_cache_get(Object *object, ParticleSystem *psys, ModifierData *md, int subdiv, int thickness_res)
Definition: draw_hair.c:128
char datatoc_common_hair_lib_glsl[]
ParticleRefineShader
Definition: draw_hair.c:48
@ PART_REFINE_MAX_SHADER
Definition: draw_hair.c:50
@ PART_REFINE_CATMULL_ROM
Definition: draw_hair.c:49
void DRW_hair_duplimat_get(Object *object, ParticleSystem *psys, ModifierData *UNUSED(md), float(*dupli_mat)[4])
Definition: draw_hair.c:188
static GPUShader * g_refine_shaders[PART_REFINE_MAX_SHADER]
Definition: draw_hair.c:69
GPUVertBuf * DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md)
Definition: draw_hair.c:175
void DRW_hair_init(void)
Definition: draw_hair.c:103
char datatoc_common_hair_refine_vert_glsl[]
void DRW_hair_free(void)
Definition: draw_hair.c:376
static DRWPass * g_tf_pass
Definition: draw_hair.c:70
#define MAX_LAYER_NAME_CT
struct Object * DRW_object_get_dupli_parent(const Object *UNUSED(ob))
Definition: draw_manager.c:301
struct DupliObject * DRW_object_get_dupli(const Object *UNUSED(ob))
Definition: draw_manager.c:306
const DRWContextState * DRW_context_state_get(void)
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_call_procedural_points(DRWShadingGroup *shgroup, Object *ob, uint point_count)
void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, const char *name, const float(*value)[4], int arraysize)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
DRWShadingGroup * DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, GPUVertBuf *tf_target)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
DRWPass * DRW_pass_create(const char *name, DRWState state)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_draw_pass(DRWPass *pass)
void DRW_draw_pass_subset(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group)
GPUShader * DRW_shader_create_with_transform_feedback(const char *vert, const char *geom, const char *defines, const eGPUShaderTFBType prim_type, const char **varying_names, const int varying_count)
GPUTexture * DRW_texture_pool_query_2d(int w, int h, eGPUTextureFormat format, DrawEngineType *engine_type)
void GPU_framebuffer_read_color(GPUFrameBuffer *gpu_fb, int x, int y, int w, int h, int channels, int slot, eGPUDataFormat format, void *data)
BLI_INLINE float fb(float length, float L)
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong * next
static void update(bNodeTree *ntree)
float instance_offset[3]
struct Scene * scene
Definition: DRW_render.h:745
struct Object * ob
Definition: BKE_duplilist.h:45
struct Collection * instance_collection
float obmat[4][4]
GPUTexture * uv_tex[MAX_MTFACE]
char uv_layer_names[MAX_MTFACE][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]
GPUTexture * strand_seg_tex
GPUTexture * point_tex
char col_layer_names[MAX_MCOL][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]
GPUTexture * strand_tex
GPUTexture * col_tex[MAX_MCOL]
ParticleHairFinalCache final[MAX_HAIR_SUBDIV]
GPUBatch * proc_hairs[MAX_THICKRES]
ParticleSettings * part
struct RenderData r