2023-07-22 23:59:17 +08:00
|
|
|
#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)
|
2023-07-25 19:06:12 +08:00
|
|
|
//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
|
2023-07-22 23:59:17 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
layout(std140, binding = 0) uniform fs_ub {
|
|
|
|
vec2 center;
|
|
|
|
vec2 resolution;
|
|
|
|
vec2 u_screenSize;
|
|
|
|
vec4 u_Time;
|
|
|
|
};
|
|
|
|
|
2023-07-25 19:06:12 +08:00
|
|
|
layout(location = SV_Target0) out vec4 FragColor;
|
2023-07-22 23:59:17 +08:00
|
|
|
|
|
|
|
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.);
|
|
|
|
}
|