1// Compatibility #ifdefs needed for parameters 2#ifdef GL_ES 3#define COMPAT_PRECISION mediump 4#else 5#define COMPAT_PRECISION 6#endif 7 8// Parameter lines go here: 9#pragma parameter RETRO_PIXEL_SIZE "Retro Pixel Size" 0.84 0.0 1.0 0.01 10#ifdef PARAMETER_UNIFORM 11// All parameter floats need to have COMPAT_PRECISION in front of them 12uniform COMPAT_PRECISION float RETRO_PIXEL_SIZE; 13#else 14#define RETRO_PIXEL_SIZE 0.84 15#endif 16 17#if defined(VERTEX) 18 19#if __VERSION__ >= 130 20#define COMPAT_VARYING out 21#define COMPAT_ATTRIBUTE in 22#define COMPAT_TEXTURE texture 23#else 24#define COMPAT_VARYING varying 25#define COMPAT_ATTRIBUTE attribute 26#define COMPAT_TEXTURE texture2D 27#endif 28 29#ifdef GL_ES 30#define COMPAT_PRECISION mediump 31#else 32#define COMPAT_PRECISION 33#endif 34 35COMPAT_ATTRIBUTE vec4 VertexCoord; 36COMPAT_ATTRIBUTE vec4 COLOR; 37COMPAT_ATTRIBUTE vec4 TexCoord; 38COMPAT_VARYING vec4 COL0; 39COMPAT_VARYING vec4 TEX0; 40// out variables go here as COMPAT_VARYING whatever 41 42vec4 _oPosition1; 43uniform mat4 MVPMatrix; 44uniform COMPAT_PRECISION int FrameDirection; 45uniform COMPAT_PRECISION int FrameCount; 46uniform COMPAT_PRECISION vec2 OutputSize; 47uniform COMPAT_PRECISION vec2 TextureSize; 48uniform COMPAT_PRECISION vec2 InputSize; 49 50// compatibility #defines 51#define vTexCoord TEX0.xy 52#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 53#define OutSize vec4(OutputSize, 1.0 / OutputSize) 54 55void main() 56{ 57 gl_Position = MVPMatrix * VertexCoord; 58 TEX0.xy = VertexCoord.xy; 59// Paste vertex contents here: 60} 61 62#elif defined(FRAGMENT) 63 64#if __VERSION__ >= 130 65#define COMPAT_VARYING in 66#define COMPAT_TEXTURE texture 67out vec4 FragColor; 68#else 69#define COMPAT_VARYING varying 70#define FragColor gl_FragColor 71#define COMPAT_TEXTURE texture2D 72#endif 73 74#ifdef GL_ES 75#ifdef GL_FRAGMENT_PRECISION_HIGH 76precision highp float; 77#else 78precision mediump float; 79#endif 80#define COMPAT_PRECISION mediump 81#else 82#define COMPAT_PRECISION 83#endif 84 85uniform COMPAT_PRECISION int FrameDirection; 86uniform COMPAT_PRECISION int FrameCount; 87uniform COMPAT_PRECISION vec2 OutputSize; 88uniform COMPAT_PRECISION vec2 TextureSize; 89uniform COMPAT_PRECISION vec2 InputSize; 90uniform sampler2D Texture; 91COMPAT_VARYING vec4 TEX0; 92// in variables go here as COMPAT_VARYING whatever 93 94// compatibility #defines 95#define Source Texture 96#define vTexCoord TEX0.xy 97 98#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize 99#define OutSize vec4(OutputSize, 1.0 / OutputSize) 100 101// delete all 'params.' or 'registers.' or whatever in the fragment 102float iGlobalTime = float(FrameCount)*0.025; 103vec2 iResolution = OutputSize.xy; 104 105 106 107// 2D rotation. Always handy. 108mat2 rot(float th){ float cs = cos(th), si = sin(th); return mat2(cs, -si, si, cs); } 109 110// 3D Voronoi-like function. Cheap, low quality, 1st and 2nd order 3D Voronoi imitation. 111// 112// I wrote this a while back because I wanted a stand-alone algorithm fast enough to produce regular, or 2nd order, 113// Voronoi-looking patterns in a raymarching setting. Anyway, this is what I came up with. Obviously, it wouldn't 114// pass as genuine 3D Voronoi, but there's only so much you can do with a few lines. Even so, it has a Voronoi feel 115// to it. Hence, Voronesque. 116// 117// Here's a rough explanation of how it works: Instead of partitioning space into cubes, partition it into its 118// simplex form, namely tetrahedrons. Use the four tetrahedral vertices to create some random falloff values, then 119// pick off the two highest, or lowest, depending on perspective. That's it. If you'd like to know more, the 120// function is roughly commented, plus there's a simplex noise related link below that should make it more clear. 121// 122// Credits: Ken Perlin, the creator of simplex noise, of course. Stefan Gustavson's paper - "Simplex Noise Demystified." 123// IQ, other "ShaderToy.com" people, Brian Sharpe (does interesting work), etc. 124// 125// My favorite simplex-related write up: "Simplex Noise, keeping it simple." - Jasper Flick? 126// http://catlikecoding.com/unity/tutorials/simplex-noise/ 127// 128float Voronesque( in vec3 p ){ 129 130 // Skewing the cubic grid, then determining the first vertice. 131 vec3 i = floor(p + dot(p, vec3(0.333333)) ); p -= i - dot(i, vec3(0.166666)) ; 132 133 // Breaking the skewed cube into tetrahedra with partitioning planes, then determining which side of the 134 // intersecting planes the skewed point is on. Ie: Determining which tetrahedron the point is in. 135 vec3 i1 = step(0., p-p.yzx), i2 = max(i1, 1.0-i1.zxy); i1 = min(i1, 1.0-i1.zxy); 136 137 // Using the above to calculate the other three vertices. Now we have all four tetrahedral vertices. 138 vec3 p1 = p - i1 + 0.166666, p2 = p - i2 + 0.333333, p3 = p - 0.5; 139 140 vec3 rnd = vec3(7, 157, 113); // I use this combination to pay homage to Shadertoy.com. :) 141 142 // Falloff values from the skewed point to each of the tetrahedral points. 143 vec4 v = max(0.5 - vec4(dot(p, p), dot(p1, p1), dot(p2, p2), dot(p3, p3)), 0.); 144 145 // Assigning four random values to each of the points above. 146 vec4 d = vec4( dot(i, rnd), dot(i + i1, rnd), dot(i + i2, rnd), dot(i + 1., rnd) ); 147 148 // Further randomizing "d," then combining it with "v" to produce the final random falloff values. Range [0, 1] 149 d = fract(sin(d)*262144.)*v*2.; 150 151 // Reusing "v" to determine the largest, and second largest falloff values. Analogous to distance. 152 v.x = max(d.x, d.y), v.y = max(d.z, d.w), v.z = max(min(d.x, d.y), min(d.z, d.w)), v.w = min(v.x, v.y); 153 154 return max(v.x, v.y)- max(v.z, v.w); // Maximum minus second order, for that beveled Voronoi look. Range [0, 1]. 155 //return max(v.x, v.y); // Maximum, or regular value for the regular Voronoi aesthetic. Range [0, 1]. 156} 157 158 159void mainImage( out vec4 fragColor, in vec2 fragCoord ){ 160 161 // Screen coordinates, plus some movement about the center. 162 vec2 uv = (fragCoord.xy - iResolution.xy*0.5)/iResolution.y + vec2(0.5*cos(iGlobalTime*0.5), 0.25*sin(iGlobalTime*0.5)); 163 164 // Unit direction ray. 165 vec3 rd = normalize(vec3(uv, 1.)); 166 rd.xy *= rot(sin(iGlobalTime*0.25)*0.5); // Very subtle look around, just to show it's a 3D effect. 167 rd.xz *= rot(sin(iGlobalTime*0.25)*0.5); 168 169 // Screen color. Initialized to black. 170 vec3 col = vec3(0); 171 172 // Ray intersection of a cylinder (radius one) - centered at the origin - from a ray-origin that has XY coordinates 173 // also centered at the origin. 174 //float sDist = max(dot(rd.xy, rd.xy), 1e-16); // Analogous to the surface function. 175 //sDist = 1./sqrt(sDist); // Ray origin to surface distance. 176 177 // Same as above, but using a Minkowski distance and scaling factor. I tried it on a whim, and it seemed to work. 178 // I know, not scientific at all, but it kind of makes sense. They'll let anyone get behind a computer these days. :) 179 vec2 scale = vec2(0.75, 1.); 180 float power = 6.; 181 float sDist = max(dot( pow(abs(rd.xy)*scale, vec2(power)), vec2(1.) ), 1e-16); // Analogous to the surface function. 182 sDist = 1./pow( sDist, 1./power ); // Ray origin to surface distance. 183 184 //if(sDist>1e-8){ 185 186 // Using the the distance "sDist" above to calculate the surface position. Ie: sp = ro + rd*t; 187 // I've hardcoded "ro" to reduce line count. Note that "ro.xy" is centered on zero. The cheap 188 // ray-intersection formula above relies on that. 189 vec3 sp = vec3(0.0, 0.0, iGlobalTime*2.) + rd*sDist; 190 191 // The surface normal. Based on the derivative of the surface description function. See above. 192 //vec3 sn = normalize(vec3(-sp.xy, 0.)); // Cylinder normal. 193 vec3 sn = normalize(-sign(sp)*vec3(pow(abs(sp.xy)*scale, vec2(power-1.)), 0.)); // Minkowski normal. 194 195 // Bump mapping. 196 // 197 // I wanted to make this example as simple as possible, but it's only a few extra lines. Note the larger 198 // "eps" number. Increasing the value spreads the samples out, which effectively blurs the result, thus 199 // reducing the jaggies. The downside is loss of bump precision, which isn't noticeable in this particular 200 // example. Decrease the value to "0.001" to see what I'm talking about. 201 const vec2 eps = vec2(0.025, 0.); 202 float c = Voronesque(sp*2.5); // Base value. Used below to color the surface. 203 // 3D gradient vector... of sorts. Based on the bump function. In this case, Voronoi. 204 vec3 gr = (vec3(Voronesque((sp-eps.xyy)*2.5), Voronesque((sp-eps.yxy)*2.5), Voronesque((sp-eps.yyx)*2.5))-c)/eps.x; 205 gr -= sn*dot(sn, gr); // There's a reason for this... but I need more room. :) 206 sn = normalize(sn + gr*0.1); // Combining the bump gradient vector with the object surface normal. 207 208 // Lighting. 209 // 210 // The light is hovering just in front of the viewer. 211 vec3 lp = vec3(0.0, 0.0, iGlobalTime*2. + 3.); 212 vec3 ld = lp - sp; // Light direction. 213 float dist = max(length(ld), 0.001); // Distance from light to the surface. 214 ld /= dist; // Use the distance to normalize "ld." 215 216 // Light attenuation, based on the distance above. 217 float atten = min(1.0/max(0.75 + dist*0.25 + dist*dist*0.05, 0.001), 1.0); 218 219 220 float diff = max(dot(sn, ld), 0.); // Diffuse light value. 221 float spec = pow(max(dot(reflect(-ld, sn), -rd), 0.), 16.); // Specular highlighting. 222 // Adding some fake, reflective environment information. 223 float ref = Voronesque((sp + reflect(rd, sn)*0.5)*2.5); 224 225 // Coloring the surface with the Voronesque function that is used to bump the surface. See "bump mapping" above. 226 vec3 objCol = vec3(min(c*1.5, 1.), pow(c, 2.5), pow(c, 12.)); // Cheap, but effective, red palette. 227 //vec3 objCol = vec3(c*c*0.9, c, c*c*0.4); // Cheap green palette. 228 //vec3 objCol = vec3(pow(c, 1.6), pow(c, 1.7), c); // Purpley blue. 229 //vec3 objCol = vec3(c); // Grey scale. 230 231 // Using the values above to produce the final color. 232 //col = (objCol*(diff + ref*0.25 + 0.25) + vec3(1., 0.8, 0.9)*ref*0.25 + spec*vec3(0.75, 0.9, 1.))*atten; 233 col = (objCol*(vec3(1.0, 0.97, 0.92)*diff + ref*0.5 + 0.25) + vec3(1., 0.8, 0.9)*ref*0.3 + vec3(1., 0.9, 0.7)*spec)*atten; 234 //col = ((vec3(1.0, 0.97, 0.92)*diff + ref*0.5 + 0.25)*c + vec3(1., 0.8, 0.9)*ref*0.3 + vec3(0.75, 0.9, 1.)*spec)*atten; 235 236 237 //} 238 239 fragColor = vec4(min(col, 1.), 1.); 240} 241 242void main(void) 243{ 244 //just some shit to wrap shadertoy's stuff 245 vec2 FragCoord = vTexCoord.xy*OutputSize.xy; 246 mainImage(FragColor,FragCoord); 247} 248#endif