$darkmode
Suckless OGL 1.0.0
A lean, high-performance C11 PBR Renderer
postprocess.c File Reference
#include "postprocess.h"
#include "app_settings.h"
#include "effects/fx_auto_exposure.h"
#include "effects/fx_bloom.h"
#include "effects/fx_dof.h"
#include "effects/fx_motion_blur.h"
#include "gl_common.h"
#include "gl_debug.h"
#include "log.h"
#include "render_utils.h"
#include "shader.h"
#include "utils.h"
#include <cglm/types.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "profiler.h"
Include dependency graph for postprocess.c:

Data Structures

struct  EffectMetadata
 

Macros

#define EFFECT_COUNT   (sizeof(ALL_EFFECTS) / sizeof(ALL_EFFECTS[0]))
 

Enumerations

enum  {
  POSTPROCESS_TEX_UNIT_SCENE = 0 , POSTPROCESS_TEX_UNIT_BLOOM = 1 , POSTPROCESS_TEX_UNIT_DEPTH = 2 , POSTPROCESS_TEX_UNIT_EXPOSURE = 3 ,
  POSTPROCESS_TEX_UNIT_VELOCITY = 4 , POSTPROCESS_TEX_UNIT_NEIGHBOR_MAX = 5 , POSTPROCESS_TEX_UNIT_DOF_BLUR = 6 , POSTPROCESS_TEX_UNIT_STENCIL = 7 ,
  POSTPROCESS_TEX_UNIT_LUT3D = 8
}
 
enum  { POSTPROCESS_COMPUTE_GROUP_SIZE = 16 }
 
enum  { MAX_SHADER_DEFINES = 32 , MAX_DEFINE_LENGTH = 64 }
 

Functions

static int create_framebuffer (PostProcess *post_processing)
 
static void destroy_framebuffer (PostProcess *post_processing)
 
static void destroy_screen_quad (PostProcess *post_processing)
 
static bool is_shader_in_cache (PostProcess *post_processing, Shader *shader)
 
int postprocess_init (PostProcess *post_processing, GPUProfiler *external_profiler, int width, int height)
 Initializes the post-processing pipeline. More...
 
void postprocess_set_dummy_textures (PostProcess *post_processing, GLuint dummy_black)
 Internal helper to set fallback textures. More...
 
static void destroy_readback_buffers (PostProcess *post_processing)
 
static void destroy_cached_shaders (PostProcess *post_processing)
 
void postprocess_cleanup (PostProcess *post_processing)
 Releases all GPU and CPU resources. More...
 
void postprocess_resize (PostProcess *post_processing, int width, int height)
 Recreates all internal buffers for a new resolution. More...
 
static void postprocess_on_state_change (PostProcess *post_processing)
 
void postprocess_enable (PostProcess *post_processing, PostProcessEffect effect)
 Enables a specific effect. More...
 
void postprocess_disable (PostProcess *post_processing, PostProcessEffect effect)
 Disables a specific effect. More...
 
void postprocess_toggle (PostProcess *post_processing, PostProcessEffect effect)
 Toggles the current state of an effect. More...
 
int postprocess_is_enabled (PostProcess *post_processing, PostProcessEffect effect)
 Returns true if an effect is currently active. More...
 
void postprocess_set_vignette (PostProcess *post_processing, float intensity, float smoothness, float roundness)
 
void postprocess_set_grain (PostProcess *post_processing, float intensity)
 
void postprocess_set_exposure (PostProcess *post_processing, float exposure)
 
void postprocess_set_chrom_abbr (PostProcess *post_processing, float strength)
 
void postprocess_set_white_balance (PostProcess *post_processing, float temperature, float tint)
 
void postprocess_set_color_grading (PostProcess *post_processing, float saturation, float contrast, float gamma, float gain, float offset, float lift)
 
void postprocess_set_tonemapper (PostProcess *post_processing, float slope, float toe, float shoulder, float black_clip, float white_clip)
 
void postprocess_set_bloom (PostProcess *post_processing, float intensity, float threshold, float soft_threshold)
 
