Blender V4.5
draw_hair.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "DNA_scene_types.h"
12#include "DRW_render.hh"
13
14#include "BLI_math_matrix.h"
15#include "BLI_math_vector.h"
16
18#include "DNA_modifier_types.h"
19#include "DNA_particle_types.h"
20
21#include "BKE_duplilist.hh"
22
23#include "GPU_batch.hh"
24#include "GPU_capabilities.hh"
25#include "GPU_material.hh"
26#include "GPU_shader.hh"
27#include "GPU_texture.hh"
28#include "GPU_vertex_buffer.hh"
29
30#include "DRW_gpu_wrapper.hh"
31
32#include "draw_common_c.hh"
34#include "draw_hair_private.hh"
35#include "draw_manager.hh"
36#include "draw_shader.hh"
37#include "draw_shader_shared.hh"
38
39static void drw_hair_particle_cache_update_compute(ParticleHairCache *cache, const int subdiv)
40{
41 const int strands_len = cache->strands_len;
42 const int final_points_len = cache->final[subdiv].strands_res * strands_len;
43 if (final_points_len > 0) {
44 using namespace blender::draw;
46
47 /* TODO(fclem): Remove Global access. */
49 pass.shader_set(shader);
50 pass.bind_texture("hairPointBuffer", cache->proc_point_buf);
51 pass.bind_texture("hairStrandBuffer", cache->proc_strand_buf);
52 pass.bind_texture("hairStrandSegBuffer", cache->proc_strand_seg_buf);
53 pass.push_constant("hairStrandsRes", &cache->final[subdiv].strands_res);
54 pass.bind_ssbo("posTime", cache->final[subdiv].proc_buf);
55
56 const int max_strands_per_call = GPU_max_work_group_count(0);
57 int strands_start = 0;
58 while (strands_start < strands_len) {
59 int batch_strands_len = std::min(strands_len - strands_start, max_strands_per_call);
60 pass.push_constant("hairStrandOffset", strands_start);
61 pass.dispatch(int3(batch_strands_len, cache->final[subdiv].strands_res, 1));
62 strands_start += batch_strands_len;
63 }
64 }
65}
66
68 ParticleSystem *psys,
69 ModifierData *md,
70 GPUMaterial *gpu_material,
71 int subdiv,
72 int thickness_res)
73{
74 using namespace blender::draw;
75 ParticleHairCache *cache;
77 object, psys, md, &cache, gpu_material, subdiv, thickness_res);
78
79 if (update) {
81 }
82 return cache;
83}
84
86 ParticleSystem *psys,
87 ModifierData *md)
88{
89 const DRWContext *draw_ctx = DRW_context_get();
90 Scene *scene = draw_ctx->scene;
91
92 int subdiv = scene->r.hair_subdiv;
93 int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
94
96 object, psys, md, nullptr, subdiv, thickness_res);
97
98 return cache->final[subdiv].proc_buf;
99}
100
102 ParticleSystem * /*psys*/,
103 ModifierData * /*md*/,
104 float (*dupli_mat)[4])
105{
106 Object *dupli_parent = ob_ref.dupli_parent;
107 DupliObject *dupli_object = ob_ref.dupli_object;
108
109 if ((dupli_parent != nullptr) && (dupli_object != nullptr)) {
110 if (dupli_object->type & OB_DUPLICOLLECTION) {
111 unit_m4(dupli_mat);
112 Collection *collection = dupli_parent->instance_collection;
113 if (collection != nullptr) {
114 sub_v3_v3(dupli_mat[3], collection->instance_offset);
115 }
116 mul_m4_m4m4(dupli_mat, dupli_parent->object_to_world().ptr(), dupli_mat);
117 }
118 else {
119 copy_m4_m4(dupli_mat, dupli_object->ob->object_to_world().ptr());
120 invert_m4(dupli_mat);
121 mul_m4_m4m4(dupli_mat, ob_ref.object->object_to_world().ptr(), dupli_mat);
122 }
123 }
124 else {
125 unit_m4(dupli_mat);
126 }
127}
128
129/* New Draw Manager. */
130#include "draw_common.hh"
131
132namespace blender::draw {
133
135 ParticleSystem *psys,
136 ModifierData *md,
137 GPUMaterial *gpu_material,
138 int subdiv,
139 int thickness_res)
140{
141 using namespace blender::draw;
142 ParticleHairCache *cache;
144 object, psys, md, &cache, gpu_material, subdiv, thickness_res);
145
146 if (!update) {
147 return cache;
148 }
149
151
152 const int strands_len = cache->strands_len;
153 const int final_points_len = cache->final[subdiv].strands_res * strands_len;
154 if (final_points_len > 0) {
155 PassSimple::Sub &ob_ps = module.refine.sub("Object Pass");
156
158
159 ob_ps.bind_texture("hairPointBuffer", cache->proc_point_buf);
160 ob_ps.bind_texture("hairStrandBuffer", cache->proc_strand_buf);
161 ob_ps.bind_texture("hairStrandSegBuffer", cache->proc_strand_seg_buf);
162 ob_ps.push_constant("hairStrandsRes", &cache->final[subdiv].strands_res);
163 ob_ps.bind_ssbo("posTime", cache->final[subdiv].proc_buf);
164
165 const int max_strands_per_call = GPU_max_work_group_count(0);
166 int strands_start = 0;
167 while (strands_start < strands_len) {
168 int batch_strands_len = std::min(strands_len - strands_start, max_strands_per_call);
169 PassSimple::Sub &sub_ps = ob_ps.sub("Sub Pass");
170 sub_ps.push_constant("hairStrandOffset", strands_start);
171 sub_ps.dispatch(int3(batch_strands_len, cache->final[subdiv].strands_res, 1));
172 strands_start += batch_strands_len;
173 }
174 }
175
176 return cache;
177}
178
180 Object *object,
181 ParticleSystem *psys,
182 ModifierData *md)
183{
184 int subdiv = scene->r.hair_subdiv;
185 int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
186
188 object, psys, md, nullptr, subdiv, thickness_res);
189
190 return cache->final[subdiv].proc_buf;
191}
192
193template<typename PassT>
194blender::gpu::Batch *hair_sub_pass_setup_implementation(PassT &sub_ps,
195 const Scene *scene,
196 const ObjectRef &ob_ref,
197 ParticleSystem *psys,
198 ModifierData *md,
199 GPUMaterial *gpu_material)
200{
202 Object *object = ob_ref.object;
203
204 int subdiv = scene->r.hair_subdiv;
205 int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
207 object, psys, md, gpu_material, subdiv, thickness_res);
208
209 /* TODO(fclem): Remove Global access. */
211
212 /* Ensure we have no unbound resources.
213 * Required for Vulkan.
214 * Fixes issues with certain GL drivers not drawing anything. */
215 sub_ps.bind_texture("u", module.dummy_vbo);
216 sub_ps.bind_texture("au", module.dummy_vbo);
217 sub_ps.bind_texture("a", module.dummy_vbo);
218 sub_ps.bind_texture("c", module.dummy_vbo);
219 sub_ps.bind_texture("ac", module.dummy_vbo);
220 if (gpu_material) {
221 ListBase attr_list = GPU_material_attributes(gpu_material);
223 for (const GPUMaterialAttribute *attr : attrs) {
224 sub_ps.bind_texture(attr->input_name, module.dummy_vbo);
225 }
226 }
227
228 /* TODO: optimize this. Only bind the ones #GPUMaterial needs. */
229 for (int i : IndexRange(hair_cache->num_uv_layers)) {
230 for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->uv_layer_names[i][n][0] != '\0'; n++) {
231 sub_ps.bind_texture(hair_cache->uv_layer_names[i][n], hair_cache->uv_tex[i]);
232 }
233 }
234 for (int i : IndexRange(hair_cache->num_col_layers)) {
235 for (int n = 0; n < MAX_LAYER_NAME_CT && hair_cache->col_layer_names[i][n][0] != '\0'; n++) {
236 sub_ps.bind_texture(hair_cache->col_layer_names[i][n], hair_cache->col_tex[i]);
237 }
238 }
239
240 float4x4 dupli_mat;
241 DRW_hair_duplimat_get(ob_ref, psys, md, dupli_mat.ptr());
242
243 /* Get hair shape parameters. */
244 ParticleSettings *part = psys->part;
245 float hair_rad_shape = part->shape;
246 float hair_rad_root = part->rad_root * part->rad_scale * 0.5f;
247 float hair_rad_tip = part->rad_tip * part->rad_scale * 0.5f;
248 bool hair_close_tip = (part->shape_flag & PART_SHAPE_CLOSE_TIP) != 0;
249
250 sub_ps.bind_texture("hairPointBuffer", hair_cache->final[subdiv].proc_buf);
251 if (hair_cache->proc_length_buf) {
252 sub_ps.bind_texture("l", hair_cache->proc_length_buf);
253 }
254
255 sub_ps.bind_ubo("drw_curves", module.ubo_pool.dummy_get());
256 sub_ps.push_constant("hairStrandsRes", &hair_cache->final[subdiv].strands_res, 1);
257 sub_ps.push_constant("hairThicknessRes", thickness_res);
258 sub_ps.push_constant("hairRadShape", hair_rad_shape);
259 sub_ps.push_constant("hairDupliMatrix", dupli_mat);
260 sub_ps.push_constant("hairRadRoot", hair_rad_root);
261 sub_ps.push_constant("hairRadTip", hair_rad_tip);
262 sub_ps.push_constant("hairCloseTip", hair_close_tip);
263
264 return hair_cache->final[subdiv].proc_hairs[thickness_res - 1];
265}
266
267blender::gpu::Batch *hair_sub_pass_setup(PassMain::Sub &sub_ps,
268 const Scene *scene,
269 const ObjectRef &ob_ref,
270 ParticleSystem *psys,
271 ModifierData *md,
272 GPUMaterial *gpu_material)
273{
274 return hair_sub_pass_setup_implementation(sub_ps, scene, ob_ref, psys, md, gpu_material);
275}
276
277blender::gpu::Batch *hair_sub_pass_setup(PassSimple::Sub &sub_ps,
278 const Scene *scene,
279 const ObjectRef &ob_ref,
280 ParticleSystem *psys,
281 ModifierData *md,
282 GPUMaterial *gpu_material)
283{
284 return hair_sub_pass_setup_implementation(sub_ps, scene, ob_ref, psys, md, gpu_material);
285}
286
287} // namespace blender::draw
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4(float mat[4][4])
void unit_m4(float m[4][4])
MINLINE void sub_v3_v3(float r[3], const float a[3])
Object groups, one object can be in many groups at once.
@ OB_DUPLICOLLECTION
@ PART_SHAPE_CLOSE_TIP
@ SCE_HAIR_SHAPE_STRAND
int GPU_max_work_group_count(int index)
ListBase GPU_material_attributes(const GPUMaterial *material)
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:681
void dispatch(int group_len)
Definition draw_pass.hh:994
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:490
void DRW_hair_duplimat_get(const blender::draw::ObjectRef &ob_ref, ParticleSystem *psys, ModifierData *md, float(*dupli_mat)[4])
Definition draw_hair.cc:101
const DRWContext * DRW_context_get()
DRWContext & drw_get()
blender::gpu::VertBuf * DRW_hair_pos_buffer_get(Object *object, ParticleSystem *psys, ModifierData *md)
Definition draw_hair.cc:85
static void drw_hair_particle_cache_update_compute(ParticleHairCache *cache, const int subdiv)
Definition draw_hair.cc:39
void DRW_hair_duplimat_get(const blender::draw::ObjectRef &ob_ref, ParticleSystem *, ModifierData *, float(*dupli_mat)[4])
Definition draw_hair.cc:101
static ParticleHairCache * drw_hair_particle_cache_get(Object *object, ParticleSystem *psys, ModifierData *md, GPUMaterial *gpu_material, int subdiv, int thickness_res)
Definition draw_hair.cc:67
@ PART_REFINE_CATMULL_ROM
#define MAX_LAYER_NAME_CT
GPUShader * DRW_shader_hair_refine_get(ParticleRefineShader)
detail::Pass< command::DrawCommandBuf > PassSimple
blender::gpu::Batch * hair_sub_pass_setup_implementation(PassT &sub_ps, const Scene *scene, const ObjectRef &ob_ref, ParticleSystem *psys, ModifierData *md, GPUMaterial *gpu_material)
Definition draw_hair.cc:194
gpu::Batch * hair_sub_pass_setup(PassMain::Sub &sub_ps, const Scene *scene, const ObjectRef &ob_ref, ParticleSystem *psys, ModifierData *md, GPUMaterial *gpu_material=nullptr)
Definition draw_hair.cc:267
bool particles_ensure_procedural_data(Object *object, ParticleSystem *psys, ModifierData *md, ParticleHairCache **r_hair_cache, GPUMaterial *gpu_material, int subdiv, int thickness_res)
gpu::VertBuf * hair_pos_buffer_get(Scene *scene, Object *object, ParticleSystem *psys, ModifierData *md)
Definition draw_hair.cc:179
static ParticleHairCache * hair_particle_cache_get(Object *object, ParticleSystem *psys, ModifierData *md, GPUMaterial *gpu_material, int subdiv, int thickness_res)
Definition draw_hair.cc:134
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 3 > int3
ListBaseWrapperTemplate< ListBase, T > ListBaseWrapper
static void update(bNodeTree *ntree)
static struct PyModuleDef module
Definition python.cpp:796
DRWData * data
Scene * scene
blender::draw::CurvesModule * curves_module
struct Collection * instance_collection
GPUTexture * uv_tex[MAX_MTFACE]
blender::gpu::VertBuf * proc_length_buf
blender::gpu::VertBuf * proc_strand_buf
blender::gpu::VertBuf * proc_strand_seg_buf
char uv_layer_names[MAX_MTFACE][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]
blender::gpu::VertBuf * proc_point_buf
ParticleHairFinalCache final[MAX_HAIR_SUBDIV]
char(* col_layer_names)[MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]
blender::gpu::VertBuf * proc_buf
blender::gpu::Batch * proc_hairs[MAX_THICKRES]
ParticleSettings * part
struct RenderData r
const c_style_mat & ptr() const
DupliObject * dupli_object
i
Definition text_draw.cc:230