commit 022fcab07b32e305a1967197846158b3d0fe1482
Author: Andrew Kloet <andrew@kloet.net>
Date: Wed, 7 Jan 2026 07:28:48 -0500
initial commit
Diffstat:
| A | genuary1.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, ¤tScreenSize,
+ 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, ¤tScreenSize,
+ 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;
+}