OBS image-source插件
+ -

OBS色源渲染

2024-06-05 17 0

OBS色源渲染使用函数color_source_render实现

static void color_source_render(void *data, gs_effect_t *effect)
{
    UNUSED_PARAMETER(effect);

    struct color_source *context = data;

    /* need linear path for correct alpha blending */
    //是否需要半透明融合?
    const bool linear_srgb = gs_get_linear_srgb() ||(context->color.w < 1.0f);

    const bool previous = gs_framebuffer_srgb_enabled();
    gs_enable_framebuffer_srgb(linear_srgb);

    if (linear_srgb)
        color_source_render_helper(context, &context->color_srgb);
    else
        color_source_render_helper(context, &context->color);

    gs_enable_framebuffer_srgb(previous);
}

渲染分析

    const bool linear_srgb = gs_get_linear_srgb() ||(context->color.w < 1.0f);

这一句判断了w即alapha的值小于1.0,故需要进行alpha半透明融合。

gs_enable_framebuffer_srgb函数如下:

void gs_enable_framebuffer_srgb(bool enable)
{
    graphics_t *graphics = thread_graphics;

    if (!gs_valid("gs_enable_framebuffer_srgb"))
        return;

    graphics->exports.device_enable_framebuffer_srgb(graphics->device, enable);
}

其对应的D3D11函数为:

void device_enable_framebuffer_srgb(gs_device_t *device, bool enable)
{
    if (device->curFramebufferSrgb != enable) {
        device->curFramebufferSrgb = enable;
        device->curFramebufferInvalidate = true;
    }
}

color_source_render_helper函数原码如下:

static void color_source_render_helper(struct color_source *context,
                       struct vec4 *colorVal)
{
    gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
    gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
    gs_technique_t *tech = gs_effect_get_technique(solid, "Solid");

//设置颜色值到像素着色器pass中的参数值,后面会使用upload_parameters更新到着色器中;
    gs_effect_set_vec4(color, colorVal);

    gs_technique_begin(tech);
    gs_technique_begin_pass(tech, 0);

    gs_draw_sprite(0, 0, context->width, context->height);

    gs_technique_end_pass(tech);
    gs_technique_end(tech);
}

从这里大概来看,使用的是着色器来进行渲染的。着色器源文件为solid.effect。

    filename = obs_find_data_file("solid.effect");
    video->solid_effect = gs_effect_create_from_file(filename, NULL);
    bfree(filename);

而开始tech和pass也仅仅是设置要使用的TECH,在draw时会自动调用。

size_t gs_technique_begin(gs_technique_t *tech)
{
    if (!tech)
        return 0;

    tech->effect->cur_technique = tech;
    tech->effect->graphics->cur_effect = tech->effect;

    return tech->passes.num;
}

设置当前pass是会加载ps和VS着色器,并加载参数到gs_effect_set_vec4设置的参数到着色器中。

bool gs_technique_begin_pass(gs_technique_t *tech, size_t idx)
{
    struct gs_effect_pass *passes;
    struct gs_effect_pass *cur_pass;

    if (!tech || idx >= tech->passes.num)
        return false;

    passes = tech->passes.array;
    cur_pass = passes + idx;

    tech->effect->cur_pass = cur_pass;
    gs_load_vertexshader(cur_pass->vertshader);
    gs_load_pixelshader(cur_pass->pixelshader);
    upload_parameters(tech->effect, false);

    return true;
}

参数设置

    gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
    gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
    gs_effect_set_vec4(color, colorVal);

相关函数如下:

void gs_effect_set_vec4(gs_eparam_t *param, const struct vec4 *val)
{
    effect_setval_inline(param, val, sizeof(struct vec4));
}

static inline void effect_setval_inline(gs_eparam_t *param, const void *data,size_t size)
{
    bool size_changed;
...
    size_changed = param->cur_val.num != size;

    if (size_changed)
        da_resize(param->cur_val, size);

    if (size_changed || memcmp(param->cur_val.array, data, size) != 0) 
    {
        memcpy(param->cur_val.array, data, size);
        param->changed = true;
    }

194316447046

0 篇笔记 写笔记

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

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

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