void postprocess_set_dof (PostProcess *post_processing, float focal_distance, float focal_range, float bokeh_scale)
 
void postprocess_set_dof_anamorphic (PostProcess *post_processing, float anamorphic_ratio)
 
float postprocess_get_exposure (PostProcess *post_processing)
 
void postprocess_set_auto_exposure (PostProcess *post_processing, float min_luminance, float max_luminance, float speed_up, float speed_down, float key_value)
 
void postprocess_set_fxaa (PostProcess *post_processing, float subpix, float edge_threshold, float edge_threshold_min)
 
void postprocess_set_banding (PostProcess *post_processing, BandingMode mode, float levels)
 
void postprocess_set_banding_dither (PostProcess *post_processing, float strength)
 
void postprocess_set_banding_perceptual (PostProcess *post_processing, float gamma)
 
void postprocess_set_banding_channels (PostProcess *post_processing, float red, float green, float blue)
 
void postprocess_set_fog (PostProcess *post_processing, float density, float start, float height_falloff, float fog_r, float fog_g, float fog_b)
 
void postprocess_set_grading_ue_default (PostProcess *post_processing)
 
void postprocess_apply_preset (PostProcess *post_processing, const PostProcessPreset *preset)
 Applies all settings from a preset atomically. More...
 
void postprocess_begin (PostProcess *post_processing)
 Binds the HDR FBO and prepares for scene rendering. Should be called BEFORE the main render loop. More...
 
void postprocess_end (PostProcess *post_processing)
 Processes the HDR scene and renders the final LDR result to screen. Should be called AFTER the main render loop. More...
 
void postprocess_update_time (PostProcess *post_processing, float delta_time)
 Increments internal clocks. More...
 
GLuint postprocess_get_exposure_pbo (PostProcess *post_processing, int index)
 
GLuint postprocess_get_histogram_pbo (PostProcess *post_processing, int index)
 
GLsync postprocess_get_exposure_sync (PostProcess *post_processing, int index)
 
GLsync postprocess_get_histogram_sync (PostProcess *post_processing, int index)
 
void postprocess_set_exposure_sync (PostProcess *post_processing, int index, GLsync sync)
 
void postprocess_set_histogram_sync (PostProcess *post_processing, int index, GLsync sync)
 
void postprocess_update_readbacks (PostProcess *post_processing, uint64_t frame_count)
 Updates all async GPU readbacks (Exposure, Histogram). Handles PBO mapping and Sync management internally to avoid CPU stalls. More...
 
void postprocess_set_exposure_target (PostProcess *post_processing, float threshold)
 Updates the target exposure threshold for AE. More...
 
static void fill_histogram_buckets (const float *lum_data, int *buckets, int size, float *min_lum, float *max_lum)
 
static void trigger_histogram_readback (PostProcess *post_processing, int write_idx)
 
int postprocess_compute_luminance_histogram (PostProcess *post_processing, uint64_t frame_count, int *buckets, int size, float *min_lum, float *max_lum)
 Computes the luminance histogram from the GPU readback. More...
 
void postprocess_update_matrices (PostProcess *post_processing, mat4 view_proj)
 Updates view-projection matrices for effects requiring depth-reconstruction. More...
 
static void setup_sampler_uniforms (PostProcess *post_processing)
 Sets sampler uniform → texture unit bindings on the postprocess shader. These are program state (not context state) and only need to be set once per shader program, not every frame. More...
 
static void log_optimized_effects (unsigned int flags)
 
static Shaderfind_shader_in_cache (PostProcess *post_processing, unsigned int static_flags)
 
static void update_current_shader (PostProcess *post_processing, Shader *new_shader, bool is_optimized)
 
void postprocess_compile_optimized (PostProcess *post_processing, unsigned int static_flags)
 Compiles a specialized Uber-shader for maximum performance. More...
 
void postprocess_use_dynamic (PostProcess *post_processing)
 Switches back to the dynamic/generic Uber-shader. More...
 
void postprocess_set_lut3d (PostProcess *post_processing, float intensity, GLuint texture)
 
int postprocess_load_lut3d (PostProcess *post_processing, const char *path)
 

Variables

static const float LUM_MIN_EXTREME = 1e30F
 
static const float LUM_MAX_EXTREME = -1e30F
 
static const EffectMetadata ALL_EFFECTS []
 

Macro Definition Documentation

◆ EFFECT_COUNT

#define EFFECT_COUNT   (sizeof(ALL_EFFECTS) / sizeof(ALL_EFFECTS[0]))

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
POSTPROCESS_TEX_UNIT_SCENE 
POSTPROCESS_TEX_UNIT_BLOOM 
POSTPROCESS_TEX_UNIT_DEPTH 
POSTPROCESS_TEX_UNIT_EXPOSURE 
POSTPROCESS_TEX_UNIT_VELOCITY 
POSTPROCESS_TEX_UNIT_NEIGHBOR_MAX 
POSTPROCESS_TEX_UNIT_DOF_BLUR 
POSTPROCESS_TEX_UNIT_STENCIL 
POSTPROCESS_TEX_UNIT_LUT3D 

◆ anonymous enum

anonymous enum
Enumerator
POSTPROCESS_COMPUTE_GROUP_SIZE 

◆ anonymous enum

anonymous enum
Enumerator
MAX_SHADER_DEFINES 
MAX_DEFINE_LENGTH 

Function Documentation

◆ create_framebuffer()

static int create_framebuffer ( PostProcess post_processing)
static
Here is the call graph for this function:

◆ destroy_cached_shaders()

static void destroy_cached_shaders ( PostProcess post_processing)
static

◆ destroy_framebuffer()

static void destroy_framebuffer ( PostProcess post_processing)
static
Here is the call graph for this function:

◆ destroy_readback_buffers()

static void destroy_readback_buffers ( PostProcess post_processing)
static

◆ destroy_screen_quad()

static void destroy_screen_quad ( PostProcess post_processing)
static

◆ fill_histogram_buckets()

static void fill_histogram_buckets ( const float *  lum_data,
int *  buckets,
int  size,
float *  min_lum,
float *  max_lum 
)
static

◆ find_shader_in_cache()

static Shader* find_shader_in_cache ( PostProcess post_processing,
unsigned int  static_flags 
)
static

◆ is_shader_in_cache()

static bool is_shader_in_cache ( PostProcess post_processing,
Shader shader 
)
static

◆ log_optimized_effects()

static void log_optimized_effects ( unsigned int  flags)
static

◆ postprocess_apply_preset()

void postprocess_apply_preset ( PostProcess post_processing,
const PostProcessPreset preset 
)

Applies all settings from a preset atomically.

Parameters
post_processingPointer to the struct.
presetPointer to the preset values.
See also
postprocess_presets.h
Here is the call graph for this function:

◆ postprocess_begin()

void postprocess_begin ( PostProcess post_processing)

Binds the HDR FBO and prepares for scene rendering. Should be called BEFORE the main render loop.

◆ postprocess_cleanup()

void postprocess_cleanup ( PostProcess post_processing)

Releases all GPU and CPU resources.

Parameters
post_processingPointer to the struct.
Here is the call graph for this function:

◆ postprocess_compile_optimized()

void postprocess_compile_optimized ( PostProcess post_processing,
unsigned int  static_flags 
)

Compiles a specialized Uber-shader for maximum performance.

Parameters
post_processingPointer to the struct.
static_flagsBitmask of effects to bake into the shader.
Here is the call graph for this function:

◆ postprocess_compute_luminance_histogram()

int postprocess_compute_luminance_histogram ( PostProcess post_processing,
uint64_t  frame_count,
int *  buckets,
int  size,
float *  min_lum,
float *  max_lum 
)

Computes the luminance histogram from the GPU readback.

Returns
1 if buckets were updated, 0 otherwise.
Here is the call graph for this function:

◆ postprocess_disable()

void postprocess_disable ( PostProcess post_processing,
PostProcessEffect  effect 
)

Disables a specific effect.

Here is the call graph for this function:

◆ postprocess_enable()

void postprocess_enable ( PostProcess post_processing,
PostProcessEffect  effect 
)

Enables a specific effect.

Here is the call graph for this function:

◆ postprocess_end()

void postprocess_end ( PostProcess post_processing)

Processes the HDR scene and renders the final LDR result to screen. Should be called AFTER the main render loop.

Here is the call graph for this function:

◆ postprocess_get_exposure()

float postprocess_get_exposure ( PostProcess post_processing)
Here is the call graph for this function:

◆ postprocess_get_exposure_pbo()

GLuint postprocess_get_exposure_pbo ( PostProcess post_processing,
int  index 
)

◆ postprocess_get_exposure_sync()

GLsync postprocess_get_exposure_sync ( PostProcess post_processing,
int  index 
)

◆ postprocess_get_histogram_pbo()

GLuint postprocess_get_histogram_pbo ( PostProcess post_processing,
int  index 
)

◆ postprocess_get_histogram_sync()

GLsync postprocess_get_histogram_sync ( PostProcess post_processing,
int  index 
)

◆ postprocess_init()

int postprocess_init ( PostProcess post_processing,
GPUProfiler external_profiler,
int  width,
int  height 
)

Initializes the post-processing pipeline.

Parameters
post_processingPointer to the struct.
external_profilerPointer to the GPU profiler for timing stages.
widthInitial resolution width.
heightInitial resolution height.
Returns
0 on success, negative on error.
Here is the call graph for this function:

◆ postprocess_is_enabled()

int postprocess_is_enabled ( PostProcess post_processing,
PostProcessEffect  effect 
)

Returns true if an effect is currently active.

◆ postprocess_load_lut3d()

int postprocess_load_lut3d ( PostProcess post_processing,
const char *  path 
)

◆ postprocess_on_state_change()

static void postprocess_on_state_change ( PostProcess post_processing)
static
Here is the call graph for this function:

◆ postprocess_resize()

void postprocess_resize ( PostProcess post_processing,
int  width,
int  height 
)

Recreates all internal buffers for a new resolution.

Parameters
post_processingPointer to the struct.
widthNew width.
heightNew height.
Here is the call graph for this function:

◆ postprocess_set_auto_exposure()

void postprocess_set_auto_exposure ( PostProcess post_processing,
float  min_luminance,
float  max_luminance,
float  speed_up,
float  speed_down,
float  key_value 
)

◆ postprocess_set_banding()

void postprocess_set_banding ( PostProcess post_processing,
BandingMode  mode,
float  levels 
)

◆ postprocess_set_banding_channels()

void postprocess_set_banding_channels ( PostProcess post_processing,
float  red,
float  green,
float  blue 
)

◆ postprocess_set_banding_dither()

void postprocess_set_banding_dither ( PostProcess post_processing,
float  strength 
)

◆ postprocess_set_banding_perceptual()

void postprocess_set_banding_perceptual ( PostProcess post_processing,
float  gamma 
)

◆ postprocess_set_bloom()

void postprocess_set_bloom ( PostProcess post_processing,
float  intensity,
float  threshold,
float  soft_threshold 
)

◆ postprocess_set_chrom_abbr()

void postprocess_set_chrom_abbr ( PostProcess post_processing,
float  strength 
)

◆ postprocess_set_color_grading()

void postprocess_set_color_grading ( PostProcess post_processing,
float  saturation,
float  contrast,
float  gamma,
float  gain,
float  offset,
float  lift 
)

◆ postprocess_set_dof()

void postprocess_set_dof ( PostProcess post_processing,
float  focal_distance,
float  focal_range,
float  bokeh_scale 
)

◆ postprocess_set_dof_anamorphic()

void postprocess_set_dof_anamorphic ( PostProcess post_processing,
float  anamorphic_ratio 
)

◆ postprocess_set_dummy_textures()

void postprocess_set_dummy_textures ( PostProcess post_processing,
GLuint  dummy_black 
)

Internal helper to set fallback textures.

◆ postprocess_set_exposure()

void postprocess_set_exposure ( PostProcess post_processing,
float  exposure 
)

