Add texture UV support to 2D drawing
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
1ffb316a11
commit
75566a8510
33
src/main.zig
33
src/main.zig
|
@ -6,6 +6,10 @@ const ona = @import("ona");
|
||||||
|
|
||||||
const Actors = struct {
|
const Actors = struct {
|
||||||
instances: coral.stack.Sequential(ona.gfx.Queue.Instance2D) = .{.allocator = coral.heap.allocator},
|
instances: coral.stack.Sequential(ona.gfx.Queue.Instance2D) = .{.allocator = coral.heap.allocator},
|
||||||
|
body_texture: ona.gfx.Queue.Handle = .none,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Player = struct {
|
||||||
move_x: ona.act.Axis = .{.keys = .{.a, .d}},
|
move_x: ona.act.Axis = .{.keys = .{.a, .d}},
|
||||||
move_y: ona.act.Axis = .{.keys = .{.w, .s}},
|
move_y: ona.act.Axis = .{.keys = .{.w, .s}},
|
||||||
};
|
};
|
||||||
|
@ -17,14 +21,31 @@ pub fn main() !void {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load(display: coral.ReadBlocking(ona.gfx.Display), actors: coral.Write(Actors)) !void {
|
fn load(display: coral.ReadBlocking(ona.gfx.Display), actors: coral.Write(Actors), gfx: ona.gfx.Queue) !void {
|
||||||
display.res.resize(1280, 720);
|
display.res.resize(1280, 720);
|
||||||
|
|
||||||
try actors.res.instances.push_many(800, .{
|
try actors.res.instances.push_many(800, .{
|
||||||
.origin = .{75, 75},
|
.origin = .{75, 75},
|
||||||
.xbasis = .{100, 0},
|
.xbasis = .{100, 0},
|
||||||
.ybasis = .{0, 100},
|
.ybasis = .{0, 100},
|
||||||
.color = ona.gfx.color.compress(ona.gfx.color.rgb(1, 0, 0)),
|
});
|
||||||
|
|
||||||
|
const crap = [_]u32{
|
||||||
|
0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFF000000,
|
||||||
|
0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF,
|
||||||
|
0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF, 0xFF000000,
|
||||||
|
0xFF000000, 0xFFFFFFFF, 0xFF000000, 0xFFFFFFFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
actors.res.body_texture = try gfx.buffer.open(.{
|
||||||
|
.resource = .{
|
||||||
|
.texture = .{
|
||||||
|
.data = coral.io.bytes_of(&crap),
|
||||||
|
.width = 4,
|
||||||
|
.access = .static,
|
||||||
|
.format = .bgra8888,
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,18 +57,20 @@ fn render(gfx: ona.gfx.Queue, actors: coral.Write(Actors)) !void {
|
||||||
try gfx.buffer.draw_2d(.{
|
try gfx.buffer.draw_2d(.{
|
||||||
.mesh_2d = gfx.primitives.quad_mesh,
|
.mesh_2d = gfx.primitives.quad_mesh,
|
||||||
.instances = actors.res.instances.values,
|
.instances = actors.res.instances.values,
|
||||||
|
.texture = actors.res.body_texture,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(actors: coral.Write(Actors), mapping: coral.Read(ona.act.Mapping)) !void {
|
fn update(player: coral.Read(Player), actors: coral.Write(Actors), mapping: coral.Read(ona.act.Mapping)) !void {
|
||||||
actors.res.instances.values[0].origin += .{
|
actors.res.instances.values[0].origin += .{
|
||||||
mapping.res.axis_strength(actors.res.move_x),
|
mapping.res.axis_strength(player.res.move_x),
|
||||||
mapping.res.axis_strength(actors.res.move_y),
|
mapping.res.axis_strength(player.res.move_y),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(world: *coral.World, events: ona.App.Events) !void {
|
fn setup(world: *coral.World, events: ona.App.Events) !void {
|
||||||
try world.set_resource(.none, Actors{});
|
try world.set_resource(.none, Actors{});
|
||||||
|
try world.set_resource(.none, Player{});
|
||||||
|
|
||||||
try world.on_event(events.load, coral.system_fn(load), .{.label = "load"});
|
try world.on_event(events.load, coral.system_fn(load), .{.label = "load"});
|
||||||
try world.on_event(events.update, coral.system_fn(update), .{.label = "update"});
|
try world.on_event(events.update, coral.system_fn(update), .{.label = "update"});
|
||||||
|
|
|
@ -19,6 +19,7 @@ const AtomicBool = std.atomic.Value(bool);
|
||||||
|
|
||||||
const RenderWork = struct {
|
const RenderWork = struct {
|
||||||
pipeline_2d: sokol.gfx.Pipeline,
|
pipeline_2d: sokol.gfx.Pipeline,
|
||||||
|
instance_2d_sampler: sokol.gfx.Sampler,
|
||||||
instance_2d_buffers: coral.stack.Sequential(sokol.gfx.Buffer),
|
instance_2d_buffers: coral.stack.Sequential(sokol.gfx.Buffer),
|
||||||
resources: coral.stack.Sequential(Resource),
|
resources: coral.stack.Sequential(Resource),
|
||||||
|
|
||||||
|
@ -28,6 +29,10 @@ const RenderWork = struct {
|
||||||
vertex_buffer: sokol.gfx.Buffer,
|
vertex_buffer: sokol.gfx.Buffer,
|
||||||
index_buffer: sokol.gfx.Buffer,
|
index_buffer: sokol.gfx.Buffer,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
texture: struct {
|
||||||
|
image: sokol.gfx.Image,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const buffer_indices = .{
|
const buffer_indices = .{
|
||||||
|
@ -50,6 +55,10 @@ const RenderWork = struct {
|
||||||
sokol.gfx.destroyBuffer(mesh_2d.vertex_buffer);
|
sokol.gfx.destroyBuffer(mesh_2d.vertex_buffer);
|
||||||
sokol.gfx.destroyBuffer(mesh_2d.index_buffer);
|
sokol.gfx.destroyBuffer(mesh_2d.index_buffer);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.texture => |texture| {
|
||||||
|
sokol.gfx.destroyImage(texture.image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +81,11 @@ const RenderWork = struct {
|
||||||
.buffer_index = buffer_indices.mesh,
|
.buffer_index = buffer_indices.mesh,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
attrs[draw_2d.ATTR_vs_mesh_uv] = .{
|
||||||
|
.format = .FLOAT2,
|
||||||
|
.buffer_index = buffer_indices.mesh,
|
||||||
|
};
|
||||||
|
|
||||||
attrs[draw_2d.ATTR_vs_instance_xbasis] = .{
|
attrs[draw_2d.ATTR_vs_instance_xbasis] = .{
|
||||||
.format = .FLOAT2,
|
.format = .FLOAT2,
|
||||||
.buffer_index = buffer_indices.instance,
|
.buffer_index = buffer_indices.instance,
|
||||||
|
@ -97,6 +111,11 @@ const RenderWork = struct {
|
||||||
.buffer_index = buffer_indices.instance,
|
.buffer_index = buffer_indices.instance,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
attrs[draw_2d.ATTR_vs_instance_rect] = .{
|
||||||
|
.format = .FLOAT4,
|
||||||
|
.buffer_index = buffer_indices.instance,
|
||||||
|
};
|
||||||
|
|
||||||
break: get attrs;
|
break: get attrs;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -113,6 +132,10 @@ const RenderWork = struct {
|
||||||
.index_type = .UINT16,
|
.index_type = .UINT16,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
.instance_2d_sampler = sokol.gfx.makeSampler(.{
|
||||||
|
.label = "instance 2D sampler",
|
||||||
|
}),
|
||||||
|
|
||||||
.instance_2d_buffers = .{.allocator = coral.heap.allocator},
|
.instance_2d_buffers = .{.allocator = coral.heap.allocator},
|
||||||
.resources = .{.allocator = allocator},
|
.resources = .{.allocator = allocator},
|
||||||
};
|
};
|
||||||
|
@ -130,7 +153,7 @@ const RenderWork = struct {
|
||||||
|
|
||||||
for (commands) |command| {
|
for (commands) |command| {
|
||||||
const mesh_2d = &self.resources.values[command.mesh_2d.index().?].mesh_2d;
|
const mesh_2d = &self.resources.values[command.mesh_2d.index().?].mesh_2d;
|
||||||
|
const texture = &self.resources.values[command.texture.index().?].texture;
|
||||||
const instance_size = @sizeOf(Queue.Instance2D);
|
const instance_size = @sizeOf(Queue.Instance2D);
|
||||||
const full_instance_buffer_count = command.instances.len / max_instances;
|
const full_instance_buffer_count = command.instances.len / max_instances;
|
||||||
|
|
||||||
|
@ -160,6 +183,24 @@ const RenderWork = struct {
|
||||||
},
|
},
|
||||||
|
|
||||||
.index_buffer = mesh_2d.index_buffer,
|
.index_buffer = mesh_2d.index_buffer,
|
||||||
|
|
||||||
|
.fs = .{
|
||||||
|
.images = get: {
|
||||||
|
var images = [_]sokol.gfx.Image{.{}} ** 12;
|
||||||
|
|
||||||
|
images[0] = texture.image;
|
||||||
|
|
||||||
|
break: get images;
|
||||||
|
},
|
||||||
|
|
||||||
|
.samplers = get: {
|
||||||
|
var samplers = [_]sokol.gfx.Sampler{.{}} ** 8;
|
||||||
|
|
||||||
|
samplers[0] = self.instance_2d_sampler;
|
||||||
|
|
||||||
|
break: get samplers;
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
sokol.gfx.updateBuffer(self.instance_2d_buffers.values[instance_2d_buffers_used], .{
|
sokol.gfx.updateBuffer(self.instance_2d_buffers.values[instance_2d_buffers_used], .{
|
||||||
|
@ -194,6 +235,24 @@ const RenderWork = struct {
|
||||||
break: get_buffers buffers;
|
break: get_buffers buffers;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.fs = .{
|
||||||
|
.images = get: {
|
||||||
|
var images = [_]sokol.gfx.Image{.{}} ** 12;
|
||||||
|
|
||||||
|
images[0] = texture.image;
|
||||||
|
|
||||||
|
break: get images;
|
||||||
|
},
|
||||||
|
|
||||||
|
.samplers = get: {
|
||||||
|
var samplers = [_]sokol.gfx.Sampler{.{}} ** 8;
|
||||||
|
|
||||||
|
samplers[0] = self.instance_2d_sampler;
|
||||||
|
|
||||||
|
break: get samplers;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
.index_buffer = mesh_2d.index_buffer,
|
.index_buffer = mesh_2d.index_buffer,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -208,11 +267,34 @@ const RenderWork = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_queue(self: *RenderWork, buffer: *const Queue.Buffer, target: Queue.Target) std.mem.Allocator.Error!void {
|
fn process_open_commands(self: *RenderWork, commands: []const Queue.Buffer.OpenCommand) std.mem.Allocator.Error!void {
|
||||||
for (buffer.open_commands.values) |command| {
|
for (commands) |command| {
|
||||||
switch (command.resource) {
|
switch (command.resource) {
|
||||||
.texture => {
|
.texture => |texture| {
|
||||||
|
const stride = texture.width * texture.format.byte_size();
|
||||||
|
|
||||||
|
const image = sokol.gfx.makeImage(.{
|
||||||
|
.width = texture.width,
|
||||||
|
.height = @intCast(texture.data.len / stride),
|
||||||
|
|
||||||
|
.data = .{
|
||||||
|
.subimage = get: {
|
||||||
|
var subimage = [_][16]sokol.gfx.Range{.{.{}} ** 16} ** 6;
|
||||||
|
|
||||||
|
subimage[0][0] = sokol.gfx.asRange(texture.data);
|
||||||
|
|
||||||
|
break: get subimage;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
errdefer sokol.gfx.destroyImage(image);
|
||||||
|
|
||||||
|
try self.resources.push(.{
|
||||||
|
.texture = .{
|
||||||
|
.image = image,
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
.mesh_2d => |mesh_2d| {
|
.mesh_2d => |mesh_2d| {
|
||||||
|
@ -245,7 +327,10 @@ const RenderWork = struct {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_queue(self: *RenderWork, buffer: *const Queue.Buffer, target: Queue.Target) std.mem.Allocator.Error!void {
|
||||||
|
try self.process_open_commands(buffer.open_commands.values);
|
||||||
try self.process_draw_2d_commands(buffer.draw_2d_commands.values, target);
|
try self.process_draw_2d_commands(buffer.draw_2d_commands.values, target);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub const Buffer = struct {
|
||||||
|
|
||||||
pub const Draw2DCommand = struct {
|
pub const Draw2DCommand = struct {
|
||||||
instances: []const Instance2D,
|
instances: []const Instance2D,
|
||||||
|
texture: Handle,
|
||||||
mesh_2d: Handle,
|
mesh_2d: Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,8 +41,8 @@ pub const Buffer = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Texture = struct {
|
pub const Texture = struct {
|
||||||
|
data: []const coral.io.Byte,
|
||||||
width: u16,
|
width: u16,
|
||||||
height: u16,
|
|
||||||
format: Format,
|
format: Format,
|
||||||
access: Access,
|
access: Access,
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ pub const Buffer = struct {
|
||||||
pub fn draw_2d(self: *Buffer, command: Draw2DCommand) std.mem.Allocator.Error!void {
|
pub fn draw_2d(self: *Buffer, command: Draw2DCommand) std.mem.Allocator.Error!void {
|
||||||
try self.draw_2d_commands.push(.{
|
try self.draw_2d_commands.push(.{
|
||||||
.instances = try self.arena.allocator().dupe(Instance2D, command.instances),
|
.instances = try self.arena.allocator().dupe(Instance2D, command.instances),
|
||||||
|
.texture = command.texture,
|
||||||
.mesh_2d = command.mesh_2d,
|
.mesh_2d = command.mesh_2d,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -124,8 +126,8 @@ pub const Buffer = struct {
|
||||||
.resource = switch (command.resource) {
|
.resource = switch (command.resource) {
|
||||||
.texture => |texture| .{
|
.texture => |texture| .{
|
||||||
.texture = .{
|
.texture = .{
|
||||||
|
.data = try arena_allocator.dupe(coral.io.Byte, texture.data),
|
||||||
.width = texture.width,
|
.width = texture.width,
|
||||||
.height = texture.height,
|
|
||||||
.format = texture.format,
|
.format = texture.format,
|
||||||
.access = texture.access,
|
.access = texture.access,
|
||||||
},
|
},
|
||||||
|
@ -167,6 +169,8 @@ pub const Instance2D = extern struct {
|
||||||
origin: Point2D = @splat(0),
|
origin: Point2D = @splat(0),
|
||||||
color: color.Compressed = color.compress(color.white),
|
color: color.Compressed = color.compress(color.white),
|
||||||
depth: f32 = 0,
|
depth: f32 = 0,
|
||||||
|
texture_offset: Point2D = @splat(0),
|
||||||
|
texture_size: Point2D = @splat(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
const Node = struct {
|
const Node = struct {
|
||||||
|
@ -235,6 +239,7 @@ pub const Target = struct {
|
||||||
|
|
||||||
pub const Vertex2D = struct {
|
pub const Vertex2D = struct {
|
||||||
xy: Point2D,
|
xy: Point2D,
|
||||||
|
uv: Point2D,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn bind(context: coral.system.BindContext) std.mem.Allocator.Error!State {
|
pub fn bind(context: coral.system.BindContext) std.mem.Allocator.Error!State {
|
||||||
|
@ -275,10 +280,10 @@ pub fn bind(context: coral.system.BindContext) std.mem.Allocator.Error!State {
|
||||||
.indices = &.{0, 1, 2, 0, 2, 3},
|
.indices = &.{0, 1, 2, 0, 2, 3},
|
||||||
|
|
||||||
.vertices = &.{
|
.vertices = &.{
|
||||||
.{.xy = .{-half_extent, half_extent}},// .uv = .{0, 1}},
|
.{.xy = .{-half_extent, half_extent}, .uv = .{0, 1}},
|
||||||
.{.xy = .{half_extent, half_extent}},// .uv = .{1, 1}},
|
.{.xy = .{half_extent, half_extent}, .uv = .{1, 1}},
|
||||||
.{.xy = .{half_extent, -half_extent}},// .uv = .{1, 0}},
|
.{.xy = .{half_extent, -half_extent}, .uv = .{1, 0}},
|
||||||
.{.xy = .{-half_extent, -half_extent}},// .uv = .{0, 0}},
|
.{.xy = .{-half_extent, -half_extent}, .uv = .{0, 0}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,18 +3,21 @@
|
||||||
|
|
||||||
@vs vs
|
@vs vs
|
||||||
in vec2 mesh_xy;
|
in vec2 mesh_xy;
|
||||||
|
in vec2 mesh_uv;
|
||||||
|
|
||||||
in vec2 instance_xbasis;
|
in vec2 instance_xbasis;
|
||||||
in vec2 instance_ybasis;
|
in vec2 instance_ybasis;
|
||||||
in vec2 instance_origin;
|
in vec2 instance_origin;
|
||||||
in vec4 instance_color;
|
in vec4 instance_color;
|
||||||
in float instance_depth;
|
in float instance_depth;
|
||||||
|
in vec4 instance_rect;
|
||||||
|
|
||||||
uniform Screen {
|
uniform Screen {
|
||||||
vec2 screen_size;
|
vec2 screen_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
out vec2 uv;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Calculate the world position of the vertex
|
// Calculate the world position of the vertex
|
||||||
|
@ -26,18 +29,28 @@ void main() {
|
||||||
|
|
||||||
// Set the position of the vertex in clip space
|
// Set the position of the vertex in clip space
|
||||||
gl_Position = vec4(ndc_position, instance_depth, 1.0);
|
gl_Position = vec4(ndc_position, instance_depth, 1.0);
|
||||||
|
|
||||||
// Set the output color
|
|
||||||
color = instance_color;
|
color = instance_color;
|
||||||
|
|
||||||
|
// Calculate the width and height from left, top, right, bottom configuration
|
||||||
|
const vec2 rect_pos = instance_rect.xy; // left, top
|
||||||
|
const vec2 rect_size = instance_rect.zw - instance_rect.xy; // right - left, bottom - top
|
||||||
|
|
||||||
|
// Calculate the adjusted UV coordinates using the instance_rect
|
||||||
|
uv = rect_pos + (mesh_uv * rect_size);
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@fs fs
|
@fs fs
|
||||||
|
uniform texture2D tex;
|
||||||
|
uniform sampler smp;
|
||||||
|
|
||||||
in vec4 color;
|
in vec4 color;
|
||||||
|
in vec2 uv;
|
||||||
|
|
||||||
out vec4 texel;
|
out vec4 texel;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
texel = color;
|
texel = texture(sampler2D(tex, smp), uv) * color;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue