Files
komplex/tools/packsrc/Voxel Land 2/shaders/Image.frag
Digital Artifex c8f3f1e981 Added shader packs
2025-08-19 09:33:45 -04:00

115 lines
3.9 KiB
GLSL

// Parameters
#define CAMERA_FOCAL_LENGTH 1.5
#define VOXEL_STEP 50.0
#define SOUND
#define MOUSE
#define HSV2RGB_FAST
// Constants
#define PI 3.14159265359
#define SQRT2 1.41421356237
// PRNG
// From https://www.shadertoy.com/view/4djSRW
float rand (in vec2 seed) {
seed = fract (seed * vec2 (5.3983, 5.4427));
seed += dot (seed.yx, seed.xy + vec2 (21.5351, 14.3137));
return fract (seed.x * seed.y * 95.4337);
}
// HSV to RGB
vec3 hsv2rgb (in vec3 hsv) {
#ifdef HSV2RGB_SAFE
hsv.yz = clamp (hsv.yz, 0.0, 1.0);
#endif
#ifdef HSV2RGB_FAST
return hsv.z * (1.0 + 0.5 * hsv.y * (cos (2.0 * PI * (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0))) - 1.0));
#else
return hsv.z * (1.0 + hsv.y * clamp (abs (fract (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0)) * 6.0 - 3.0) - 2.0, -1.0, 0.0));
#endif
}
// Main function
void mainImage (out vec4 fragColor, in vec2 fragCoord) {
// Define the ray corresponding to this fragment
vec3 ray = normalize (vec3 ((2.0 * fragCoord.xy - iResolution.xy) / iResolution.y, CAMERA_FOCAL_LENGTH));
// Get the music info
#ifdef SOUND
float soundBass = texture (iChannel0, vec2 (0.0)).x;
float soundTreble = texture (iChannel0, vec2 (0.9, 0.0)).x;
#else
float soundBass = 0.6 + 0.4 * cos (iTime * 0.2);
float soundTreble = 0.5 + 0.5 * cos (iTime * 1.2);
#endif
// Set the camera
vec3 origin = vec3 (0.0, 6.0 - 3.0 * cos (iTime * 0.3), iTime * 2.0 + 700.0 * (0.5 + 0.5 * sin (iTime * 0.1)));
float cameraAngle = iTime * 0.1;
#ifdef MOUSE
cameraAngle += 2.0 * PI * iMouse.x / iResolution.x;
#endif
vec3 cameraForward = vec3 (cos (cameraAngle), cos (iTime * 0.3) - 1.5, sin (cameraAngle));
vec3 cameraUp = vec3 (0.2 * cos (iTime * 0.7), 1.0, 0.0);
mat3 cameraRotation;
cameraRotation [2] = normalize (cameraForward);
cameraRotation [0] = normalize (cross (cameraUp, cameraForward));
cameraRotation [1] = cross (cameraRotation [2], cameraRotation [0]);
ray = cameraRotation * ray;
// Voxel
vec3 color = vec3 (0.0);
vec2 voxelSign = sign (ray.xz);
vec2 voxelIncrement = voxelSign / ray.xz;
float voxelTimeCurrent = 0.0;
vec2 voxelTimeNext = (0.5 + voxelSign * (0.5 - fract (origin.xz + 0.5))) * voxelIncrement;
vec2 voxelPosition = floor (origin.xz + 0.5);
float voxelHeight = 0.0;
bool voxelDone = false;
vec3 voxelNormal = vec3 (0.0);
for (float voxelStep = 1.0; voxelStep <= VOXEL_STEP; ++voxelStep) {
// Compute the height of this column
voxelHeight = 2.0 * rand (voxelPosition) * smoothstep (0.2, 0.5, soundBass) * sin (soundBass * 8.0 + voxelPosition.x * voxelPosition.y) - 5.0 * (0.5 + 0.5 * cos (voxelPosition.y * 0.15));
// Check whether we hit the side of the column
if (voxelDone = voxelHeight > origin.y + voxelTimeCurrent * ray.y) {
break;
}
// Check whether we hit the top of the column
float timeNext = min (voxelTimeNext.x, voxelTimeNext.y);
float timeIntersect = (voxelHeight - origin.y) / ray.y;
if (voxelDone = timeIntersect > voxelTimeCurrent && timeIntersect < timeNext) {
voxelTimeCurrent = timeIntersect;
voxelNormal = vec3 (0.0, 1.0, 0.0);
break;
}
// Next voxel...
voxelTimeCurrent = timeNext;
voxelNormal.xz = step (voxelTimeNext.xy, voxelTimeNext.yx);
voxelTimeNext += voxelNormal.xz * voxelIncrement;
voxelPosition += voxelNormal.xz * voxelSign;
}
if (voxelDone) {
origin += voxelTimeCurrent * ray;
// Compute the local color
vec3 mapping = origin;
mapping.y -= voxelHeight + 0.5;
mapping *= 1.0 - voxelNormal;
mapping += 0.5;
float id = rand (voxelPosition);
color = hsv2rgb (vec3 ((iTime + floor (mapping.y)) * 0.05 + voxelPosition.x * 0.01, smoothstep (0.2, 0.4, soundBass), 0.7 + 0.3 * cos (id * iTime + PI * soundTreble)));
color *= smoothstep (0.8 - 0.6 * cos (soundBass * PI), 0.1, length (fract (mapping) - 0.5));
color *= 0.5 + smoothstep (0.90, 0.95, cos (id * 100.0 + soundTreble * PI * 0.5 + iTime * 0.5));
color *= 1.0 - voxelTimeCurrent / VOXEL_STEP * SQRT2;
}
// Set the fragment color
fragColor = vec4 (color, 1.0);
}