static void chroma_key_render(void *data, gs_effect_t *effect) { struct chroma_key_filter_data *filter = data; obs_source_t *target = obs_filter_get_target(filter->context); uint32_t width = obs_source_get_base_width(target); uint32_t height = obs_source_get_base_height(target); struct vec2 pixel_size; obs_source_process_filter_begin(filter->context, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING); vec2_set(&pixel_size, 1.0f / (float)width, 1.0f / (float)height); gs_effect_set_vec4(filter->color_param, &filter->color); gs_effect_set_float(filter->contrast_param, filter->contrast); gs_effect_set_float(filter->brightness_param, filter->brightness); gs_effect_set_float(filter->gamma_param, filter->gamma); gs_effect_set_vec2(filter->chroma_param, &filter->chroma); gs_effect_set_vec4(filter->key_rgb_param, &filter->key_rgb); gs_effect_set_vec2(filter->pixel_size_param, &pixel_size); gs_effect_set_float(filter->similarity_param, filter->similarity); gs_effect_set_float(filter->smoothness_param, filter->smoothness); gs_effect_set_float(filter->spill_param, filter->spill); obs_source_process_filter_end(filter->context, filter->effect, 0, 0); UNUSED_PARAMETER(effect); }
static void crop_filter_render(void *data, gs_effect_t *effect) { struct crop_filter_data *filter = data; obs_source_process_filter_begin(filter->context, GS_RGBA, OBS_NO_DIRECT_RENDERING); gs_effect_set_vec2(filter->param_mul, &filter->mul_val); gs_effect_set_vec2(filter->param_add, &filter->add_val); obs_source_process_filter_end(filter->context, filter->effect, filter->width, filter->height); UNUSED_PARAMETER(effect); }
static void scale_filter_render(void *data, gs_effect_t *effect) { struct scale_filter_data *filter = data; const char *technique = filter->undistort ? "DrawUndistort" : "Draw"; if (!filter->valid || !filter->target_valid) { obs_source_skip_video_filter(filter->context); return; } if (!obs_source_process_filter_begin(filter->context, GS_RGBA, OBS_NO_DIRECT_RENDERING)) return; if (filter->dimension_param) gs_effect_set_vec2(filter->dimension_param, &filter->dimension_i); if (filter->undistort_factor_param) gs_effect_set_float(filter->undistort_factor_param, (float)filter->undistort_factor); if (filter->sampling == OBS_SCALE_POINT) gs_effect_set_next_sampler(filter->image_param, filter->point_sampler); obs_source_process_filter_tech_end(filter->context, filter->effect, filter->cx_out, filter->cy_out, technique); UNUSED_PARAMETER(effect); }
void deinterlace_render(obs_source_t *s) { gs_effect_t *effect = s->deinterlace_effect; uint64_t frame2_ts; gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image"); gs_eparam_t *prev = gs_effect_get_param_by_name(effect, "previous_image"); gs_eparam_t *field = gs_effect_get_param_by_name(effect, "field_order"); gs_eparam_t *frame2 = gs_effect_get_param_by_name(effect, "frame2"); gs_eparam_t *dimensions = gs_effect_get_param_by_name(effect, "dimensions"); struct vec2 size = {(float)s->async_width, (float)s->async_height}; bool yuv = format_is_yuv(s->async_format); bool limited_range = yuv && !s->async_full_range; const char *tech = yuv ? "DrawMatrix" : "Draw"; gs_texture_t *cur_tex = s->async_texrender ? gs_texrender_get_texture(s->async_texrender) : s->async_texture; gs_texture_t *prev_tex = s->async_prev_texrender ? gs_texrender_get_texture(s->async_prev_texrender) : s->async_prev_texture; if (!cur_tex || !prev_tex || !s->async_width || !s->async_height) return; gs_effect_set_texture(image, cur_tex); gs_effect_set_texture(prev, prev_tex); gs_effect_set_int(field, s->deinterlace_top_first); gs_effect_set_vec2(dimensions, &size); if (yuv) { gs_eparam_t *color_matrix = gs_effect_get_param_by_name( effect, "color_matrix"); gs_effect_set_val(color_matrix, s->async_color_matrix, sizeof(float) * 16); } if (limited_range) { const size_t size = sizeof(float) * 3; gs_eparam_t *color_range_min = gs_effect_get_param_by_name( effect, "color_range_min"); gs_eparam_t *color_range_max = gs_effect_get_param_by_name( effect, "color_range_max"); gs_effect_set_val(color_range_min, s->async_color_range_min, size); gs_effect_set_val(color_range_max, s->async_color_range_max, size); } frame2_ts = s->deinterlace_frame_ts + s->deinterlace_offset + s->deinterlace_half_duration - TWOX_TOLERANCE; gs_effect_set_bool(frame2, obs->video.video_time >= frame2_ts); while (gs_effect_loop(effect, tech)) gs_draw_sprite(NULL, s->async_flip ? GS_FLIP_V : 0, s->async_width, s->async_height); }
static inline void render_output_texture(struct obs_core_video *video, int cur_texture, int prev_texture) { profile_start(render_output_texture_name); gs_texture_t *texture = video->render_textures[prev_texture]; gs_texture_t *target = video->output_textures[cur_texture]; uint32_t width = gs_texture_get_width(target); uint32_t height = gs_texture_get_height(target); struct vec2 base_i; vec2_set(&base_i, 1.0f / (float)video->base_width, 1.0f / (float)video->base_height); 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, "Draw"); } else { tech = gs_effect_get_technique(effect, "DrawMatrix"); } gs_eparam_t *image = gs_effect_get_param_by_name(effect, "image"); gs_eparam_t *matrix = gs_effect_get_param_by_name(effect, "color_matrix"); gs_eparam_t *bres_i = gs_effect_get_param_by_name(effect, "base_dimension_i"); size_t passes, i; if (!video->textures_rendered[prev_texture]) goto end; gs_set_render_target(target, NULL); set_render_size(width, height); if (bres_i) gs_effect_set_vec2(bres_i, &base_i); gs_effect_set_val(matrix, video->color_matrix, sizeof(float) * 16); gs_effect_set_texture(image, texture); 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); video->textures_output[cur_texture] = true; end: profile_end(render_output_texture_name); }
static void crop_filter_render(void *data, gs_effect_t *effect) { struct crop_filter_data *filter = data; struct vec2 mul_val; struct vec2 add_val; vec2_zero(&mul_val); vec2_zero(&add_val); calc_crop_dimensions(filter, &mul_val, &add_val); obs_source_process_filter_begin(filter->context, GS_RGBA, OBS_NO_DIRECT_RENDERING); gs_effect_set_vec2(filter->param_mul, &mul_val); gs_effect_set_vec2(filter->param_add, &add_val); obs_source_process_filter_end(filter->context, filter->effect, filter->width, filter->height); UNUSED_PARAMETER(effect); }
static void render_item_texture(struct obs_scene_item *item) { gs_texture_t *tex = gs_texrender_get_texture(item->item_render); gs_effect_t *effect = obs->video.default_effect; enum obs_scale_type type = item->scale_filter; uint32_t cx = gs_texture_get_width(tex); uint32_t cy = gs_texture_get_height(tex); if (type != OBS_SCALE_DISABLE) { if (type == OBS_SCALE_POINT) { gs_eparam_t *image = gs_effect_get_param_by_name( effect, "image"); gs_effect_set_next_sampler(image, obs->video.point_sampler); } else if (!close_float(item->output_scale.x, 1.0f, EPSILON) || !close_float(item->output_scale.y, 1.0f, EPSILON)) { gs_eparam_t *scale_param; if (item->output_scale.x < 0.5f || item->output_scale.y < 0.5f) { effect = obs->video.bilinear_lowres_effect; } else if (type == OBS_SCALE_BICUBIC) { effect = obs->video.bicubic_effect; } else if (type == OBS_SCALE_LANCZOS) { effect = obs->video.lanczos_effect; } scale_param = gs_effect_get_param_by_name(effect, "base_dimension_i"); if (scale_param) { struct vec2 base_res_i = { 1.0f / (float)cx, 1.0f / (float)cy }; gs_effect_set_vec2(scale_param, &base_res_i); } } } while (gs_effect_loop(effect, "Draw")) obs_source_draw(tex, 0, 0, 0, 0, 0); }