mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-28 18:41:14 +00:00
transition-shader: New transition examples
Color Shift: Uses HSL and some math to smoothly shift Hue Saturation and Lightness between A and B. Luma Burn: "Burns" away the Luminosity of A to reveal the B side. Pixelator: Classic/Retro pixelation effect often seen in older games to transition between settings.
This commit is contained in:
parent
ba97ea06b0
commit
7d5c4361e3
3 changed files with 353 additions and 0 deletions
135
data/examples/shaders/transition/color-shift.effect
Normal file
135
data/examples/shaders/transition/color-shift.effect
Normal file
|
@ -0,0 +1,135 @@
|
|||
// 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 texture2d InputB<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform float TransitionTime<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform int2 TransitionSize<
|
||||
bool automatic = true;
|
||||
>;
|
||||
|
||||
uniform float Sharpness<
|
||||
string field_type = "slider";
|
||||
string suffix = " %";
|
||||
float minimum = 8.0;
|
||||
float maximum = 128.0;
|
||||
float step = 0.01;
|
||||
float scale = 1.0;
|
||||
> = 10.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;
|
||||
}
|
||||
|
||||
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 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 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 hslT = hslB - hslA;
|
||||
if (hslT.r > 0.5) {
|
||||
hslB.r = 1.0 + (-1.0 + hslB.r);
|
||||
}
|
||||
if (hslT.g > 0.5) {
|
||||
hslB.g = 1.0 + (-1.0 + hslB.g);
|
||||
}
|
||||
if (hslT.b > 0.5) {
|
||||
hslB.b = 1.0 + (-1.0 + hslB.b);
|
||||
}
|
||||
|
||||
float4 rgb = HSLtoRGB(lerp(hslA, hslB, TransitionTime));
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
technique Draw
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSDefault(v_in);
|
||||
}
|
||||
}
|
99
data/examples/shaders/transition/luma-burn.effect
Normal file
99
data/examples/shaders/transition/luma-burn.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 texture2d InputB<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform float TransitionTime<
|
||||
bool automatic = true;
|
||||
>;
|
||||
uniform int2 TransitionSize<
|
||||
bool automatic = true;
|
||||
>;
|
||||
|
||||
uniform float Sharpness<
|
||||
string field_type = "slider";
|
||||
string suffix = " %";
|
||||
float minimum = 8.0;
|
||||
float maximum = 128.0;
|
||||
float step = 0.01;
|
||||
float scale = 1.0;
|
||||
> = 10.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;
|
||||
}
|
||||
|
||||
float4 RGBtoYUV(float4 rgba, float3x3 yuv) {
|
||||
return float4(
|
||||
rgba.r * yuv._m00 + rgba.g * yuv._m01 + rgba.b * yuv._m02,
|
||||
rgba.r * yuv._m10 + rgba.g * yuv._m11 + rgba.b * yuv._m12,
|
||||
rgba.r * yuv._m20 + rgba.g * yuv._m21 + rgba.b * yuv._m22,
|
||||
rgba.a
|
||||
) + float4(0,0.5,0.5,0);
|
||||
}
|
||||
|
||||
float4 PSDefault(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 transition = sharpinv + sampleAYUV.r * (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 Draw
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSDefault(v_in);
|
||||
}
|
||||
}
|
119
data/examples/shaders/transition/pixelator.effect
Normal file
119
data/examples/shaders/transition/pixelator.effect
Normal file
|
@ -0,0 +1,119 @@
|
|||
// 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 _0_oldStyle<
|
||||
string name = "Retro Style";
|
||||
|
||||
> = false;
|
||||
uniform float2 _1_pixelateCenter<
|
||||
string name = "Pixelation Center";
|
||||
string field_type = "slider";
|
||||
float2 minimum = {0., 0.};
|
||||
float2 maximum = {100., 100.};
|
||||
float2 scale = {0.01, 0.01};
|
||||
> = {50., 50.};
|
||||
uniform float _2_maximumBlockSize<
|
||||
string name = "Maximum Pixelation";
|
||||
string field_type = "slider";
|
||||
float minimum = 1.0;
|
||||
float maximum = 16.0;
|
||||
float step = 1.0;
|
||||
> = 12.;
|
||||
uniform float2 _3_blockOffset<
|
||||
string name = "Block Offset";
|
||||
string field_type = "slider";
|
||||
float2 minimum = {0., 0.};
|
||||
float2 maximum = {100., 100.};
|
||||
float2 scale = {0.01, 0.01};
|
||||
> = {50., 50.};
|
||||
|
||||
// ---------- 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 {
|
||||
float animProgress = TransitionTime;
|
||||
|
||||
// Progress as a bounce value (0..1..0)
|
||||
float animStuff = 1.0 - (abs(animProgress - 0.5) * 2.0);
|
||||
// There are two ways to calculate this, one is pixel aligned the other is block aligned.
|
||||
float animBlockSize = 0;
|
||||
if (_0_oldStyle) {
|
||||
// Block Size, always a multiple of 2. (Block Aligned)
|
||||
animBlockSize = pow(2.0, floor(_2_maximumBlockSize * animStuff));
|
||||
} else {
|
||||
// Block Size, always a multiple of 2. (Pixel Aligned)
|
||||
animBlockSize = floor(pow(2.0, _2_maximumBlockSize * animStuff));
|
||||
}
|
||||
|
||||
// UV Calculations
|
||||
float2 finalUV = v_in.uv;
|
||||
finalUV -= _1_pixelateCenter; // Offset by the pixelation center.
|
||||
finalUV *= ViewSize.xy; // Convert to 0..Resolution UVs for pixelation.
|
||||
finalUV /= animBlockSize; // Divide by current block size.
|
||||
finalUV = floor(finalUV) + _3_blockOffset; // Use floor() on it to get aligned pixels.
|
||||
finalUV *= animBlockSize; // Multiply by current block size.
|
||||
finalUV *= ViewSize.zw; // Convert back to 0..1 UVs for texture sampling.
|
||||
finalUV += _1_pixelateCenter; // Revert the offset by the pixelation center again.
|
||||
|
||||
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.));
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
technique Draw
|
||||
{
|
||||
pass
|
||||
{
|
||||
vertex_shader = VSDefault(v_in);
|
||||
pixel_shader = PSDefault(v_in);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue