add screen scalar
This commit is contained in:
parent
796ffa5b2d
commit
782ccae6e2
12
src/app.zig
12
src/app.zig
@ -15,6 +15,9 @@ const Gfx = Platform.Gfx;
|
||||
const Audio = Platform.Audio;
|
||||
const ImGUI = Platform.ImGUI;
|
||||
const Rect = Platform.Rect;
|
||||
const Color = Platform.Color;
|
||||
|
||||
const CanvasScaler = @import("./canvas_scaler.zig");
|
||||
|
||||
const App = @This();
|
||||
|
||||
@ -324,9 +327,16 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
||||
dir_y = 0;
|
||||
}
|
||||
|
||||
Gfx.setClearColor(.rgb(40, 40, 40));
|
||||
const clear_color = Color.rgb(40, 40, 40);
|
||||
Gfx.setClearColor(clear_color);
|
||||
|
||||
const tile_size = Vec2.init(48, 48);
|
||||
var canvas = CanvasScaler{
|
||||
.size = Vec2.initFromInt(usize, self.tilemap.width, self.tilemap.height).multiply(tile_size)
|
||||
};
|
||||
canvas.push();
|
||||
defer canvas.pop(clear_color);
|
||||
|
||||
for (0..self.tilemap.height) |y| {
|
||||
for (0..self.tilemap.width) |x| {
|
||||
const tile = self.tilemap.get(x, y);
|
||||
|
||||
71
src/canvas_scaler.zig
Normal file
71
src/canvas_scaler.zig
Normal file
@ -0,0 +1,71 @@
|
||||
const Math = @import("math");
|
||||
const Vec2 = Math.Vec2;
|
||||
|
||||
const Platform = @import("platform/root.zig");
|
||||
const Gfx = Platform.Gfx;
|
||||
const Color = Platform.Color;
|
||||
|
||||
const Canvas = @This();
|
||||
|
||||
size: Vec2,
|
||||
|
||||
fn getScale(self: Canvas) f32 {
|
||||
const window_size = Gfx.getWindowSize();
|
||||
const canvas_size = self.size;
|
||||
|
||||
const scale_x = window_size.x / canvas_size.x;
|
||||
const scale_y = window_size.y / canvas_size.y;
|
||||
return @min(scale_x, scale_y);
|
||||
}
|
||||
|
||||
fn getScaledCanvas(self: Canvas) Vec2 {
|
||||
return self.size.multiplyScalar(self.getScale());
|
||||
}
|
||||
|
||||
pub fn push(self: Canvas) void {
|
||||
Gfx.transformPush();
|
||||
|
||||
const scale = self.getScale();
|
||||
const window_size = Gfx.getWindowSize();
|
||||
const scaled_canvas = self.size.multiplyScalar(scale);
|
||||
|
||||
Gfx.transformTranslate(.init(
|
||||
(window_size.x - scaled_canvas.x) / 2,
|
||||
(window_size.y - scaled_canvas.y) / 2,
|
||||
));
|
||||
|
||||
Gfx.transformScale(.init(scale, scale));
|
||||
}
|
||||
|
||||
pub fn pop(self: Canvas, color: Color) void {
|
||||
Gfx.transformPop();
|
||||
|
||||
const scale = self.getScale();
|
||||
const window_size = Gfx.getWindowSize();
|
||||
const scaled_canvas = self.size.multiplyScalar(scale);
|
||||
if (window_size.x > scaled_canvas.x) {
|
||||
const margin_x = (window_size.x - scaled_canvas.x) / 2;
|
||||
Gfx.drawRectangle(
|
||||
.init(0, 0),
|
||||
.init(margin_x, window_size.y),
|
||||
color
|
||||
);
|
||||
Gfx.drawRectangle(
|
||||
.init(window_size.x-margin_x, 0),
|
||||
.init(margin_x, window_size.y),
|
||||
color
|
||||
);
|
||||
} else {
|
||||
const margin_y = (window_size.y - scaled_canvas.y) / 2;
|
||||
Gfx.drawRectangle(
|
||||
.init(0, 0),
|
||||
.init(window_size.x, margin_y),
|
||||
color
|
||||
);
|
||||
Gfx.drawRectangle(
|
||||
.init(0, window_size.y-margin_y),
|
||||
.init(window_size.x, margin_y),
|
||||
color
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -28,6 +28,7 @@ const Frame = struct {
|
||||
quads: std.ArrayList(VertexQuad),
|
||||
transforms: std.ArrayList(TransformFrame),
|
||||
|
||||
window_size: Vec2,
|
||||
clear_color: Color = .black,
|
||||
pass_started: bool = false
|
||||
};
|
||||
@ -176,7 +177,8 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
||||
.index = 0,
|
||||
.quads = .initBuffer(&self.quads_buffer),
|
||||
.transforms = .initBuffer(&self.transforms_buffer),
|
||||
.clear_color = .black
|
||||
.clear_color = .black,
|
||||
.window_size = .init(0, 0)
|
||||
}
|
||||
};
|
||||
|
||||
@ -248,24 +250,6 @@ pub fn deinit() void {
|
||||
sg.shutdown();
|
||||
}
|
||||
|
||||
fn createProjectionMatrix(screen_size: Vec2) Mat4 {
|
||||
return Mat4.initIdentity()
|
||||
// Convert normalized [-1; 1] coordinates to [0; 1]
|
||||
.multiply(Mat4.initTranslate(.{ .x = -1, .y = -1, .z = 0 }))
|
||||
.multiply(Mat4.initScale(.{ .x = 2, .y = 2, .z = 0 }))
|
||||
|
||||
// Make the top-left corner (0,0)
|
||||
.multiply(Mat4.initTranslate(.{ .x = 0, .y = 1, .z = 0 }))
|
||||
.multiply(Mat4.initScale(.{ .x = 1, .y = -1, .z = 0 }))
|
||||
|
||||
// Scretch [0; 1] so that they map 1-to-1 on to screen coordinates.
|
||||
.multiply(Mat4.initScale(.{
|
||||
.x = 1/screen_size.x,
|
||||
.y = 1/screen_size.y,
|
||||
.z = 0
|
||||
}));
|
||||
}
|
||||
|
||||
fn toSokolColor(color: Color) sokol.gfx.Color {
|
||||
// TODO: Assert and do cast
|
||||
return sokol.gfx.Color{
|
||||
@ -331,7 +315,8 @@ pub fn beginFrame() void {
|
||||
self.frame = Frame{
|
||||
.index = self.frame.index,
|
||||
.quads = self.frame.quads,
|
||||
.transforms = self.frame.transforms
|
||||
.transforms = self.frame.transforms,
|
||||
.window_size = Vec2.init(sapp.widthf(), sapp.heightf())
|
||||
};
|
||||
|
||||
self.frame.transforms.appendAssumeCapacity(TransformFrame{
|
||||
@ -412,10 +397,14 @@ pub fn showDebug() void {
|
||||
|
||||
pub fn setClearColor(color: Color) void {
|
||||
const self = &g_state;
|
||||
|
||||
self.frame.clear_color = color;
|
||||
}
|
||||
|
||||
pub fn getWindowSize() Vec2 {
|
||||
const self = &g_state;
|
||||
return self.frame.window_size;
|
||||
}
|
||||
|
||||
pub fn getFrameIndex() u32 {
|
||||
const self = &g_state;
|
||||
return self.frame.index;
|
||||
@ -467,16 +456,29 @@ pub fn flush() void {
|
||||
|
||||
self.bindings.vertex_buffer_offsets[0] = sg.appendBuffer(vertex_buffer, data);
|
||||
|
||||
// TODO: Rectify `window_size` vs `gfx.window_size`
|
||||
const window_size = Vec2.init(sapp.widthf(), sapp.heightf());
|
||||
|
||||
var vs_params: shd.VsParams = .{
|
||||
// TODO: Maybe 'view' matrix is not needed.
|
||||
// We probably should only have a combined 'mvp' matrix
|
||||
.view = .initIdentity(),
|
||||
.projection = createProjectionMatrix(window_size)
|
||||
};
|
||||
var mvp = Mat4.initIdentity();
|
||||
{
|
||||
// Convert normalized [-1; 1] coordinates to [0; 1]
|
||||
mvp = mvp.multiply(Mat4.initTranslate(.{ .x = -1, .y = -1, .z = 0 }));
|
||||
mvp = mvp.multiply(Mat4.initScale(.{ .x = 2, .y = 2, .z = 0 }));
|
||||
|
||||
// Make the top-left corner (0,0)
|
||||
mvp = mvp.multiply(Mat4.initTranslate(.{ .x = 0, .y = 1, .z = 0 }));
|
||||
mvp = mvp.multiply(Mat4.initScale(.{ .x = 1, .y = -1, .z = 0 }));
|
||||
|
||||
// Scretch [0; 1] so that they map 1-to-1 on to screen coordinates.
|
||||
mvp = mvp.multiply(Mat4.initScale(.{
|
||||
.x = 1/window_size.x,
|
||||
.y = 1/window_size.y,
|
||||
.z = 0
|
||||
}));
|
||||
}
|
||||
|
||||
var vs_params: shd.VsParams = .{
|
||||
.mvp = mvp
|
||||
};
|
||||
var fs_params: shd.FsParams = .{
|
||||
.texture_mode = 0,
|
||||
};
|
||||
@ -750,13 +752,6 @@ pub fn drawTexture(id: Texture.Id, pos: Vec2, size: Vec2, color: Color) void {
|
||||
});
|
||||
}
|
||||
|
||||
fn bindView(view: sg.View) void {
|
||||
_ = view; // autofix
|
||||
const self = &g_state;
|
||||
_ = self; // autofix
|
||||
|
||||
}
|
||||
|
||||
pub fn setDefaultSampler(sampler: Sampler) void {
|
||||
const self = &g_state;
|
||||
self.default_sampler = sampler;
|
||||
|
||||
@ -10,12 +10,11 @@ out vec4 color;
|
||||
out vec4 uv;
|
||||
|
||||
layout(binding = 0) uniform vs_params {
|
||||
mat4 view;
|
||||
mat4 projection;
|
||||
mat4 mvp;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = projection * view * vec4(position, 0, 1);
|
||||
gl_Position = mvp * vec4(position, 0, 1);
|
||||
color = color0;
|
||||
uv = vec4(texcoord0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user