mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-29 11:01:23 +00:00
filter-shader: New filter examples
CRT Curvature: Emulate an old CRT TVs curvature ... CRT Scanlines: ... and emulate an old CRT TVs scanlines, rollbar and bleeding! Hexagonize: Turn things into hexagons. You know, like the thing you see in my streams.
This commit is contained in:
parent
79406b0b08
commit
4fda7de573
3 changed files with 373 additions and 0 deletions
99
data/examples/shaders/filter/crt-curvature.effect
Normal file
99
data/examples/shaders/filter/crt-curvature.effect
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
// Always provided by OBS
|
||||||
|
uniform float4x4 ViewProj<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "View Projection Matrix";
|
||||||
|
>;
|
||||||
|
|
||||||
|
// Provided by Stream Effects
|
||||||
|
uniform float4 Time<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "Time Array";
|
||||||
|
string description = "A float4 value containing the total time, rendering time and the time since the last tick. The last value is a random number between 0 and 1.";
|
||||||
|
>;
|
||||||
|
uniform float4x4 Random<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "Random Array";
|
||||||
|
string description = "A float4x4 value containing random values between 0 and 1";
|
||||||
|
>;
|
||||||
|
uniform texture2d InputA<
|
||||||
|
bool automatic = true;
|
||||||
|
>;
|
||||||
|
|
||||||
|
uniform float _0_strength<
|
||||||
|
string name = "Strength";
|
||||||
|
string field_type = "slider";
|
||||||
|
float minimum = 0.;
|
||||||
|
float maximum = 100.;
|
||||||
|
float step = 0.01;
|
||||||
|
float scale = 0.01;
|
||||||
|
> = 33.33;
|
||||||
|
uniform float4 _1_border<
|
||||||
|
string name = "Border Color";
|
||||||
|
string field_type = "slider";
|
||||||
|
float4 minimum = {0., 0., 0., 0.};
|
||||||
|
float4 maximum = {100., 100., 100., 100.};
|
||||||
|
float4 step = {0.01, 0.01, 0.01, 0.01};
|
||||||
|
float4 scale = {0.01, 0.01, 0.01, 0.01};
|
||||||
|
> = {0., 0., 0., 0.};
|
||||||
|
uniform float _2_feathering<
|
||||||
|
string name = "Feathering";
|
||||||
|
string field_type = "slider";
|
||||||
|
float minimum = 0.01;
|
||||||
|
float maximum = 100.;
|
||||||
|
float step = 0.01;
|
||||||
|
float scale = 0.01;
|
||||||
|
> = 33.33;
|
||||||
|
|
||||||
|
#define PI 3.1415926f
|
||||||
|
#define TwoPI 6.2831853f
|
||||||
|
#define HalfPI 1.5707963f
|
||||||
|
|
||||||
|
// ---------- Shader Code
|
||||||
|
sampler_state def_sampler {
|
||||||
|
AddressU = Clamp;
|
||||||
|
AddressV = Clamp;
|
||||||
|
Filter = Linear;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertData {
|
||||||
|
float4 pos : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VertData VSDefault(VertData v_in) {
|
||||||
|
VertData vert_out;
|
||||||
|
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
|
||||||
|
vert_out.uv = v_in.uv;
|
||||||
|
return vert_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PSDefault(VertData v_in) : TARGET {
|
||||||
|
float2 center = {0.5, 0.5};
|
||||||
|
|
||||||
|
float2 cc = v_in.uv - center;
|
||||||
|
float dist = dot(cc, cc) * _0_strength;
|
||||||
|
float2 bentUV = v_in.uv + cc * (1.0 + dist) * dist;
|
||||||
|
|
||||||
|
if ((bentUV.x <= 0. || bentUV.x >= 1.) || (bentUV.y <= 0. || bentUV.y >= 1.)) {
|
||||||
|
return _1_border;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate border distance from texel center by ignoring the sign bit and normalizing the distance to 0..1.
|
||||||
|
float2 borderDistance = (center - abs(bentUV - center)) / center;
|
||||||
|
float2 borderArea = center * _2_feathering;
|
||||||
|
|
||||||
|
// Now apply a modifier so that we only get the border area.
|
||||||
|
borderDistance = (min(borderDistance - center * _2_feathering, 0) + borderArea) / borderArea;
|
||||||
|
float borderFade = sin(borderDistance.x * HalfPI) * sin(borderDistance.y * HalfPI);
|
||||||
|
|
||||||
|
return lerp(_1_border, InputA.Sample(def_sampler, bentUV), borderFade);
|
||||||
|
}
|
||||||
|
|
||||||
|
technique Draw
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
vertex_shader = VSDefault(v_in);
|
||||||
|
pixel_shader = PSDefault(v_in);
|
||||||
|
}
|
||||||
|
}
|
136
data/examples/shaders/filter/crt-scanlines.effect
Normal file
136
data/examples/shaders/filter/crt-scanlines.effect
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
// Always provided by OBS
|
||||||
|
uniform float4x4 ViewProj<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "View Projection Matrix";
|
||||||
|
>;
|
||||||
|
|
||||||
|
// Provided by Stream Effects
|
||||||
|
uniform float4 Time<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "Time Array";
|
||||||
|
string description = "A float4 value containing the total time, rendering time and the time since the last tick. The last value is a random number between 0 and 1.";
|
||||||
|
>;
|
||||||
|
uniform float4x4 Random<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "Random Array";
|
||||||
|
string description = "A float4x4 value containing random values between 0 and 1";
|
||||||
|
>;
|
||||||
|
uniform float4 ViewSize<
|
||||||
|
bool automatic = true;
|
||||||
|
>;
|
||||||
|
uniform texture2d InputA<
|
||||||
|
bool automatic = true;
|
||||||
|
>;
|
||||||
|
|
||||||
|
uniform float _0_Strength<
|
||||||
|
string name = "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 = "Intensity Limits";
|
||||||
|
string field_type = "slider";
|
||||||
|
float2 minimum = {0., 0.};
|
||||||
|
float2 maximum = {100., 100.};
|
||||||
|
float2 step = {0.01, 0.01};
|
||||||
|
float2 scale = {0.01, 0.01};
|
||||||
|
> = {95.0, 100.0};
|
||||||
|
uniform bool _2_EnableBleed<
|
||||||
|
string name = "Enable NTSC 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;
|
||||||
|
|
||||||
|
|
||||||
|
#define PI 3.1415926f
|
||||||
|
#define TwoPI 6.2831853f
|
||||||
|
#define HalfPI 1.5707963f
|
||||||
|
|
||||||
|
// ---------- Shader Code
|
||||||
|
sampler_state def_sampler {
|
||||||
|
AddressU = Clamp;
|
||||||
|
AddressV = Clamp;
|
||||||
|
Filter = Linear;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertData {
|
||||||
|
float4 pos : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VertData VSDefault(VertData v_in) {
|
||||||
|
VertData vert_out;
|
||||||
|
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
|
||||||
|
vert_out.uv = v_in.uv;
|
||||||
|
return vert_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PSDefault(VertData v_in) : TARGET {
|
||||||
|
float2 uv = v_in.uv;
|
||||||
|
float time_offset = Time.y * _4_Speed;
|
||||||
|
|
||||||
|
// Scanline stuff.
|
||||||
|
uint scanline_index = floor(fmod((uv.y + time_offset), 1.) * _1_Scanlines);
|
||||||
|
uint scanline_intensity = scanline_index % 2;
|
||||||
|
|
||||||
|
// Calculate final color;
|
||||||
|
float4 rgb = InputA.Sample(def_sampler, uv);
|
||||||
|
|
||||||
|
// Bleeding
|
||||||
|
if (_2_EnableBleed) {
|
||||||
|
// Not true bleeding, missing some gaussian blur.
|
||||||
|
float offset = float(scanline_intensity) * 0.0005;
|
||||||
|
|
||||||
|
float colorShift = 0.001;
|
||||||
|
float r = InputA.Sample(def_sampler, uv + offset + colorShift).r;
|
||||||
|
float g = InputA.Sample(def_sampler, uv + offset - colorShift).g;
|
||||||
|
float b = rgb.b;
|
||||||
|
|
||||||
|
rgb.rgb = float3(r, g, b); // g * 0.99?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intensity;
|
||||||
|
rgb.rgb *= clamp(float(scanline_intensity), _1_Intensity.x, _1_Intensity.y);
|
||||||
|
|
||||||
|
// rollbar
|
||||||
|
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) * TwoPI);
|
||||||
|
rgb.rgb = lerp(rgb, rgb + (rollbar * 0.1), _0_Strength);
|
||||||
|
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
technique Draw
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
vertex_shader = VSDefault(v_in);
|
||||||
|
pixel_shader = PSDefault(v_in);
|
||||||
|
}
|
||||||
|
}
|
138
data/examples/shaders/filter/hexagonize.effect
Normal file
138
data/examples/shaders/filter/hexagonize.effect
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
// Always provided by OBS
|
||||||
|
uniform float4x4 ViewProj<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "View Projection Matrix";
|
||||||
|
>;
|
||||||
|
|
||||||
|
// Provided by Stream Effects
|
||||||
|
uniform float4 Time<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "Time Array";
|
||||||
|
string description = "A float4 value containing the total time, rendering time and the time since the last tick. The last value is a random number between 0 and 1.";
|
||||||
|
>;
|
||||||
|
uniform float4x4 Random<
|
||||||
|
bool automatic = true;
|
||||||
|
string name = "Random Array";
|
||||||
|
string description = "A float4x4 value containing random values between 0 and 1";
|
||||||
|
>;
|
||||||
|
uniform float4 ViewSize<
|
||||||
|
bool automatic = true;
|
||||||
|
>;
|
||||||
|
uniform texture2d InputA<
|
||||||
|
bool automatic = true;
|
||||||
|
>;
|
||||||
|
|
||||||
|
uniform float HexagonScale<
|
||||||
|
string name = "Hexagon Scale";
|
||||||
|
string field_type = "slider";
|
||||||
|
float minimum = 1.0;
|
||||||
|
float maximum = 1024.0;
|
||||||
|
float step = 1.0;
|
||||||
|
> = 120.0;
|
||||||
|
uniform float HexagonWallScale<
|
||||||
|
string name = "Hexagon Wall Scale";
|
||||||
|
string field_type = "slider";
|
||||||
|
float minimum = 0.0;
|
||||||
|
float maximum = 100.0;
|
||||||
|
float step = 0.01;
|
||||||
|
float scale = 0.01;
|
||||||
|
> = 100.0;
|
||||||
|
|
||||||
|
// ---------- Shader Code
|
||||||
|
sampler_state def_sampler {
|
||||||
|
AddressU = Clamp;
|
||||||
|
AddressV = Clamp;
|
||||||
|
Filter = Linear;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertData {
|
||||||
|
float4 pos : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VertData VSDefault(VertData v_in) {
|
||||||
|
VertData vert_out;
|
||||||
|
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
|
||||||
|
vert_out.uv = v_in.uv;
|
||||||
|
return vert_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PI 3.1415926f
|
||||||
|
#define TAU 6.2831853f
|
||||||
|
#define deg30 0.20943951
|
||||||
|
|
||||||
|
float hexDist(float2 a, float2 b){
|
||||||
|
float2 p = abs(b-a);
|
||||||
|
float s = sin(deg30);
|
||||||
|
float c = cos(deg30);
|
||||||
|
|
||||||
|
float diagDist = s*p.x + c*p.y;
|
||||||
|
return max(diagDist, p.x)/c;
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 nearestHex(float s, float2 st){
|
||||||
|
float h = sin(deg30)*s;
|
||||||
|
float r = cos(deg30)*s;
|
||||||
|
float b = s + 2.0*h;
|
||||||
|
float a = 2.0*r;
|
||||||
|
float m = h/r;
|
||||||
|
|
||||||
|
float2 sect = st/float2(2.0*r, h+s);
|
||||||
|
float2 sectPxl = fmod(st, float2(2.0*r, h+s));
|
||||||
|
|
||||||
|
float aSection = fmod(floor(sect.y), 2.0);
|
||||||
|
|
||||||
|
float2 coord = floor(sect);
|
||||||
|
if(aSection > 0.0){
|
||||||
|
if(sectPxl.y < (h-sectPxl.x*m)){
|
||||||
|
coord -= 1.0;
|
||||||
|
}
|
||||||
|
else if(sectPxl.y < (-h + sectPxl.x*m)){
|
||||||
|
coord.y -= 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(sectPxl.x > r){
|
||||||
|
if(sectPxl.y < (2.0*h - sectPxl.x * m)){
|
||||||
|
coord.y -= 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(sectPxl.y < (sectPxl.x*m)){
|
||||||
|
coord.y -= 1.0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
coord.x -= 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float xoff = fmod(coord.y, 2.0)*r;
|
||||||
|
return float2(coord.x*2.0*r-xoff, coord.y*(h+s))+float2(r*2.0, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PSDefault(VertData v_in) : TARGET {
|
||||||
|
float2 coord = v_in.uv * ViewSize.xy;
|
||||||
|
float s = ViewSize.x/HexagonScale;
|
||||||
|
float2 nearest = nearestHex(s, coord);
|
||||||
|
float4 texel = InputA.Sample(def_sampler, nearest / ViewSize.xy);//, -100.0);
|
||||||
|
float dist = hexDist(coord, nearest);
|
||||||
|
|
||||||
|
float luminance = (texel.r + texel.g + texel.b)/3.0;
|
||||||
|
//float interiorSize = luminance*s;
|
||||||
|
float interiorSize = s * HexagonWallScale;
|
||||||
|
float interior = 1.0 - smoothstep(interiorSize-1.0, interiorSize, dist);
|
||||||
|
//fragColor = float4(dist);
|
||||||
|
return float4(texel.rgb*interior, 1.0);
|
||||||
|
//fragColor = float4(nearest, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
technique Draw
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
vertex_shader = VSDefault(v_in);
|
||||||
|
pixel_shader = PSDefault(v_in);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue