post_processing/
post_processing.rs

1use macroquad::prelude::*;
2
3#[macroquad::main("Post processing")]
4async fn main() {
5    let render_target = render_target(320, 150);
6    render_target.texture.set_filter(FilterMode::Nearest);
7
8    let material = load_material(
9        ShaderSource::Glsl {
10            vertex: CRT_VERTEX_SHADER,
11            fragment: CRT_FRAGMENT_SHADER,
12        },
13        Default::default(),
14    )
15    .unwrap();
16
17    loop {
18        // drawing to the texture
19
20        // 0..100, 0..100 camera
21        set_camera(&Camera2D {
22            zoom: vec2(0.01, 0.01),
23            target: vec2(0.0, 0.0),
24            render_target: Some(render_target.clone()),
25            ..Default::default()
26        });
27
28        clear_background(LIGHTGRAY);
29        draw_line(-30.0, 45.0, 30.0, 45.0, 3.0, BLUE);
30        draw_circle(-45.0, -35.0, 20.0, YELLOW);
31        draw_circle(45.0, -35.0, 20.0, GREEN);
32
33        // drawing to the screen
34
35        set_default_camera();
36
37        clear_background(WHITE);
38        gl_use_material(&material);
39        draw_texture_ex(
40            &render_target.texture,
41            0.,
42            0.,
43            WHITE,
44            DrawTextureParams {
45                dest_size: Some(vec2(screen_width(), screen_height())),
46                ..Default::default()
47            },
48        );
49        gl_use_default_material();
50
51        next_frame().await;
52    }
53}
54
55const CRT_FRAGMENT_SHADER: &'static str = r#"#version 100
56precision lowp float;
57
58varying vec4 color;
59varying vec2 uv;
60
61uniform sampler2D Texture;
62
63// https://www.shadertoy.com/view/XtlSD7
64
65vec2 CRTCurveUV(vec2 uv)
66{
67    uv = uv * 2.0 - 1.0;
68    vec2 offset = abs( uv.yx ) / vec2( 6.0, 4.0 );
69    uv = uv + uv * offset * offset;
70    uv = uv * 0.5 + 0.5;
71    return uv;
72}
73
74void DrawVignette( inout vec3 color, vec2 uv )
75{
76    float vignette = uv.x * uv.y * ( 1.0 - uv.x ) * ( 1.0 - uv.y );
77    vignette = clamp( pow( 16.0 * vignette, 0.3 ), 0.0, 1.0 );
78    color *= vignette;
79}
80
81
82void DrawScanline( inout vec3 color, vec2 uv )
83{
84    float iTime = 0.1;
85    float scanline 	= clamp( 0.95 + 0.05 * cos( 3.14 * ( uv.y + 0.008 * iTime ) * 240.0 * 1.0 ), 0.0, 1.0 );
86    float grille 	= 0.85 + 0.15 * clamp( 1.5 * cos( 3.14 * uv.x * 640.0 * 1.0 ), 0.0, 1.0 );
87    color *= scanline * grille * 1.2;
88}
89
90void main() {
91    vec2 crtUV = CRTCurveUV(uv);
92    vec3 res = texture2D(Texture, uv).rgb * color.rgb;
93    if (crtUV.x < 0.0 || crtUV.x > 1.0 || crtUV.y < 0.0 || crtUV.y > 1.0)
94    {
95        res = vec3(0.0, 0.0, 0.0);
96    }
97    DrawVignette(res, crtUV);
98    DrawScanline(res, uv);
99    gl_FragColor = vec4(res, 1.0);
100
101}
102"#;
103
104const CRT_VERTEX_SHADER: &'static str = "#version 100
105attribute vec3 position;
106attribute vec2 texcoord;
107attribute vec4 color0;
108
109varying lowp vec2 uv;
110varying lowp vec4 color;
111
112uniform mat4 Model;
113uniform mat4 Projection;
114
115void main() {
116    gl_Position = Projection * Model * vec4(position, 1);
117    color = color0 / 255.0;
118    uv = texcoord;
119}
120";