1 //------------------------------------------------------------------------------ 2 // cube.d - Example Sokol Cube 3 // 4 // Shader with uniform data. 5 //------------------------------------------------------------------------------ 6 module examples.cube; 7 8 private: 9 10 import sg = sokol.gfx; 11 import app = sokol.app; 12 import log = sokol.log; 13 import handmade.math : Mat4, Vec3; 14 import sglue = sokol.glue; 15 import shd = examples.shaders.cube; 16 17 extern (C): 18 @safe: 19 20 struct State 21 { 22 float rx = 0; 23 float ry = 0; 24 25 sg.Pipeline pip; 26 sg.Bindings bind; 27 sg.PassAction passAction = { 28 colors: [ 29 { 30 load_action: sg.LoadAction.Clear, 31 clear_value: {r: 0.25, g: 0.5, b: 0.75, a: 1.0} 32 } 33 ] 34 }; 35 36 Mat4 view() 37 { 38 return Mat4.lookAt(Vec3(0.0, 1.5, 6.0), Vec3.zero(), Vec3.up()); 39 } 40 } 41 42 static State state; 43 44 void init() 45 { 46 sg.Desc gfxd = {environment: sglue.environment, 47 logger: {func: &log.func}}; 48 sg.setup(gfxd); 49 50 float[168] vertices = [ 51 -1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 52 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 53 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 54 -1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 55 56 -1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 57 1.0, -1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 58 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 59 -1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 60 61 -1.0, -1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 62 -1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0, 63 -1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 64 -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 65 66 1.0, -1.0, -1.0, 1.0, 0.5, 0.0, 1.0, 67 1.0, 1.0, -1.0, 1.0, 0.5, 0.0, 1.0, 68 1.0, 1.0, 1.0, 1.0, 0.5, 0.0, 1.0, 69 1.0, -1.0, 1.0, 1.0, 0.5, 0.0, 1.0, 70 71 -1.0, -1.0, -1.0, 0.0, 0.5, 1.0, 1.0, 72 -1.0, -1.0, 1.0, 0.0, 0.5, 1.0, 1.0, 73 1.0, -1.0, 1.0, 0.0, 0.5, 1.0, 1.0, 74 1.0, -1.0, -1.0, 0.0, 0.5, 1.0, 1.0, 75 76 -1.0, 1.0, -1.0, 1.0, 0.0, 0.5, 1.0, 77 -1.0, 1.0, 1.0, 1.0, 0.0, 0.5, 1.0, 78 1.0, 1.0, 1.0, 1.0, 0.0, 0.5, 1.0, 79 1.0, 1.0, -1.0, 1.0, 0.0, 0.5, 1.0 80 ]; 81 sg.BufferDesc vbufd = {data: {ptr: vertices.ptr, size: vertices.sizeof},}; 82 state.bind.vertex_buffers[0] = sg.makeBuffer(vbufd); 83 84 ushort[36] indices = [ 85 0, 1, 2, 0, 2, 3, 86 6, 5, 4, 7, 6, 4, 87 8, 9, 10, 8, 10, 11, 88 14, 13, 12, 15, 14, 12, 89 16, 17, 18, 16, 18, 19, 90 22, 21, 20, 23, 22, 20, 91 ]; 92 sg.BufferDesc ibufd = { 93 type: sg.BufferType.Indexbuffer, 94 data: {ptr: indices.ptr, size: indices.sizeof}, 95 }; 96 state.bind.index_buffer = sg.makeBuffer(ibufd); 97 98 sg.PipelineDesc pld = { 99 layout: { 100 attrs: [ 101 shd.ATTR_CUBE_POSITION: {format: sg.VertexFormat.Float3}, 102 shd.ATTR_CUBE_COLOR0: {format: sg.VertexFormat.Float4}, 103 ], 104 }, 105 shader: sg.makeShader(shd.cubeShaderDesc(sg.queryBackend())), 106 index_type: sg.IndexType.Uint16, 107 cull_mode: sg.CullMode.Back, 108 depth: {write_enabled: true, 109 compare: sg.CompareFunc.Less_equal}, 110 }; 111 state.pip = sg.makePipeline(pld); 112 } 113 114 void frame() 115 { 116 immutable float t = cast(float)(app.frameDuration() * 60.0); 117 118 state.rx += 1.0 * t; 119 state.ry += 2.0 * t; 120 121 shd.VsParams vsParams = {mvp: computeMvp(state.rx, state.ry)}; 122 123 sg.Pass pass = {action: state.passAction, swapchain: sglue.swapchain()}; 124 sg.beginPass(pass); 125 sg.applyPipeline(state.pip); 126 sg.applyBindings(state.bind); 127 sg.Range r = {ptr: &vsParams, size: vsParams.sizeof}; 128 sg.applyUniforms(shd.UB_VS_PARAMS, r); 129 sg.draw(0, 36, 1); 130 sg.endPass(); 131 sg.commit(); 132 } 133 134 void cleanup() 135 { 136 sg.shutdown(); 137 } 138 139 Mat4 computeMvp(float rx, float ry) 140 { 141 immutable proj = Mat4.perspective(60.0, app.widthf() / app.heightf(), 0.01, 10.0); 142 immutable rxm = Mat4.rotate(rx, Vec3(1.0, 0.0, 0.0)); 143 immutable rym = Mat4.rotate(ry, Vec3(0.0, 1.0, 0.0)); 144 immutable model = Mat4.mul(rxm, rym); 145 immutable view_proj = Mat4.mul(proj, state.view()); 146 return Mat4.mul(view_proj, model); 147 } 148 149 void main() 150 { 151 app.Desc runner = { 152 window_title: "cube.d", 153 init_cb: &init, 154 frame_cb: &frame, 155 cleanup_cb: &cleanup, 156 width: 800, 157 height: 600, 158 sample_count: 4, 159 icon: {sokol_default: true}, 160 logger: {func: &log.func} 161 }; 162 app.run(runner); 163 }