mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-28 18:41:14 +00:00
examples: Fix some example shaders and add new ones
* Fixed 'Pixelator's color transition point being off-center and uncontrollable. * Fixed 'Drunk' filter not working at all. * Added an inverted mode to 'Luma Burn'. * Added exponential Luma to 'Luma Burn'. * Fixed odd color behavior in the 'Color Shift' transition by switching out HSL with HSV. * Added a new 'Sliding Bars' transition shader, for an example of it see this clip: https://clips.twitch.tv/RacyEndearingHorseradishAMPTropPunch .
This commit is contained in:
parent
984a1132bf
commit
a989709b6f
5 changed files with 284 additions and 81 deletions
|
@ -15,22 +15,17 @@ uniform float4x4 Random<
|
|||
string name = "Random Array";
|
||||
string description = "A float4x4 value containing random values between 0 and 1";
|
||||
>;
|
||||
uniform texture2d ImageSource<
|
||||
bool visible = false;
|
||||
string name = "Source Texture (Filter, Transition)";
|
||||
uniform float4 ViewSize<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform float2 ImageSource_Size<
|
||||
bool visible = false;
|
||||
string name = "Source Texture Size (Filter, Transition)";
|
||||
>;
|
||||
uniform float2 ImageSource_Texel<
|
||||
bool visible = false;
|
||||
string name = "Source Texture Texel Size (Filter, Transition)";
|
||||
uniform texture2d InputA<
|
||||
bool automatic = true;
|
||||
>;
|
||||
|
||||
// Shader Parameters
|
||||
uniform float p_drunk_strength<
|
||||
bool visible = true;
|
||||
string field_type = "slider";
|
||||
string name = "Strength";
|
||||
float minimum = 0.;
|
||||
float maximum = 100.;
|
||||
|
@ -38,6 +33,7 @@ uniform float p_drunk_strength<
|
|||
> = 25.0;
|
||||
uniform float p_drunk_speed<
|
||||
bool visible = true;
|
||||
string field_type = "slider";
|
||||
string name = "Speed";
|
||||
float minimum = 0.;
|
||||
float maximum = 100.;
|
||||
|
@ -56,19 +52,11 @@ struct VertData {
|
|||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct FragData {
|
||||
float4 pos : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
FragData VSDefault(VertData v_in) {
|
||||
FragData vert_out;
|
||||
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
|
||||
vert_out.uv = v_in.uv;
|
||||
return vert_out;
|
||||
VertData VSDefault(VertData vtx) {
|
||||
vtx.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
|
||||
return vtx;
|
||||
}
|
||||
|
||||
// ---------- Fixed Color
|
||||
#define MAX_PTS 5
|
||||
#define MAX_LINE 5.
|
||||
|
||||
|
@ -96,30 +84,30 @@ float2 mult_at(int x, int y) {
|
|||
return mult;
|
||||
}
|
||||
|
||||
float4 PS_Drunk(FragData v_in) : TARGET {
|
||||
float2 uvs[MAX_PTS + 1][MAX_PTS + 1];
|
||||
float4 PSDrunkStage1(VertData vtx) : TARGET {
|
||||
float2 uvs[MAX_PTS + 1][MAX_PTS + 1];
|
||||
for (int x = 0; x <= MAX_PTS; x++) {
|
||||
for (int y = 0; y <= MAX_PTS; y++) {
|
||||
float2 off = float2(0, 0);
|
||||
if ((x > 0) && (x < MAX_PTS)) {
|
||||
off.x = cos(Time.y * p_drunk_speed + random_time_at(x, y)) * ImageSource_Texel.x;
|
||||
off.x = cos(Time.x * p_drunk_speed + random_time_at(x, y)) * ViewSize.z;
|
||||
}
|
||||
if ((y > 0) && (y < MAX_PTS)) {
|
||||
off.y = sin(Time.y * p_drunk_speed + random_time_at(x, y)) * ImageSource_Texel.y;
|
||||
off.y = sin(Time.x * p_drunk_speed + random_time_at(x, y)) * ViewSize.w;
|
||||
}
|
||||
off *= (p_drunk_strength / 100.0) * ImageSource_Size * 0.5 * mult_at(x, y);
|
||||
off *= (p_drunk_strength / 100.0) * ViewSize.xy * 0.5 * mult_at(x, y);
|
||||
|
||||
uvs[x][y] = float2(x / MAX_LINE + off.x, y / MAX_LINE + off.y);
|
||||
}
|
||||
}
|
||||
|
||||
float2 fade = frac(v_in.uv * MAX_LINE);
|
||||
float2 fade = frac(vtx.uv * MAX_LINE);
|
||||
fade = (sin((fade - 0.5) * 3.141) + 1.0) * 0.5;
|
||||
|
||||
int2 _low = int2(floor(v_in.uv * MAX_LINE));
|
||||
int2 _hig = int2(ceil(v_in.uv * MAX_LINE));
|
||||
int2 _low = int2(floor(vtx.uv * MAX_LINE));
|
||||
int2 _hig = int2(ceil(vtx.uv * MAX_LINE));
|
||||
|
||||
float2 uv = v_in.uv;
|
||||
float2 uv = vtx.uv;
|
||||
float2 uv_tl = uvs[_low.x][_low.y];
|
||||
float2 uv_tr = uvs[_hig.x][_low.y];
|
||||
float2 uv_bl = uvs[_low.x][_hig.y];
|
||||
|
@ -129,14 +117,14 @@ float4 PS_Drunk(FragData v_in) : TARGET {
|
|||
float2 uv_b = lerp(uv_bl, uv_br, fade.x);
|
||||
uv = lerp(uv_t, uv_b, fade.y);
|
||||
|
||||
return ImageSource.Sample(def_sampler, uv);
|
||||
return InputA.Sample(def_sampler, uv);
|
||||
}
|
||||
|
||||
technique Draw
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PS_Drunk(v_in);
|
||||
vertex_shader = VSDefault(vtx);
|
||||
pixel_shader = PSDrunkStage1(vtx);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,59 +56,29 @@ VertData VSDefault(VertData v_in) {
|
|||
return vert_out;
|
||||
}
|
||||
|
||||
float4 HSLtoRGB(float4 HSLA) {
|
||||
float3 rgb = clamp(
|
||||
abs(
|
||||
fmod(
|
||||
HSLA.x * 6.0 + float3(0.0, 4.0, 2.0),
|
||||
6.0
|
||||
) - 3.0
|
||||
) - 1.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
return float4(HSLA.z + HSLA.y * (rgb - 0.5) * (1.0 - abs(2.0 * HSLA.z - 1.0)), HSLA.a);
|
||||
float4 RGBtoHSV(float4 RGBA) {
|
||||
const float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
const float e = 1.0e-10;
|
||||
float4 p = lerp(float4(RGBA.bg, K.wz), float4(RGBA.gb, K.xy), step(RGBA.b, RGBA.g));
|
||||
float4 q = lerp(float4(p.xyw, RGBA.r), float4(RGBA.r, p.yzx), step(p.x, RGBA.r));
|
||||
float d = q.x - min(q.w, q.y);
|
||||
return float4(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x, RGBA.a);
|
||||
}
|
||||
|
||||
float4 RGBtoHSL(float4 RGBA) {
|
||||
float h = 0.0;
|
||||
float s = 0.0;
|
||||
float l = 0.0;
|
||||
float r = RGBA.r;
|
||||
float g = RGBA.g;
|
||||
float b = RGBA.b;
|
||||
float cMin = min( r, min( g, b ) );
|
||||
float cMax = max( r, max( g, b ) );
|
||||
|
||||
l = ( cMax + cMin ) / 2.0;
|
||||
if ( cMax > cMin ) {
|
||||
float cDelta = cMax - cMin;
|
||||
|
||||
//s = l < .05 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) ); Original
|
||||
s = l < .0 ? cDelta / ( cMax + cMin ) : cDelta / ( 2.0 - ( cMax + cMin ) );
|
||||
|
||||
if ( r == cMax ) {
|
||||
h = ( g - b ) / cDelta;
|
||||
} else if ( g == cMax ) {
|
||||
h = 2.0 + ( b - r ) / cDelta;
|
||||
} else {
|
||||
h = 4.0 + ( r - g ) / cDelta;
|
||||
}
|
||||
|
||||
if ( h < 0.0) {
|
||||
h += 6.0;
|
||||
}
|
||||
h = h / 6.0;
|
||||
}
|
||||
return float4( h, s, l, RGBA.a );
|
||||
float4 HSVtoRGB(float4 HSVA) {
|
||||
const float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
float4 v = float4(0,0,0,0);
|
||||
v.rgb = HSVA.z * lerp(K.xxx, clamp(abs(frac(HSVA.xxx + K.xyz) * 6.0 - K.www) - K.xxx, 0.0, 1.0), HSVA.y);
|
||||
v.a = HSVA.a;
|
||||
return v;
|
||||
}
|
||||
|
||||
float4 PSDefault(VertData v_in) : TARGET {
|
||||
float4 sampleA = InputA.Sample(def_sampler, v_in.uv);
|
||||
float4 sampleB = InputB.Sample(def_sampler, v_in.uv);
|
||||
|
||||
float4 hslA = RGBtoHSL(sampleA);
|
||||
float4 hslB = RGBtoHSL(sampleB);
|
||||
float4 hslA = RGBtoHSV(sampleA);
|
||||
float4 hslB = RGBtoHSV(sampleB);
|
||||
float4 hslT = hslB - hslA;
|
||||
if (hslT.r > 0.5) {
|
||||
hslB.r = 1.0 + (-1.0 + hslB.r);
|
||||
|
@ -120,7 +90,7 @@ float4 PSDefault(VertData v_in) : TARGET {
|
|||
hslB.b = 1.0 + (-1.0 + hslB.b);
|
||||
}
|
||||
|
||||
float4 rgb = HSLtoRGB(lerp(hslA, hslB, TransitionTime));
|
||||
float4 rgb = HSVtoRGB(lerp(hslA, hslB, TransitionTime));
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
|
|
@ -37,6 +37,18 @@ uniform float Sharpness<
|
|||
float scale = 1.0;
|
||||
> = 10.0;
|
||||
|
||||
uniform bool LumaIsExponential<
|
||||
string name = "Is Luminosity exponential?";
|
||||
>;
|
||||
uniform float LumaExponent<
|
||||
string name = "Luminosity Exponent";
|
||||
string field_type = "slider";
|
||||
float minimum = 0.;
|
||||
float maximum = 500.;
|
||||
float step = .01;
|
||||
float scale = .01;
|
||||
> = 150.;
|
||||
|
||||
// ---------- Shader Code
|
||||
sampler_state def_sampler {
|
||||
AddressU = Clamp;
|
||||
|
@ -65,6 +77,9 @@ float4 RGBtoYUV(float4 rgba, float3x3 yuv) {
|
|||
) + float4(0,0.5,0.5,0);
|
||||
}
|
||||
|
||||
#define C_e 2,7182818284590452353602874713527
|
||||
#define C_log2_e 1.4426950408889634073599246810019 // Windows calculator: log(e(1)) / log(2)
|
||||
|
||||
float4 PSDefault(VertData v_in) : TARGET {
|
||||
const float3x3 mYUV709n = { // Normalized
|
||||
0.2126, 0.7152, 0.0722,
|
||||
|
@ -79,7 +94,11 @@ float4 PSDefault(VertData v_in) : TARGET {
|
|||
float4 sampleBYUV = RGBtoYUV(sampleB, mYUV709n);
|
||||
|
||||
float sharpinv = 1.0 / Sharpness;
|
||||
float transition = sharpinv + sampleAYUV.r * (1.0 - sharpinv);
|
||||
float luma = sampleAYUV.r;
|
||||
if (LumaIsExponential) {
|
||||
luma = exp2(luma * LumaExponent * LumaExponent * -C_log2_e);
|
||||
}
|
||||
float transition = sharpinv + luma * (1.0 - sharpinv);
|
||||
transition -= TransitionTime;
|
||||
transition *= Sharpness;
|
||||
transition += 0.5;
|
||||
|
@ -97,3 +116,40 @@ technique Draw
|
|||
pixel_shader = PSDefault(v_in);
|
||||
}
|
||||
}
|
||||
|
||||
float4 PSInverse(VertData v_in) : TARGET {
|
||||
const float3x3 mYUV709n = { // Normalized
|
||||
0.2126, 0.7152, 0.0722,
|
||||
-0.1145721060573399, -0.3854278939426601, 0.5,
|
||||
0.5, -0.4541529083058166, -0.0458470916941834
|
||||
};
|
||||
|
||||
float4 sampleA = InputA.Sample(def_sampler, v_in.uv);
|
||||
float4 sampleB = InputB.Sample(def_sampler, v_in.uv);
|
||||
|
||||
float4 sampleAYUV = RGBtoYUV(sampleA, mYUV709n);
|
||||
float4 sampleBYUV = RGBtoYUV(sampleB, mYUV709n);
|
||||
|
||||
float sharpinv = 1.0 / Sharpness;
|
||||
float luma = (1.0 - sampleAYUV.r);
|
||||
if (LumaIsExponential) {
|
||||
luma = exp2(luma * LumaExponent * LumaExponent * -C_log2_e);
|
||||
}
|
||||
float transition = sharpinv + luma * (1.0 - sharpinv);
|
||||
transition -= TransitionTime;
|
||||
transition *= Sharpness;
|
||||
transition += 0.5;
|
||||
transition = clamp(transition, 0., 1.);
|
||||
|
||||
return sampleB * (1.0 - transition) + sampleA * (transition);
|
||||
//return transition;
|
||||
}
|
||||
|
||||
technique DrawInverse
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSInverse(v_in);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,14 @@ uniform float2 _3_blockOffset<
|
|||
float2 maximum = {100., 100.};
|
||||
float2 scale = {0.01, 0.01};
|
||||
> = {50., 50.};
|
||||
uniform float _4_transitionRange<
|
||||
string name = "Transition Range";
|
||||
string field_type = "slider";
|
||||
float minimum = 0.;
|
||||
float maximum = 100.;
|
||||
float scale = .005;
|
||||
float step = .01;
|
||||
> = 25.0;
|
||||
|
||||
// ---------- Shader Code
|
||||
sampler_state def_sampler {
|
||||
|
@ -104,7 +112,13 @@ float4 PSDefault(VertData v_in) : TARGET {
|
|||
float4 sampleA = InputA.Sample(def_sampler, finalUV);
|
||||
float4 sampleB = InputB.Sample(def_sampler, finalUV);
|
||||
|
||||
float4 rgb = lerp(sampleA, sampleB, clamp((TransitionTime - 0.45) * (1.0 / 0.45), 0., 1.));
|
||||
float transition = clamp(
|
||||
((TransitionTime - 0.5) / _4_transitionRange) * .5 + .5,
|
||||
0.,
|
||||
1.
|
||||
);
|
||||
|
||||
float4 rgb = lerp(sampleA, sampleB, transition);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
|
175
data/examples/shaders/transition/sliding-bars.effect
Normal file
175
data/examples/shaders/transition/sliding-bars.effect
Normal file
|
@ -0,0 +1,175 @@
|
|||
// 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 texture2d InputB<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform float TransitionTime<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform int2 TransitionSize<
|
||||
bool automatic = true;
|
||||
>;
|
||||
|
||||
uniform bool _49_FadeToColor<
|
||||
string name = "Fade To Color?";
|
||||
> = true;
|
||||
|
||||
uniform float4 _50_Color<
|
||||
string name = "Color";
|
||||
string field_type = "slider";
|
||||
float4 minimum = {0.,0.,0.,0.};
|
||||
float4 maximum = {100.,100.,100.,100.};
|
||||
float4 scale = {.01,.01,.01,.01};
|
||||
float4 step = {.01,.01,.01,.01};
|
||||
> = {0., 0., 0., 100.};
|
||||
|
||||
uniform float _100_Rotation<
|
||||
string name = "Rotation";
|
||||
string field_type = "slider";
|
||||
float minimum = -90.;
|
||||
float maximum = 90.;
|
||||
float scale = 1.;
|
||||
float step = .01;
|
||||
> = 30.;
|
||||
|
||||
uniform float _200_Bars<
|
||||
string name = "Number of Bars";
|
||||
string field_type = "slider";
|
||||
float minimum = 1.;
|
||||
float maximum = 100.;
|
||||
float scale = 1.;
|
||||
float step = .5;
|
||||
> = 20.;
|
||||
|
||||
// ---------- Shader Code
|
||||
sampler_state def_sampler {
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
Filter = Linear;
|
||||
};
|
||||
|
||||
struct VertData {
|
||||
float4 pos : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define TO_RAD(x) (x * (PI/180.))
|
||||
#define TO_DEG(x) (x * (180./PI))
|
||||
|
||||
VertData VSDefault(VertData vtx) {
|
||||
vtx.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
|
||||
return vtx;
|
||||
}
|
||||
|
||||
float2 rotate2D(float2 xy, float angle) {
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
return float2(xy.x * c + xy.y * s, xy.x * -s + xy.y * c);
|
||||
}
|
||||
|
||||
// https://www.shadertoy.com/view/4dXBRH
|
||||
float hash( in float2 p ) // replace this by something better
|
||||
{
|
||||
p = 50.0*frac( p*0.3183099 + float2(0.71,0.113));
|
||||
return -1.0+2.0*frac( p.x*p.y*(p.x+p.y) );
|
||||
}
|
||||
|
||||
// return value noise (in x) and its derivatives (in yz)
|
||||
float3 noised( in float2 p )
|
||||
{
|
||||
float2 i = floor( p );
|
||||
float2 f = frac( p );
|
||||
|
||||
// quintic interpolation
|
||||
float2 u = f*f*f*(f*(f*6.0-15.0)+10.0);
|
||||
float2 du = 30.0*f*f*(f*(f-2.0)+1.0);
|
||||
|
||||
float va = hash( i + float2(0.0,0.0) );
|
||||
float vb = hash( i + float2(1.0,0.0) );
|
||||
float vc = hash( i + float2(0.0,1.0) );
|
||||
float vd = hash( i + float2(1.0,1.0) );
|
||||
|
||||
float k0 = va;
|
||||
float k1 = vb - va;
|
||||
float k2 = vc - va;
|
||||
float k4 = va - vb - vc + vd;
|
||||
|
||||
return float3( va+(vb-va)*u.x+(vc-va)*u.y+(va-vb-vc+vd)*u.x*u.y, // value
|
||||
du*(u.yx*(va-vb-vc+vd) + float2(vb,vc) - va) ); // derivative
|
||||
}
|
||||
|
||||
bool compare_a_b(float time, float x, float dir) {
|
||||
if (dir < .5) {
|
||||
return time > x;
|
||||
} else {
|
||||
return (1. - time) < x;
|
||||
}
|
||||
}
|
||||
|
||||
float4 PSDefault(VertData vtx) : TARGET {
|
||||
float2 ruv = (rotate2D(vtx.uv - .5, TO_RAD(_100_Rotation)) + .5);
|
||||
|
||||
float bar_offset_max = .2;
|
||||
float bar_id = floor(ruv.y * _200_Bars);
|
||||
float bar_offset = 0.;
|
||||
float bar_direction = 0.;
|
||||
if (TransitionTime < .5 || !_49_FadeToColor) {
|
||||
bar_offset = noised(float2(bar_id, 0.)).x * bar_offset_max;
|
||||
bar_direction = step(noised(float2(bar_id, 1.)).x, .5);
|
||||
} else {
|
||||
bar_offset = noised(float2(bar_id, 1.)).x * bar_offset_max;
|
||||
bar_direction = step(noised(float2(bar_id, 0.)).x, .5);
|
||||
}
|
||||
|
||||
if (_49_FadeToColor) {
|
||||
float bar_time_a = (TransitionTime * 3.) + bar_offset;
|
||||
float bar_time_b = (TransitionTime * 3. - 2.) - bar_offset;
|
||||
if (compare_a_b(bar_time_a, vtx.uv.x, bar_direction)) {
|
||||
if (compare_a_b(bar_time_b, vtx.uv.x, bar_direction)) {
|
||||
return InputB.Sample(def_sampler, vtx.uv);
|
||||
} else {
|
||||
return _50_Color;
|
||||
}
|
||||
} else {
|
||||
return InputA.Sample(def_sampler, vtx.uv);
|
||||
}
|
||||
} else {
|
||||
float bar_time_a = clamp((TransitionTime + bar_offset) / (1. - bar_offset_max), 0., 1.);
|
||||
if (compare_a_b(bar_time_a, vtx.uv.x, bar_direction)) {
|
||||
return InputB.Sample(def_sampler, vtx.uv);
|
||||
} else {
|
||||
return InputA.Sample(def_sampler, vtx.uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
technique Draw
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(vtx);
|
||||
pixel_shader = PSDefault(vtx);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue