Files
test2/source/blender/draw/intern/draw_pointcloud.cc
Clément Foucault e57359726f GPU: VertexFormat: Use new data types
This prevents the use of unaligned data types in
vertex formats. These formats are not supported on many
platform.

This simplify the `GPUVertexFormat` class a lot as
we do not need packing shenanigans anymore and just
compute the vertex stride.

The old enums are kept for progressive porting of the
backends and user code.

This will break compatibility with python addons.

TODO:
- [x] Deprecation warning for PyGPU (4.5)
  - [x] Deprecate matrix attributes
- [x] Error handling for PyGPU (5.0)
- [x] Backends
  - [x] Metal
  - [x] OpenGL
  - [x] Vulkan

Pull Request: https://projects.blender.org/blender/blender/pulls/138846
2025-06-10 17:20:45 +02:00

124 lines
3.9 KiB
C++

/* SPDX-FileCopyrightText: 2017 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup draw
*/
#include "DNA_pointcloud_types.h"
#include "GPU_batch.hh"
#include "GPU_material.hh"
#include "GPU_shader.hh"
#include "GPU_texture.hh"
#include "GPU_vertex_buffer.hh"
#include "DRW_render.hh"
#include "draw_cache_impl.hh"
#include "draw_common.hh"
#include "draw_common_c.hh"
#include "draw_context_private.hh"
#include "draw_pointcloud_private.hh"
/* For drw_curves_get_attribute_sampler_name. */
#include "draw_curves_private.hh"
namespace blender::draw {
struct PointCloudModule {
gpu::VertBuf *dummy_vbo = create_dummy_vbo();
~PointCloudModule()
{
GPU_VERTBUF_DISCARD_SAFE(dummy_vbo);
}
private:
gpu::VertBuf *create_dummy_vbo()
{
GPUVertFormat format = {0};
uint dummy_id = GPU_vertformat_attr_add(
&format, "dummy", gpu::VertAttrType::SFLOAT_32_32_32_32);
gpu::VertBuf *vbo = GPU_vertbuf_create_with_format_ex(
format, GPU_USAGE_STATIC | GPU_USAGE_FLAG_BUFFER_TEXTURE_ONLY);
const float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f};
GPU_vertbuf_data_alloc(*vbo, 1);
GPU_vertbuf_attr_fill(vbo, dummy_id, vert);
return vbo;
}
};
void DRW_pointcloud_init(DRWData *drw_data)
{
if (drw_data == nullptr) {
drw_data = drw_get().data;
}
if (drw_data->pointcloud_module == nullptr) {
drw_data->pointcloud_module = MEM_new<PointCloudModule>("PointCloudModule");
}
}
void DRW_pointcloud_module_free(PointCloudModule *pointcloud_module)
{
MEM_delete(pointcloud_module);
}
template<typename PassT>
gpu::Batch *pointcloud_sub_pass_setup_implementation(PassT &sub_ps,
Object *object,
GPUMaterial *gpu_material)
{
BLI_assert(object->type == OB_POINTCLOUD);
PointCloud &pointcloud = DRW_object_get_data_for_drawing<PointCloud>(*object);
/* An empty point cloud should never result in a draw-call. However, the buffer binding commands
* will still be executed. In this case, in order to avoid assertion, we bind dummy VBOs. */
bool is_empty = pointcloud.totpoint == 0;
PointCloudModule &module = *drw_get().data->pointcloud_module;
/* Fix issue with certain driver not drawing anything if there is no texture bound to
* "ac", "au", "u" or "c". */
sub_ps.bind_texture("u", module.dummy_vbo);
sub_ps.bind_texture("au", module.dummy_vbo);
sub_ps.bind_texture("c", module.dummy_vbo);
sub_ps.bind_texture("ac", module.dummy_vbo);
gpu::VertBuf *pos_rad_buf = pointcloud_position_and_radius_get(&pointcloud);
sub_ps.bind_texture("ptcloud_pos_rad_tx", is_empty ? module.dummy_vbo : pos_rad_buf);
if (gpu_material != nullptr) {
ListBase gpu_attrs = GPU_material_attributes(gpu_material);
LISTBASE_FOREACH (GPUMaterialAttribute *, gpu_attr, &gpu_attrs) {
char sampler_name[32];
/** NOTE: Reusing curve attribute function. */
drw_curves_get_attribute_sampler_name(gpu_attr->name, sampler_name);
gpu::VertBuf **attribute_buf = DRW_pointcloud_evaluated_attribute(&pointcloud,
gpu_attr->name);
sub_ps.bind_texture(sampler_name,
(attribute_buf && !is_empty) ? attribute_buf : &module.dummy_vbo);
}
}
gpu::Batch *geom = pointcloud_surface_get(&pointcloud);
return geom;
}
gpu::Batch *pointcloud_sub_pass_setup(PassMain::Sub &sub_ps,
Object *object,
GPUMaterial *gpu_material)
{
return pointcloud_sub_pass_setup_implementation(sub_ps, object, gpu_material);
}
gpu::Batch *pointcloud_sub_pass_setup(PassSimple::Sub &sub_ps,
Object *object,
GPUMaterial *gpu_material)
{
return pointcloud_sub_pass_setup_implementation(sub_ps, object, gpu_material);
}
} // namespace blender::draw