◆ postprocess_set_exposure_sync()

void postprocess_set_exposure_sync ( PostProcess post_processing,
int  index,
GLsync  sync 
)

◆ postprocess_set_exposure_target()

void postprocess_set_exposure_target ( PostProcess post_processing,
float  threshold 
)

Updates the target exposure threshold for AE.

Here is the call graph for this function:

◆ postprocess_set_fog()

void postprocess_set_fog ( PostProcess post_processing,
float  density,
float  start,
float  height_falloff,
float  fog_r,
float  fog_g,
float  fog_b 
)

◆ postprocess_set_fxaa()

void postprocess_set_fxaa ( PostProcess post_processing,
float  subpix,
float  edge_threshold,
float  edge_threshold_min 
)

◆ postprocess_set_grading_ue_default()

void postprocess_set_grading_ue_default ( PostProcess post_processing)
Here is the call graph for this function:

◆ postprocess_set_grain()

void postprocess_set_grain ( PostProcess post_processing,
float  intensity 
)

◆ postprocess_set_histogram_sync()

void postprocess_set_histogram_sync ( PostProcess post_processing,
int  index,
GLsync  sync 
)

◆ postprocess_set_lut3d()

void postprocess_set_lut3d ( PostProcess post_processing,
float  intensity,
GLuint  texture 
)

◆ postprocess_set_tonemapper()

void postprocess_set_tonemapper ( PostProcess post_processing,
float  slope,
float  toe,
float  shoulder,
float  black_clip,
float  white_clip 
)

◆ postprocess_set_vignette()

void postprocess_set_vignette ( PostProcess post_processing,
float  intensity,
float  smoothness,
float  roundness 
)

◆ postprocess_set_white_balance()

void postprocess_set_white_balance ( PostProcess post_processing,
float  temperature,
float  tint 
)

◆ postprocess_toggle()

void postprocess_toggle ( PostProcess post_processing,
PostProcessEffect  effect 
)

Toggles the current state of an effect.

Here is the call graph for this function:

◆ postprocess_update_matrices()

void postprocess_update_matrices ( PostProcess post_processing,
mat4  view_proj 
)

Updates view-projection matrices for effects requiring depth-reconstruction.

Parameters
post_processingPointer to the struct.
view_projThe current frame's View-Proj matrix.

◆ postprocess_update_readbacks()

void postprocess_update_readbacks ( PostProcess post_processing,
uint64_t  frame_count 
)

Updates all async GPU readbacks (Exposure, Histogram). Handles PBO mapping and Sync management internally to avoid CPU stalls.

Here is the call graph for this function:

◆ postprocess_update_time()

void postprocess_update_time ( PostProcess post_processing,
float  delta_time 
)

Increments internal clocks.

Parameters
post_processingPointer to the struct.
delta_timeSECONDS elapsed since last frame.

◆ postprocess_use_dynamic()

void postprocess_use_dynamic ( PostProcess post_processing)

Switches back to the dynamic/generic Uber-shader.

Parameters
post_processingPointer to the struct.
Here is the call graph for this function:

◆ setup_sampler_uniforms()

static void setup_sampler_uniforms ( PostProcess post_processing)
static

Sets sampler uniform → texture unit bindings on the postprocess shader. These are program state (not context state) and only need to be set once per shader program, not every frame.

Here is the call graph for this function:

◆ trigger_histogram_readback()

static void trigger_histogram_readback ( PostProcess post_processing,
int  write_idx 
)
static

◆ update_current_shader()

static void update_current_shader ( PostProcess post_processing,
Shader new_shader,
bool  is_optimized 
)
static
Here is the call graph for this function:

Variable Documentation

◆ ALL_EFFECTS

