1 //------------------------------------------------------------------------------
2 //  sgl_points.d
3 //
4 //  Test sokol-gl point rendering.
5 //
6 //  (port of this C sample: https://floooh.github.io/sokol-html5/sgl-points-sapp.html)
7 //------------------------------------------------------------------------------
8 
9 module examples.sgl_points;
10 
11 import sg = sokol.gfx;
12 import sglue = sokol.glue;
13 import sapp = sokol.app;
14 import slog = sokol.log;
15 import sgl = sokol.gl;
16 import handmade.math : sin, cos, floor;
17 
18 extern (C):
19 @safe:
20 
21 struct RGB {
22     float r = 0.0, g = 0.0, b = 0.0;
23 }
24 
25 struct State {
26     sg.PassAction pass_action = {
27         colors: [
28             {
29                 load_action: sg.LoadAction.Clear,
30                 clear_value: {r: 0.0, g: 0.0, b: 0.0, a: 1.0},
31             }
32         ]
33     };
34 }
35 static State state;
36 
37 immutable float[3][16] palette = [
38     [0.957, 0.263, 0.212],
39     [0.914, 0.118, 0.388],
40     [0.612, 0.153, 0.690],
41     [0.404, 0.227, 0.718],
42     [0.247, 0.318, 0.710],
43     [0.129, 0.588, 0.953],
44     [0.012, 0.663, 0.957],
45     [0.000, 0.737, 0.831],
46     [0.000, 0.588, 0.533],
47     [0.298, 0.686, 0.314],
48     [0.545, 0.765, 0.290],
49     [0.804, 0.863, 0.224],
50     [1.000, 0.922, 0.231],
51     [1.000, 0.757, 0.027],
52     [1.000, 0.596, 0.000],
53     [1.000, 0.341, 0.133],
54 ];
55 
56 void init() {
57     sg.Desc gfx = {
58         environment: sglue.environment(),
59         logger: { func: &slog.func }
60     };
61     sg.setup(gfx);
62     sgl.Desc gl = {
63         logger: { func: &slog.func }
64     };
65     sgl.setup(gl);
66 }
67 
68 void frame() {
69     immutable float angle = sapp.frameCount() % 360.0;
70     sgl.defaults();
71     sgl.beginPoints();
72     float psize = 5.0;
73     foreach (i; 0 .. 360) {
74         auto a = sgl.asRadians(angle + i);
75         auto color = computeColor(((sapp.frameCount() + i) % 300) / 300.0);
76         auto r = sin(a * 4.0);
77         auto s = sin(a);
78         auto c = cos(a);
79         auto x = s * r;
80         auto y = c * r;
81         sgl.c3f(color.r, color.g, color.b);
82         sgl.pointSize(psize);
83         sgl.v2f(x, y);
84         psize *= 1.005;
85     }
86     sgl.end();
87 
88     sg.Pass pass = { action: state.pass_action, swapchain: sglue.swapchain() };
89     sg.beginPass(pass);
90     sgl.draw();
91     sg.endPass();
92     sg.commit();
93 }
94 
95 void cleanup() {
96     sgl.shutdown();
97     sg.shutdown();
98 }
99 
100 void main() {
101     sapp.Desc runner = {
102         window_title: "sgl-points.d",
103         init_cb: &init,
104         frame_cb: &frame,
105         cleanup_cb: &cleanup,
106         width: 512,
107         height: 512,
108         logger: {func: &slog.func},
109         icon: {sokol_default: true}
110     };
111     sapp.run(runner);
112 }
113 
114 RGB computeColor(float t) {
115     const(size_t) idx0 = cast(size_t)(t * 16) % 16;
116     const(size_t) idx1 = cast(size_t)(idx0 + 1) % 16;
117     const l = (t * 16) - floor(t * 16);
118     const c0 = palette[idx0];
119     const c1 = palette[idx1];
120     RGB rgb = {
121         r: (c0[0] * (1 - l)) + (c1[0] * l),
122         g: (c0[1] * (1 - l)) + (c1[1] * l),
123         b: (c0[2] * (1 - l)) + (c1[2] * l),
124     };
125     return rgb;
126 }