xxxxxxxxxx
119
// Just a pass-through vertex shader, nothing fancy here
const vert = `attribute vec3 aPosition;
attribute vec3 aNormal;
attribute vec2 aTexCoord;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat3 uNormalMatrix;
varying highp vec2 vVertTexCoord;
void main(void) {
vec4 positionVec4 = vec4(aPosition, 1.0);
gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;
vVertTexCoord = aTexCoord;
}
`
const frag = `precision mediump float;
varying highp vec2 vVertTexCoord;
// Noise functions
// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
float rand(float n) {
return fract(sin(n) * 43758.5453123);
}
float rand(vec2 n) {
return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);
}
float noise(float p) {
float fl = floor(p);
float fc = fract(p);
return mix(rand(fl), rand(fl + 1.0), fc);
}
float noise(vec2 n) {
const vec2 d = vec2(0.0, 1.0);
vec2 b = floor(n);
vec2 f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
}
void main() {
float color = 0.;
vec2 coord = gl_FragCoord.xy;
float noiseOffset = fract(10. * noise(coord * 0.2) + 5. * noise(coord * 1.1)) - 0.5;
vec2 fromPlanetCenter = vVertTexCoord - vec2(0.5, 0.5);
float planetR = 0.15;
float onPlanet = length(fromPlanetCenter) < planetR ? 1. : 0.;
if (onPlanet > 0.) {
// planetR = sqrt(x^2 + y^2 + z^2)
// planetR^2 = x^2 + y^2 + z^2
// z = sqrt(0.25^2 - x^2 - y^2)
vec3 normal = normalize(vec3(
fromPlanetCenter,
-sqrt(planetR*planetR - fromPlanetCenter.x*fromPlanetCenter.x - fromPlanetCenter.y*fromPlanetCenter.y)
));
vec3 lightDir = -normalize(vec3(0.5, 0.5, 0.) - vec3(1., 0., -0.7));
// Shading is standard Lambertian shading (same as what p5's lights use)
float lambertian = max(dot(lightDir, normal), 0.0);
float planetColor = lambertian;
color = mix(color, planetColor, onPlanet);
}
float angle = ${Math.PI * 0.1};
vec2 rotatedCoord = (mat3(
cos(angle), sin(angle), 0.,
-sin(angle), cos(angle), 0.,
0., 0., 1.
) * vec3(vVertTexCoord - vec2(0.5, 0.5), 1.)).xy;
rotatedCoord *= vec2(1., 3.);
float toRingCenter = length(rotatedCoord);
if (toRingCenter > planetR + 0.05 && toRingCenter < planetR + 0.18) {
float angle = atan(rotatedCoord.y, rotatedCoord.x);
if (onPlanet == 0. || angle > 0.) {
float brightness = 0.;
if (angle < ${-Math.PI * 0.5}) {
brightness = smoothstep(${-Math.PI*0.67}, ${-Math.PI*0.67}+0.8, angle);
} else {
brightness = 1. - smoothstep(${Math.PI*0.85}, ${Math.PI*0.85}+0.5, angle);
}
brightness *= noise(toRingCenter * 200.);
color = brightness * 0.9;
}
}
float dithered = color + noiseOffset > 0.5 ? 1. : 0.;
vec3 dark = vec3(44., 44., 71.)/255.;
vec3 light = vec3(245., 236., 211.)/255.;
gl_FragColor = vec4(mix(dark, light, dithered), 1.);
}
`
let spaceShader
function setup() {
createCanvas(600, 600, WEBGL)
spaceShader = createShader(vert, frag)
noLoop()
}
function mousePressed() {
save('genuary3.png')
}
function draw() {
background(0)
rectMode(CENTER)
imageMode(CENTER)
noStroke()
push()
shader(spaceShader)
rect(0, 0, width, height)
pop()
}