1 //------------------------------------------------------------------------------ 2 // blend.d - Example Sokol Blend 3 // 4 // Shader with uniform data. 5 //------------------------------------------------------------------------------ 6 module examples.blend; 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.blend; 16 17 extern (C): 18 @safe: 19 20 immutable NUM_BLEND_FACTORS = 15; 21 22 struct State 23 { 24 float r = 0.0f; 25 sg.Pipeline bg_pip; 26 sg.Pipeline[NUM_BLEND_FACTORS][NUM_BLEND_FACTORS] pips; 27 sg.Bindings bind; 28 sg.PassAction passAction = { 29 colors: [{load_action: sg.LoadAction.Dontcare}], 30 depth: {load_action: sg.LoadAction.Dontcare}, 31 stencil: {load_action: sg.LoadAction.Dontcare} 32 }; 33 shd.QuadVsParams quad_vs_params; 34 shd.BgFsParams bg_fs_params; 35 } 36 37 static State state; 38 39 void init() 40 { 41 sg.Desc gfx = { 42 pipeline_pool_size: NUM_BLEND_FACTORS * NUM_BLEND_FACTORS + 1, 43 environment: sglue.environment, 44 logger: {func: &log.func} 45 }; 46 sg.setup(gfx); 47 48 float[28] vertices = [ 49 // pos color 50 -1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.5, 51 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 52 -1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.5, 53 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.5, 54 ]; 55 56 // create vertex buffer 57 sg.BufferDesc vbufd = {data: {ptr: vertices.ptr, 58 size: vertices.sizeof,}}; 59 state.bind.vertex_buffers[0] = sg.makeBuffer(vbufd); 60 61 sg.PipelineDesc pld = { 62 shader: sg.makeShader(shd.bgShaderDesc(sg.queryBackend())), 63 layout: { 64 buffers: [{stride: 28}], 65 attrs: [ 66 shd.ATTR_BG_POSITION: {format: sg.VertexFormat.Float2}, 67 ], 68 }, 69 primitive_type: sg.PrimitiveType.Triangle_strip 70 }; 71 state.bg_pip = sg.makePipeline(pld); 72 73 sg.PipelineDesc pip_desc = { 74 shader: sg.makeShader(shd.quadShaderDesc(sg.queryBackend())), 75 layout: { 76 attrs: [ 77 shd.ATTR_QUAD_POSITION: {format: sg.VertexFormat.Float3}, 78 shd.ATTR_QUAD_COLOR0: {format: sg.VertexFormat.Float4}, 79 ], 80 }, 81 primitive_type: sg.PrimitiveType.Triangle_strip, 82 blend_color: {r: 1.0, g: 0.0, b: 0.0, a: 1.0}, 83 colors: [ 84 { 85 blend: { 86 enabled: true, 87 src_factor_alpha: sg.BlendFactor.One, 88 dst_factor_alpha: sg.BlendFactor.Zero 89 } 90 } 91 ] 92 }; 93 foreach (src; 0 .. NUM_BLEND_FACTORS) 94 { 95 foreach (dst; 0 .. NUM_BLEND_FACTORS) 96 { 97 pip_desc.colors[0].blend.src_factor_rgb = cast(sg.BlendFactor)(src + 1); 98 pip_desc.colors[0].blend.dst_factor_rgb = cast(sg.BlendFactor)(dst + 1); 99 state.pips[src][dst] = sg.makePipeline(pip_desc); 100 } 101 } 102 } 103 104 void frame() 105 { 106 immutable float t = cast(float)(app.frameDuration() * 60.0); 107 108 state.r += 0.6 * t; 109 state.bg_fs_params.tick += 1.0 * t; 110 111 // view-projection matrix 112 immutable proj = Mat4.perspective(90.0, app.widthf() / app.heightf(), 0.01, 100.0); 113 immutable view = Mat4.lookAt(Vec3(0.0, 0.0, 25.0), Vec3.zero(), Vec3.up()); 114 immutable view_proj = Mat4.mul(proj, view); 115 116 sg.Pass pass = {action: state.passAction, swapchain: sglue.swapchain()}; 117 sg.beginPass(pass); 118 sg.Range r = {ptr: &state.bg_fs_params, 119 size: state.bg_fs_params.sizeof,}; 120 sg.applyPipeline(state.bg_pip); 121 sg.applyBindings(state.bind); 122 sg.applyUniforms(shd.UB_BG_FS_PARAMS, r); 123 sg.draw(0, 4, 1); 124 125 // draw the blended quads 126 float r0 = state.r; 127 foreach (src; 0 .. NUM_BLEND_FACTORS) 128 { 129 foreach (dst; 0 .. NUM_BLEND_FACTORS) 130 { 131 // compute model-view-proj matrix 132 auto rm = Mat4.rotate(state.r, Vec3(0.0, 1.0, 0.0)); 133 immutable x = (dst - (NUM_BLEND_FACTORS / 2)) * 3.0; 134 immutable y = (src - (NUM_BLEND_FACTORS / 2)) * 2.2; 135 immutable model = Mat4.mul(Mat4.translate(Vec3(x, y, 0.0)), rm); 136 state.quad_vs_params.mvp = Mat4.mul(view_proj, model); 137 sg.Range rg = { 138 ptr: &state.quad_vs_params, 139 size: state.quad_vs_params.sizeof, 140 }; 141 sg.applyPipeline(state.pips[src][dst]); 142 sg.applyBindings(state.bind); 143 sg.applyUniforms(shd.UB_QUAD_VS_PARAMS, rg); 144 sg.draw(0, 4, 1); 145 r0 += 0.6; 146 } 147 } 148 sg.endPass(); 149 sg.commit(); 150 } 151 152 void cleanup() 153 { 154 sg.shutdown(); 155 } 156 157 void main() 158 { 159 app.Desc runner = { 160 window_title: "blend.d", 161 init_cb: &init, 162 frame_cb: &frame, 163 cleanup_cb: &cleanup, 164 width: 800, 165 height: 600, 166 sample_count: 4, 167 icon: {sokol_default: true}, 168 logger: {func: &log.func} 169 }; 170 app.run(runner); 171 }