mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-26 01:11:32 +11:00
444 lines
9 KiB
Plaintext
444 lines
9 KiB
Plaintext
#version 450
|
|
// Xafer - 2017-04-30
|
|
// https://www.shadertoy.com/view/4dlyzl
|
|
|
|
// Reflections, refractions, lights such
|
|
|
|
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;
|
|
|
|
#define NEAR 0.01
|
|
#define FAR 12.0
|
|
|
|
#define STEP_SIZE 0.1
|
|
#define MAX_ITER 300
|
|
#define MAX_CYCLES 2
|
|
#define DELTA 0.01
|
|
#define A_SPEED 0.3
|
|
#define CAM_DIST 3.3
|
|
|
|
#define RECAST_MAX 5
|
|
|
|
#define GLOW_POWER 6.0
|
|
#define GLOW_COLOR vec3(0.2,0.4,0.4)
|
|
#define GRASS_SIZE vec2(0.005,0.4)
|
|
|
|
#define SKY_COLOR vec3(0.1,0.3,0.4)
|
|
|
|
|
|
//Structures
|
|
|
|
struct Light
|
|
{
|
|
vec3 pos;
|
|
vec3 color;
|
|
float radius;
|
|
float intensity;
|
|
};
|
|
|
|
struct lComp
|
|
{
|
|
vec3 specular;
|
|
float specularIntensity;
|
|
vec3 diffuse;
|
|
};
|
|
|
|
struct Ray
|
|
{
|
|
vec3 pos;
|
|
vec3 dir;
|
|
float dist;
|
|
float near;
|
|
};
|
|
|
|
struct Material
|
|
{
|
|
vec3 color;
|
|
float specular;
|
|
float diffuse;//
|
|
float ambient;//Ambient light factor
|
|
float refl;//How reflective is a surface
|
|
float refr;//Refraction index
|
|
float opacity;//For refractions
|
|
};
|
|
|
|
|
|
//Signed Distance Functions
|
|
|
|
float sdSphere(vec3 p)
|
|
{
|
|
return length(p) - 1.0;
|
|
}
|
|
|
|
float sdPlane(vec3 p)
|
|
{
|
|
return -p.y;
|
|
}
|
|
|
|
float sdBox( vec3 p)
|
|
{
|
|
vec3 d = abs(p) - vec3(1.0);
|
|
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
|
|
}
|
|
|
|
float opAdd(float d1, float d2)
|
|
{
|
|
return min(d1,d2);
|
|
}
|
|
|
|
float opSub(float d1, float d2)
|
|
{
|
|
return max(-d1,d2);
|
|
}
|
|
|
|
float opInter(float d1, float d2)
|
|
{
|
|
return max(d1,d2);
|
|
}
|
|
|
|
|
|
//Combinations
|
|
|
|
float walls(vec3 p)
|
|
{
|
|
p.y -= 1.0;
|
|
p.y * 2.0;
|
|
|
|
vec3 p2 = p;
|
|
vec3 p3 = p;
|
|
|
|
float width = 0.1;
|
|
vec2 dist = vec2(5.0);
|
|
|
|
p2.xz = mod(p2.xz,dist)-(dist/2.0);
|
|
p2.x /= width;
|
|
p2.z /= 2.0;
|
|
|
|
p3.xz = mod(p3.xz,dist)-(dist/2.0);
|
|
p3.z /= width;
|
|
p3.x /= 2.0;
|
|
|
|
float env = opAdd(sdPlane(p),opAdd(sdBox(p2),sdBox(p3)));
|
|
|
|
env = opSub(max(-p.y - 0.3, p.y + 0.2),max(env,sdSphere(p/(CAM_DIST-0.4))));
|
|
|
|
env = opAdd(env,sdSphere(p/0.7 + vec3(0,0.5,0)));
|
|
|
|
return opSub(sdSphere(p),env);
|
|
}
|
|
|
|
float map(vec3 pos, float factor)
|
|
{
|
|
return walls(pos);
|
|
}
|
|
|
|
float map(vec3 pos)
|
|
{
|
|
return map(pos,0.0);
|
|
}
|
|
|
|
//Environment propreties
|
|
|
|
vec3 getNormal(vec3 p)
|
|
{
|
|
vec2 delta = vec2 (DELTA, 0.0);
|
|
vec3 normal = normalize (vec3 (
|
|
map (p + delta.xyy) - map (p - delta.xyy),
|
|
map (p + delta.yxy) - map (p - delta.yxy),
|
|
map (p + delta.yyx) - map (p - delta.yyx)));
|
|
|
|
return normalize(normal);
|
|
}
|
|
|
|
|
|
|
|
Material getMaterial(vec3 pos)
|
|
{
|
|
Material mat;
|
|
mat.color = vec3(sin(pos.y),cos(pos.x),sin(pos.z))/2.0 + 0.5;
|
|
mat.refl = 0.0;
|
|
mat.refr = 0.8;
|
|
mat.opacity = 0.7;
|
|
|
|
mat.color = mix(mat.color,getNormal(pos),0.2);
|
|
|
|
return mat;
|
|
}
|
|
|
|
//RayMarching
|
|
|
|
Ray march(Ray ray, int iterations)
|
|
{
|
|
float n = 1.0 / min(iResolution.x, iResolution.y);
|
|
|
|
for(int i = 0; i < iterations; i++)
|
|
{
|
|
ray.near = map(ray.pos,sqrt(ray.dist)*n);
|
|
|
|
if(ray.near < DELTA || ray.dist > FAR)
|
|
break;
|
|
|
|
float n = ray.near * STEP_SIZE;
|
|
ray.pos += ray.dir * n;
|
|
ray.dist += n;
|
|
}
|
|
|
|
return ray;
|
|
}
|
|
|
|
lComp getLighting(Ray ray)
|
|
{
|
|
lComp lightComposition;
|
|
|
|
//Looping through lights
|
|
Light light;
|
|
light.radius = 3.5;
|
|
light.intensity = 1.0;
|
|
light.pos = vec3(0,-1,0);
|
|
light.color = vec3(1.0,0.8,0.6);
|
|
|
|
float specular;
|
|
float diffuse;
|
|
|
|
vec3 rayPos = ray.pos;
|
|
vec3 dir = light.pos - ray.pos;
|
|
float lDist = length(dir);
|
|
|
|
dir = normalize(dir);
|
|
|
|
rayPos += DELTA*dir;
|
|
|
|
float near = 0.0;
|
|
float dist = 0.0;
|
|
|
|
float l;
|
|
|
|
for(int i =0 ; i < MAX_ITER;i++)
|
|
{
|
|
near = map(rayPos);
|
|
l = length(rayPos-light.pos);
|
|
if(near < DELTA || dist > lDist)
|
|
break;
|
|
|
|
float n = abs(near * 0.1);
|
|
|
|
rayPos += n*dir;
|
|
dist += n;
|
|
}
|
|
|
|
if(near < DELTA)
|
|
diffuse = 0.0;
|
|
else if(dist > lDist)
|
|
{
|
|
diffuse = max(0.0,1.0 - (lDist/light.radius));
|
|
specular = dot(reflect(ray.dir,getNormal(ray.pos)),dir)/2.0 + 0.5;
|
|
specular = -cos(specular*3.1416)/2.0 + 0.5;
|
|
specular = pow(specular,lDist*lDist);
|
|
//if(specular > 0.9);
|
|
// specular /= 20.0;
|
|
}
|
|
|
|
vec3 normal = getNormal(ray.pos);
|
|
|
|
lightComposition.diffuse = mix(SKY_COLOR, light.color, diffuse);
|
|
lightComposition.specular = light.color;
|
|
lightComposition.specularIntensity = specular;
|
|
|
|
return lightComposition;
|
|
}
|
|
|
|
//Marching through refractions
|
|
|
|
vec3 getRefraction(Ray ray)
|
|
{
|
|
vec3 color;
|
|
float colorFactor;
|
|
|
|
float intensity = 1.0;
|
|
Material mat = getMaterial(ray.pos);;
|
|
|
|
for(int i = 0; i < MAX_CYCLES; i++)
|
|
{
|
|
vec3 normal = getNormal(ray.pos);
|
|
ray.dir = refract(ray.dir, normal, mat.refr);
|
|
|
|
vec3 m = ray.dir*DELTA*2.0;
|
|
|
|
int inside = 0;
|
|
|
|
for(int j = 0; j < MAX_ITER && (ray.near < DELTA || inside == 1); j++)
|
|
{
|
|
ray.pos += m;
|
|
ray.dist += DELTA*2.0;
|
|
ray.near = map(ray.pos);
|
|
}
|
|
|
|
ray.dir = refract(ray.dir,normal,mat.refr);
|
|
ray = march(ray,MAX_ITER);
|
|
|
|
if(ray.near > DELTA || ray.dist > FAR)
|
|
{
|
|
color += SKY_COLOR*intensity;
|
|
colorFactor += intensity;
|
|
break;
|
|
}
|
|
|
|
lComp lightComposition = getLighting(ray);
|
|
|
|
mat = getMaterial(ray.pos);
|
|
|
|
vec3 col = mix(mat.color * lightComposition.diffuse,lightComposition.specular, lightComposition.specularIntensity);
|
|
|
|
color += mix(col,SKY_COLOR,ray.dist/FAR)*intensity;
|
|
colorFactor += intensity;
|
|
|
|
intensity *= 1.0 - mat.opacity;
|
|
}
|
|
|
|
return color/colorFactor;
|
|
}
|
|
|
|
//Marching through reflections
|
|
|
|
vec3 getReflection(Ray ray)
|
|
{
|
|
vec3 color;
|
|
float colorFactor;
|
|
|
|
float intensity = 1.0;
|
|
|
|
for(int i = 0; i < MAX_CYCLES; i++)
|
|
{
|
|
vec3 normal = getNormal(ray.pos);
|
|
ray.dir = reflect(ray.dir,normal);
|
|
ray.pos += ray.dir * DELTA;
|
|
|
|
ray = march(ray, MAX_ITER);
|
|
|
|
Material mat = getMaterial(ray.pos);
|
|
|
|
intensity *= mat.refl;
|
|
|
|
lComp lightComposition = getLighting(ray);
|
|
|
|
vec3 col = mix(mat.color * lightComposition.diffuse, lightComposition.specular, lightComposition.specularIntensity);
|
|
|
|
color += mix(col,SKY_COLOR,ray.dist/FAR)*intensity;
|
|
colorFactor += intensity;
|
|
}
|
|
|
|
return color/colorFactor;
|
|
}
|
|
|
|
//Getting the color at the specified point
|
|
|
|
vec3 getColor(Ray ray)
|
|
{
|
|
|
|
vec3 color;
|
|
vec3 normal = getNormal(ray.pos);
|
|
|
|
if(ray.dist > FAR)
|
|
{
|
|
color = SKY_COLOR;
|
|
}
|
|
else if(ray.near <= DELTA)
|
|
{
|
|
Material mat = getMaterial(ray.pos);
|
|
|
|
color = mat.color;
|
|
|
|
lComp lightComposition = getLighting(ray);
|
|
color *= lightComposition.diffuse;
|
|
|
|
if(mat.refr > 0.0)
|
|
color = mix(getRefraction(ray),color,mat.opacity);
|
|
|
|
if(mat.refl > 0.0)
|
|
color = mix(color,getReflection(ray),mat.refl);
|
|
|
|
color = mix(color, lightComposition.specular, lightComposition.specularIntensity);
|
|
|
|
color = mix(color, SKY_COLOR , ray.dist/FAR);
|
|
color = mix(color, SKY_COLOR , dot(ray.dir,normal)/2.0 + 0.5);
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
vec3 castRay(vec3 origin, vec3 direction)
|
|
{
|
|
//Generating ray
|
|
Ray ray;
|
|
ray.pos = origin;
|
|
ray.dir = direction;
|
|
ray.dist = 0.0;
|
|
|
|
//Move the ray to a surface up to far distance
|
|
ray = march(ray, MAX_ITER*2);
|
|
|
|
return getColor(ray);
|
|
}
|
|
|
|
//Initialisation
|
|
|
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
|
{
|
|
|
|
//Setting up screen-correct uv
|
|
vec2 uv = ( fragCoord.xy / iResolution.xy ) * 2.0 - vec2( 1 );
|
|
uv.x *= iResolution.x/iResolution.y;
|
|
|
|
//Setting up rotation
|
|
float sa = sin( iGlobalTime * A_SPEED );
|
|
float ca = cos( iGlobalTime * A_SPEED );
|
|
|
|
float cDist = CAM_DIST + sin(iGlobalTime * A_SPEED);
|
|
|
|
//Creating ray
|
|
vec3 or = vec3(sa*cDist,0.5,-ca*cDist);
|
|
vec3 di = -normalize(vec3(uv.x,uv.y,-1.0));
|
|
|
|
//Rotating orientation
|
|
mat3 r;
|
|
r[0] = vec3(ca,0,sa);
|
|
r[1] = vec3(0,1,0);
|
|
r[2] = vec3(-sa,0,ca);
|
|
di = r*di;
|
|
|
|
vec3 color = castRay(or,di);
|
|
|
|
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);
|
|
}
|