OBS image-source插件
+ -

gs_draw_sprite渲染

2024-06-19 7 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);
}

坐标如下:
162513428986

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!