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