obs-StreamFX/data/examples/shaders/filter/crt-scanlines.effect

147 lines
4.9 KiB
Plaintext

// AUTOGENERATED COPYRIGHT HEADER START
// Copyright (C) 2020-2023 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
// AUTOGENERATED COPYRIGHT HEADER END
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#define IS_FILTER
#include "../base.effect"
//------------------------------------------------------------------------------
// Uniforms
//------------------------------------------------------------------------------
uniform float _0_Strength<
string name = "Rollbar Strength";
string field_type = "slider";
float minimum = 0.;
float maximum = 100.;
float step = 0.01;
float scale = 0.01;
> = 100.0;
uniform int _1_Scanlines<
string name = "Scanlines";
string field_type = "slider";
int minimum = 128;
int maximum = 16384;
int step = 1;
> = 525;
uniform float2 _1_Intensity<
string name = "Scanline Brightness Min/Max";
string field_type = "slider";
float2 minimum = {0., 0.};
float2 maximum = {200., 200.};
float2 step = {0.01, 0.01};
float2 scale = {0.01, 0.01};
> = {95.0, 100.0};
uniform bool _2_EnableBleed<
string name = "Enable Color Bleeding";
> = true;
uniform float _3_ScanlineSize<
string name = "Scanline Scaling";
string field_type = "slider";
float minimum = 0.01;
float maximum = 100.;
float step = 0.01;
float scale = 0.01;
> = 100.0;
uniform float _4_Speed<
string name = "Timescale";
string field_type = "slider";
float minimum = 0.01;
float maximum = 100.;
float step = 0.01;
float scale = 0.01;
> = 60.0;
//------------------------------------------------------------------------------
// Technique: Version 1.0
//------------------------------------------------------------------------------
float4 Version1_0(VertexInformation vtx) : TARGET {
float2 uv = vtx.texcoord0.xy;
// 1. Calculate our current time offset based on the provided speed.
float time_offset = Time.y * _4_Speed;
// 2. Sample the original input.
float4 rgb = InputA.Sample(LinearClampSampler, uv);
// 3. If the user requested Scan Lines...
if (!is_float_equal(_1_Intensity.x, _1_Intensity.y)) {
// 1. Calculate the vertical index of the line.
uint scanline_index = uint(floor(fmod((uv.y + time_offset), 1.) * _1_Scanlines));
// 2. Map it back into a useful range.
uint scanline_intensity = scanline_index % 2;
// 3. Calculate the multiplier based on the index.
float slmul = scanline_intensity == 0 ? _1_Intensity.x : _1_Intensity.y;
// 4. Does the user want naive CRT bleeding?
if (_2_EnableBleed) {
// Very naive bleeding, but it gets the effect across.
float offset = float(scanline_intensity) * 0.0005;
float colorShift = 0.001;
float r = InputA.Sample(LinearClampSampler, uv + offset + colorShift).r;
float g = InputA.Sample(LinearClampSampler, uv + offset - colorShift).g;
float b = rgb.b;
rgb.rgb = float3(r, g, b); // g * 0.99?
}
// 4. Apply the multiplier.
rgb.rgb *= slmul;
} else {
rgb.rgb *= _1_Intensity.x;
}
// 4. Does the user want the rollbar effect?
if (is_float_equal(_0_Strength, .01) || (_0_Strength > 0.01)) {
const float rollbar_cycle_length = 5.;
float rollbar_cycle = Time.y + fmod(Time.z, rollbar_cycle_length);
float rollbar = sin((uv.y + rollbar_cycle / rollbar_cycle_length) * TAU);
rgb.rgb = lerp(rgb.rgb, rgb.rgb + (rollbar * 0.1), _0_Strength);
}
return rgb;
}
technique Draw {
pass {
vertex_shader = DefaultVertexShader(vtx);
pixel_shader = Version1_0(vtx);
}
}
technique V1_0 {
pass {
vertex_shader = DefaultVertexShader(vtx);
pixel_shader = Version1_0(vtx);
}
}