gs_draw_sprite渲染
2024-06-19
13
0
关于gs_draw_sprite函数
void gs_draw_sprite(gs_texture_t *tex, uint32_t flip, uint32_t width,
uint32_t height)
{
graphics_t *graphics = thread_graphics;
float fcx, fcy;
struct gs_vb_data *data;
//没有指定texture,执行else
if (tex) {
if (gs_get_texture_type(tex) != GS_TEXTURE_2D) {
blog(LOG_ERROR, "A sprite must be a 2D texture");
return;
}
} else {
if (!width || !height) {
blog(LOG_ERROR, "A sprite cannot be drawn without "
"a width/height");
return;
}
}
//因为有指定,直接用传递的width和height
fcx = width ? (float)width : (float)gs_texture_get_width(tex);
fcy = height ? (float)height : (float)gs_texture_get_height(tex);
//返回顶点向量
data = gs_vertexbuffer_get_data(graphics->sprite_buffer);
if (tex && gs_texture_is_rect(tex))
build_sprite_rect(data, tex, fcx, fcy, flip);//填充顶点数据和纹理数据到顶点坐标
else
build_sprite_norm(data, fcx, fcy, flip);//flip=0不裁剪,这里指定uv坐标
//加载数据到对应的缓冲区
gs_vertexbuffer_flush(graphics->sprite_buffer);
//设置sprite_buffer为device->curVertexBuffer
gs_load_vertexbuffer(graphics->sprite_buffer);
//使用的是顶点缓制,索引置为NULL
gs_load_indexbuffer(NULL);
//使用上面的参数并调用Draw
gs_draw(GS_TRISTRIP, 0, 0);
}
顶点的来源
顶点来源于
struct gs_vb_data * data = gs_vertexbuffer_get_data(graphics->sprite_buffer);
函数如下:
struct gs_vb_data *gs_vertexbuffer_get_data(const gs_vertbuffer_t *vertbuffer)
{
if (!gs_valid_p("gs_vertexbuffer_get_data", vertbuffer))
return NULL;
return thread_graphics->exports.gs_vertexbuffer_get_data(vertbuffer);
}
在d3d11中如下:
struct gs_vb_data *gs_vertexbuffer_get_data(const gs_vertbuffer_t *vertbuffer)
{
return vertbuffer->vbd.data;
}
其实就是:graphics->sprite_buffer.vbd.data
其中vertbuffer
gs_vertbuffer_t vertbuffer;
VBDataPtr vbd;
struct VBDataPtr {
gs_vb_data *data;
inline VBDataPtr(gs_vb_data *data) : data(data) {}
inline ~VBDataPtr() { gs_vbdata_destroy(data); }
};
struct gs_vb_data {
size_t num;
struct vec3 *points;
struct vec3 *normals;
struct vec3 *tangents;
uint32_t *colors;
size_t num_tex;
struct gs_tvertarray *tvarray;
};
更多见:https://www.vaczh.com/article/detail-89.html
顶点及纹理的位置
build_sprite_norm函数
static inline void build_sprite_norm(struct gs_vb_data *data,
float fcx , //=width
float fcy, //=height
uint32_t flip//=0
)
{
float start_u, end_u;
float start_v, end_v;
//flip=0,故起始为0,结束为1.0
assign_sprite_uv(&start_u, &end_u, (flip & GS_FLIP_U) != 0);
assign_sprite_uv(&start_v, &end_v, (flip & GS_FLIP_V) != 0);
build_sprite(data, fcx, fcy, start_u, end_u, start_v, end_v);
}
static inline void assign_sprite_uv(float *start, float *end, bool flip)
{
if (!flip) {
*start = 0.0f;
*end = 1.0f;
} else {
*start = 1.0f;
*end = 0.0f;
}
}
build_sprite参数如下
static void build_sprite(struct gs_vb_data *data,
float fcx, //=width
float fcy,//height
float start_u,//=0
float end_u, //=1.0
float start_v, //=0
float end_v //=1.o
)
{
struct vec2 *tvarray = data->tvarray[0].array;
//设置顶点坐标值
vec3_zero(data->points);//第一个点为(0,0,0)
vec3_set(data->points + 1, fcx, 0.0f, 0.0f);
vec3_set(data->points + 2, 0.0f, fcy, 0.0f);
vec3_set(data->points + 3, fcx, fcy, 0.0f);
//设置纹理坐标
vec2_set(tvarray, start_u, start_v);
vec2_set(tvarray + 1, end_u, start_v);
vec2_set(tvarray + 2, start_u, end_v);
vec2_set(tvarray + 3, end_u, end_v);
}
坐标如下: