#version 310 es precision highp float; precision highp int; //uniform float iChannelTime[4]; // channel playback time (in seconds) //uniform vec3 iChannelResolution[4]; // channel resolution (in pixels) //vec4 iMouse = vec4(0,0,0,0); // mouse pixel coords. xy: current (if MLB down), zw: click //layout(binding = 0) uniform sampler2D iChannel0; // input channel. XX = 2D/Cube layout(std140, binding = 0) uniform fs_ub { vec2 center; vec2 resolution; vec2 u_screenSize; vec4 u_Time; }; layout(location = SV_Target0) out vec4 FragColor; void main(void) { #ifdef METAL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; #endif vec2 iResolution = resolution; // viewport resolution (in pixels) float iGlobalTime = u_Time[1]; // shader playback time (in seconds) float pointRadius = 0.06; float linkSize = 0.04; float noiseStrength = 0.08; // range: 0-1 float minDimension = min(iResolution.x, iResolution.y); vec2 bounds = vec2(iResolution.x / minDimension, iResolution.y / minDimension); //vec2 uv = fragCoord.xy / minDimension; vec2 uv = (2. * fragCoord.xy - center.xy) / iResolution.xy; vec3 pointR = vec3(0.0, 0.0, 1.0); vec3 pointG = vec3(0.0, 0.0, 1.0); vec3 pointB = vec3(0.0, 0.0, 1.0); // Make the points orbit round the origin in 3 dimensions. // Coefficients are arbitrary to give different behaviours. // The Z coordinate should always be >0.0, as it's used directly to // multiply the radius to give the impression of depth. pointR.x += 0.32 * sin(1.32 * iGlobalTime); pointR.y += 0.3 * sin(1.03 * iGlobalTime); pointR.z += 0.4 * sin(1.32 * iGlobalTime); pointG.x += 0.31 * sin(0.92 * iGlobalTime); pointG.y += 0.29 * sin(0.99 * iGlobalTime); pointG.z += 0.38 * sin(1.24 * iGlobalTime); pointB.x += 0.33 * sin(1.245 * iGlobalTime); pointB.y += 0.3 * sin(1.41 * iGlobalTime); pointB.z += 0.41 * sin(1.11 * iGlobalTime); // Centre the points in the display vec2 midUV = vec2(bounds.x * 0.5, bounds.y * 0.5); pointR.xy += midUV; pointG.xy += midUV; pointB.xy += midUV; // Calculate the vectors from the current fragment to the coloured points vec2 vecToR = pointR.xy - uv; vec2 vecToG = pointG.xy - uv; vec2 vecToB = pointB.xy - uv; vec2 dirToR = normalize(vecToR.xy); vec2 dirToG = normalize(vecToG.xy); vec2 dirToB = normalize(vecToB.xy); float distToR = length(vecToR); float distToG = length(vecToG); float distToB = length(vecToB); // Calculate the dot product between vectors from the current fragment to each pair // of adjacent coloured points. This helps us determine how close the current fragment // is to a link between points. float dotRG = dot(dirToR, dirToG); float dotGB = dot(dirToG, dirToB); float dotBR = dot(dirToB, dirToR); // Start with a bright coloured dot around each point FragColor.x = 1.0 - smoothstep(distToR, 0.0, pointRadius * pointR.z); FragColor.y = 1.0 - smoothstep(distToG, 0.0, pointRadius * pointG.z); FragColor.z = 1.0 - smoothstep(distToB, 0.0, pointRadius * pointB.z); FragColor.w = 1.0; // We want to show a coloured link between adjacent points. // Determine the strength of each link at the current fragment. // This tends towards 1.0 as the vectors to each point tend towards opposite directions. float linkStrengthRG = 1.0 - smoothstep(dotRG, -1.01, -1.0 + (linkSize * pointR.z * pointG.z)); float linkStrengthGB = 1.0 - smoothstep(dotGB, -1.01, -1.0 + (linkSize * pointG.z * pointB.z)); float linkStrengthBR = 1.0 - smoothstep(dotBR, -1.01, -1.0 + (linkSize * pointB.z * pointR.z)); // If the current fragment is in a link, we need to know how much the // linked points contribute of their colour. float sumDistRG = distToR + distToG; float sumDistGB = distToG + distToB; float sumDistBR = distToB + distToR; float contribRonRG = 1.0 - (distToR / sumDistRG); float contribRonBR = 1.0 - (distToR / sumDistBR); float contribGonRG = 1.0 - (distToG / sumDistRG); float contribGonGB = 1.0 - (distToG / sumDistGB); float contribBonGB = 1.0 - (distToB / sumDistGB); float contribBonBR = 1.0 - (distToB / sumDistBR); // Additively blend the link colours into the fragment. FragColor.x += (linkStrengthRG * contribRonRG) + (linkStrengthBR * contribRonBR); FragColor.y += (linkStrengthGB * contribGonGB) + (linkStrengthRG * contribGonRG); FragColor.z += (linkStrengthBR * contribBonBR) + (linkStrengthGB * contribBonGB); // Use an underlying texture to provide some noise float noiseMin = 1.0 - noiseStrength; FragColor.xyz *= (1.0 - noiseStrength) + (noiseStrength * 0.); }