1 //------------------------------------------------------------------------------ 2 // texcube.d - Example Sokol Texcube 3 // 4 // Texture creation, rendering with texture, packed vertex components. 5 //------------------------------------------------------------------------------ 6 module examples.texcube; 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.texcube; 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 29 Mat4 view() 30 { 31 return Mat4.lookAt(Vec3(0.0, 1.5, 6.0), Vec3.zero(), Vec3.up()); 32 } 33 } 34 35 struct Vertex 36 { 37 float x = 0.0, y = 0.0, z = 0.0; 38 int color = 0; 39 short u = 0, v = 0; 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 Vertex[24] vertices = [ 51 Vertex(-1.0, -1.0, -1.0, 0xFF0000FF, 0, 0), 52 Vertex(1.0, -1.0, -1.0, 0xFF0000FF, 32_767, 0), 53 Vertex(1.0, 1.0, -1.0, 0xFF0000FF, 32_767, 32_767), 54 Vertex(-1.0, 1.0, -1.0, 0xFF0000FF, 0, 32_767), 55 56 Vertex(-1.0, -1.0, 1.0, 0xFF00FF00, 0, 0), 57 Vertex(1.0, -1.0, 1.0, 0xFF00FF00, 32_767, 0), 58 Vertex(1.0, 1.0, 1.0, 0xFF00FF00, 32_767, 32_767), 59 Vertex(-1.0, 1.0, 1.0, 0xFF00FF00, 0, 32_767), 60 61 Vertex(-1.0, -1.0, -1.0, 0xFFFF0000, 0, 0), 62 Vertex(-1.0, 1.0, -1.0, 0xFFFF0000, 32_767, 0), 63 Vertex(-1.0, 1.0, 1.0, 0xFFFF0000, 32_767, 32_767), 64 Vertex(-1.0, -1.0, 1.0, 0xFFFF0000, 0, 32_767), 65 66 Vertex(1.0, -1.0, -1.0, 0xFFFF007F, 0, 0), 67 Vertex(1.0, 1.0, -1.0, 0xFFFF007F, 32_767, 0), 68 Vertex(1.0, 1.0, 1.0, 0xFFFF007F, 32_767, 32_767), 69 Vertex(1.0, -1.0, 1.0, 0xFFFF007F, 0, 32_767), 70 71 Vertex(-1.0, -1.0, -1.0, 0xFFFF7F00, 0, 0), 72 Vertex(-1.0, -1.0, 1.0, 0xFFFF7F00, 32_767, 0), 73 Vertex(1.0, -1.0, 1.0, 0xFFFF7F00, 32_767, 32_767), 74 Vertex(1.0, -1.0, -1.0, 0xFFFF7F00, 0, 32_767), 75 76 Vertex(-1.0, 1.0, -1.0, 0xFF007FFF, 0, 0), 77 Vertex(-1.0, 1.0, 1.0, 0xFF007FFF, 32_767, 0), 78 Vertex(1.0, 1.0, 1.0, 0xFF007FFF, 32_767, 32_767), 79 Vertex(1.0, 1.0, -1.0, 0xFF007FFF, 0, 32_767), 80 ]; 81 82 sg.BufferDesc vbufd = {data: {ptr: vertices.ptr, size: vertices.sizeof},}; 83 state.bind.vertex_buffers[0] = sg.makeBuffer(vbufd); 84 85 ushort[36] indices = [ 86 0, 1, 2, 0, 2, 3, 87 6, 5, 4, 7, 6, 4, 88 8, 9, 10, 8, 10, 11, 89 14, 13, 12, 15, 14, 12, 90 16, 17, 18, 16, 18, 19, 91 22, 21, 20, 23, 22, 20, 92 ]; 93 94 int[4][4] colors = [ 95 [0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFF000000], 96 [0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF], 97 [0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFF000000], 98 [0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF] 99 ]; 100 // dfmt off 101 sg.BufferDesc ibufd = { 102 type: sg.BufferType.Indexbuffer, 103 data: {ptr: indices.ptr, size: indices.sizeof}, 104 }; 105 state.bind.index_buffer = sg.makeBuffer(ibufd); 106 107 sg.PipelineDesc pld = { 108 layout: { 109 attrs: [ 110 shd.ATTR_TEXCUBE_POS: {format: sg.VertexFormat.Float3}, 111 shd.ATTR_TEXCUBE_COLOR0: {format: sg.VertexFormat.Ubyte4n}, 112 shd.ATTR_TEXCUBE_TEXCOORD0: {format: sg.VertexFormat.Short2n}, 113 ], 114 }, 115 shader: sg.makeShader(shd.texcubeShaderDesc(sg.queryBackend())), 116 index_type: sg.IndexType.Uint16, 117 cull_mode: sg.CullMode.Back, 118 depth: { 119 write_enabled: true, 120 compare: sg.CompareFunc.Less_equal 121 }, 122 }; 123 sg.ImageData img_data = { 124 subimage: [[{ 125 ptr: cast(ubyte*)colors.ptr, 126 size: colors.sizeof, 127 }]] 128 }; 129 // create a small checker-board texture 130 sg.ImageDesc img_desc = { 131 width: 4, 132 height: 4, 133 data: img_data, 134 }; 135 // dfmt on 136 state.bind.images[shd.IMG_TEX] = sg.makeImage(img_desc); 137 138 sg.SamplerDesc smpld = {}; 139 state.bind.samplers[shd.SMP_SMP] = sg.makeSampler(smpld); 140 141 state.pip = sg.makePipeline(pld); 142 } 143 144 void frame() 145 { 146 immutable float t = cast(float)(app.frameDuration() * 60.0); 147 148 state.rx += 1.0 * t; 149 state.ry += 2.0 * t; 150 151 shd.VsParams vsParams = {mvp: computeMvp(state.rx, state.ry)}; 152 153 sg.Pass pass = {action: state.passAction, swapchain: sglue.swapchain()}; 154 sg.beginPass(pass); 155 sg.applyPipeline(state.pip); 156 sg.applyBindings(state.bind); 157 sg.Range r = {ptr: &vsParams, size: vsParams.sizeof}; 158 sg.applyUniforms(shd.UB_VS_PARAMS, r); 159 sg.draw(0, 36, 1); 160 sg.endPass(); 161 sg.commit(); 162 } 163 164 void cleanup() 165 { 166 sg.shutdown(); 167 } 168 169 Mat4 computeMvp(float rx, float ry) 170 { 171 immutable proj = Mat4.perspective(60.0, app.widthf() / app.heightf(), 0.01, 10.0); 172 immutable rxm = Mat4.rotate(rx, Vec3(1.0, 0.0, 0.0)); 173 immutable rym = Mat4.rotate(ry, Vec3(0.0, 1.0, 0.0)); 174 immutable model = Mat4.mul(rxm, rym); 175 immutable view_proj = Mat4.mul(proj, state.view()); 176 return Mat4.mul(view_proj, model); 177 } 178 179 // dfmt off 180 void main() 181 { 182 app.Desc runner = { 183 window_title: "texcube.d", 184 init_cb: &init, 185 frame_cb: &frame, 186 cleanup_cb: &cleanup, 187 width: 800, 188 height: 600, 189 sample_count: 4, 190 icon: {sokol_default: true}, 191 logger: {func: &log.func} 192 }; 193 app.run(runner); 194 } 195 // dfmt on