Blender如何优雅的使用OpenGL之VertBuffer

本文介绍了在Blender中使用GPUVertBuf结构体和相关类(如VertBuf和GLVertBuf)处理VBO,包括数据格式定义、内存使用跟踪、顶点数据管理以及与OpenGL的整合,强调了无符号字符类型指针在处理不同格式顶点数据中的灵活性和效率。
摘要由CSDN通过智能技术生成
在blender中,对VBO定义分了三个层次:
  1. 使用GPUVertBuf结构体在各种对象间传递数据;
  2. 使用VertBuf类描述顶点数据的数据结构
  3. 使用GLVertBuf类补充和OpenGL相关的参数
在blender中使用VertBuf描述一个VBO对象,需要包含以下接口和信息:
  1. static size_t memory_usage;:静态成员变量,用于跟踪VertBuf类的内存使用情况。

  2. GPUVertFormat format = {};GPUVertFormat类型的成员变量,用于指定顶点的格式。

  3. uint vertex_len = 0;:无符号整数类型的成员变量,表示要绘制的顶点数量。

  4. uint vertex_alloc = 0;:无符号整数类型的成员变量,表示分配的顶点数据的数量。

  5. GPUVertBufStatus flag = GPU_VERTBUF_INVALID;GPUVertBufStatus类型的成员变量,表示顶点缓冲区的状态。

  6. uchar *data = nullptr;:指向无符号字符类型的指针,用于存储顶点数据的内存地址,

    在这个代码中,使用一个指向无符号字符类型的指针来表示顶点数据的存储位置,可能是为了灵活性和通用性的考虑。

    无符号字符类型(uchar)是一个字节大小的数据类型,可以用来表示任意类型的数据。通过使用指向无符号字符类型的指针,可以将顶点数据的存储位置指向任意类型的数据,而不仅仅局限于特定的数据类型。

    这种灵活性对于处理不同格式的顶点数据非常有用。顶点数据可以包含各种属性,如位置、颜色、法线等,每个属性可能有不同的数据类型和格式。使用指向无符号字符类型的指针,可以轻松地处理不同格式的顶点数据,而不需要为每种格式定义不同的数据结构。

    此外,使用指针还可以方便地进行内存管理和数据传输。通过在指针中存储顶点数据的起始地址,可以轻松地在内存中分配和释放顶点数据,以及在需要时将数据传输到显存中供GPU使用。

    总而言之,使用指向无符号字符类型的指针来表示顶点数据的存储位置,提供了灵活性、通用性和方便性,使得处理不同格式的顶点数据更加简便和高效。

  7. GPUUsageType extended_usage_;GPUUsageType类型的成员变量,表示扩展的使用类型。

  8. GPUUsageType usage_;GPUUsageType类型的成员变量,表示使用类型的提示,用于OpenGL优化。

  9. int handle_refcount_ = 1;:整数类型的成员变量,表示引用计数器,用于避免释放GPUVertBuf对象。

namespace blender::gpu {

/**
 * Implementation of Vertex Buffers.
 * Base class which is then specialized for each implementation (GL, VK, ...).
 */
class VertBuf {
 public:
  static size_t memory_usage;

  GPUVertFormat format = {};
  /** Number of verts we want to draw. */
  uint vertex_len = 0;
  /** Number of verts data. */
  uint vertex_alloc = 0;
  /** Status flag. */
  GPUVertBufStatus flag = GPU_VERTBUF_INVALID;
  /** NULL indicates data in VRAM (unmapped) */
  uchar *data = nullptr;

#ifndef NDEBUG
  /** Usage including extended usage flags. */
  GPUUsageType extended_usage_ = GPU_USAGE_STATIC;
#endif

 protected:
  /** Usage hint for GL optimization. */
  GPUUsageType usage_ = GPU_USAGE_STATIC;

 private:
  /** This counter will only avoid freeing the #GPUVertBuf, not the data. */
  int handle_refcount_ = 1;

 public:
  VertBuf();
  virtual ~VertBuf();

  void init(const GPUVertFormat *format, GPUUsageType usage);
  void clear();

  /* Data management. */
  void allocate(uint vert_len);
  void resize(uint vert_len);
  void upload();
  virtual void bind_as_ssbo(uint binding) = 0;
  virtual void bind_as_texture(uint binding) = 0;

  virtual void wrap_handle(uint64_t handle) = 0;

  VertBuf *duplicate();

  /* Size of the data allocated. */
  size_t size_alloc_get() const
  {
    BLI_assert(format.packed);
    return vertex_alloc * format.stride;
  }
  /* Size of the data uploaded to the GPU. */
  size_t size_used_get() const
  {
    BLI_assert(format.packed);
    return vertex_len * format.stride;
  }

  void reference_add()
  {
    handle_refcount_++;
  }
  void reference_remove()
  {
    BLI_assert(handle_refcount_ > 0);
    handle_refcount_--;
    if (handle_refcount_ == 0) {
      delete this;
    }
  }

  GPUUsageType get_usage_type() const
  {
    return usage_;
  }

  virtual void update_sub(uint start, uint len, const void *data) = 0;
  virtual void read(void *data) const = 0;

 protected:
  virtual void acquire_data() = 0;
  virtual void resize_data() = 0;
  virtual void release_data() = 0;
  virtual void upload_data() = 0;
  virtual void duplicate_data(VertBuf *dst) = 0;
};

/* Syntactic sugar. */
static inline GPUVertBuf *wrap(VertBuf *vert)
{
  return reinterpret_cast<GPUVertBuf *>(vert);
}
static inline VertBuf *unwrap(GPUVertBuf *vert)
{
  return reinterpret_cast<VertBuf *>(vert);
}
static inline const VertBuf *unwrap(const GPUVertBuf *vert)
{
  return reinterpret_cast<const VertBuf *>(vert);
}

}  // namespace blender::gpu
最后使用GLVertBuf补充与OpenGL相关的参数
  1. GLuint vbo_id_ = 0;:无符号整数类型的成员变量,表示OpenGL缓冲区的句柄。

  2. ::GPUTexture *buffer_texture_ = nullptr;:指向GPUTexture类型的指针,表示如果缓冲区被绑定为缓冲区纹理,则使用的纹理。在首次使用时进行初始化。

  3. bool is_wrapper_ = false;:布尔类型的成员变量,表示缓冲区句柄是否由GLVertBuf包装,即我们不拥有它并且不应该释放它。

  4. size_t vbo_size_ = 0;:表示在GPU上的缓冲区大小

namespace blender {
namespace gpu {

class GLVertBuf : public VertBuf {
  friend class GLTexture;    /* For buffer texture. */
  friend class GLShader;     /* For transform feedback. */
  friend class GLStorageBuf; /* For sub copy. */

 private:
  /** OpenGL buffer handle. Init on first upload. Immutable after that. */
  GLuint vbo_id_ = 0;
  /** Texture used if the buffer is bound as buffer texture. Init on first use. */
  ::GPUTexture *buffer_texture_ = nullptr;
  /** Defines whether the buffer handle is wrapped by this GLVertBuf, i.e. we do not own it and
   * should not free it. */
  bool is_wrapper_ = false;
  /** Size on the GPU. */
  size_t vbo_size_ = 0;

 public:
  void bind();

  void update_sub(uint start, uint len, const void *data) override;

  void read(void *data) const override;

  void wrap_handle(uint64_t handle) override;

 protected:
  void acquire_data() override;
  void resize_data() override;
  void release_data() override;
  void upload_data() override;
  void duplicate_data(VertBuf *dst) override;
  void bind_as_ssbo(uint binding) override;
  void bind_as_texture(uint binding) override;

 private:
  bool is_active() const;

  MEM_CXX_CLASS_ALLOC_FUNCS("GLVertBuf");
};

static inline GLenum to_gl(GPUUsageType type)
{
  switch (type) {
    case GPU_USAGE_STREAM:
      return GL_STREAM_DRAW;
    case GPU_USAGE_DYNAMIC:
      return GL_DYNAMIC_DRAW;
    case GPU_USAGE_STATIC:
    case GPU_USAGE_DEVICE_ONLY:
      return GL_STATIC_DRAW;
    default:
      BLI_assert(0);
      return GL_STATIC_DRAW;
  }
}

static inline GLenum to_gl(GPUVertCompType type)
{
  switch (type) {
    case GPU_COMP_I8:
      return GL_BYTE;
    case GPU_COMP_U8:
      return GL_UNSIGNED_BYTE;
    case GPU_COMP_I16:
      return GL_SHORT;
    case GPU_COMP_U16:
      return GL_UNSIGNED_SHORT;
    case GPU_COMP_I32:
      return GL_INT;
    case GPU_COMP_U32:
      return GL_UNSIGNED_INT;
    case GPU_COMP_F32:
      return GL_FLOAT;
    case GPU_COMP_I10:
      return GL_INT_2_10_10_10_REV;
    default:
      BLI_assert(0);
      return GL_FLOAT;
  }
}

}  // namespace gpu
}  // namespace blender

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值