mirror of
https://github.com/libretro/slang-shaders.git
synced 2024-11-23 08:19:54 +00:00
327 lines
8.7 KiB
Plaintext
327 lines
8.7 KiB
Plaintext
#version 450
|
|
// Generators - Kali - 2013-10-10
|
|
// https://www.shadertoy.com/view/Xtf3Rn
|
|
|
|
// Generators!
|
|
|
|
layout(std140, set = 0, binding = 0) uniform UBO
|
|
{
|
|
mat4 MVP;
|
|
vec4 OutputSize;
|
|
vec4 OriginalSize;
|
|
vec4 SourceSize;
|
|
uint FrameCount;
|
|
} global;
|
|
|
|
#pragma stage vertex
|
|
layout(location = 0) in vec4 Position;
|
|
layout(location = 1) in vec2 TexCoord;
|
|
layout(location = 0) out vec2 vTexCoord;
|
|
const vec2 madd = vec2(0.5, 0.5);
|
|
void main()
|
|
{
|
|
gl_Position = global.MVP * Position;
|
|
vTexCoord = gl_Position.xy;
|
|
}
|
|
|
|
#pragma stage fragment
|
|
layout(location = 0) in vec2 vTexCoord;
|
|
layout(location = 0) out vec4 FragColor;
|
|
float iGlobalTime = float(global.FrameCount)*0.025;
|
|
vec2 iResolution = global.OutputSize.xy;
|
|
|
|
// "GENERATORS REDUX" by Kali
|
|
|
|
// Same fractal as "Ancient Temple" + rotations, improved shading
|
|
// (better coloring, AO and shadows), some lighting effects, and a path for the camera
|
|
// following a liquid metal ball.
|
|
|
|
|
|
#define ENABLE_HARD_SHADOWS // turn off to enable faster AO soft shadows
|
|
//#define ENABLE_VIBRATION
|
|
//#define ENABLE_POSTPROCESS // Works better on window view rather than full screen
|
|
|
|
|
|
#define RAY_STEPS 70
|
|
#define SHADOW_STEPS 50
|
|
#define LIGHT_COLOR vec3(.85,.9,1.)
|
|
#define AMBIENT_COLOR vec3(.8,.83,1.)
|
|
#define FLOOR_COLOR vec3(1.,.7,.9)
|
|
#define ENERGY_COLOR vec3(1.,.7,.4)
|
|
#define BRIGHTNESS .9
|
|
#define GAMMA 1.3
|
|
#define SATURATION .85
|
|
|
|
|
|
#define detail .00005
|
|
#define t iGlobalTime*.25
|
|
|
|
|
|
|
|
vec3 lightdir=normalize(vec3(0.5,-0.3,-1.));
|
|
vec3 ambdir=normalize(vec3(0.,0.,1.));
|
|
const vec3 origin=vec3(0.,3.11,0.);
|
|
vec3 energy=vec3(0.01);
|
|
#ifdef ENABLE_VIBRATION
|
|
float vibration=sin(iGlobalTime*60.)*.0013;
|
|
#else
|
|
float vibration=0.;
|
|
#endif
|
|
float det=0.0;
|
|
vec3 pth1;
|
|
|
|
|
|
mat2 rot(float a) {
|
|
return mat2(cos(a),sin(a),-sin(a),cos(a));
|
|
}
|
|
|
|
|
|
vec3 path(float ti) {
|
|
return vec3(sin(ti),.3-sin(ti*.632)*.3,cos(ti*.5))*.5;
|
|
}
|
|
|
|
float Sphere(vec3 p, vec3 rd, float r){//A RAY TRACED SPHERE
|
|
float b = dot( -p, rd );
|
|
float inner = b * b - dot( p, p ) + r * r;
|
|
if( inner < 0.0 ) return -1.0;
|
|
return b - sqrt( inner );
|
|
}
|
|
|
|
vec2 de(vec3 pos) {
|
|
float hid=0.;
|
|
vec3 tpos=pos;
|
|
tpos.xz=abs(.5-mod(tpos.xz,1.));
|
|
vec4 p=vec4(tpos,1.);
|
|
float y=max(0.,.35-abs(pos.y-3.35))/.35;
|
|
for (int i=0; i<7; i++) {//LOWERED THE ITERS
|
|
p.xyz = abs(p.xyz)-vec3(-0.02,1.98,-0.02);
|
|
p=p*(2.0+vibration*y)/clamp(dot(p.xyz,p.xyz),.4,1.)-vec4(0.5,1.,0.4,0.);
|
|
p.xz*=mat2(-0.416,-0.91,0.91,-0.416);
|
|
}
|
|
float fl=pos.y-3.013;
|
|
float fr=(length(max(abs(p.xyz)-vec3(0.1,5.0,0.1),vec3(0.0)))-0.05)/p.w;//RETURN A RRECT
|
|
//float fr=length(p.xyz)/p.w;
|
|
float d=min(fl,fr);
|
|
d=min(d,-pos.y+3.95);
|
|
if (abs(d-fl)<.001) hid=1.;
|
|
return vec2(d,hid);
|
|
}
|
|
|
|
|
|
vec3 normal(vec3 p) {
|
|
vec3 e = vec3(0.0,det,0.0);
|
|
|
|
return normalize(vec3(
|
|
de(p+e.yxx).x-de(p-e.yxx).x,
|
|
de(p+e.xyx).x-de(p-e.xyx).x,
|
|
de(p+e.xxy).x-de(p-e.xxy).x
|
|
)
|
|
);
|
|
}
|
|
|
|
float shadow(vec3 pos, vec3 sdir) {//THIS ONLY RUNS WHEN WITH HARD SHADOWS
|
|
float sh=1.0;
|
|
float totdist =2.0*det;
|
|
float dist=10.;
|
|
float t1=Sphere((pos-.005*sdir)-pth1,-sdir,0.015);
|
|
if (t1>0. && t1<.5) {
|
|
vec3 sphglowNorm=normalize(pos-t1*sdir-pth1);
|
|
sh=1.-pow(max(.0,dot(sphglowNorm,sdir))*1.2,3.);
|
|
}
|
|
for (int steps=0; steps<SHADOW_STEPS; steps++) {
|
|
if (totdist<.6 && dist>detail) {
|
|
vec3 p = pos - totdist * sdir;
|
|
dist = de(p).x;
|
|
sh = min( sh, max(50.*dist/totdist,0.0) );
|
|
totdist += max(.01,dist);
|
|
}
|
|
}
|
|
|
|
return clamp(sh,0.1,1.0);
|
|
}
|
|
|
|
|
|
float calcAO( const vec3 pos, const vec3 nor ) {
|
|
float aodet=detail*40.;
|
|
float totao = 0.0;
|
|
float sca = 14.0;
|
|
for( int aoi=0; aoi<5; aoi++ ) {
|
|
float hr = aodet*float(aoi*aoi);
|
|
vec3 aopos = nor * hr + pos;
|
|
float dd = de( aopos ).x;
|
|
totao += -(dd-hr)*sca;
|
|
sca *= 0.7;
|
|
}
|
|
return clamp( 1.0 - 5.0*totao, 0., 1.0 );
|
|
}
|
|
|
|
float _texture(vec3 p) {
|
|
p=abs(.5-fract(p*10.));
|
|
vec3 c=vec3(3.);
|
|
float es, l=es=0.;
|
|
for (int i = 0; i < 10; i++) {
|
|
p = abs(p + c) - abs(p - c) - p;
|
|
p/= clamp(dot(p, p), .0, 1.);
|
|
p = p* -1.5 + c;
|
|
if ( mod(float(i), 2.) < 1. ) {
|
|
float pl = l;
|
|
l = length(p);
|
|
es+= exp(-1. / abs(l - pl));
|
|
}
|
|
}
|
|
return es;
|
|
}
|
|
|
|
vec3 light(in vec3 p, in vec3 dir, in vec3 n, in float hid) {//PASSING IN THE NORMAL
|
|
#ifdef ENABLE_HARD_SHADOWS
|
|
float sh=shadow(p, lightdir);
|
|
#else
|
|
float sh=calcAO(p,-2.5*lightdir);//USING AO TO MAKE VERY SOFT SHADOWS
|
|
#endif
|
|
float ao=calcAO(p,n);
|
|
float diff=max(0.,dot(lightdir,-n))*sh;
|
|
float y=3.35-p.y;
|
|
vec3 amb=max(.5,dot(dir,-n))*.5*AMBIENT_COLOR;
|
|
if (hid<.5) {
|
|
amb+=max(0.2,dot(vec3(0.,1.,0.),-n))*FLOOR_COLOR*pow(max(0.,.2-abs(3.-p.y))/.2,1.5)*2.;
|
|
amb+=energy*pow(max(0.,.4-abs(y))/.4,2.)*max(0.2,dot(vec3(0.,-sign(y),0.),-n))*2.;
|
|
}
|
|
vec3 r = reflect(lightdir,n);
|
|
float spec=pow(max(0.,dot(dir,-r))*sh,10.);
|
|
vec3 col;
|
|
float energysource=pow(max(0.,.04-abs(y))/.04,4.)*2.;
|
|
if (hid>1.5) {col=vec3(1.); spec=spec*spec;}
|
|
else{
|
|
float k=_texture(p)*.23+.2;
|
|
k=min(k,1.5-energysource);
|
|
col=mix(vec3(k,k*k,k*k*k),vec3(k),.3);
|
|
if (abs(hid-1.)<.001) col*=FLOOR_COLOR*1.3;
|
|
}
|
|
col=col*(amb+diff*LIGHT_COLOR)+spec*LIGHT_COLOR;
|
|
if (hid<.5) {
|
|
col=max(col,energy*2.*energysource);
|
|
}
|
|
col*=min(1.,ao+length(energy)*.5*max(0.,.1-abs(y))/.1);
|
|
return col;
|
|
}
|
|
|
|
vec3 raymarch(in vec3 from, in vec3 dir)
|
|
|
|
{
|
|
float ey=mod(t*.5,1.);
|
|
float glow,eglow,ref,sphdist,totdist=glow=eglow=ref=sphdist=0.;
|
|
vec2 d=vec2(1.,0.);
|
|
vec3 p, col=vec3(0.);
|
|
vec3 origdir=dir,origfrom=from,sphNorm;
|
|
|
|
//FAKING THE SQUISHY BALL BY MOVING A RAY TRACED BALL
|
|
vec3 wob=cos(dir*500.0*length(from-pth1)+(from-pth1)*250.+iGlobalTime*10.)*0.0005;
|
|
float t1=Sphere(from-pth1+wob,dir,0.015);
|
|
float tg=Sphere(from-pth1+wob,dir,0.02);
|
|
if(t1>0.){
|
|
ref=1.0;from+=t1*dir;sphdist=t1;
|
|
sphNorm=normalize(from-pth1+wob);
|
|
dir=reflect(dir,sphNorm);
|
|
}
|
|
else if (tg>0.) {
|
|
vec3 sphglowNorm=normalize(from+tg*dir-pth1+wob);
|
|
glow+=pow(max(0.,dot(sphglowNorm,-dir)),5.);
|
|
};
|
|
|
|
for (int i=0; i<RAY_STEPS; i++) {
|
|
if (d.x>det && totdist<3.0) {
|
|
p=from+totdist*dir;
|
|
d=de(p);
|
|
det=detail*(1.+totdist*60.)*(1.+ref*5.);
|
|
totdist+=d.x;
|
|
energy=ENERGY_COLOR*(1.5+sin(iGlobalTime*20.+p.z*10.))*.25;
|
|
if(d.x<0.015)glow+=max(0.,.015-d.x)*exp(-totdist);
|
|
if (d.y<.5 && d.x<0.03){//ONLY DOING THE GLOW WHEN IT IS CLOSE ENOUGH
|
|
float glw=min(abs(3.35-p.y-ey),abs(3.35-p.y+ey));//2 glows at once
|
|
eglow+=max(0.,.03-d.x)/.03*
|
|
(pow(max(0.,.05-glw)/.05,5.)
|
|
+pow(max(0.,.15-abs(3.35-p.y))/.15,8.))*1.5;
|
|
}
|
|
}
|
|
}
|
|
float l=pow(max(0.,dot(normalize(-dir.xz),normalize(lightdir.xz))),2.);
|
|
l*=max(0.2,dot(-dir,lightdir));
|
|
vec3 backg=.5*(1.2-l)+LIGHT_COLOR*l*.7;
|
|
backg*=AMBIENT_COLOR;
|
|
if (d.x<=det) {
|
|
vec3 norm=normal(p-abs(d.x-det)*dir);//DO THE NORMAL CALC OUTSIDE OF LIGHTING (since we already have the sphere normal)
|
|
col=light(p-abs(d.x-det)*dir, dir, norm, d.y)*exp(-.2*totdist*totdist);
|
|
col = mix(col, backg, 1.0-exp(-1.*pow(totdist,1.5)));
|
|
} else {
|
|
col=backg;
|
|
}
|
|
vec3 lglow=LIGHT_COLOR*pow(l,30.)*.5;
|
|
col+=glow*(backg+lglow)*1.3;
|
|
col+=pow(eglow,2.)*energy*.015;
|
|
col+=lglow*min(1.,totdist*totdist*.3);
|
|
if (ref>0.5) {
|
|
vec3 sphlight=light(origfrom+sphdist*origdir,origdir,sphNorm,2.);
|
|
col=mix(col*.3+sphlight*.7,backg,1.0-exp(-1.*pow(sphdist,1.5)));
|
|
}
|
|
return col;
|
|
}
|
|
|
|
vec3 move(inout mat2 rotview1,inout mat2 rotview2) {
|
|
vec3 go=path(t);
|
|
vec3 adv=path(t+.7);
|
|
vec3 advec=normalize(adv-go);
|
|
float an=atan(advec.x,advec.z);
|
|
rotview1=mat2(cos(an),sin(an),-sin(an),cos(an));
|
|
an=advec.y*1.7;
|
|
rotview2=mat2(cos(an),sin(an),-sin(an),cos(an));
|
|
return go;
|
|
}
|
|
|
|
|
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
|
{
|
|
pth1 = path(t+.3)+origin+vec3(0.,.01,0.);
|
|
vec2 uv = fragCoord.xy / iResolution.xy*2.-1.;
|
|
vec2 uv2=uv;
|
|
#ifdef ENABLE_POSTPROCESS
|
|
uv*=1.+pow(length(uv2*uv2*uv2*uv2),4.)*.07;
|
|
#endif
|
|
uv.y*=iResolution.y/iResolution.x;
|
|
#ifdef MOUSE
|
|
vec2 mouse=(iMouse.xy/iResolution.xy-.5)*3.;
|
|
if (iMouse.z<1.) mouse=vec2(0.);
|
|
#else
|
|
vec2 mouse = vec2(0.0, 0.0);
|
|
#endif
|
|
mat2 rotview1, rotview2;
|
|
vec3 from=origin+move(rotview1,rotview2);
|
|
vec3 dir=normalize(vec3(uv*.8,1.));
|
|
dir.yz*=rot(mouse.y);
|
|
dir.xz*=rot(mouse.x);
|
|
dir.yz*=rotview2;
|
|
dir.xz*=rotview1;
|
|
vec3 color=raymarch(from,dir);
|
|
color=clamp(color,vec3(.0),vec3(1.));
|
|
color=pow(color,vec3(GAMMA))*BRIGHTNESS;
|
|
color=mix(vec3(length(color)),color,SATURATION);
|
|
#ifdef ENABLE_POSTPROCESS
|
|
vec3 rain=pow(texture(iChannel0,uv2+iGlobalTime*7.25468).rgb,vec3(1.5));
|
|
color=mix(rain,color,clamp(iGlobalTime*.5-.5,0.,1.));
|
|
color*=1.-pow(length(uv2*uv2*uv2*uv2)*1.1,6.);
|
|
uv2.y *= iResolution.y / 360.0;
|
|
color.r*=(.5+abs(.5-mod(uv2.y ,.021)/.021)*.5)*1.5;
|
|
color.g*=(.5+abs(.5-mod(uv2.y+.007,.021)/.021)*.5)*1.5;
|
|
color.b*=(.5+abs(.5-mod(uv2.y+.014,.021)/.021)*.5)*1.5;
|
|
color*=.9+rain*.35;
|
|
#endif
|
|
fragColor = vec4(color,1.);
|
|
}
|
|
|
|
void main(void)
|
|
{
|
|
//just some shit to wrap shadertoy's stuff
|
|
vec2 FragmentCoord = vTexCoord.xy*global.OutputSize.xy;
|
|
FragmentCoord.y = -FragmentCoord.y;
|
|
mainImage(FragColor,FragmentCoord);
|
|
}
|