add texture sampling

This commit is contained in:
Rokas Puzonas 2026-07-06 22:15:34 +03:00
parent 1d9f1cfa6a
commit 40bbfff775
3 changed files with 111 additions and 44 deletions

View File

@ -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();

View File

@ -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,
};

View File

@ -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