OBS图形及渲染
+ -

渲染流程及纹理关系render_video

2024-10-17 15 0

160512815918

渲染主函数为render_video

static inline void render_video(struct obs_core_video *video, bool raw_active,
                const bool gpu_active, int cur_texture)
{
    gs_begin_scene();

    gs_enable_depth_test(false);
    gs_set_cull_mode(GS_NEITHER);

    render_main_texture(video);

    if (raw_active || gpu_active) {
        gs_texture_t *texture = render_output_texture(video);

#ifdef _WIN32
        if (gpu_active)
            gs_flush();
#endif

        if (video->gpu_conversion)
            render_convert_texture(video, texture);

#ifdef _WIN32
        if (gpu_active) {
            gs_flush();
            output_gpu_encoders(video, raw_active);
        }
#endif

        if (raw_active)
            stage_output_texture(video, cur_texture);
    }

    gs_set_render_target(NULL, NULL);
    gs_enable_blending(true);

    gs_end_scene();
}

render_main_texture将各个加入的视频图片渲染到video->render_texture上

static const char *render_main_texture_name = "render_main_texture";
static inline void render_main_texture(struct obs_core_video *video)
{
    profile_start(render_main_texture_name);
    GS_DEBUG_MARKER_BEGIN(GS_DEBUG_COLOR_MAIN_TEXTURE,render_main_texture_name);

    struct vec4 clear_color;
    vec4_set(&clear_color, 0.0f, 0.0f, 0.0f, 0.0f);

    gs_set_render_target(video->render_texture, NULL);
    gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0);

    set_render_size(video->base_width, video->base_height);

    pthread_mutex_lock(&obs->data.draw_callbacks_mutex);

    for (size_t i = obs->data.draw_callbacks.num; i > 0; i--) {
        struct draw_callback *callback;
        callback = obs->data.draw_callbacks.array + (i - 1);
        callback->draw(callback->param, video->base_width,video->base_height);
    }

    pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);

    obs_view_render(&obs->data.main_view);

    video->texture_rendered = true;

    GS_DEBUG_MARKER_END();
    profile_end(render_main_texture_name);
}

如果画布和输出大小不致,则需要将video->render_texture按比例缩放到video->output_texture上,如果相等,就直接用video->render_texture。

static inline gs_texture_t *render_output_texture(struct obs_core_video *video)
{
    gs_texture_t *texture = video->render_texture;
    gs_texture_t *target = video->output_texture;
    uint32_t width = gs_texture_get_width(target);
    uint32_t height = gs_texture_get_height(target);

    gs_effect_t *effect = get_scale_effect(video, width, height);
    gs_technique_t *tech;

    if (video->ovi.output_format == VIDEO_FORMAT_RGBA)
    {
        tech = gs_effect_get_technique(effect, "DrawAlphaDivide");
    }
    else
    {
        if ((effect == video->default_effect) &&  (width == video->base_width) &&  (height == video->base_height))
        {
            return texture;
        }

        tech = gs_effect_get_technique(effect, "Draw");
    }

    profile_start(render_output_texture_name);

    gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image");
    gs_eparam_t *bres = gs_effect_get_param_by_name(effect, "base_dimension");
    gs_eparam_t *bres_i = gs_effect_get_param_by_name(effect, "base_dimension_i");
    size_t passes, i;

    gs_set_render_target(target, NULL);
    set_render_size(width, height);

    if (bres)
    {
        struct vec2 base;
        vec2_set(&base, (float)video->base_width, (float)video->base_height);
        gs_effect_set_vec2(bres, &base);
    }

    if (bres_i)
    {
        struct vec2 base_i;
        vec2_set(&base_i, 1.0f / (float)video->base_width, 1.0f / (float)video->base_height);
        gs_effect_set_vec2(bres_i, &base_i);
    }

    gs_effect_set_texture_srgb(image, texture);

    gs_enable_framebuffer_srgb(true);
    gs_enable_blending(false);
    passes = gs_technique_begin(tech);
    for (i = 0; i < passes; i++) {
        gs_technique_begin_pass(tech, i);
        gs_draw_sprite(texture, 0, width, height);
        gs_technique_end_pass(tech);
    }
    gs_technique_end(tech);
    gs_enable_blending(true);
    gs_enable_framebuffer_srgb(false);

    profile_end(render_output_texture_name);

    return target;
}
  • 如果输出为RGB格式,使用technique DrawAlphaDivide
  • 如果为YUV,则使用Draw

0 篇笔记 写笔记

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

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

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