This introduces the next custom vertex description format: fvfex. The earliest d3d used fvf to describe the vertex format in a vertex buffer, because at that time, the element types in the vertex were several, which can be written into a fixed form, however, in order to allow users to define the element type of vertices, d3d adopted a very difficult vertex declaration to define a VB vertex format. Of course, there is no way to do this, after all, d3d should consider the needs of all users. however, in my opinion, the types of vertex elements used in an engine are still very limited (in the current engine, apart from the Special Vertex data used on the surface, most vertex data can be described in the most primitive fvf format). vertex declaration is inconvenient for creation, modification, and resolution, therefore, I have defined a format similar to fvf system. I call it fvfex system. It uses an unsigned int64 to represent a vertex format, in this way, up to 64 different vertex element types can be supported. Each vertex element in the engine is allocated to a specific bit and defined in a header file, as shown in the following figure: typedef unsigned _ int64 fvfex; # define fvfex_mask (V) (fvfex) 0x1) <(V) # define fvfex_null 0x0 # define fvfex_xyz0 fvfex_mask (0) # define fvfex_xyz1 fvfex_mask (1) # define fvfex_normal0 Fvfex_mask (2) # define fvfex_normal1 Fvfex_mask (3) # define fvfex_binormal Fvfex_mask (4) # define fvfex_tangent Fvfex_mask (5) // more vertex element types... A table matches These macro definitions. In this table, each custom vertex element type has some corresponding information, which can be used to fill in a d3dvertexelement9 structure, struct fvfexinfo { Fvfexinfo (fvfex fvf, int type, DWORD size, int usage, int usageindex) { M_fvf = fvf; M_type = type; M_size = size; M_usage = usage; M_usageindex = usageindex; } Fvfex m_fvf; Int m_type; DWORD m_size; Int m_usage; Int m_usageindex;}; fvfexinfo g_afvflist [] = { Fvfexinfo (fvfex_xyz0, D3ddecltypex_float3, 12, D3ddeclusagex_position, 0 ), Fvfexinfo (fvfex_xyz1, D3ddecltypex_float3, 12, D3ddeclusagex_position, 1 ), Fvfexinfo (fvfex_normal0, D3ddecltypex_float3, 12, D3ddeclusagex_normal, 0 ), Fvfexinfo (fvfex_normal1, D3ddecltypex_float3, 12, D3ddeclusagex_normal, 1 ), Fvfexinfo (fvfex_binormal, D3ddecltypex_float3, 12, D3ddeclusagex_binormal, 0 ), Fvfexinfo (fvfex_tangent, D3ddecltypex_float3, 12, D3ddeclusagex_tangent, 0), // more vertex element types ...}; In this way, we can use this table to convert a fvfex format + A stream number into a vertex declaration. Based on the test results many years ago, it is very slow to create a vertex declaration. Therefore, we will maintain a hash table and use it when binding a VB table, we can find the corresponding vertex declaration based on the fvfex and stream numbers as the key, and then set it to the device.
We will convert fvfex to vertex declaration only when binding a VB to a device, while in other places of the engine, we only use fvfex to define a Verter buffer's vertex format. For this reason, I have written some functions to support this system. Some of the common examples are:
Extern DWORD fvfsize (fvfex fvf); // obtain the data size of a vertex, in byte Extern int fvfoffset (fvfex fvf, fvfex fvfpart); // get the offset of an element in the vertex format, in byte, return-1 if error Extern void fvfcopy (DWORD nvertice, void * pdest, fvfex fvfdest, void * psrc, fvfex fvfsrc); // copy all the copyable elements from source buffer to DEST Buffer Extern int fvftod3dvertexelement9 (fvfex fvftotal, fvfex fvf, d3dvertexelement9 * pelements, int istream); // convert it to the d3dvertexelement9 Structure ... This is roughly the case for fvfex. Next we will introduce mesh resources.