渲染流程及纹理关系render_video
2024-10-17
15
0
渲染主函数为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