Nimbin[12]?Games / Entropie / entropie/src/render/renderer.h

Entropie git · main

Entropie festival game; first steps

sdl c game entropie cmake · first commit 2026-10-10 · last commit 2026-11-02 (18 hours ago) · synced 10 hours ago

C 88.5% Markdown 9.1% GLSL 2.3%
git clone https://git.christianimmanuel.de/games/Entropie.gitwget https://git.christianimmanuel.de/games/Entropie/archive/Entropie.tar.gz
entropie/src/render/renderer.h 7.6 KB · 169 lines raw
#ifndef RENDER_RENDERER_H
#define RENDER_RENDERER_H

/*
 * Painterly renderer ("Waking Life" look).
 *
 * The scene is drawn into an offscreen target (color + view normal/depth),
 * then an ink pass draws boiling outlines, misregistered fills and paper grain
 * onto the screen. Geometry wobbles in the vertex shaders; the animation
 * steps at BOIL_FPS like hand-drawn frames.
 *
 * Per frame:
 *   Renderer_beginFrame
 *   Renderer_beginShadowPass, Renderer_drawShadowCaster..., Renderer_endShadowPass
 *   Renderer_beginScenePass,  Renderer_drawMesh...
 *   (sky)
 *   Renderer_endFrame         -> ink pass to the screen
 */

#include <stdbool.h>

#include "core/gl.h"
#include "math/frustum.h"
#include "math/linalg.h"
#include "render/camera.h"
#include "render/figure.h"
#include "render/mesh.h"

typedef struct {
    Vec3  sun_direction;    /* towards the sun, may be below the horizon */
    Vec3  light_direction;  /* towards the key light (sun by day, moon by night) */
    Vec3  light_color;      /* tint of lit areas */
    Vec3  shadow_color;     /* tint of shaded areas */
    Vec3  sky_top;
    Vec3  sky_horizon;
    float shadow_strength;  /* 0..1, fades out around sunrise and sunset */
    float day_factor;       /* 0 = night, 1 = day */
    Vec3  fire_position;    /* a campfire's light ... */
    float fire_strength;    /* ... and how bright it is (0 = none) */
    float wet;              /* 0..1 everything wet from rain (darker, the ground damp) */
    float overcast;         /* 0..1 clouded over (the sky: more and darker clouds, no sun, moon or stars) */
} Lighting;

typedef struct {
    GLuint program;
    GLint  model, view, projection, light_space, boil_time;
    GLint  view_pos, light_dir, light_color, shadow_color, sky_top, sky_horizon;
    GLint  shadow_strength, shadow_map, fire_light;
    GLint  terrain_size, grass_depth, wear_map, water_map, surface_map;  /* terrain only */
    GLint  decal_size;                           /* things lying on the ground: sink with it */
    GLint  tint;                                 /* color multiplier and ember glow */
    GLint  puff;                                 /* > 0: soft and see-through (smoke), this thick */
    GLint  grass;                                /* grass blades: terrain size while drawing them */
    GLint  rain_wet;                             /* everything wet from rain (0..1) */
    GLint  holes, hole_size, hole_count;         /* holes in the ground (basements): not drawn there */
} SceneShader;

typedef struct {
    GLuint program;
    GLint  model, light_space, boil_time;
} ShadowShader;

typedef struct {
    GLuint program;
    GLint  color_tex, normal_depth_tex, texel, boil_time, time, drunk, dark;
} InkShader;

typedef struct {
    GLuint program;
    GLint  view_proj, view, light_space, shadow_pass, boil_time;
    GLint  figure_pos, facing, card_center, card_u, card_v, card_min, card_max, joints;
    GLint  skin, hair, shirt, pants, shoes, hair_style, long_sleeves, cast;
    GLint  head_forward, head_up, chest_forward, waist_bend, face, expression;
    GLint  stream, stream_kind, stream_width;
    GLint  garment, undress, top, jacket_tied, belly, wet, hood, hat, hat_color;
    GLint  cig_a, cig_tip, cig_glow, jacket, uri_a, uri_b, uri;
    GLint  species, tail_a, tail_b;
    GLint  view_pos, light_dir, light_color, shadow_color, sky_top, sky_horizon;
    GLint  shadow_strength, shadow_map, fire_light;
} FigureShader;

/* Offscreen target the scene is painted into. */
typedef struct {
    GLuint fbo;
    GLuint color;         /* RGBA8 */
    GLuint normal_depth;  /* RGBA16F: view-space normal, view distance */
    GLuint depth;
    int    width;
    int    height;
} SceneTarget;

