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 = 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 usage: { index_buffer: true }, 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 // create a small checker-board image and texture view 124 sg.ImageData img_data = { 125 mip_levels: [{ 126 ptr: cast(ubyte*)colors.ptr, 127 size: colors.sizeof, 128 }] 129 }; 130 sg.ImageDesc img_desc = { 131 width: 4, 132 height: 4, 133 data: img_data, 134 }; 135 // dfmt on 136 auto img = sg.makeImage(img_desc); 137 sg.ViewDesc view_desc = { 138 texture: { image: img }, 139 }; 140 state.bind.views[shd.VIEW_TEX] = sg.makeView(view_desc); 141 142 sg.SamplerDesc smpld = {}; 143 state.bind.samplers[shd.SMP_SMP] = sg.makeSampler(smpld); 144 145 state.pip = sg.makePipeline(pld); 146 } 147 148 void frame() 149 { 150 immutable float t = cast(float)(app.frameDuration() * 60.0); 151 152 state.rx += 1.0 * t; 153 state.ry += 2.0 * t; 154 155 shd.VsParams vsParams = {mvp: computeMvp(state.rx, state.ry)}; 156 157 sg.Pass pass = {action: state.passAction, swapchain: sglue.swapchain()}; 158 sg.beginPass(pass); 159 sg.applyPipeline(state.pip); 160 sg.applyBindings(state.bind); 161 sg.Range r = {ptr: &vsParams, size: vsParams.sizeof}; 162 sg.applyUniforms(shd.UB_VS_PARAMS, r); 163 sg.draw(0, 36, 1); 164 sg.endPass(); 165 sg.commit(); 166 } 167 168 void cleanup() 169 { 170 sg.shutdown(); 171 } 172 173 Mat4 computeMvp(float rx, float ry) 174 { 175 immutable proj = Mat4.perspective(60.0, app.widthf() / app.heightf(), 0.01, 10.0); 176 immutable rxm = Mat4.rotate(rx, Vec3(1.0, 0.0, 0.0)); 177 immutable rym = Mat4.rotate(ry, Vec3(0.0, 1.0, 0.0)); 178 immutable model = Mat4.mul(rxm, rym); 179 immutable view_proj = Mat4.mul(proj, state.view()); 180 return Mat4.mul(view_proj, model); 181 } 182 183 // dfmt off 184 void main() 185 { 186 app.Desc runner = { 187 window_title: "texcube.d", 188 init_cb: &init, 189 frame_cb: &frame, 190 cleanup_cb: &cleanup, 191 width: 800, 192 height: 600, 193 sample_count: 4, 194 icon: {sokol_default: true}, 195 logger: {func: &log.func} 196 }; 197 app.run(runner); 198 } 199 // dfmt on 200 201 version (WebAssembly) 202 { 203 debug 204 { 205 import emscripten.assertd; 206 } 207 }