diff --git a/src/app.zig b/src/app.zig index 7e08e7c..64b1842 100644 --- a/src/app.zig +++ b/src/app.zig @@ -26,20 +26,21 @@ pub fn init(self: *App, plt: Platform.Init) !?u8 { pub fn frame(self: *App, plt: *Platform.Frame) !void { const gfx = plt.gfx; + const input = plt.input; const dt = plt.deltaTime(); var dir: Vec2 = .init(0, 0); - if (plt.input.isKeyDown(.S)) { + if (input.isKeyDown(.S)) { dir.y += 1; } - if (plt.input.isKeyDown(.W)) { + if (input.isKeyDown(.W)) { dir.y -= 1; } - if (plt.input.isKeyDown(.D)) { + if (input.isKeyDown(.D)) { dir.x += 1; } - if (plt.input.isKeyDown(.A)) { + if (input.isKeyDown(.A)) { dir.x -= 1; } dir = dir.normalized(); diff --git a/src/graphics.zig b/src/graphics.zig index bef4c71..9966ab2 100644 --- a/src/graphics.zig +++ b/src/graphics.zig @@ -18,46 +18,52 @@ const shd = @import("shader"); const max_quads = 2048; pub const System = struct { + shader: sg.Shader, pipeline: sg.Pipeline, bindings: sg.Bindings, - pub fn init(self: *System, logger: sg.Logger) void { - self.* = @This(){ - .pipeline = .{}, - .bindings = .{}, - }; + default_image: sg.Image, + default_view: sg.View, + default_sampler: sg.Sampler, + pub fn init(self: *System, logger: sg.Logger) void { sg.setup(.{ .environment = sglue.environment(), .logger = logger }); - self.bindings.vertex_buffers[0] = sg.makeBuffer(.{ - .size = @sizeOf(Quad) * max_quads, - .usage = .{ .vertex_buffer = true, .dynamic_update = true }, - .label = "quad-vertices" - }); - - const index_count = max_quads * 6; - var indices: [index_count]u16 = undefined; - for (0..max_quads) |i| { - indices[6*i + 0] = @intCast(4*i + 0); - indices[6*i + 1] = @intCast(4*i + 1); - indices[6*i + 2] = @intCast(4*i + 2); - - indices[6*i + 3] = @intCast(4*i + 1); - indices[6*i + 4] = @intCast(4*i + 3); - indices[6*i + 5] = @intCast(4*i + 2); - } - - self.bindings.index_buffer = sg.makeBuffer(.{ - .data = sg.asRange(&indices), - .usage = .{ .index_buffer = true, }, - .label = "indices" - }); - const shader = sg.makeShader(shd.mainShaderDesc(sg.queryBackend())); - self.pipeline = sg.makePipeline(.{ + assert(shader.id != sg.invalid_id); + + var pixels: [8 * 8 * 4]u8 = undefined; + @memset(&pixels, 0xFF); + var image_data: sg.ImageData = .{}; + image_data.mip_levels[0] = sg.asRange(&pixels); + const default_image = sg.makeImage(.{ + .type = ._2D, + .width = 8, + .height = 8, + .num_mipmaps = 1, + .pixel_format = .RGBA8, + .data = image_data, + .label = "default-texture" + }); + assert(default_image.id != sg.invalid_id); + + const default_view = sg.makeView(.{ + .texture = .{ .image = default_image }, + .label = "default-view" + }); + assert(default_view.id != sg.invalid_id); + + const default_sampler = sg.makeSampler(.{ + .min_filter = .NEAREST, + .mag_filter = .NEAREST, + .label = "default-sampler" + }); + assert(default_sampler.id != sg.invalid_id); + + const pipeline = sg.makePipeline(.{ .primitive_type = .TRIANGLES, .index_type = .UINT16, .colors = init: { @@ -79,15 +85,60 @@ pub const System = struct { .layout = init: { var l = sg.VertexLayoutState{}; l.attrs[shd.ATTR_main_position].format = .FLOAT2; + l.attrs[shd.ATTR_main_texcoord0].format = .FLOAT2; l.attrs[shd.ATTR_main_color0].format = .FLOAT4; break :init l; }, .label = "main-pipeline" }); + assert(pipeline.id != sg.invalid_id); + + var bindings: sg.Bindings = .{}; + { + bindings.vertex_buffers[0] = sg.makeBuffer(.{ + .size = @sizeOf(Quad) * max_quads, + .usage = .{ .vertex_buffer = true, .dynamic_update = true }, + .label = "quad-vertices" + }); + + const index_count = max_quads * 6; + var indices: [index_count]u16 = undefined; + for (0..max_quads) |i| { + indices[6*i + 0] = @intCast(4*i + 0); + indices[6*i + 1] = @intCast(4*i + 1); + indices[6*i + 2] = @intCast(4*i + 2); + + indices[6*i + 3] = @intCast(4*i + 1); + indices[6*i + 4] = @intCast(4*i + 3); + indices[6*i + 5] = @intCast(4*i + 2); + } + + bindings.index_buffer = sg.makeBuffer(.{ + .data = sg.asRange(&indices), + .usage = .{ .index_buffer = true, }, + .label = "indices" + }); + + bindings.views[shd.VIEW_tex] = default_view; + bindings.samplers[shd.SMP_smp] = default_sampler; + } + + self.* = @This(){ + .shader = shader, + .pipeline = pipeline, + .bindings = bindings, + .default_image = default_image, + .default_view = default_view, + .default_sampler = default_sampler + }; } pub fn deinit(self: System) void { - _ = self; // autofix + sg.destroyPipeline(self.pipeline); + sg.destroyShader(self.shader); + sg.destroyImage(self.default_image); + sg.destroyView(self.default_view); + sg.destroySampler(self.default_sampler); sg.shutdown(); } @@ -168,19 +219,23 @@ pub const Interface = struct { self.drawQuad(Quad{ Vertex{ .position = pos, - .color = color_vec4 + .color = color_vec4, + .texcoord = .init(0, 0) }, Vertex{ .position = pos.add(.{ .x = size.x, .y = 0 }), - .color = color_vec4 + .color = color_vec4, + .texcoord = .init(1, 0) }, Vertex{ .position = pos.add(.{ .x = 0, .y = size.y }), - .color = color_vec4 + .color = color_vec4, + .texcoord = .init(0, 1) }, Vertex{ .position = pos.add(size), - .color = color_vec4 + .color = color_vec4, + .texcoord = .init(1, 1) }, }); } @@ -196,19 +251,23 @@ pub const Interface = struct { drawQuad(Quad{ Vertex{ .position = top_right, - .color = color + .color = color, + .texcoord = .init(0, 0) }, Vertex{ .position = top_left, - .color = color + .color = color, + .texcoord = .init(1, 0) }, Vertex{ .position = bottom_right, - .color = color + .color = color, + .texcoord = .init(0, 1) }, Vertex{ .position = bottom_left, - .color = color + .color = color, + .texcoord = .init(1, 1) }, }); } @@ -216,6 +275,7 @@ pub const Interface = struct { pub const Vertex = extern struct { position: Vec2, + texcoord: Vec2, color: Vec4, }; diff --git a/src/shader.glsl b/src/shader.glsl index d2be216..5e966ee 100644 --- a/src/shader.glsl +++ b/src/shader.glsl @@ -4,8 +4,10 @@ /* main vertex shader */ @vs vs in vec2 position; +in vec2 texcoord0; in vec4 color0; out vec4 color; +out vec4 uv; layout(binding = 0) uniform vs_params { mat4 view; @@ -15,16 +17,20 @@ layout(binding = 0) uniform vs_params { void main() { gl_Position = projection * view * vec4(position, 0, 1); color = color0; + uv = vec4(texcoord0, 0.0, 1.0); } @end /* main fragment shader */ @fs fs +layout(binding=0) uniform texture2D tex; +layout(binding=0) uniform sampler smp; in vec4 color; +in vec4 uv; out vec4 frag_color; void main() { - frag_color = color; + frag_color = texture(sampler2D(tex, smp), uv.xy) * color; } @end