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 Audio = Platform.Audio;
|
||||||
const ImGUI = Platform.ImGUI;
|
const ImGUI = Platform.ImGUI;
|
||||||
const Rect = Platform.Rect;
|
const Rect = Platform.Rect;
|
||||||
|
const Color = Platform.Color;
|
||||||
|
|
||||||
|
const CanvasScaler = @import("./canvas_scaler.zig");
|
||||||
|
|
||||||
const App = @This();
|
const App = @This();
|
||||||
|
|
||||||
@ -324,9 +327,16 @@ pub fn frame(self: *App, plt: Platform.Frame) !void {
|
|||||||
dir_y = 0;
|
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);
|
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.height) |y| {
|
||||||
for (0..self.tilemap.width) |x| {
|
for (0..self.tilemap.width) |x| {
|
||||||
const tile = self.tilemap.get(x, y);
|
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),
|
quads: std.ArrayList(VertexQuad),
|
||||||
transforms: std.ArrayList(TransformFrame),
|
transforms: std.ArrayList(TransformFrame),
|
||||||
|
|
||||||
|
window_size: Vec2,
|
||||||
clear_color: Color = .black,
|
clear_color: Color = .black,
|
||||||
pass_started: bool = false
|
pass_started: bool = false
|
||||||
};
|
};
|
||||||
@ -176,7 +177,8 @@ pub fn init(gpa: std.mem.Allocator, logger: sg.Logger) !void {
|
|||||||
.index = 0,
|
.index = 0,
|
||||||
.quads = .initBuffer(&self.quads_buffer),
|
.quads = .initBuffer(&self.quads_buffer),
|
||||||
.transforms = .initBuffer(&self.transforms_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();
|
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 {
|
fn toSokolColor(color: Color) sokol.gfx.Color {
|
||||||
// TODO: Assert and do cast
|
// TODO: Assert and do cast
|
||||||
return sokol.gfx.Color{
|
return sokol.gfx.Color{
|
||||||
@ -331,7 +315,8 @@ pub fn beginFrame() void {
|
|||||||
self.frame = Frame{
|
self.frame = Frame{
|
||||||
.index = self.frame.index,
|
.index = self.frame.index,
|
||||||
.quads = self.frame.quads,
|
.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{
|
self.frame.transforms.appendAssumeCapacity(TransformFrame{
|
||||||
@ -412,10 +397,14 @@ pub fn showDebug() void {
|
|||||||
|
|
||||||
pub fn setClearColor(color: Color) void {
|
pub fn setClearColor(color: Color) void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
|
|
||||||
self.frame.clear_color = color;
|
self.frame.clear_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getWindowSize() Vec2 {
|
||||||
|
const self = &g_state;
|
||||||
|
return self.frame.window_size;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn getFrameIndex() u32 {
|
pub fn getFrameIndex() u32 {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
return self.frame.index;
|
return self.frame.index;
|
||||||
@ -467,16 +456,29 @@ pub fn flush() void {
|
|||||||
|
|
||||||
self.bindings.vertex_buffer_offsets[0] = sg.appendBuffer(vertex_buffer, data);
|
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());
|
const window_size = Vec2.init(sapp.widthf(), sapp.heightf());
|
||||||
|
|
||||||
var vs_params: shd.VsParams = .{
|
var mvp = Mat4.initIdentity();
|
||||||
// TODO: Maybe 'view' matrix is not needed.
|
{
|
||||||
// We probably should only have a combined 'mvp' matrix
|
// Convert normalized [-1; 1] coordinates to [0; 1]
|
||||||
.view = .initIdentity(),
|
mvp = mvp.multiply(Mat4.initTranslate(.{ .x = -1, .y = -1, .z = 0 }));
|
||||||
.projection = createProjectionMatrix(window_size)
|
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 = .{
|
var fs_params: shd.FsParams = .{
|
||||||
.texture_mode = 0,
|
.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 {
|
pub fn setDefaultSampler(sampler: Sampler) void {
|
||||||
const self = &g_state;
|
const self = &g_state;
|
||||||
self.default_sampler = sampler;
|
self.default_sampler = sampler;
|
||||||
|
|||||||
@ -10,12 +10,11 @@ out vec4 color;
|
|||||||
out vec4 uv;
|
out vec4 uv;
|
||||||
|
|
||||||
layout(binding = 0) uniform vs_params {
|
layout(binding = 0) uniform vs_params {
|
||||||
mat4 view;
|
mat4 mvp;
|
||||||
mat4 projection;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = projection * view * vec4(position, 0, 1);
|
gl_Position = mvp * vec4(position, 0, 1);
|
||||||
color = color0;
|
color = color0;
|
||||||
uv = vec4(texcoord0, 0.0, 1.0);
|
uv = vec4(texcoord0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user