1 //------------------------------------------------------------------------------
2 //  bufferoffsets.d
3 //
4 //  Render separate geometries in vertex- and index-buffers with
5 //  buffer offsets.
6 //------------------------------------------------------------------------------
7 module examples.bufferoffsets;
8 
9 private:
10 
11 import sg = sokol.gfx;
12 import app = sokol.app;
13 import log = sokol.log;
14 import sglue = sokol.glue;
15 import shd = examples.shaders.bufferoffsets;
16 
17 extern (C):
18 @safe:
19 
20 struct State
21 {
22     sg.Pipeline pip;
23     sg.Bindings bind;
24     sg.PassAction passAction = {};
25 }
26 
27 struct Vertex
28 {
29     float x = 0.0f, y = 0.0f;
30     float r = 0.0f, g = 0.0f, b = 0.0f;
31 }
32 
33 static State state;
34 
35 void init()
36 {
37     sg.Desc gfxd = {environment: sglue.environment,
38     logger: {func: &log.func}};
39     sg.setup(gfxd);
40 
41     state.passAction.colors[0].load_action = sg.LoadAction.Clear;
42     state.passAction.colors[0].clear_value.r = 0.5;
43     state.passAction.colors[0].clear_value.g = 0.5;
44     state.passAction.colors[0].clear_value.b = 1.0;
45     state.passAction.colors[0].clear_value.a = 1.0;
46 
47     Vertex[7] vertices = [
48         Vertex(0.0, 0.55, 1.0, 0.0, 0.0),
49         Vertex(0.25, 0.05, 0.0, 1.0, 0.0),
50         Vertex(-0.25, 0.05, 0.0, 0.0, 1.0),
51 
52         Vertex(-0.25, -0.05, 0.0, 0.0, 1.0),
53         Vertex(0.25, -0.05, 0.0, 1.0, 0.0),
54         Vertex(0.25, -0.55, 1.0, 0.0, 0.0),
55         Vertex(-0.25, -0.55, 1.0, 1.0, 0.0),
56     ];
57 
58     sg.BufferDesc vbufd = {data: {ptr: vertices.ptr, size: vertices.sizeof},};
59     state.bind.vertex_buffers[0] = sg.makeBuffer(vbufd);
60 
61     ushort[9] indices = [
62         0, 1, 2,
63         0, 1, 2,
64         0, 2, 3,
65     ];
66 
67     // dfmt off
68     sg.BufferDesc ibufd = {
69         type: sg.BufferType.Indexbuffer,
70         data: {ptr: indices.ptr, size: indices.sizeof},
71     };
72     state.bind.index_buffer = sg.makeBuffer(ibufd);
73 
74     sg.PipelineDesc pld = {
75         layout: {
76             attrs: [
77                 shd.ATTR_BUFFEROFFSETS_POSITION: {format: sg.VertexFormat.Float2},
78                 shd.ATTR_BUFFEROFFSETS_COLOR0: {format: sg.VertexFormat.Float3},
79             ],
80         },
81         shader: sg.makeShader(shd.bufferoffsetsShaderDesc(sg.queryBackend())),
82         index_type: sg.IndexType.Uint16,
83     };
84     // dfmt on
85     state.pip = sg.makePipeline(pld);
86 }
87 
88 void frame()
89 {
90     sg.Pass pass = {action: state.passAction, swapchain: sglue.swapchain()};
91     sg.beginPass(pass);
92     sg.applyPipeline(state.pip);
93 
94     // render the triangle
95     state.bind.vertex_buffer_offsets[0] = 0;
96     state.bind.index_buffer_offset = 0;
97     sg.applyBindings(state.bind);
98     sg.draw(0, 3, 1);
99 
100     // render the quad
101     state.bind.vertex_buffer_offsets[0] = 3 * Vertex.sizeof;
102     state.bind.index_buffer_offset = 3 * ushort.sizeof;
103     sg.applyBindings(state.bind);
104     sg.draw(0, 6, 1);
105 
106     sg.endPass();
107     sg.commit();
108 }
109 
110 void cleanup()
111 {
112     sg.shutdown();
113 }
114 
115 // dfmt off
116 void main()
117 {
118     app.Desc runner = {
119         window_title: "bufferoffsets.d",
120         init_cb: &init,
121         frame_cb: &frame,
122         cleanup_cb: &cleanup,
123         width: 800,
124         height: 600,
125         sample_count: 4,
126         icon: {sokol_default: true},
127         logger: {func: &log.func}
128     };
129     app.run(runner);
130 }
131 // dfmt on