obs-StreamFX/data/examples/shaders/source/shadertoy-3l23Rh.effect

220 lines
6.1 KiB
Text
Raw Normal View History

// Protean clouds by nimitz (twitter: @stormoid)
// https://www.shadertoy.com/view/3l23Rh
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// Contact the author for other licensing options
#define vec2 float2
#define vec3 float3
#define vec4 float4
#define ivec2 int2
#define ivec3 int3
#define ivec4 int4
#define mat2 float2x2
#define mat3 float3x3
#define mat4 float4x4
#define fract frac
#define mix lerp
#define iTime Time.x
#define iResolution ViewSize
uniform float2 mouse<
string name = "Virtual Mouse Coordinates";
string field_type = "slider";
float2 minimum = {0, 0};
float2 maximum = {100., 100.};
float2 scale = {.01, .01};
float2 step = {.01, .01};
> = {0., 0.};
uniform float4x4 ViewProj<
bool automatic = true;
>;
uniform float4 Time<
bool automatic = true;
>;
uniform float4 ViewSize<
bool automatic = true;
>;
int2 iMouse() {
return int2(mouse.x * ViewSize.x, mouse.y * ViewSize.y);
}
/*
Technical details:
The main volume noise is generated from a deformed periodic grid, which can produce
a large range of noise-like patterns at very cheap evalutation cost. Allowing for multiple
fetches of volume gradient computation for improved lighting.
To further accelerate marching, since the volume is smooth, more than half the the density
information isn't used to rendering or shading but only as an underlying volume distance to
determine dynamic step size, by carefully selecting an equation (polynomial for speed) to
step as a function of overall density (not necessarialy rendered) the visual results can be
the same as a naive implementation with ~40% increase in rendering performance.
Since the dynamic marching step size is even less uniform due to steps not being rendered at all
the fog is evaluated as the difference of the fog integral at each rendered step.
*/
mat2 rot(in float a) {
float c = cos(a), s = sin(a);
return mat2(c,-s,s,c);
}
float mag2(vec2 p) {
return dot(p,p);
}
float linstep(in float mn, in float mx, in float x) {
return clamp((x - mn)/(mx - mn), 0., 1.);
}
// ToDo: obs parser doesn't like static - ensure that these move into functions
//float prm1;
//vec2 bsMo;
vec2 disp(float t) {
return vec2(sin(t*0.22)*1., cos(t*0.175)*1.) * 2.;
}
vec2 map(vec3 p, inout float prm1, inout vec2 bsMo) {
const mat3 m3 = mat3(0.33338, 0.56034, -0.71817, -0.87887, 0.32651, -0.15323, 0.15162, 0.69596, 0.61339)*1.93;
vec3 p2 = p;
p2.xy -= disp(p.z).xy;
p.xy = mul(p.xy, rot(sin(p.z+iTime)*(0.1 + prm1*0.05) + iTime*0.09));
float cl = mag2(p2.xy);
float d = 0.;
p *= .61;
float z = 1.;
float trk = 1.;
float dspAmp = 0.1 + prm1*0.2;
for(int i = 0; i < 5; i++) {
p += sin(p.zxy*0.75*trk + iTime*trk*.8)*dspAmp;
d -= abs(dot(cos(p), sin(p.yzx))*z);
z *= 0.57;
trk *= 1.4;
p = mul(p, m3);
}
d = abs(d + prm1*3.)+ prm1*.3 - 2.5 + bsMo.y;
return vec2(d + cl*.2 + 0.25, cl);
}
vec4 render( in vec3 ro, in vec3 rd, float time, inout float prm1, inout vec2 bsMo) {
vec4 rez = vec4(0, 0, 0, 0);
const float ldst = 8.;
float2 dispt = disp(time + ldst) * 0.5;
vec3 lpos = vec3(dispt.x, dispt.y, time + ldst);
float t = 1.5;
float fogT = 0.;
for(int i=0; i<130; i++) {
if(rez.a > 0.99)break;
vec3 pos = ro + t*rd;
vec2 mpv = map(pos, prm1, bsMo);
float den = clamp(mpv.x-0.3,0.,1.)*1.12;
float dn = clamp((mpv.x + 2.),0.,3.);
vec4 col = vec4(0, 0, 0, 0);
if (mpv.x > 0.6) {
col = vec4(sin(vec3(5.,0.4,0.2) + mpv.y*0.1 +sin(pos.z*0.4)*0.5 + 1.8)*0.5 + 0.5,0.08);
col *= den*den*den;
col.rgb *= linstep(4.,-2.5, mpv.x)*2.3;
float dif = clamp((den - map(pos+.8, prm1, bsMo).x)/9., 0.001, 1. );
dif += clamp((den - map(pos+.35, prm1, bsMo).x)/2.5, 0.001, 1. );
col.xyz *= den*(vec3(0.005,.045,.075) + 1.5*vec3(0.033,0.07,0.03)*dif);
}
float fogC = exp(t*0.2 - 2.2);
col.rgba += vec4(0.06,0.11,0.11, 0.1)*clamp(fogC-fogT, 0., 1.);
fogT = fogC;
rez = rez + col*(1. - rez.a);
t += clamp(0.5 - dn*dn*.05, 0.09, 0.3);
}
return clamp(rez, 0.0, 1.0);
}
float getsat(vec3 c) {
float mi = min(min(c.x, c.y), c.z);
float ma = max(max(c.x, c.y), c.z);
return (ma - mi)/(ma+ 1e-7);
return 0;
}
//from my "Will it blend" shader (https://www.shadertoy.com/view/lsdGzN)
vec3 iLerp(in vec3 a, in vec3 b, in float x) {
vec3 ic = mix(a, b, x) + vec3(1e-6,0.,0.);
float sd = abs(getsat(ic) - mix(getsat(a), getsat(b), x));
vec3 dir = normalize(vec3(2.*ic.x - ic.y - ic.z, 2.*ic.y - ic.x - ic.z, 2.*ic.z - ic.y - ic.x));
float lgt = dot(vec3(1.0, 1.0, 1.0), ic);
float ff = dot(dir, normalize(ic));
ic += 1.5*dir*sd*ff*lgt;
return clamp(ic,0.,1.);
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
float prm1 = 0.;
vec2 bsMo = {0., 0.};
vec2 q = fragCoord.xy/iResolution.xy;
vec2 p = (fragCoord.xy - 0.5*iResolution.xy)/iResolution.y;
bsMo = (iMouse().xy - 0.5*iResolution.xy)/iResolution.y;
float time = iTime*3.;
vec3 ro = vec3(0,0,time);
ro += vec3(sin(iTime)*0.5,sin(iTime*1.)*0.,0);
float dspAmp = .85;
ro.xy += disp(ro.z)*dspAmp;
float tgtDst = 3.5;
vec3 target = normalize(ro - vec3(disp(time + tgtDst)*dspAmp, time + tgtDst));
ro.x -= bsMo.x*2.;
vec3 rightdir = normalize(cross(target, vec3(0,1,0)));
vec3 updir = normalize(cross(rightdir, target));
rightdir = normalize(cross(updir, target));
vec3 rd = normalize((p.x*rightdir + p.y*updir)*1. - target);
rd.xy = mul(rd.xy, rot(-disp(time + 3.5).x*0.2 + bsMo.x));
prm1 = smoothstep(-0.4, 0.4,sin(iTime*0.3));
vec4 scn = render(ro, rd, time, prm1, bsMo);
vec3 col = scn.rgb;
col = iLerp(col.bgr, col.rgb, clamp(1.-prm1,0.05,1.));
col = pow(col, vec3(.55,0.65,0.6))*vec3(1.,.97,.9);
col *= pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.12)*0.7+0.3; //Vign
fragColor = vec4( col, 1.0 );
}
struct VertFragData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertFragData VSDefault(VertFragData vtx) {
vtx.pos = mul(float4(vtx.pos.xyz, 1.0), ViewProj);
return vtx;
}
float4 PSDefault(VertFragData vtx) : TARGET {
float4 col = float4(1., 1., 1., 1.);
mainImage(col, vtx.uv * ViewSize.xy);
return col;
}
technique Draw
{
pass
{
vertex_shader = VSDefault(vtx);
pixel_shader = PSDefault(vtx);
}
}