这篇是想讲一下Blender中对于Mesh对象的资源管理机制,为了脉络清晰,就先自下而上的梳理一下相关的资源吧。
1.GUPBatch
这是用来存储网格几何信息的结构体
typedef struct GPUBatch {
/** verts[0] is required, others can be NULL */
GPUVertBuf *verts[GPU_BATCH_VBO_MAX_LEN];
/** Instance attributes. */
GPUVertBuf *inst[GPU_BATCH_INST_VBO_MAX_LEN];
/** NULL if element list not needed */
GPUIndexBuf *elem;
/** Resource ID attribute workaround. */
GPUStorageBuf *resource_id_buf;
/** Bookkeeping. */
eGPUBatchFlag flag;
/** Type of geometry to draw. */
GPUPrimType prim_type;
/** Current assigned shader. DEPRECATED. Here only for uniform binding. */
struct GPUShader *shader;
} GPUBatch;
这个结构体用于管理GPU批处理相关的信息。让我来解释一下其中的一些重要成员变量:
-
verts[GPU_BATCH_VBO_MAX_LEN]
: 这是一个GPUVertBuf指针数组,用于存储顶点缓冲区。verts[0]
是必需的,其他位置可以是NULL。 -
inst[GPU_BATCH_INST_VBO_MAX_LEN]
: 这是一个GPUVertBuf指针数组,用于存储实例属性的顶点缓冲区。 -
elem
: 这是一个GPUIndexBuf指针,用于存储元素列表的索引缓冲区。如果不需要元素列表,则为NULL。 -
resource_id_buf
: 这是一个GPUStorageBuf指针,用于资源ID属性的缓冲区。 -
flag
: 这是一个枚举类型eGPUBatchFlag
,用于记录一些状态信息。 -
prim_type
: 这是一个枚举类型GPUPrimType
,表示要绘制的几何类型。 -
shader
: 这是一个指向GPUShader结构体的指针,用于表示当前分配的着色器。在注释中标记为DEPRECATED,可能是因为这个成员变量已经不推荐使用,只用于统一绑定。
2. MeshBatchList
这个结构体是用来描述Mesh对象用到的各种用途的GUPBatch.
struct MeshBatchList {
/* Surfaces / Render */
GPUBatch *surface;
GPUBatch *surface_weights;
/* Edit mode */
GPUBatch *edit_triangles;
GPUBatch *edit_vertices;
GPUBatch *edit_edges;
GPUBatch *edit_vnor;
GPUBatch *edit_lnor;
GPUBatch *edit_fdots;
GPUBatch *edit_mesh_analysis;
GPUBatch *edit_skin_roots;
/* Edit UVs */
GPUBatch *edituv_faces_stretch_area;
GPUBatch *edituv_faces_stretch_angle;
GPUBatch *edituv_faces;
GPUBatch *edituv_edges;
GPUBatch *edituv_verts;
GPUBatch *edituv_fdots;
/* Edit selection */
GPUBatch *edit_selection_verts;
GPUBatch *edit_selection_edges;
GPUBatch *edit_selection_faces;
GPUBatch *edit_selection_fdots;
/* Common display / Other */
GPUBatch *all_verts;
GPUBatch *all_edges;
GPUBatch *loose_edges;
GPUBatch *edge_detection;
/* Individual edges with face normals. */
GPUBatch *wire_edges;
/* Loops around faces. no edges between selected faces */
GPUBatch *wire_loops;
/* Same as wire_loops but only has uvs. */
GPUBatch *wire_loops_uvs;
GPUBatch *sculpt_overlays;
GPUBatch *surface_viewer_attribute;
};
这段代码定义了一个名为MeshBatchList
的结构体,用于管理不同类型的GPUBatch
对象。让我来解释一下这个结构体中的一些重要成员变量:
-
surface
,surface_weights
: 用于表示表面和表面权重的GPUBatch
对象。 -
edit_triangles
,edit_vertices
,edit_edges
,edit_vnor
,edit_lnor
,edit_fdots
,edit_mesh_analysis
,edit_skin_roots
: 用于编辑模式下的三角形、顶点、边缘、顶点法线、面法线、面点、网格分析和皮肤根的GPUBatch
对象。 -
edituv_faces_stretch_area
,edituv_faces_stretch_angle
,edituv_faces
,edituv_edges
,edituv_verts
,edituv_fdots
: 用于编辑UV的面拉伸区域、面拉伸角度、面、边缘、顶点和面点的GPUBatch
对象。 -
edit_selection_verts
,edit_selection_edges
,edit_selection_faces
,edit_selection_fdots
: 用于编辑选择的顶点、边缘、面和面点的GPUBatch
对象。 -
all_verts
,all_edges
,loose_edges
,edge_detection
: 用于通用显示和其他用途的所有顶点、所有边缘、松散边缘和边缘检测的GPUBatch
对象。 -
wire_edges
,wire_loops
,wire_loops_uvs
: 用于具有面法线的单独边缘、面周围的循环(选定面之间没有边缘)和仅具有UV的线圈的GPUBatch
对象。 -
sculpt_overlays
,surface_viewer_attribute
: 用于雕刻叠加和表面查看器属性的GPUBatch
对象。
这个结构体的设计旨在管理不同类型的GPUBatch
对象,以便在渲染和编辑模式下有效地管理和使用GPU资源
3.MeshBufferList
这用来管理GPUBuffer,包含一个管理VBO资源的结构体和一个管理IBO资源的结构体。
struct MeshBufferList {
/* Every VBO below contains at least enough data for every loop in the mesh
* (except fdots and skin roots). For some VBOs, it extends to (in this exact order) :
* loops + loose_edges * 2 + loose_verts */
struct {
GPUVertBuf *pos_nor; /* extend */
GPUVertBuf *lnor; /* extend */
GPUVertBuf *edge_fac; /* extend */
GPUVertBuf *weights; /* extend */
GPUVertBuf *uv;
GPUVertBuf *tan;
GPUVertBuf *sculpt_data;
GPUVertBuf *orco;
/* Only for edit mode. */
GPUVertBuf *edit_data; /* extend */
GPUVertBuf *edituv_data;
GPUVertBuf *edituv_stretch_area;
GPUVertBuf *edituv_stretch_angle;
GPUVertBuf *mesh_analysis;
GPUVertBuf *fdots_pos;
GPUVertBuf *fdots_nor;
GPUVertBuf *fdots_uv;
// GPUVertBuf *fdots_edit_data; /* inside fdots_nor for now. */
GPUVertBuf *fdots_edituv_data;
GPUVertBuf *skin_roots;
/* Selection */
GPUVertBuf *vert_idx; /* extend */
GPUVertBuf *edge_idx; /* extend */
GPUVertBuf *face_idx;
GPUVertBuf *fdot_idx;
GPUVertBuf *attr[GPU_MAX_ATTR];
GPUVertBuf *attr_viewer;
} vbo;
/* Index Buffers:
* Only need to be updated when topology changes. */
struct {
/* Indices to vloops. Ordered per material. */
GPUIndexBuf *tris;
/* Loose edges last. */
GPUIndexBuf *lines;
/* Sub buffer of `lines` only containing the loose edges. */
GPUIndexBuf *lines_loose;
GPUIndexBuf *points;
GPUIndexBuf *fdots;
/* 3D overlays. */
/* no loose edges. */
GPUIndexBuf *lines_paint_mask;
GPUIndexBuf *lines_adjacency;
/* Uv overlays. (visibility can differ from 3D view) */
GPUIndexBuf *edituv_tris;
GPUIndexBuf *edituv_lines;
GPUIndexBuf *edituv_points;
GPUIndexBuf *edituv_fdots;
} ibo;
};
这段代码定义了一个名为MeshBufferList
的结构体,用于管理不同类型的顶点缓冲对象(VBO)和索引缓冲对象(IBO),以便有效地存储和更新网格数据。让我来解释一下这个结构体中的一些重要成员变量:
-
vbo
: 这个结构体成员包含了各种类型的顶点缓冲对象,用于存储网格的位置、法线、边缘因子、权重、UV坐标、切线、雕刻数据、原始坐标等信息。其中一些顶点缓冲对象在编辑模式下扩展到包含编辑数据、编辑UV数据、编辑UV拉伸区域、编辑UV拉伸角度、网格分析、面点位置、面点法线、面点UV、编辑UV数据等信息。还包括用于选择的顶点索引、边缘索引、面索引、面点索以及其他属性的顶点缓冲对象。 -
ibo
: 这个结构体成员包含了不同类型的索引缓冲对象,用于存储网格的三角形索引、边缘索引、点索引、面点索引等信息。其中包括三角形索引、边缘索引、松散边缘索引、点索引、面点索引等索引缓冲对象,以及用于3D叠加和UV叠加的索引缓冲对象。
这个结构体的设计旨在有效地管理和更新网格数据的顶点和索引缓冲对象,以便在渲染和编辑模式下高效地使用GPU资源。
4.MeshBufferCache
管理Buffer的缓存对象
/**
* Data that are kept around between extractions to reduce rebuilding time.
*
* - Loose geometry.
*/
struct MeshBufferCache {
MeshBufferList buff;
MeshExtractLooseGeom loose_geom;
SortedFaceData face_sorted;
};
这段代码定义了一个名为MeshBufferCache
的结构体,用于在提取之间保留数据以减少重建时间。让我来解释一下这个结构体中的一些重要成员变量:
-
buff
: 这是一个MeshBufferList
类型的成员变量,用于存储顶点缓冲对象和索引缓冲对象,以便在提取之间共享和重用网格数据。 -
loose_geom
: 这是一个MeshExtractLooseGeom
类型的成员变量,用于存储松散几何数据。松散几何通常指的是不属于任何面或边的额外几何数据,例如孤立的顶点或边。 -
face_sorted
: 这是一个SortedFaceData
类型的成员变量,用于存储经过排序的面数据。面数据可能需要按照特定的顺序进行排序以提高渲染或其他操作的效率。
通过使用MeshBufferCache
结构体,可以在不同的提取操作之间保留和共享关键数据,从而减少重建时间并提高性能。这种设计有助于优化处理网格数据的效率。
5.MeshBatchCache
管理Mesh所以的资源的一个结构体对象
struct MeshBatchCache {
MeshBufferCache final, cage, uv_cage;
MeshBatchList batch;
/* Index buffer per material. These are sub-ranges of `ibo.tris`. */
GPUIndexBuf **tris_per_mat;
GPUBatch **surface_per_mat;
DRWSubdivCache *subdiv_cache;
DRWBatchFlag batch_requested;
DRWBatchFlag batch_ready;
/* Settings to determine if cache is invalid. */
int edge_len;
int tri_len;
int face_len;
int vert_len;
int mat_len;
/* Instantly invalidates cache, skipping mesh check */
bool is_dirty;
bool is_editmode;
bool is_uvsyncsel;
DRW_MeshWeightState weight_state;
DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time;
DRW_Attributes attr_used, attr_needed, attr_used_over_time;
int lastmatch;
/* Valid only if edge_detection is up to date. */
bool is_manifold;
/* Total areas for drawing UV Stretching. Contains the summed area in mesh
* space (`tot_area`) and the summed area in uv space (`tot_uvarea`).
*
* Only valid after `DRW_mesh_batch_cache_create_requested` has been called. */
float tot_area, tot_uv_area;
bool no_loose_wire;
eV3DShadingColorType color_type;
bool pbvh_is_drawing;
};
这段代码定义了一个名为MeshBatchCache
的结构体,用于缓存和管理批处理网格数据的相关信息。让我来解释一下这个结构体中的一些重要成员变量:
-
final
,cage
,uv_cage
: 这些成员变量是MeshBufferCache
类型的结构体,用于存储最终网格、笼子网格和UV笼子网格的缓存数据。 -
batch
: 这是一个MeshBatchList
类型的成员变量,用于存储批处理网格的列表数据。 -
tris_per_mat
: 这是一个指向GPU索引缓冲对象数组的指针,用于存储每种材质的索引缓冲对象的子范围。 -
surface_per_mat
: 这是一个指向GPUBatch对象数组的指针,用于存储每种材质的批处理对象。 -
subdiv_cache
: 这是一个指向DRWSubdivCache对象的指针,用于存储细分缓存数据。 -
batch_requested
,batch_ready
: 这些成员变量用于标记批处理请求和准备就绪的状态。 -
其他成员变量如
edge_len
,tri_len
,face_len
,vert_len
,mat_len
等用于确定缓存是否有效的设置,以及一些标志变量如is_dirty
,is_editmode
,is_uvsyncsel
等。 -
tot_area
,tot_uv_area
: 这些成员变量存储绘制UV拉伸所需的总面积数据,包括在网格空间和UV空间中的总面积。 -
其他成员变量如
no_loose_wire
,color_type
,pbvh_is_drawing
等用于存储与绘制和渲染相关的信息。
通过MeshBatchCache
结构体,可以有效地管理批处理网格数据的缓存和相关信息,以提高渲染和处理效率。
6.GPUBatch和MeshBufferList
功能区别分析
GPUBatch
和MeshBufferList
都用于存储GPUVertBuf
和GPUIndexBuf
类型的数据,但它们在功能上有一些区别:
-
MeshBufferList
: 这个结构体主要用于存储顶点缓冲对象和索引缓冲对象,通常用于存储单个网格的顶点和索引数据。MeshBufferList
旨在提供一种组织和管理网格数据的方式,以便在提取之间共享和重用数据。 -
GPUBatch
: 这个结构体通常用于表示一批渲染对象,其中包含了与渲染相关的数据,例如顶点缓冲对象、索引缓冲对象、材质信息等。GPUBatch
可以看作是一组渲染数据的集合,用于一次性提交给GPU进行渲染。
因此,MeshBufferList
更专注于存储单个网格的顶点和索引数据,而GPUBatch
则更多地用于表示一批渲染对象,其中可能包含多个网格的数据以及其他与渲染相关的信息。