const EffectMetadata ALL_EFFECTS[]
static
Initial value:
= {
{POSTFX_VIGNETTE, "Vignette", "OPT_ENABLE_VIGNETTE"},
{POSTFX_GRAIN, "Film Grain", "OPT_ENABLE_GRAIN"},
{POSTFX_EXPOSURE, "Manual Exposure", "OPT_ENABLE_EXPOSURE"},
{POSTFX_CHROM_ABBR, "Chromatic Aberration", "OPT_ENABLE_CHROM_ABBR"},
{POSTFX_BLOOM, "Bloom", "OPT_ENABLE_BLOOM"},
{POSTFX_COLOR_GRADING, "Color Grading", "OPT_ENABLE_COLOR_GRADING"},
{POSTFX_DOF, "Depth of Field", "OPT_ENABLE_DOF"},
{POSTFX_DOF_DEBUG, "DoF Debug View", "OPT_ENABLE_DOF_DEBUG"},
{POSTFX_AUTO_EXPOSURE, "Auto-Exposure", "OPT_ENABLE_AUTO_EXPOSURE"},
{POSTFX_EXPOSURE_DEBUG, "Exposure Debug View", "OPT_ENABLE_EXPOSURE_DEBUG"},
{POSTFX_MOTION_BLUR, "Motion Blur", "OPT_ENABLE_MOTION_BLUR"},
{POSTFX_MOTION_BLUR_DEBUG, "Motion Blur Debug View",
"OPT_ENABLE_MOTION_BLUR_DEBUG"},
{POSTFX_FXAA, "FXAA", "OPT_ENABLE_FXAA"},
{POSTFX_FXAA_DEBUG, "FXAA Debug View", "OPT_ENABLE_FXAA_DEBUG"},
{POSTFX_BANDING, "Banding", "OPT_ENABLE_BANDING"},
{POSTFX_VECTOR_FIELD_DEBUG, "Vector Field Debug",
"OPT_ENABLE_VECTOR_FIELD_DEBUG"},
{POSTFX_STENCIL_DEBUG, "Stencil Debug View", "OPT_ENABLE_STENCIL_DEBUG"},
{POSTFX_BLOOM_DEBUG, "Bloom Debug View", "OPT_ENABLE_BLOOM_DEBUG"},
{POSTFX_FOG, "Atmospheric Fog", "OPT_ENABLE_FOG"},
{POSTFX_FOG_DEBUG, "Fog Debug View", "OPT_ENABLE_FOG_DEBUG"},
{POSTFX_LUT3D, "3D LUT Gamut Mapping", "OPT_ENABLE_LUT3D"},
}
@ POSTFX_BANDING
Definition: postprocess.h:99
@ POSTFX_BLOOM_DEBUG
Definition: postprocess.h:103
@ POSTFX_AUTO_EXPOSURE
Definition: postprocess.h:90
@ POSTFX_MOTION_BLUR
Definition: postprocess.h:94
@ POSTFX_DOF_DEBUG
Definition: postprocess.h:89
@ POSTFX_COLOR_GRADING
Definition: postprocess.h:86
@ POSTFX_EXPOSURE_DEBUG
Definition: postprocess.h:92
@ POSTFX_GRAIN
Definition: postprocess.h:82
@ POSTFX_MOTION_BLUR_DEBUG
Definition: postprocess.h:95
@ POSTFX_VECTOR_FIELD_DEBUG
Definition: postprocess.h:100
@ POSTFX_FXAA
Definition: postprocess.h:97
@ POSTFX_DOF
Definition: postprocess.h:88
@ POSTFX_STENCIL_DEBUG
Definition: postprocess.h:102
@ POSTFX_BLOOM
Definition: postprocess.h:85
@ POSTFX_FXAA_DEBUG
Definition: postprocess.h:98
@ POSTFX_LUT3D
Definition: postprocess.h:106
@ POSTFX_FOG_DEBUG
Definition: postprocess.h:105
@ POSTFX_EXPOSURE
Definition: postprocess.h:83
@ POSTFX_FOG
Definition: postprocess.h:104
@ POSTFX_VIGNETTE
Definition: postprocess.h:81
@ POSTFX_CHROM_ABBR
Definition: postprocess.h:84

◆ LUM_MAX_EXTREME

const float LUM_MAX_EXTREME = -1e30F
static

◆ LUM_MIN_EXTREME

const float LUM_MIN_EXTREME = 1e30F
static