genuary

demo program for genuary 1st 2026
Download | Log | Files | Refs

commit 022fcab07b32e305a1967197846158b3d0fe1482
Author: Andrew Kloet <andrew@kloet.net>
Date:   Wed,  7 Jan 2026 07:28:48 -0500

initial commit

Diffstat:
Agenuary1.c | 316+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 316 insertions(+), 0 deletions(-)

diff --git a/genuary1.c b/genuary1.c @@ -0,0 +1,316 @@ +#include "raylib.h" +#include "raymath.h" +#include "rlgl.h" +#include <math.h> + +#define SCREEN_WIDTH 1000 +#define SCREEN_HEIGHT 1000 + +#define FIELD_SIZE 64 +#define CHAIN_HEIGHT 1024 +#define MAX_INSTANCES ((FIELD_SIZE * 2) * (FIELD_SIZE * 2) * CHAIN_HEIGHT / 2) + +#define CUBE_SIZE 0.5f +#define VERTICAL_SPACING (CUBE_SIZE * 1.7320508f) +#define SPACING 8.0f + +#define TILT_STRENGTH 0.30f +#define OFFSET_STRENGTH 3.00f + +#define FADE_START_DISTANCE SPACING * 2 +#define FADE_END_DISTANCE SPACING * 8 +#define RENDER_CULL_DISTANCE FADE_END_DISTANCE +#define RENDER_CULL_SQ (RENDER_CULL_DISTANCE * RENDER_CULL_DISTANCE) + +#define HUE 91.0f +#define SATURATION 0.15f +#define VALUE 0.78f + +#define HASH(x, z) \ + (((x) * 73856093u ^ (z) * 19349663u) * 0x85ebca6b & 0x7FFFFFFF) / \ + (float)0x7FFFFFFF + +const char *vsCode = + "#version 330\n" + "layout(location = 0) in vec3 vertexPosition;\n" + "layout(location = 1) in vec2 vertexTexCoord;\n" + "layout(location = 2) in vec3 vertexNormal;\n" + "layout(location = 3) in mat4 instanceTransform;\n" + "\n" + "uniform mat4 mvp;\n" + "\n" + "out vec3 fragPosition;\n" + "\n" + "void main() {\n" + " vec4 worldPos = instanceTransform * vec4(vertexPosition, 1.0);\n" + " fragPosition = vec3(worldPos);\n" + " gl_Position = mvp * worldPos;\n" + "}\n"; + +const char *fsCode = "#version 330\n" + "in vec3 fragPosition;\n" + "out vec4 finalColor;\n" + "\n" + "uniform vec3 viewPos;\n" + "uniform float fadeStart;\n" + "uniform float fadeEnd;\n" + "uniform vec3 baseColor;\n" + "\n" + "const float bayer8x8[64] = float[](\n" + " 0.0, 32.0, 8.0, 40.0, 2.0, 34.0, 10.0, 42.0,\n" + " 48.0, 16.0, 56.0, 24.0, 50.0, 18.0, 58.0, 26.0,\n" + " 12.0, 44.0, 4.0, 36.0, 14.0, 46.0, 6.0, 38.0,\n" + " 60.0, 28.0, 52.0, 20.0, 62.0, 30.0, 54.0, 22.0,\n" + " 3.0, 35.0, 11.0, 43.0, 1.0, 33.0, 9.0, 41.0,\n" + " 51.0, 19.0, 59.0, 27.0, 49.0, 17.0, 57.0, 25.0,\n" + " 15.0, 47.0, 7.0, 39.0, 13.0, 45.0, 5.0, 37.0,\n" + " 63.0, 31.0, 55.0, 23.0, 61.0, 29.0, 53.0, 21.0\n" + ");\n" + "\n" + "void main() {\n" + " float dist = distance(fragPosition, viewPos);\n" + " float intensity = 1.0 - clamp((dist - fadeStart) / " + "(fadeEnd - fadeStart), 0.0, 1.0);\n" + "\n" + " int x = int(gl_FragCoord.x) % 8;\n" + " int y = int(gl_FragCoord.y) % 8;\n" + " float rawValue = bayer8x8[y * 8 + x];\n" + " float threshold = (rawValue + 0.5) / 64.0;\n" + " if (intensity < threshold) {\n" + " finalColor = vec4(0.0, 0.0, 0.0, 1.0);\n" + " } else {\n" + " finalColor = vec4(baseColor, 1.0);\n" + " }\n" + "}\n"; + +const char *liquifyFsCode = + "#version 330\n" + "in vec2 fragTexCoord;\n" + "in vec4 fragColor;\n" + "out vec4 finalColor;\n" + "\n" + "uniform sampler2D texture0;\n" + "uniform vec4 colDiffuse;\n" + "uniform vec2 center1;\n" + "uniform vec2 center2;\n" + "uniform vec2 screenSize;\n" + "\n" + "const float radius = 1.80;\n" + "const float strength = 0.10;\n" + "\n" + "vec2 calculateDistortion(vec2 uv, vec2 center) {\n" + " float aspect = screenSize.x / screenSize.y;\n" + " vec2 uvCorrected = uv;\n" + " uvCorrected.x *= aspect;\n" + " vec2 centerCorrected = center;\n" + " centerCorrected.x *= aspect;\n" + "\n" + " vec2 delta = uvCorrected - centerCorrected;\n" + " float dist = length(delta);\n" + " \n" + " // Smoothstep creates a soft edge 0.0 to radius\n" + " float mask = 1.0 - smoothstep(0.0, radius, dist);\n" + " \n" + " // Distort UV towards the center point\n" + " return (uv - center) * mask * strength;\n" + "}\n" + "\n" + "void main() {\n" + " vec2 uv = fragTexCoord;\n" + " vec2 offset1 = calculateDistortion(uv, center1);\n" + " vec2 offset2 = calculateDistortion(uv, center2);\n" + " uv -= (offset1 + offset2);\n" + " finalColor = texture(texture0, uv) * colDiffuse * fragColor;\n" + "}\n"; + +Matrix transforms[MAX_INSTANCES]; + +Vector2 GetPerimeterPosition(float t) { + float cycle = fmodf(t / 100, 4.0f); + + if (cycle < 1.0f) { + return (Vector2){cycle, 0.0f}; + } else if (cycle < 2.0f) { + return (Vector2){1.0f, cycle - 1.0f}; + } else if (cycle < 3.0f) { + return (Vector2){1.0f - (cycle - 2.0f), 1.0f}; + } else { + return (Vector2){0.0f, 1.0f - (cycle - 3.0f)}; + } +} + +int main(void) { + SetConfigFlags(FLAG_WINDOW_RESIZABLE); + InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "GENUARY 1. ONE SHAPE, ONE COLOR"); + + Camera3D camera = {0}; + camera.up = (Vector3){0.0f, 1.0f, 0.0f}; + camera.fovy = 30.0f; + camera.projection = CAMERA_PERSPECTIVE; + + SetTargetFPS(144); + + Shader ditherShader = LoadShaderFromMemory(vsCode, fsCode); + ditherShader.locs[SHADER_LOC_MATRIX_MVP] = + GetShaderLocation(ditherShader, "mvp"); + ditherShader.locs[SHADER_LOC_VECTOR_VIEW] = + GetShaderLocation(ditherShader, "viewPos"); + ditherShader.locs[SHADER_LOC_MATRIX_MODEL] = 3; + + int fadeStartLoc = GetShaderLocation(ditherShader, "fadeStart"); + int fadeEndLoc = GetShaderLocation(ditherShader, "fadeEnd"); + int colorLoc = GetShaderLocation(ditherShader, "baseColor"); + float fadeStartVal = FADE_START_DISTANCE; + float fadeEndVal = FADE_END_DISTANCE; + Color c = ColorFromHSV(HUE, SATURATION, VALUE); + Vector3 colorVal = {(float)c.r / 255.0f, (float)c.g / 255.0f, + (float)c.b / 255.0f}; + SetShaderValue(ditherShader, fadeStartLoc, &fadeStartVal, + SHADER_UNIFORM_FLOAT); + SetShaderValue(ditherShader, fadeEndLoc, &fadeEndVal, SHADER_UNIFORM_FLOAT); + SetShaderValue(ditherShader, colorLoc, &colorVal, SHADER_UNIFORM_VEC3); + + Shader liquifyShader = LoadShaderFromMemory(0, liquifyFsCode); + int locCenter1 = GetShaderLocation(liquifyShader, "center1"); + int locCenter2 = GetShaderLocation(liquifyShader, "center2"); + int locScreenSize = GetShaderLocation(liquifyShader, "screenSize"); + + RenderTexture2D target = + LoadRenderTexture(GetScreenWidth(), GetScreenHeight()); + Vector2 currentScreenSize = {(float)GetScreenWidth(), + (float)GetScreenHeight()}; + SetShaderValue(liquifyShader, locScreenSize, &currentScreenSize, + SHADER_UNIFORM_VEC2); + + Mesh cubeMesh = GenMeshCube(CUBE_SIZE, CUBE_SIZE, CUBE_SIZE); + Material cubeMat = LoadMaterialDefault(); + cubeMat.shader = ditherShader; + + Matrix rotZ = MatrixRotateZ(54.7356f * DEG2RAD); + Matrix rotY = MatrixRotateY(45.0f * DEG2RAD); + Matrix baseRotation = MatrixMultiply(rotY, rotZ); + + Vector3 upVector = {0.0f, 1.0f, 0.0f}; + + float timeAccumulator = 0.0f; + + while (!WindowShouldClose()) { + float dt = GetFrameTime(); + timeAccumulator += dt; + + if (IsWindowResized()) { + UnloadRenderTexture(target); + target = LoadRenderTexture(GetScreenWidth(), GetScreenHeight()); + currentScreenSize = + (Vector2){(float)GetScreenWidth(), (float)GetScreenHeight()}; + SetShaderValue(liquifyShader, locScreenSize, &currentScreenSize, + SHADER_UNIFORM_VEC2); + } + + float t1 = timeAccumulator * 0.1f; + float t2 = 4.0f - (timeAccumulator * 0.6f + 2.0f); + while (t2 < 0) + t2 += 400.0f; + + Vector2 p1 = GetPerimeterPosition(t1); + Vector2 p2 = GetPerimeterPosition(t2); + + SetShaderValue(liquifyShader, locCenter1, &p1, SHADER_UNIFORM_VEC2); + SetShaderValue(liquifyShader, locCenter2, &p2, SHADER_UNIFORM_VEC2); + + float t03 = timeAccumulator * 0.05f; + float t042 = timeAccumulator * 0.05f; + float t015 = timeAccumulator * 0.05f; + camera.position = (Vector3){sinf(t03) * 10.0f, 0.0f, cosf(t042) * 10.0f}; + camera.target = + (Vector3){sinf(t03 + 1.0f) * 5.0f, 0.0f, cosf(t042 + 1.0f) * 5.0f}; + UpdateCamera(&camera, CAMERA_ORBITAL); + + float camPos[3] = {camera.position.x, camera.position.y, camera.position.z}; + SetShaderValue(ditherShader, ditherShader.locs[SHADER_LOC_VECTOR_VIEW], + camPos, SHADER_UNIFORM_VEC3); + + Vector2 camPos2D = {camera.position.x, camera.position.z}; + int count = 0; + int gridOffsetX = (int)(camera.position.x / SPACING); + int gridOffsetZ = (int)(camera.position.z / SPACING); + + for (int x = -FIELD_SIZE / 2; x < FIELD_SIZE / 2; x++) { + int seedX = gridOffsetX + x; + float baseX = seedX * SPACING + (SPACING / 2); + + for (int z = -FIELD_SIZE / 2; z < FIELD_SIZE / 2; z++) { + int seedZ = gridOffsetZ + z; + float baseZ = seedZ * SPACING + (SPACING / 2); + + float tiltX = HASH(seedX, seedZ) * TILT_STRENGTH; + float tiltZ = HASH(seedZ, seedX) * TILT_STRENGTH; + float offsetX = HASH(seedX, seedZ) * OFFSET_STRENGTH; + float offsetZ = HASH(seedZ, seedX) * OFFSET_STRENGTH; + + float chainAtCamY_X = baseX + (camera.position.y * tiltX) + offsetX; + float chainAtCamY_Z = baseZ + (camera.position.y * tiltZ) + offsetZ; + + if (Vector2DistanceSqr((Vector2){chainAtCamY_X, chainAtCamY_Z}, + camPos2D) > RENDER_CULL_SQ) + continue; + + Vector3 chainDir = Vector3Normalize((Vector3){tiltX, 1.0f, tiltZ}); + Vector3 rotationAxis = Vector3CrossProduct(upVector, chainDir); + float rotationAngle = acosf(Vector3DotProduct(upVector, chainDir)); + Matrix tiltRotation = MatrixRotate(rotationAxis, rotationAngle); + + Matrix instanceMatrix = MatrixMultiply(baseRotation, tiltRotation); + + for (int yIndex = -CHAIN_HEIGHT / 2; yIndex < CHAIN_HEIGHT / 2; + yIndex++) { + float yy = yIndex * VERTICAL_SPACING; + + if (fabsf(yy - camera.position.y) > RENDER_CULL_DISTANCE) + continue; + + if (count < MAX_INSTANCES) { + float finalX = baseX + (yy * tiltX) + offsetX; + float finalZ = baseZ + (yy * tiltZ) + offsetZ; + + transforms[count] = instanceMatrix; + transforms[count].m12 = finalX; + transforms[count].m13 = yy; + transforms[count].m14 = finalZ; + count++; + } + } + } + } + + BeginTextureMode(target); + ClearBackground(BLACK); + BeginMode3D(camera); + if (count > 0) { + DrawMeshInstanced(cubeMesh, cubeMat, transforms, count); + } + EndMode3D(); + EndTextureMode(); + + BeginDrawing(); + ClearBackground(BLACK); + BeginShaderMode(liquifyShader); + DrawTexturePro( + target.texture, + (Rectangle){0, 0, (float)target.texture.width, + (float)-target.texture.height}, + (Rectangle){0, 0, (float)GetScreenWidth(), (float)GetScreenHeight()}, + (Vector2){0, 0}, 0.0f, WHITE); + EndShaderMode(); + EndDrawing(); + } + + UnloadRenderTexture(target); + UnloadMesh(cubeMesh); + UnloadMaterial(cubeMat); + UnloadShader(ditherShader); + UnloadShader(liquifyShader); + + CloseWindow(); + return 0; +}