Created
June 8, 2024 18:50
-
-
Save upgradeQ/890913abe3bfd0e4e68f1860e6b97c53 to your computer and use it in GitHub Desktop.
frame_blend
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
S = obslua | |
local function skip_tick_render(ctx) | |
local target = S.obs_filter_get_target(ctx.source) | |
local width, height; | |
if target == nil then width = 0; height = 0; else | |
width = S.obs_source_get_base_width(target) | |
height = S.obs_source_get_base_height(target) | |
end | |
ctx.width, ctx.height = width , height | |
end | |
local SourceDef = {} | |
function SourceDef:new(o) | |
o = o or {} | |
setmetatable(o, self) | |
self.__index = self | |
return o | |
end | |
function SourceDef:create(source) | |
local instance = {} | |
instance.width = 1 | |
instance.height = 1 | |
instance.source = source | |
instance.current_time = 0 | |
instance.frame_number = 0 | |
instance.strength = 0.001 | |
instance.texture1 = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.texture2 = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.texture3 = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.texture4 = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.texture5 = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.texture6 = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.clear_flags = bit.bor(S.GS_CLEAR_COLOR) | |
instance.current_texrender = S.gs_texrender_create(S.GS_RGBA, S.GS_ZS_NONE) | |
instance.texture_clear_color = S.vec4() | |
instance.clear_flags = bit.bor(S.GS_CLEAR_COLOR) | |
S.obs_enter_graphics() | |
instance.effect = S.gs_effect_create(SHADER1, nil, nil) | |
if instance.effect ~= nil then | |
instance.params = {} | |
instance.params.itime = S.gs_effect_get_param_by_name(instance.effect, 'itime') | |
instance.params.strength = S.gs_effect_get_param_by_name(instance.effect, 'strength') | |
instance.params.tex1 = S.gs_effect_get_param_by_name(instance.effect, 'tex1') | |
instance.params.tex2 = S.gs_effect_get_param_by_name(instance.effect, 'tex2') | |
instance.params.tex3 = S.gs_effect_get_param_by_name(instance.effect, 'tex3') | |
instance.params.tex4 = S.gs_effect_get_param_by_name(instance.effect, 'tex4') | |
instance.params.tex5 = S.gs_effect_get_param_by_name(instance.effect, 'tex5') | |
instance.params.tex6 = S.gs_effect_get_param_by_name(instance.effect, 'tex6') | |
instance.params.current_frame = S.gs_effect_get_param_by_name(instance.effect, 'current_frame') | |
end | |
instance.default_effect = S.obs_get_base_effect(S.OBS_EFFECT_DEFAULT) | |
instance.params.default_image = S.gs_effect_get_param_by_name(instance.default_effect, 'image') | |
instance.params.itime = S.gs_effect_get_param_by_name(instance.effect, 'itime') | |
S.obs_leave_graphics() | |
if instance.effect == nil then | |
SourceDef.destroy(instance) | |
return nil | |
end | |
--SourceDef.update(instance,self) -- initialize, self = settings | |
return instance | |
end | |
function SourceDef:destroy() | |
if self.effect ~= nil then | |
S.obs_enter_graphics() | |
S.gs_texrender_destroy(self.texture1) | |
S.gs_texrender_destroy(self.texture2) | |
S.gs_texrender_destroy(self.texture3) | |
S.gs_texrender_destroy(self.texture4) | |
S.gs_texrender_destroy(self.texture5) | |
S.gs_texrender_destroy(self.texture6) | |
S.gs_texrender_destroy(self.current_texrender) | |
S.gs_effect_destroy(self.effect) | |
S.obs_leave_graphics() | |
end | |
end | |
function SourceDef:get_name() return "frame blending ?" end | |
function SourceDef:get_width() return self.width end | |
function SourceDef:get_height() return self.height end | |
function SourceDef:video_tick(seconds) | |
self.current_time = self.current_time + seconds | |
skip_tick_render(self) -- if source has crop or transform applied to it, this will let it render | |
end | |
function texrender_set_texture(self, texrender, texture) | |
S.gs_texrender_reset(texrender) | |
if S.gs_texrender_begin(texrender, self.width, self.height) then | |
S.gs_ortho(0, self.width, 0, self.height, -100.0, 100.0) | |
S.gs_effect_set_texture(self.params.default_image, texture) | |
while S.gs_effect_loop(self.default_effect, "Draw") do | |
S.gs_draw_sprite(nil, 0, self.width, self.height) | |
end | |
S.gs_texrender_end(texrender) | |
end | |
end | |
function SourceDef:video_render() | |
local parent = S.obs_filter_get_parent(self.source) | |
self.width = S.obs_source_get_base_width(parent) | |
self.height = S.obs_source_get_base_height(parent) | |
S.gs_texrender_reset(self.current_texrender) | |
if S.gs_texrender_begin(self.current_texrender, self.width, self.height) then | |
S.gs_ortho(0, self.width, 0, self.height, -100.0, 100.0) | |
--S.gs_clear(self.clear_flags, self.texture_clear_color, 0, 0) | |
S.gs_effect_set_float(self.params.itime, self.current_time+0.0) | |
if not S.obs_source_process_filter_begin(self.source, S.GS_RGBA, S.OBS_ALLOW_DIRECT_RENDERING) | |
then return | |
end | |
S.obs_source_process_filter_tech_end(self.source, self.default_effect, self.width, self.height,"Draw") | |
S.gs_texrender_end(self.current_texrender) | |
end | |
local switch = self.frame_number % 6 | |
if (switch == 0) then | |
texrender_set_texture(self, self.texture1, S.gs_texrender_get_texture(self.current_texrender)) | |
elseif (switch == 1) then | |
texrender_set_texture(self, self.texture2, S.gs_texrender_get_texture(self.current_texrender)) | |
elseif (switch == 2) then | |
texrender_set_texture(self, self.texture3, S.gs_texrender_get_texture(self.current_texrender)) | |
elseif (switch == 3) then | |
texrender_set_texture(self, self.texture4, S.gs_texrender_get_texture(self.current_texrender)) | |
elseif (switch == 4) then | |
texrender_set_texture(self, self.texture5, S.gs_texrender_get_texture(self.current_texrender)) | |
elseif (switch == 5) then | |
texrender_set_texture(self, self.texture6, S.gs_texrender_get_texture(self.current_texrender)) | |
end | |
S.gs_effect_set_texture(self.params.tex1, S.gs_texrender_get_texture(self.texture1)) | |
S.gs_effect_set_texture(self.params.tex2, S.gs_texrender_get_texture(self.texture2)) | |
S.gs_effect_set_texture(self.params.tex3, S.gs_texrender_get_texture(self.texture3)) | |
S.gs_effect_set_texture(self.params.tex4, S.gs_texrender_get_texture(self.texture4)) | |
S.gs_effect_set_texture(self.params.tex5, S.gs_texrender_get_texture(self.texture5)) | |
S.gs_effect_set_texture(self.params.tex6, S.gs_texrender_get_texture(self.texture6)) | |
S.gs_effect_set_texture(self.params.current_frame, S.gs_texrender_get_texture(self.current_texrender)) | |
S.gs_effect_set_float(self.params.strength, self.strength) | |
while S.gs_effect_loop(self.effect, "DrawFinal") do | |
S.gs_draw_sprite(nil ,0,self.width,self.height) | |
end | |
self.frame_number = self.frame_number + 1 | |
end | |
function SourceDef:get_properties() | |
local props = S.obs_properties_create() | |
S.obs_properties_add_float_slider(props, "_h", "strength", 0, 1, 0.00001) | |
return props | |
end | |
function SourceDef:update(settings) | |
self.strength = S.obs_data_get_double(settings, "_h") | |
end | |
function SourceDef:get_defaults() | |
S.obs_data_set_default_double(self, "_h", 0.01) | |
end | |
function script_properties() | |
local props = S.obs_properties_create() | |
S.obs_properties_add_button(props, "button2", "frame blending ? ", | |
function() end) | |
return props | |
end | |
function script_load(settings) | |
local my_filter = SourceDef:new({id='frame_blend',type=S.OBS_SOURCE_TYPE_FILTER, | |
output_flags=bit.bor(S.OBS_SOURCE_VIDEO,S.OBS_SOURCE_CUSTOM_DRAW)}) | |
S.obs_register_source(my_filter) | |
end | |
SHADER1 = [==[ | |
// OBS-specific syntax adaptation to HLSL standard to avoid errors reported by the code editor | |
#define SamplerState sampler_state | |
#define Texture2D texture2d | |
uniform float4x4 ViewProj; | |
uniform Texture2D current_frame; | |
uniform Texture2D tex1; | |
uniform Texture2D tex2; | |
uniform Texture2D tex3; | |
uniform Texture2D tex4; | |
uniform Texture2D tex5; | |
uniform Texture2D tex6; | |
// Size of the source picture | |
uniform float itime; | |
uniform float strength; | |
SamplerState textureSampler { | |
Filter = Linear; | |
AddressU = Clamp; | |
AddressV = Clamp; | |
}; | |
struct VertDataIn { | |
float4 pos : POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
struct VertDataOut { | |
float4 pos : POSITION; | |
float2 uv : TEXCOORD0; | |
}; | |
VertDataOut VSDefault(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; | |
} | |
// https://github.com/libretro/common-shaders/blob/master/motionblur/shaders/motionblur-simple.cg | |
float4 PassThrough1(VertDataOut v_in) : TARGET | |
{ | |
float2 uv = v_in.uv; | |
float4 draw = current_frame.Sample(textureSampler, uv); | |
float4 color = tex6.Sample(textureSampler, uv); | |
color = (color + tex5.Sample(textureSampler, uv)) / 2.0; | |
color = (color + tex4.Sample(textureSampler, uv)) / 2.0; | |
color = (color + tex3.Sample(textureSampler, uv)) / 2.0; | |
color = (color + tex2.Sample(textureSampler, uv)) / 2.0; | |
color = (color + tex1.Sample(textureSampler, uv)) / 2.0; | |
color = (color + draw) / 2.0; | |
return color; | |
} | |
// https://reshade.me/forum/shader-discussion/2312-who-said-reshade-cant-do-quality-motion-blur | |
float4 PassThrough(VertDataOut v_in) : TARGET | |
{ | |
float2 uv = v_in.uv; | |
float4 draw = current_frame.Sample(textureSampler, uv); | |
float4 color = tex6.Sample(textureSampler, uv); | |
color = (color + tex5.Sample(textureSampler, uv)); | |
color = (color + tex4.Sample(textureSampler, uv)); | |
color = (color + tex3.Sample(textureSampler, uv)); | |
color = (color + tex2.Sample(textureSampler, uv)); | |
color = (color + tex1.Sample(textureSampler, uv)); | |
color = (color + draw) / 7; | |
return lerp(draw,color,strength); | |
} | |
technique DrawFinal | |
{ | |
pass | |
{ | |
vertex_shader = VSDefault(v_in); | |
pixel_shader = PassThrough(v_in); | |
} | |
} | |
]==] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment