Blender V4.3
draw_curves.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
11#include "BLI_string_utils.hh"
12#include "BLI_utildefines.h"
13
14#include "DNA_curves_types.h"
15
16#include "BKE_attribute.hh"
17#include "BKE_curves.hh"
18#include "BKE_customdata.hh"
19
20#include "GPU_batch.hh"
21#include "GPU_capabilities.hh"
22#include "GPU_compute.hh"
23#include "GPU_material.hh"
24#include "GPU_shader.hh"
25#include "GPU_texture.hh"
26#include "GPU_vertex_buffer.hh"
27
28#include "DRW_gpu_wrapper.hh"
29#include "DRW_render.hh"
30
31#include "draw_cache_impl.hh"
32#include "draw_common.hh"
34#include "draw_hair_private.hh"
35#include "draw_manager_c.hh"
36#include "draw_shader.hh"
37
38namespace blender::draw {
39
46
47static gpu::VertBuf *g_dummy_vbo = nullptr;
48static DRWPass *g_tf_pass; /* XXX can be a problem with multiple DRWManager in the future */
49
51
54 int used = 0;
55
56 void reset()
57 {
58 used = 0;
59 }
60
62 {
64 if (used >= ubos.size()) {
65 ubos.append(std::make_unique<CurvesInfosBuf>());
66 ptr = ubos.last().get();
67 }
68 else {
69 ptr = ubos[used++].get();
70 }
71
72 memset(ptr->data(), 0, sizeof(CurvesInfos));
73 return *ptr;
74 }
75};
76
78{
79 if (g_dummy_vbo != nullptr) {
80 return;
81 }
82 /* initialize vertex format */
85
88
89 const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f};
91 GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert);
92 /* Create vbo immediately to bind to texture buffer. */
94}
95
96void DRW_curves_init(DRWData *drw_data)
97{
98 /* Initialize legacy hair too, to avoid verbosity in callers. */
100
101 if (drw_data->curves_ubos == nullptr) {
102 drw_data->curves_ubos = MEM_new<CurvesUniformBufPool>("CurvesUniformBufPool");
103 }
104 CurvesUniformBufPool *pool = drw_data->curves_ubos;
105 pool->reset();
106
107 g_tf_pass = DRW_pass_create("Update Curves Pass", (DRWState)0);
108
110}
111
113{
114 MEM_delete(pool);
115}
116
118 CurvesEvalCache *cache,
119 gpu::VertBuf *point_buf)
120{
121 DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", point_buf);
122 DRW_shgroup_buffer_texture(shgrp, "hairStrandBuffer", cache->proc_strand_buf);
123 DRW_shgroup_buffer_texture(shgrp, "hairStrandSegBuffer", cache->proc_strand_seg_buf);
124 DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final.resolution, 1);
125}
126
128 const int curves_num,
129 gpu::VertBuf *output_buf,
130 gpu::VertBuf *input_buf)
131{
132 BLI_assert(input_buf != nullptr);
133 BLI_assert(output_buf != nullptr);
136 drw_curves_cache_shgrp_attach_resources(shgrp, cache, input_buf);
137 DRW_shgroup_vertex_buffer(shgrp, "posTime", output_buf);
138
139 const int max_strands_per_call = GPU_max_work_group_count(0);
140 int strands_start = 0;
141 while (strands_start < curves_num) {
142 int batch_strands_len = std::min(curves_num - strands_start, max_strands_per_call);
143 DRWShadingGroup *subgroup = DRW_shgroup_create_sub(shgrp);
144 DRW_shgroup_uniform_int_copy(subgroup, "hairStrandOffset", strands_start);
145 DRW_shgroup_call_compute(subgroup, batch_strands_len, cache->final.resolution, 1);
146 strands_start += batch_strands_len;
147 }
148}
149
151{
152 const int curves_num = cache->curves_num;
153 const int final_points_len = cache->final.resolution * curves_num;
154 if (final_points_len == 0) {
155 return;
156 }
157
158 drw_curves_cache_update_compute(cache, curves_num, cache->final.proc_buf, cache->proc_point_buf);
159
160 const DRW_Attributes &attrs = cache->final.attr_used;
161 for (int i = 0; i < attrs.num_requests; i++) {
162 /* Only refine point attributes. */
163 if (attrs.requests[i].domain == bke::AttrDomain::Curve) {
164 continue;
165 }
166
168 cache, curves_num, cache->final.attributes_buf[i], cache->proc_attributes_buf[i]);
169 }
170}
171
173 GPUMaterial *gpu_material,
174 int subdiv,
175 int thickness_res)
176{
177 CurvesEvalCache *cache;
179 &curves, &cache, gpu_material, subdiv, thickness_res);
180
181 if (update) {
183 }
184 return cache;
185}
186
188{
189 const DRWContextState *draw_ctx = DRW_context_state_get();
190 const Scene *scene = draw_ctx->scene;
191
192 const int subdiv = scene->r.hair_subdiv;
193 const int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
194
195 Curves &curves = *static_cast<Curves *>(object->data);
196 CurvesEvalCache *cache = drw_curves_cache_get(curves, nullptr, subdiv, thickness_res);
197
198 return cache->final.proc_buf;
199}
200
201static int attribute_index_in_material(GPUMaterial *gpu_material, const char *name)
202{
203 if (!gpu_material) {
204 return -1;
205 }
206
207 int index = 0;
208
209 ListBase gpu_attrs = GPU_material_attributes(gpu_material);
210 LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) {
211 if (STREQ(gpu_attr->name, name)) {
212 return index;
213 }
214
215 index++;
216 }
217
218 return -1;
219}
220
222 DRWShadingGroup *shgrp_parent,
223 GPUMaterial *gpu_material)
224{
225 const DRWContextState *draw_ctx = DRW_context_state_get();
226 const Scene *scene = draw_ctx->scene;
228 CurvesInfosBuf &curves_infos = pool->alloc();
229 Curves &curves_id = *static_cast<Curves *>(object->data);
230
231 const int subdiv = scene->r.hair_subdiv;
232 const int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
233
235 curves_id, gpu_material, subdiv, thickness_res);
236
237 DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
238
239 /* Fix issue with certain driver not drawing anything if there is nothing bound to
240 * "ac", "au", "u" or "c". */
246
247 /* TODO: Generalize radius implementation for curves data type. */
248 float hair_rad_shape = 0.0f;
249 float hair_rad_root = 0.005f;
250 float hair_rad_tip = 0.0f;
251 bool hair_close_tip = true;
252
253 /* Use the radius of the root and tip of the first curve for now. This is a workaround that we
254 * use for now because we can't use a per-point radius yet. */
255 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
256 if (curves.curves_num() >= 1) {
257 VArray<float> radii = *curves.attributes().lookup_or_default(
258 "radius", bke::AttrDomain::Point, 0.005f);
259 const IndexRange first_curve_points = curves.points_by_curve()[0];
260 const float first_radius = radii[first_curve_points.first()];
261 const float last_radius = radii[first_curve_points.last()];
262 const float middle_radius = radii[first_curve_points.size() / 2];
263 hair_rad_root = radii[first_curve_points.first()];
264 hair_rad_tip = radii[first_curve_points.last()];
265 hair_rad_shape = std::clamp(
266 math::safe_divide(middle_radius - first_radius, last_radius - first_radius) * 2.0f - 1.0f,
267 -1.0f,
268 1.0f);
269 }
270
271 DRW_shgroup_buffer_texture(shgrp, "hairPointBuffer", curves_cache->final.proc_buf);
272 if (curves_cache->proc_length_buf) {
273 DRW_shgroup_buffer_texture(shgrp, "l", curves_cache->proc_length_buf);
274 }
275
276 int curve_data_render_uv = 0;
277 int point_data_render_uv = 0;
279 curve_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.curve_data,
281 }
283 point_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.point_data,
285 }
286
287 const DRW_Attributes &attrs = curves_cache->final.attr_used;
288 for (int i = 0; i < attrs.num_requests; i++) {
289 const DRW_AttributeRequest &request = attrs.requests[i];
290 char sampler_name[32];
292
293 if (request.domain == bke::AttrDomain::Curve) {
294 if (!curves_cache->proc_attributes_buf[i]) {
295 continue;
296 }
297 DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->proc_attributes_buf[i]);
298 if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == curve_data_render_uv) {
299 DRW_shgroup_buffer_texture(shgrp, "a", curves_cache->proc_attributes_buf[i]);
300 }
301 }
302 else {
303 if (!curves_cache->final.attributes_buf[i]) {
304 continue;
305 }
306 DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->final.attributes_buf[i]);
307 if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == point_data_render_uv) {
308 DRW_shgroup_buffer_texture(shgrp, "a", curves_cache->final.attributes_buf[i]);
309 }
310 }
311
312 /* Some attributes may not be used in the shader anymore and were not garbage collected yet, so
313 * we need to find the right index for this attribute as uniforms defining the scope of the
314 * attributes are based on attribute loading order, which is itself based on the material's
315 * attributes. */
316 const int index = attribute_index_in_material(gpu_material, request.attribute_name);
317 if (index != -1) {
318 curves_infos.is_point_attribute[index][0] = request.domain == bke::AttrDomain::Point;
319 }
320 }
321
322 curves_infos.push_update();
323
324 DRW_shgroup_uniform_block(shgrp, "drw_curves", curves_infos);
325
326 DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &curves_cache->final.resolution, 1);
327 DRW_shgroup_uniform_int_copy(shgrp, "hairThicknessRes", thickness_res);
328 DRW_shgroup_uniform_float_copy(shgrp, "hairRadShape", hair_rad_shape);
329 DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", object->object_to_world().ptr());
330 DRW_shgroup_uniform_float_copy(shgrp, "hairRadRoot", hair_rad_root);
331 DRW_shgroup_uniform_float_copy(shgrp, "hairRadTip", hair_rad_tip);
332 DRW_shgroup_uniform_bool_copy(shgrp, "hairCloseTip", hair_close_tip);
333 if (gpu_material) {
334 /* NOTE: This needs to happen before the drawcall to allow correct attribute extraction.
335 * (see #101896) */
336 DRW_shgroup_add_material_resources(shgrp, gpu_material);
337 }
338 /* TODO(fclem): Until we have a better way to cull the curves and render with orco, bypass
339 * culling test. */
340 gpu::Batch *geom = curves_cache->final.proc_hairs;
341 DRW_shgroup_call_no_cull(shgrp, geom, object);
342
343 return shgrp;
344}
345
347{
348
349 /* Ensure there's a valid active view.
350 * "Next" engines use this function, but this still uses the old Draw Manager. */
351 if (DRW_view_default_get() == nullptr) {
352 /* Create a dummy default view, it's not really used. */
354 float4x4::identity().ptr(), float4x4::identity().ptr(), nullptr, nullptr, nullptr));
355 }
356 if (DRW_view_get_active() == nullptr) {
358 }
359
360 /* Update legacy hair too, to avoid verbosity in callers. */
362
365}
366
373
374/* New Draw Manager. */
375
376static PassSimple *g_pass = nullptr;
377
379{
380 if (!g_pass) {
381 g_pass = MEM_new<PassSimple>("drw_curves g_pass", "Update Curves Pass");
382 }
383 g_pass->init();
385}
386
388 GPUMaterial *gpu_material,
389 int subdiv,
390 int thickness_res)
391{
392 CurvesEvalCache *cache;
394 &curves, &cache, gpu_material, subdiv, thickness_res);
395
396 if (!update) {
397 return cache;
398 }
399
400 const int curves_num = cache->curves_num;
401 const int final_points_len = cache->final.resolution * curves_num;
402
403 auto cache_update = [&](gpu::VertBuf *output_buf, gpu::VertBuf *input_buf) {
404 PassSimple::Sub &ob_ps = g_pass->sub("Object Pass");
405
407
408 ob_ps.bind_texture("hairPointBuffer", input_buf);
409 ob_ps.bind_texture("hairStrandBuffer", cache->proc_strand_buf);
410 ob_ps.bind_texture("hairStrandSegBuffer", cache->proc_strand_seg_buf);
411 ob_ps.push_constant("hairStrandsRes", &cache->final.resolution);
412 ob_ps.bind_ssbo("posTime", output_buf);
413
414 const int max_strands_per_call = GPU_max_work_group_count(0);
415 int strands_start = 0;
416 while (strands_start < curves_num) {
417 int batch_strands_len = std::min(curves_num - strands_start, max_strands_per_call);
418 PassSimple::Sub &sub_ps = ob_ps.sub("Sub Pass");
419 sub_ps.push_constant("hairStrandOffset", strands_start);
420 sub_ps.dispatch(int3(batch_strands_len, cache->final.resolution, 1));
421 strands_start += batch_strands_len;
422 }
423 };
424
425 if (final_points_len > 0) {
426 cache_update(cache->final.proc_buf, cache->proc_point_buf);
427
428 const DRW_Attributes &attrs = cache->final.attr_used;
429 for (int i : IndexRange(attrs.num_requests)) {
430 /* Only refine point attributes. */
431 if (attrs.requests[i].domain != bke::AttrDomain::Curve) {
432 cache_update(cache->final.attributes_buf[i], cache->proc_attributes_buf[i]);
433 }
434 }
435 }
436
437 return cache;
438}
439
441{
442 const int subdiv = scene->r.hair_subdiv;
443 const int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
444
445 Curves &curves = *static_cast<Curves *>(object->data);
446 CurvesEvalCache *cache = curves_cache_get(curves, nullptr, subdiv, thickness_res);
447
448 return cache->final.proc_buf;
449}
450
456
458{
459 MEM_delete(g_pass);
460 g_pass = nullptr;
461}
462
463template<typename PassT>
464gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps,
465 const Scene *scene,
466 Object *ob,
467 GPUMaterial *gpu_material)
468{
472 CurvesInfosBuf &curves_infos = pool->alloc();
473 BLI_assert(ob->type == OB_CURVES);
474 Curves &curves_id = *static_cast<Curves *>(ob->data);
475
476 const int subdiv = scene->r.hair_subdiv;
477 const int thickness_res = (scene->r.hair_type == SCE_HAIR_SHAPE_STRAND) ? 1 : 2;
478
480 curves_id, gpu_material, subdiv, thickness_res);
481
482 /* Fix issue with certain driver not drawing anything if there is nothing bound to
483 * "ac", "au", "u" or "c". */
484 sub_ps.bind_texture("u", g_dummy_vbo);
485 sub_ps.bind_texture("au", g_dummy_vbo);
486 sub_ps.bind_texture("c", g_dummy_vbo);
487 sub_ps.bind_texture("ac", g_dummy_vbo);
488 sub_ps.bind_texture("a", g_dummy_vbo);
489
490 /* TODO: Generalize radius implementation for curves data type. */
491 float hair_rad_shape = 0.0f;
492 float hair_rad_root = 0.005f;
493 float hair_rad_tip = 0.0f;
494 bool hair_close_tip = true;
495
496 /* Use the radius of the root and tip of the first curve for now. This is a workaround that we
497 * use for now because we can't use a per-point radius yet. */
498 const bke::CurvesGeometry &curves = curves_id.geometry.wrap();
499 if (curves.curves_num() >= 1) {
500 VArray<float> radii = *curves.attributes().lookup_or_default(
501 "radius", bke::AttrDomain::Point, 0.005f);
502 const IndexRange first_curve_points = curves.points_by_curve()[0];
503 const float first_radius = radii[first_curve_points.first()];
504 const float last_radius = radii[first_curve_points.last()];
505 const float middle_radius = radii[first_curve_points.size() / 2];
506 hair_rad_root = radii[first_curve_points.first()];
507 hair_rad_tip = radii[first_curve_points.last()];
508 hair_rad_shape = std::clamp(
509 math::safe_divide(middle_radius - first_radius, last_radius - first_radius) * 2.0f - 1.0f,
510 -1.0f,
511 1.0f);
512 }
513
514 sub_ps.bind_texture("hairPointBuffer", curves_cache->final.proc_buf);
515 if (curves_cache->proc_length_buf) {
516 sub_ps.bind_texture("l", curves_cache->proc_length_buf);
517 }
518
519 int curve_data_render_uv = 0;
520 int point_data_render_uv = 0;
522 curve_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.curve_data,
524 }
526 point_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.point_data,
528 }
529
530 const DRW_Attributes &attrs = curves_cache->final.attr_used;
531 for (int i = 0; i < attrs.num_requests; i++) {
532 const DRW_AttributeRequest &request = attrs.requests[i];
533 char sampler_name[32];
535
536 if (request.domain == bke::AttrDomain::Curve) {
537 if (!curves_cache->proc_attributes_buf[i]) {
538 continue;
539 }
540 sub_ps.bind_texture(sampler_name, curves_cache->proc_attributes_buf[i]);
541 if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == curve_data_render_uv) {
542 sub_ps.bind_texture("a", curves_cache->proc_attributes_buf[i]);
543 }
544 }
545 else {
546 if (!curves_cache->final.attributes_buf[i]) {
547 continue;
548 }
549 sub_ps.bind_texture(sampler_name, curves_cache->final.attributes_buf[i]);
550 if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == point_data_render_uv) {
551 sub_ps.bind_texture("a", curves_cache->final.attributes_buf[i]);
552 }
553 }
554
555 /* Some attributes may not be used in the shader anymore and were not garbage collected yet, so
556 * we need to find the right index for this attribute as uniforms defining the scope of the
557 * attributes are based on attribute loading order, which is itself based on the material's
558 * attributes. */
559 const int index = attribute_index_in_material(gpu_material, request.attribute_name);
560 if (index != -1) {
561 curves_infos.is_point_attribute[index][0] = request.domain == bke::AttrDomain::Point;
562 }
563 }
564
565 curves_infos.push_update();
566
567 sub_ps.bind_ubo("drw_curves", curves_infos);
568
569 sub_ps.push_constant("hairStrandsRes", &curves_cache->final.resolution, 1);
570 sub_ps.push_constant("hairThicknessRes", thickness_res);
571 sub_ps.push_constant("hairRadShape", hair_rad_shape);
572 sub_ps.push_constant("hairDupliMatrix", ob->object_to_world());
573 sub_ps.push_constant("hairRadRoot", hair_rad_root);
574 sub_ps.push_constant("hairRadTip", hair_rad_tip);
575 sub_ps.push_constant("hairCloseTip", hair_close_tip);
576
577 return curves_cache->final.proc_hairs;
578}
579
581 const Scene *scene,
582 Object *ob,
583 GPUMaterial *gpu_material)
584{
585 return curves_sub_pass_setup_implementation(ps, scene, ob, gpu_material);
586}
587
589 const Scene *scene,
590 Object *ob,
591 GPUMaterial *gpu_material)
592{
593 return curves_sub_pass_setup_implementation(ps, scene, ob, gpu_material);
594}
595
596} // namespace blender::draw
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
int CustomData_get_render_layer(const CustomData *data, eCustomDataType type)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH(type, var, list)
unsigned int uint
#define STREQ(a, b)
@ CD_PROP_FLOAT2
@ OB_CURVES
@ SCE_HAIR_SHAPE_STRAND
#define DRW_shgroup_vertex_buffer(shgroup, name, vert)
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
int GPU_max_work_group_count(int index)
ListBase GPU_material_attributes(const GPUMaterial *material)
void GPU_memory_barrier(eGPUBarrier barrier)
Definition gpu_state.cc:374
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
void GPU_vertbuf_use(blender::gpu::VertBuf *)
void GPU_vertbuf_attr_fill(blender::gpu::VertBuf *, uint a_idx, const void *data)
blender::gpu::VertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat &format, GPUUsageType usage)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_USAGE_STATIC
@ GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
struct GPUShader GPUShader
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
void submit(PassSimple &pass, View &view)
void bind_texture(const char *name, GPUTexture *texture, GPUSamplerState state=sampler_auto)
PassBase< DrawCommandBufType > & sub(const char *name)
Definition draw_pass.hh:616
void dispatch(int group_len)
Definition draw_pass.hh:874
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void push_constant(const char *name, const float &data)
void bind_ssbo(const char *name, GPUStorageBuf *buffer)
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
detail::PassBase< command::DrawCommandBuf > Sub
Definition draw_pass.hh:462
void DRW_hair_init()
Definition draw_hair.cc:73
void DRW_hair_free()
Definition draw_hair.cc:259
void DRW_hair_update()
Definition draw_hair.cc:252
DRWManager DST
const DRWContextState * DRW_context_state_get()
const DRWView * DRW_view_default_get()
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_buffer_texture(DRWShadingGroup *shgroup, const char *name, blender::gpu::VertBuf *vertex_buffer)
DRWPass * DRW_pass_create(const char *name, DRWState state)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
void DRW_shgroup_call_compute(DRWShadingGroup *shgroup, int groups_x_len, int groups_y_len, int groups_z_len)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, GPUMaterial *material)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_uniform_mat4_copy(DRWShadingGroup *shgroup, const char *name, const float(*value)[4])
void DRW_view_default_set(const DRWView *view)
DRWView * DRW_view_create(const float viewmat[4][4], const float winmat[4][4], const float(*culling_viewmat)[4], const float(*culling_winmat)[4], DRWCallVisibilityFn *visibility_fn)
void DRW_draw_pass(DRWPass *pass)
void DRW_view_set_active(const DRWView *view)
const DRWView * DRW_view_get_active()
GPUShader * DRW_shader_curves_refine_get(blender::draw::CurvesEvalShader type)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_NO_DRAW
Definition draw_state.hh:27
format
static PassSimple * g_pass
void DRW_curves_init(DRWData *drw_data)
void DRW_curves_ubos_pool_free(CurvesUniformBufPool *pool)
static CurvesEvalCache * drw_curves_cache_get(Curves &curves, GPUMaterial *gpu_material, int subdiv, int thickness_res)
gpu::VertBuf * curves_pos_buffer_get(Scene *scene, Object *object)
static int attribute_index_in_material(GPUMaterial *gpu_material, const char *name)
static CurvesEvalCache * curves_cache_get(Curves &curves, GPUMaterial *gpu_material, int subdiv, int thickness_res)
void drw_curves_get_attribute_sampler_name(const char *layer_name, char r_sampler_name[32])
gpu::Batch * curves_sub_pass_setup(PassMain::Sub &ps, const Scene *scene, Object *ob, GPUMaterial *gpu_material=nullptr)
static DRWPass * g_tf_pass
static void drw_curves_cache_update_compute(CurvesEvalCache *cache, const int curves_num, gpu::VertBuf *output_buf, gpu::VertBuf *input_buf)
void DRW_curves_update()
gpu::Batch * curves_sub_pass_setup_implementation(PassT &sub_ps, const Scene *scene, Object *ob, GPUMaterial *gpu_material)
void curves_update(Manager &manager)
static gpu::VertBuf * g_dummy_vbo
DRWShadingGroup * DRW_shgroup_curves_create_sub(Object *object, DRWShadingGroup *shgrp, GPUMaterial *gpu_material)
bool curves_ensure_procedural_data(Curves *curves_id, CurvesEvalCache **r_cache, const GPUMaterial *gpu_material, const int subdiv, const int thickness_res)
static void drw_curves_ensure_dummy_vbo()
void DRW_curves_free()
static void drw_curves_cache_shgrp_attach_resources(DRWShadingGroup *shgrp, CurvesEvalCache *cache, gpu::VertBuf *point_buf)
gpu::VertBuf * DRW_curves_pos_buffer_get(Object *object)
T safe_divide(const T &a, const T &b)
VecBase< int32_t, 3 > int3
static void update(bNodeTree *ntree)
CustomData point_data
CustomData curve_data
CurvesGeometry geometry
blender::draw::CurvesUniformBufPool * curves_ubos
DRWData * vmempool
void * data
Definition RNA_types.hh:42
struct RenderData r
gpu::VertBuf * proc_attributes_buf[GPU_MAX_ATTR]
gpu::VertBuf * attributes_buf[GPU_MAX_ATTR]
Vector< std::unique_ptr< CurvesInfosBuf > > ubos
DRW_AttributeRequest requests[GPU_MAX_ATTR]
PointerRNA * ptr
Definition wm_files.cc:4126