Entropie git · main
Entropie festival game; first steps
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.gzentropie/src/render/renderer.h 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 */