typedef struct {
    int          width;
    int          height;
    float        time;       /* continuous clock (sky) */
    float        boil_time;  /* animation clock, stepped at BOIL_FPS */
    float        drunk;      /* 0..1: double vision and wavering in the ink pass */
    float        dark;       /* 0..1: fade to black (sleeping) */
    SceneShader  scene;
    ShadowShader shadow;
    InkShader    ink;
    FigureShader figure;
    GLuint       pass_program; /* program of the current pass (shadow or scene) */
    Vec3         viewer_pos;   /* camera position during the scene pass */
    Vec3         light_dir;    /* key light direction during the shadow pass */
    Vec3         shadow_focus; /* middle of the shadowed area */
    bool         shadow_pass;
    SceneTarget  target;
    GLuint       fullscreen_vao;
    GLuint       shadow_fbo;
    GLuint       shadow_map;
    int          shadow_size;
    Mat4         light_space;
    Frustum      frustum;      /* of the current pass: what lies outside isn't drawn */
    struct { int drawn, culled; } stats; /* this frame */
} Renderer;

bool Renderer_init(Renderer *r);
void Renderer_shutdown(Renderer *r);

/* Binds and clears the offscreen target. time = real seconds since start. */
void Renderer_beginFrame(Renderer *r, int width, int height, float time);

/* Could something this big (a sphere) show in the current pass? Every draw
   call checks this itself; use it to skip work before drawing. */
bool Renderer_inView(Renderer *r, Vec3 center, float radius);

/* Shadows cover an area around focus (usually just ahead of the camera). */
void Renderer_beginShadowPass(Renderer *r, const Lighting *light, Vec3 focus);
void Renderer_drawShadowCaster(Renderer *r, const Mesh *mesh, Mat4 model);
void Renderer_endShadowPass(Renderer *r);

/* Draws a 2D painted person in the current pass (shadow or scene). */
void Renderer_drawFigure(Renderer *r, const FigurePose *pose);

void Renderer_beginScenePass(Renderer *r, const Camera *camera, const Lighting *light);
/* Back to the scene pass after the sky (its settings still hold): what floats in the air. */
void Renderer_beginAirPass(Renderer *r);
/* Like Renderer_drawMesh, darkened by rgb and glowing like embers by glow (0..1). */
void Renderer_drawMeshTinted(Renderer *r, const Mesh *mesh, Mat4 model, Vec3 rgb, float glow);
/* Like Renderer_drawMeshTinted, but no ink outline round it and nothing hides behind it (smoke). */
/* Smoke: a soft, see-through ball (edges fading out), this thick (0..1). */
void Renderer_drawPuff(Renderer *r, const Mesh *mesh, Mat4 model, Vec3 rgb, float alpha);
void Renderer_drawSmoke(Renderer *r, const Mesh *mesh, Mat4 model, Vec3 rgb);
/* Grass blades (see world/meadow.h): trampled with the terrain, swaying. */
void Renderer_drawGrass(Renderer *r, const Mesh *mesh, float terrain_size, float grass_depth);
void Renderer_drawMesh(Renderer *r, const Mesh *mesh, Mat4 model);
/* Something lying flat on the ground (roads, sick): sinks with trampled grass like the
   ground itself, and gets wet with it. Draw after the terrain. */
void Renderer_drawDecal(Renderer *r, const Mesh *mesh, Mat4 model, float terrain_size);

/*
 * Ground heightfield (world-space mesh). wear_map is an R8 texture covering
 * the terrain square: 0 = fresh meadow, 1 = trampled bare path. water_map is
 * RGBA8 over the same square: soil moisture, standing water, pee, mud
 * (see world/wetness.h); surface_map too: asphalt, concrete, gravel, bare
 * earth (see Site_surface).
 */
/* Holes in the ground drawn next (up to RENDER_HOLES): each a rectangle,
   middle x, z, its x axis (cos, sin) and half sizes x, z. */
#define RENDER_HOLES 8
void Renderer_setHoles(Renderer *r, const float (*rects)[6], int count);
void Renderer_drawTerrain(Renderer *r, const Mesh *mesh, GLuint wear_map, GLuint water_map, GLuint surface_map,
                          float size, float grass_depth);

/* Ink pass: composes the offscreen target onto the screen. */
void Renderer_endFrame(Renderer *r);

#endif /* RENDER_RENDERER_H */