Last active
February 14, 2021 11:59
-
-
Save magicien/6a2c8cee52302306c8129c058d0184c4 to your computer and use it in GitHub Desktop.
OBS用スクリプト:縁取りフィルタ(簡易版)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
obs = obslua | |
bit = require('bit') | |
SETTING_ALPHA_THRESHOLD = 'alpha_threshold' | |
SETTING_LINE_COLOR = 'line_color' | |
SETTING_LINE_ALPHA = 'line_alpha' | |
SETTING_LINE_WIDTH = 'line_width' | |
TEXT_ALPHA_THRESHOLD = '透明度閾値' | |
TEXT_LINE_COLOR = '線の色' | |
TEXT_LINE_ALPHA = '線の不透明度' | |
TEXT_LINE_WIDTH = '線の幅' | |
SHADER = [[ | |
uniform float4x4 ViewProj; | |
uniform texture2d image; | |
uniform float2 pixel_size; | |
uniform float alpha_threshold; | |
uniform float4 line_color; | |
uniform float line_width; | |
sampler_state textureSampler { | |
Filter = Linear; | |
AddressU = Clamp; | |
AddressV = Clamp; | |
}; | |
struct VertDataIn { | |
float4 pos : POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
struct VertDataOut { | |
float4 pos : POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
VertDataOut VShader(VertDataIn v_in) | |
{ | |
VertDataOut vert_out; | |
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj); | |
vert_out.uv = v_in.uv; | |
return vert_out; | |
} | |
float diff(float2 uv, float2 diff) | |
{ | |
float4 col1 = image.Sample(textureSampler, uv - diff); | |
float4 col2 = image.Sample(textureSampler, uv + diff); | |
return col2.a - col1.a; | |
} | |
float4 PShader(VertDataOut v_in) : TARGET | |
{ | |
float w = pixel_size.x * line_width / 2; | |
float h = pixel_size.y * line_width / 2; | |
float d1 = diff(v_in.uv, float2(w, 0)); | |
float d2 = diff(v_in.uv, float2(0, h)); | |
float d3 = diff(v_in.uv, float2(w * 0.71, h * 0.71)); | |
float d4 = diff(v_in.uv, float2(w * 0.71, -h * 0.71)); | |
float4 color = image.Sample(textureSampler, v_in.uv); | |
return (abs(d1) > alpha_threshold | |
|| abs(d2) > alpha_threshold | |
|| abs(d3) > alpha_threshold | |
|| abs(d4) > alpha_threshold) | |
? color + line_color * (1 - color.a) | |
: color; | |
} | |
technique Draw | |
{ | |
pass | |
{ | |
vertex_shader = VShader(v_in); | |
pixel_shader = PShader(v_in); | |
} | |
} | |
]] | |
source_def = {} | |
source_def.id = 'draw-outline' | |
source_def.type = obs.OBS_SOURCE_TYPE_FILTER | |
source_def.output_flags = bit.bor(obs.OBS_SOURCE_VIDEO) | |
function set_render_size(filter) | |
target = obs.obs_filter_get_target(filter.context) | |
local width, height | |
if target == nil then | |
width = 0 | |
height = 0 | |
else | |
width = obs.obs_source_get_base_width(target) | |
height = obs.obs_source_get_base_height(target) | |
end | |
filter.width = width | |
filter.height = height | |
width = width == 0 and 1 or width | |
height = height == 0 and 1 or height | |
filter.pixel_size.x = 1.0 / width | |
filter.pixel_size.y = 1.0 / height | |
end | |
source_def.get_name = function() | |
return '縁取り' | |
end | |
source_def.create = function(settings, source) | |
filter = {} | |
filter.params = {} | |
filter.context = source | |
filter.pixel_size = obs.vec2() | |
filter.line_color = obs.vec4() | |
set_render_size(filter) | |
obs.obs_enter_graphics() | |
filter.effect = obs.gs_effect_create(SHADER, nil, nil) | |
if filter.effect ~= nil then | |
filter.params.pixel_size = obs.gs_effect_get_param_by_name(filter.effect, 'pixel_size') | |
filter.params.alpha_threshold = obs.gs_effect_get_param_by_name(filter.effect, 'alpha_threshold') | |
filter.params.line_color = obs.gs_effect_get_param_by_name(filter.effect, 'line_color') | |
filter.params.line_alpha = obs.gs_effect_get_param_by_name(filter.effect, 'line_alpha') | |
filter.params.line_width = obs.gs_effect_get_param_by_name(filter.effect, 'line_width') | |
end | |
obs.obs_leave_graphics() | |
if filter.effect == nil then | |
source_def.destroy(filter) | |
return nil | |
end | |
source_def.update(filter, settings) | |
return filter | |
end | |
source_def.destroy = function(filter) | |
if filter.effect ~= nil then | |
obs.obs_enter_graphics() | |
obs.gs_effect_destroy(filter.effect) | |
obs.obs_leave_graphics() | |
end | |
end | |
source_def.get_width = function(filter) | |
return filter.width | |
end | |
source_def.get_height = function(filter) | |
return filter.height | |
end | |
source_def.update = function(filter, settings) | |
filter.alpha_threshold = obs.obs_data_get_double(settings, SETTING_ALPHA_THRESHOLD) | |
line_color = obs.obs_data_get_int(settings, SETTING_LINE_COLOR) | |
line_alpha = math.floor(obs.obs_data_get_double(settings, SETTING_LINE_ALPHA) * 255) | |
obs.vec4_from_rgba(filter.line_color, line_color + line_alpha * 0x1000000) | |
filter.line_width = obs.obs_data_get_double(settings, SETTING_LINE_WIDTH) | |
set_render_size(filter) | |
end | |
source_def.video_render = function(filter, effect) | |
obs.obs_source_process_filter_begin(filter.context, obs.GS_RGBA, obs.OBS_NO_DIRECT_RENDERING) | |
obs.gs_effect_set_vec2(filter.params.pixel_size, filter.pixel_size) | |
obs.gs_effect_set_float(filter.params.alpha_threshold, filter.alpha_threshold) | |
obs.gs_effect_set_vec4(filter.params.line_color, filter.line_color) | |
obs.gs_effect_set_float(filter.params.line_width, filter.line_width) | |
obs.obs_source_process_filter_end(filter.context, filter.effect, filter.width, filter.height) | |
end | |
function script_description() | |
return '縁取りフィルタ。透明な箇所と不透明な箇所の境目に線を描く' | |
end | |
source_def.get_properties = function(settings) | |
props = obs.obs_properties_create() | |
obs.obs_properties_add_float_slider(props, SETTING_ALPHA_THRESHOLD, TEXT_ALPHA_THRESHOLD, 0, 1, 0.01) | |
obs.obs_properties_add_color(props, SETTING_LINE_COLOR, TEXT_LINE_COLOR) | |
obs.obs_properties_add_float_slider(props, SETTING_LINE_ALPHA, TEXT_LINE_ALPHA, 0, 1, 0.01) | |
obs.obs_properties_add_float_slider(props, SETTING_LINE_WIDTH, TEXT_LINE_WIDTH, 0, 100, 0.1) | |
return props | |
end | |
source_def.get_defaults = function(settings) | |
obs.obs_data_set_default_double(settings, SETTING_ALPHA_THRESHOLD, 0.99) | |
obs.obs_data_set_default_int(settings, SETTING_LINE_COLOR, 0x000000) | |
obs.obs_data_set_default_double(settings, SETTING_LINE_ALPHA, 1) | |
obs.obs_data_set_default_double(settings, SETTING_LINE_WIDTH, 1) | |
end | |
source_def.video_tick = function(filter, seconds) | |
set_render_size(filter) | |
end | |
obs.obs_register_source(source_def) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment