mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-22 15:51:30 +11:00
304 lines
10 KiB
Plaintext
304 lines
10 KiB
Plaintext
|
#version 450
|
||
|
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;
|
||
|
|
||
|
/*
|
||
|
|
||
|
Transparent Lattice
|
||
|
-------------------
|
||
|
|
||
|
Just a transparent lattice. Not much different to my other transparent examples,
|
||
|
except this one is point lit... In case it needs to be said, a lot of it is faked,
|
||
|
so is more of a novelty than anything else.
|
||
|
|
||
|
I wrote it some time ago, then forgot about it. I thought I'd put it up just in
|
||
|
case it's of any use to anyone. It runs reasonably fast, considering that the
|
||
|
lighting is calculated multiple times a pass, but could benefit from a little more
|
||
|
tweaking.
|
||
|
|
||
|
Related shaders:
|
||
|
|
||
|
Cloudy Spikeball - Duke
|
||
|
https://www.shadertoy.com/view/MljXDw
|
||
|
// Port from a demo by Las - Worth watching.
|
||
|
// http://www.pouet.net/topic.php?which=7920&page=29&x=14&y=9
|
||
|
|
||
|
Virtually the same thing, but with rounded cubes and less interesting lighting.
|
||
|
Transparent Cube Field - Shane
|
||
|
https://www.shadertoy.com/view/ll2SRy
|
||
|
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
// Cheap vec3 to vec3 hash. Works well enough, but there are other ways.
|
||
|
vec3 hash33(vec3 p){
|
||
|
|
||
|
float n = sin(dot(p, vec3(7, 157, 113)));
|
||
|
return fract(vec3(2097152, 262144, 32768)*n);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
// Rounded cube field, for comparison. It runs at full speed, believe it or not.
|
||
|
float map(vec3 p){
|
||
|
|
||
|
// Creating the repeat cubes, with slightly convex faces. Standard,
|
||
|
// flat faced cubes don't capture the light quite as well.
|
||
|
|
||
|
// 3D space repetition.
|
||
|
p = fract(p)-.5; // + o
|
||
|
|
||
|
// A bit of roundness. Used to give the cube faces a touch of convexity.
|
||
|
float r = dot(p, p) - 0.21;
|
||
|
|
||
|
// Max of abs(x), abs(y) and abs(z) minus a constant gives a cube.
|
||
|
// Adding a little bit of "r," above, rounds off the surfaces a bit.
|
||
|
p = abs(p);
|
||
|
return max(max(p.x, p.y), p.z)*.95 + r*0.25 - 0.21;
|
||
|
|
||
|
|
||
|
// Alternative. Egg shapes... kind of.
|
||
|
//float perturb = sin(p.x*10.)*sin(p.y*10.)*sin(p.z*10.);
|
||
|
//p += hash33(floor(p))*.15;
|
||
|
//return length(fract(p)-.5)-0.3 + perturb*0.05;
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
// A fake noise looking field. Pretty interesting.
|
||
|
float map(vec3 p){
|
||
|
|
||
|
|
||
|
p = (cos(p*.315*2.5 + sin(p.zxy*.875*2.5))); // + iGlobalTime*.5
|
||
|
|
||
|
float n = length(p);
|
||
|
|
||
|
p = sin(p*6. + cos(p.yzx*6.));
|
||
|
|
||
|
return n - 1. - abs(p.x*p.y*p.z)*.05;
|
||
|
|
||
|
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
float map(vec3 p){
|
||
|
|
||
|
|
||
|
|
||
|
vec2 c;
|
||
|
|
||
|
// SECTION 1
|
||
|
//
|
||
|
// Repeat field entity one, which is just some tubes repeated in all directions every
|
||
|
// two units, then combined with a smooth minimum function. Otherwise known as a lattice.
|
||
|
p = abs(fract(p/3.)*3.-1.5);
|
||
|
//c.x = sminP(length(p.xy),sminP(length(p.yz),length(p.xz), 0.25), 0.25)-0.75; // EQN 1
|
||
|
//c.x = sqrt(min(dot(p.xy, p.xy),min(dot(p.yz, p.yz),dot(p.xz, p.xz))))-0.75; // EQN 2
|
||
|
c.x = min(max(p.x, p.y),min(max(p.y, p.z),max(p.x, p.z)))-0.75; // EQN 3
|
||
|
//p = abs(p); c.x = max(p.x,max(p.y,p.z)) - .5;
|
||
|
|
||
|
|
||
|
// SECTION 2
|
||
|
//
|
||
|
// Repeat field entity two, which is just an abstract object repeated every half unit.
|
||
|
p = abs(fract(p*4./3.)*.75 - 0.375);
|
||
|
c.y = min(p.x,min(p.y,p.z)); // EQN 1
|
||
|
//c.y = min(max(p.x, p.y),min(max(p.y, p.z),max(p.x, p.z)))-0.125; //-0.175, etc. // EQN 2
|
||
|
//c.y = max(p.x,max(p.y,p.z)) - .4;
|
||
|
|
||
|
// SECTION 3
|
||
|
//
|
||
|
// Combining the two entities above.
|
||
|
//return length(c)-.1; // EQN 1
|
||
|
//return max(c.x, c.y)-.05; // EQN 2
|
||
|
return max(abs(c.x), abs(c.y))*.75 + length(c)*.25 - .1;
|
||
|
//return max(abs(c.x), abs(c.y))*.75 + abs(c.x+c.y)*.25 - .1;
|
||
|
//return max(abs(c.x), abs(c.y)) - .1;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Not big on accuracy, but lower on operations. Few distance function calls are important
|
||
|
// during volumetric passes.
|
||
|
vec3 calcNormal(in vec3 p, float d) {
|
||
|
const vec2 e = vec2(0.01, 0);
|
||
|
return normalize(vec3(d - map(p - e.xyy), d - map(p - e.yxy), d - map(p - e.yyx)));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
// Tetrahedral normal, to save a couple of "map" calls. Courtesy of IQ. Unfortunately, still
|
||
|
// not fast enough in this particular instance.
|
||
|
vec3 calcNormal(in vec3 p){
|
||
|
|
||
|
// Note the slightly increased sampling distance, to alleviate artifacts due to hit point inaccuracies.
|
||
|
vec2 e = vec2(0.0025, -0.0025);
|
||
|
return normalize(e.xyy * map(p + e.xyy) + e.yyx * map(p + e.yyx) + e.yxy * map(p + e.yxy) + e.x * map(p + e.xxx));
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
|
||
|
void mainImage( out vec4 fragColor, vec2 fragCoord ) {
|
||
|
|
||
|
|
||
|
// Screen coordinates.
|
||
|
vec2 uv = (fragCoord.xy - iResolution.xy*.5 )/iResolution.y;
|
||
|
|
||
|
// Unit direction ray. The last term is one of many ways to fish-lens the camera.
|
||
|
// For a regular view, set "rd.z" to something like "0.5."
|
||
|
vec3 rd = normalize(vec3(uv, (1.-dot(uv, uv)*.5)*.5)); // Fish lens, for that 1337, but tryhardish, demo look. :)
|
||
|
|
||
|
// There are a few ways to hide artifacts and inconsistencies. Making things go fast is one of them. :)
|
||
|
// Ray origin, scene color, and surface postion vector.
|
||
|
vec3 ro = vec3(0., 0., iGlobalTime*1.5), col=vec3(0), sp, sn, lp, ld, rnd;
|
||
|
|
||
|
|
||
|
// Swivel the unit ray to look around the scene.
|
||
|
// Compact 2D rotation matrix, courtesy of Shadertoy user, "Fabrice Neyret."
|
||
|
vec2 a = sin(vec2(1.5707963, 0) + iGlobalTime*0.375);
|
||
|
rd.xz = mat2(a, -a.y, a.x)*rd.xz;
|
||
|
rd.xy = mat2(a, -a.y, a.x)*rd.xy;
|
||
|
|
||
|
|
||
|
lp = vec3(0, 1, 4);
|
||
|
lp.xz = mat2(a, -a.y, a.x)*lp.xz;
|
||
|
lp.xy = mat2(a, -a.y, a.x)*lp.xy;
|
||
|
lp += ro;
|
||
|
|
||
|
|
||
|
// Unit ray jitter is another way to hide artifacts. It can also trick the viewer into believing
|
||
|
// something hard core, like global illumination, is happening. :)
|
||
|
//rd *= 0.99 + hash33(rd)*0.02;
|
||
|
|
||
|
// Some more randomization, to be used for color based jittering inside the loop.
|
||
|
rnd = hash33(rd+311.);
|
||
|
|
||
|
|
||
|
// Ray distance, bail out layer number, surface distance and normalized accumulated distance.
|
||
|
float t=0., layers=0., d, aD;
|
||
|
|
||
|
// Light variables.
|
||
|
float lDist, s, l;
|
||
|
|
||
|
// Surface distance threshold. Smaller numbers gives a thinner membrane, but lessens detail...
|
||
|
// hard to explain. It's easier to check it out for yourself.
|
||
|
float thD = .0125; // + smoothstep(-0.2, 0.2, sin(iGlobalTime*0.75 - 3.14159*0.4))*0.025;
|
||
|
|
||
|
|
||
|
// Only a few iterations seemed to be enough. Obviously, more looks better, but is slower.
|
||
|
for(float i=0.; i<64.; i++) {
|
||
|
|
||
|
// Break conditions. Anything that can help you bail early usually increases frame rate.
|
||
|
if(layers>31. || dot(col, vec3(.299, .587, .114)) > 1. || t>16.) break;
|
||
|
|
||
|
// Current ray postion. Slightly redundant here, but sometimes you may wish to reuse
|
||
|
// it during the accumulation stage.
|
||
|
sp = ro+rd*t;
|
||
|
|
||
|
d = map(sp); // Distance to nearest point on the noise surface.
|
||
|
|
||
|
// If we get within a certain distance of the surface, accumulate some surface values.
|
||
|
// Values further away have less influence on the total.
|
||
|
//
|
||
|
// aD - Accumulated distance. You could smoothly interpolate it, if you wanted.
|
||
|
//
|
||
|
// 1/.(1. + t*t*0.1) - Basic distance attenuation. Feel free to substitute your own.
|
||
|
|
||
|
// Normalized distance from the surface threshold value to our current isosurface value.
|
||
|
aD = (thD-abs(d)*31./32.)/thD;
|
||
|
|
||
|
// If we're within the surface threshold, accumulate some color.
|
||
|
// Two "if" statements in a shader loop makes me nervous. I don't suspect there'll be any
|
||
|
// problems, but if there are, let us know.
|
||
|
if(aD>0.) {
|
||
|
|
||
|
|
||
|
// Add the accumulated surface distance value, along with some basic falloff using the
|
||
|
// camera to light distance, "lDist." There's a bit of color jitter there, too.
|
||
|
|
||
|
sn = calcNormal(sp, d)*sign(d);
|
||
|
ld = (lp - sp); //vec3(.5773)
|
||
|
lDist = max(length(ld), .001);
|
||
|
ld /= lDist;
|
||
|
s = pow(max(dot(reflect(-ld, sn), -rd), 0.), 8.);
|
||
|
l = max(dot(ld, sn), 0.);
|
||
|
|
||
|
|
||
|
//float c = dot(sin(sp*128. - cos(sp.yzx*64.)), vec3(.166))+.5;
|
||
|
col += ((l + .1) + vec3(.5, .7, 1)*s)*aD/(1. + lDist*0.25 + lDist*lDist*0.05)*.2;
|
||
|
// Failed experiment with color jitter to take out more banding.
|
||
|
//col += ((l + .05 + fract(rnd + i*27.)*.1) + vec3(.5, .7, 1)*s)*aD/(1. + lDist*0.25 + lDist*lDist*0.05)*.2;
|
||
|
|
||
|
|
||
|
// The layer number is worth noting. Accumulating more layers gives a bit more glow.
|
||
|
// Lower layer numbers allow a quicker bailout. A lot of it is guess work.
|
||
|
layers++;
|
||
|
|
||
|
}
|
||
|
|
||
|
// Kind of weird the way this works. I think not allowing the ray to hone in properly is
|
||
|
// the very thing that gives an even spread of values. The figures are based on a bit
|
||
|
// of knowledge versus trial and error. If you have a faster computer, feel free to tweak
|
||
|
// them a bit.
|
||
|
t += max(abs(d)*.75, thD*.25);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
t = min(t, 16.);
|
||
|
|
||
|
|
||
|
col = mix(col, vec3(0), 1.-exp(-0.025*t*t));////1.-exp(-0.01*t*t) 1.-1./(1. + t*t*.1)
|
||
|
|
||
|
// Mixing the greytone color with a firey orange vignette. There's no meaning
|
||
|
// behind it. I just thought the artsy greyscale was a little too artsy.
|
||
|
uv = abs(fragCoord.xy/iResolution.xy - .5); // Wasteful, but the GPU can handle it.
|
||
|
col = mix(col, vec3(min(col.x*1.5, 1.), pow(col.x, 2.5), pow(col.x, 12.)).yxz,
|
||
|
min( dot(pow(uv, vec2(4.)), vec2(1))*8., 1.));
|
||
|
|
||
|
//col = vec3(min(col.z*1.5, 1.), pow(col.z, 2.5), pow(col.z, 12.));
|
||
|
|
||
|
|
||
|
// Mixing the vignette colors up a bit more.
|
||
|
col = mix(col, col.zxy, dot(sin(rd*5.), vec3(.166)) + 0.166);
|
||
|
|
||
|
|
||
|
// Presenting the color to the screen.
|
||
|
fragColor = vec4( sqrt(clamp(col, 0., 1.)), 1.0 );
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
//just some shit to wrap shadertoy's stuff
|
||
|
vec2 FragCoord = vTexCoord.xy*global.OutputSize.xy;
|
||
|
FragCoord.y = -FragCoord.y;
|
||
|
mainImage(FragColor,FragCoord);
|
||
|
}
|