OBS色源渲染
2024-06-05
29
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;
}