Multiple meshes + 1 point light
almost went crazy debuggging issue with multiple UBOs block bindings :))))) Turns out if you specify layout(binding=X) in shader and later call glUniformBlockBinding (cause you don't know what you're doing) it will mess up all your bindings, and your camera UBO will be fed to a lights array ubo and good luck debugging that.
This commit is contained in:
parent
a4d78d36f6
commit
b749d43415
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
||||
zig-out
|
||||
zig-cache
|
||||
dbg.rdbg
|
||||
.vs
|
||||
|
@ -1,9 +1,31 @@
|
||||
#version 450 core
|
||||
|
||||
layout(location = 0) in vec3 normal;
|
||||
#define MAX_POINT_LIGHTS 1
|
||||
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in vec3 normal;
|
||||
|
||||
struct Light {
|
||||
vec4 pos;
|
||||
// vec4 color;
|
||||
};
|
||||
|
||||
layout(binding = 1, std140) uniform Lights {
|
||||
Light lights[MAX_POINT_LIGHTS];
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
FragColor = vec4(0.2, 0.5, 0.2, 1.0f);
|
||||
vec3 diffuseColor = vec3(0.2, 0.5, 0.2);
|
||||
vec3 finalColor = vec3(0);
|
||||
|
||||
for (int i = 0; i < MAX_POINT_LIGHTS; i++) {
|
||||
vec3 lightVec = normalize(lights[i].pos.xyz - position);
|
||||
float ndotl = dot(normal, lightVec);
|
||||
|
||||
finalColor += ndotl * diffuseColor;
|
||||
}
|
||||
|
||||
FragColor = vec4(finalColor, 1.0f);
|
||||
}
|
||||
|
@ -3,7 +3,8 @@
|
||||
layout(location = 0) in vec3 aPos;
|
||||
layout(location = 1) in vec3 aNorm;
|
||||
|
||||
layout(location = 0) out vec3 normal;
|
||||
layout(location = 0) out vec3 position;
|
||||
layout(location = 1) out vec3 normal;
|
||||
|
||||
layout(std140, binding = 0) uniform Matrices {
|
||||
mat4 projection;
|
||||
@ -14,5 +15,7 @@ layout(location = 1) uniform mat4 model;
|
||||
|
||||
void main() {
|
||||
gl_Position = projection * view * model * vec4(aPos.xyz, 1.0);
|
||||
vec4 posWorld = model * vec4(aPos, 1.0);
|
||||
position = posWorld.xyz / posWorld.w;
|
||||
normal = aNorm;
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ pub fn build(b: *Build) void {
|
||||
.optimize = .ReleaseSafe,
|
||||
})) |sdl_dep| {
|
||||
const sdl2 = sdl_dep.artifact("SDL2");
|
||||
b.getInstallStep().dependOn(&b.addInstallArtifact(sdl2, .{ .dest_dir = .{ .override = .prefix } }).step);
|
||||
lib.linkLibrary(sdl2);
|
||||
exe.linkLibrary(sdl2);
|
||||
}
|
||||
|
@ -273,6 +273,7 @@ fn loadMeshErr(self: *AssetManager, id: AssetId) !*const LoadedMesh {
|
||||
};
|
||||
|
||||
try self.loaded_assets.put(self.allocator, id, .{ .mesh = loaded_mesh });
|
||||
try self.modified_times.put(self.allocator, id, data.modified);
|
||||
return &self.loaded_assets.getPtr(id).?.mesh;
|
||||
}
|
||||
|
||||
|
415
src/game.zig
415
src/game.zig
@ -7,7 +7,9 @@ const formats = @import("formats.zig");
|
||||
const za = @import("zalgebra");
|
||||
const Vec2 = za.Vec2;
|
||||
const Vec3 = za.Vec3;
|
||||
const Vec4 = za.Vec4;
|
||||
const Mat4 = za.Mat4;
|
||||
const Quat = za.Quat;
|
||||
const a = @import("asset_manifest");
|
||||
const windows = std.os.windows;
|
||||
|
||||
@ -26,9 +28,14 @@ pub extern "gdi32" fn D3DKMTWaitForVerticalBlankEvent(event: *const D3DKMT_WAITF
|
||||
|
||||
const FRAME_ARENA_SIZE = 1024 * 1024 * 512;
|
||||
|
||||
const MAX_FRAMES_QUEUED = 3;
|
||||
|
||||
const DEFAULT_WIDTH = 800;
|
||||
const DEFAULT_HEIGHT = 600;
|
||||
|
||||
const MAX_ENTITIES = 1024;
|
||||
const MAX_POINT_LIGHTS = 1;
|
||||
|
||||
// TODO: move out into renderer file maybe
|
||||
const Attrib = enum(gl.GLuint) {
|
||||
Position = 0,
|
||||
@ -40,6 +47,7 @@ const Attrib = enum(gl.GLuint) {
|
||||
};
|
||||
const UBO = enum(gl.GLuint) {
|
||||
CameraMatrices = 0,
|
||||
PointLights = 1,
|
||||
|
||||
pub inline fn value(self: UBO) gl.GLuint {
|
||||
return @intFromEnum(self);
|
||||
@ -55,6 +63,93 @@ pub const InitMemory = struct {
|
||||
syswm_info: c.SDL_SysWMinfo = .{},
|
||||
};
|
||||
|
||||
pub const Entity = struct {
|
||||
pub const Flags = packed struct {
|
||||
active: bool = false,
|
||||
mesh: bool = false,
|
||||
point_light: bool = false,
|
||||
};
|
||||
|
||||
pub const Transform = struct {
|
||||
pos: Vec3 = Vec3.zero(),
|
||||
rot: Quat = Quat.identity(),
|
||||
scale: Vec3 = Vec3.one(),
|
||||
|
||||
pub fn matrix(self: *Transform) Mat4 {
|
||||
// TODO: cache
|
||||
return Mat4.recompose(self.pos, self.rot, self.scale);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Mesh = struct {
|
||||
handle: AssetManager.Handle.Mesh = .{},
|
||||
};
|
||||
|
||||
pub const PointLight = struct {
|
||||
color: Vec4 = Vec4.one(),
|
||||
};
|
||||
|
||||
// Entity list and handle management
|
||||
idx: u32 = 0,
|
||||
gen: u32 = 0,
|
||||
// Free list
|
||||
next: ?*Entity = null,
|
||||
|
||||
flags: Flags = .{},
|
||||
transform: Transform = .{},
|
||||
mesh: Mesh = .{},
|
||||
point_light: PointLight = .{},
|
||||
};
|
||||
|
||||
pub const EntityHandle = packed struct {
|
||||
idx: u32,
|
||||
gen: u32,
|
||||
};
|
||||
|
||||
pub const World = struct {
|
||||
entities: [MAX_ENTITIES]Entity = [_]Entity{.{}} ** MAX_ENTITIES,
|
||||
entity_count: usize = 0,
|
||||
free_entity: ?*Entity = null,
|
||||
|
||||
pub fn addEntity(self: *World, entity: Entity) EntityHandle {
|
||||
const ent = result: {
|
||||
if (self.free_entity) |ent| {
|
||||
break :result ent;
|
||||
} else {
|
||||
const new_entity = &self.entities[self.entity_count];
|
||||
new_entity.idx = @intCast(self.entity_count);
|
||||
self.entity_count += 1;
|
||||
break :result new_entity;
|
||||
}
|
||||
};
|
||||
const next = ent.next;
|
||||
const gen = ent.gen;
|
||||
const idx = ent.idx;
|
||||
ent.* = entity;
|
||||
ent.gen = gen + 1;
|
||||
ent.idx = idx;
|
||||
ent.flags.active = true;
|
||||
self.free_entity = next;
|
||||
|
||||
return EntityHandle{ .idx = idx, .gen = ent.gen };
|
||||
}
|
||||
|
||||
pub fn getEntity(self: *World, handle: EntityHandle) ?*Entity {
|
||||
const ent = &self.entities[handle.idx];
|
||||
if (ent.gen != handle.gen) {
|
||||
return null;
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
pub fn removeEntity(self: *World, handle: EntityHandle) void {
|
||||
const ent = self.getEntity(handle) orelse return;
|
||||
ent.flags.active = false;
|
||||
ent.next = self.free_entity;
|
||||
self.free_entity = ent;
|
||||
}
|
||||
};
|
||||
|
||||
pub const GameMemory = struct {
|
||||
global_allocator: std.mem.Allocator,
|
||||
frame_fba: std.heap.FixedBufferAllocator,
|
||||
@ -63,13 +158,17 @@ pub const GameMemory = struct {
|
||||
last_frame_time: u64 = 0,
|
||||
delta_time: f32 = 0.0000001,
|
||||
mesh_vao: gl.GLuint = 0,
|
||||
tripple_buffer_index: usize = MAX_FRAMES_QUEUED - 1,
|
||||
gl_fences: [MAX_FRAMES_QUEUED]?gl.GLsync = [_]?gl.GLsync{null} ** MAX_FRAMES_QUEUED,
|
||||
camera_ubo: gl.GLuint = 0,
|
||||
camera_matrices: []CameraMatrices = &.{},
|
||||
current_camera_matrix: usize = 0,
|
||||
point_lights_ubo: gl.GLuint = 0,
|
||||
point_lights: []RenderPointLightArray = &.{},
|
||||
rotation: f32 = 0,
|
||||
input_state: InputState = .{},
|
||||
free_cam: FreeLookCamera = .{},
|
||||
mouse_focus: bool = false,
|
||||
world: World = .{},
|
||||
};
|
||||
|
||||
pub const InputState = packed struct {
|
||||
@ -126,7 +225,7 @@ fn game_init_window_err(global_allocator: std.mem.Allocator) !void {
|
||||
c.SDL_WINDOWPOS_UNDEFINED,
|
||||
DEFAULT_WIDTH,
|
||||
DEFAULT_HEIGHT,
|
||||
c.SDL_WINDOW_SHOWN | c.SDL_WINDOW_OPENGL | c.SDL_WINDOW_ALLOW_HIGHDPI,
|
||||
c.SDL_WINDOW_SHOWN | c.SDL_WINDOW_OPENGL | c.SDL_WINDOW_ALLOW_HIGHDPI | c.SDL_WINDOW_RESIZABLE,
|
||||
);
|
||||
if (maybe_window == null) {
|
||||
std.log.err("SDL Error: {s}", .{c.SDL_GetError()});
|
||||
@ -232,9 +331,12 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
gl.viewport(0, 0, g_init.width, g_init.height);
|
||||
|
||||
// MESH PROGRAM
|
||||
const mesh_program_name = g_assetman.resolveShaderProgram(mesh_program).program;
|
||||
// const mesh_program_name = g_assetman.resolveShaderProgram(mesh_program).program;
|
||||
|
||||
gl.uniformBlockBinding(mesh_program_name, 0, UBO.CameraMatrices.value());
|
||||
// !NOTE: IMPORTANT: never do this again, it messes up ubo block bindings
|
||||
|
||||
// gl.uniformBlockBinding(mesh_program_name, 0, UBO.CameraMatrices.value());
|
||||
// gl.uniformBlockBinding(mesh_program_name, 1, UBO.PointLights.value());
|
||||
|
||||
// MESH VAO
|
||||
var vao: gl.GLuint = 0;
|
||||
@ -254,36 +356,93 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
gl.vertexArrayAttribFormat(vao, Attrib.Normal.value(), 3, gl.FLOAT, gl.FALSE, 0);
|
||||
gl.enableVertexArrayAttrib(vao, Attrib.Normal.value());
|
||||
|
||||
var camera_ubo: gl.GLuint = 0;
|
||||
gl.createBuffers(1, &camera_ubo);
|
||||
|
||||
const CAMERA_MATRICES_COUNT = 120;
|
||||
const PERSISTENT_BUFFER_FLAGS: gl.GLbitfield = gl.MAP_PERSISTENT_BIT | gl.MAP_WRITE_BIT | gl.MAP_COHERENT_BIT;
|
||||
gl.namedBufferStorage(
|
||||
camera_ubo,
|
||||
@sizeOf(CameraMatrices) * CAMERA_MATRICES_COUNT,
|
||||
null,
|
||||
PERSISTENT_BUFFER_FLAGS,
|
||||
);
|
||||
const camera_matrices_c: [*c]CameraMatrices = @alignCast(@ptrCast(gl.mapNamedBufferRange(camera_ubo, 0, @sizeOf(CameraMatrices) * CAMERA_MATRICES_COUNT, PERSISTENT_BUFFER_FLAGS) orelse {
|
||||
checkGLError();
|
||||
@panic("bind camera_ubo");
|
||||
}));
|
||||
const camera_matrices = camera_matrices_c[0..CAMERA_MATRICES_COUNT];
|
||||
g_mem.camera_ubo = camera_ubo;
|
||||
g_mem.camera_matrices = camera_matrices;
|
||||
|
||||
// Camera matrices ubo
|
||||
{
|
||||
var camera_ubo: gl.GLuint = 0;
|
||||
gl.createBuffers(1, &camera_ubo);
|
||||
|
||||
gl.namedBufferStorage(
|
||||
camera_ubo,
|
||||
@sizeOf(CameraMatrices) * MAX_FRAMES_QUEUED,
|
||||
null,
|
||||
PERSISTENT_BUFFER_FLAGS,
|
||||
);
|
||||
const camera_matrices_c: [*c]CameraMatrices = @alignCast(@ptrCast(gl.mapNamedBufferRange(camera_ubo, 0, @sizeOf(CameraMatrices) * MAX_FRAMES_QUEUED, PERSISTENT_BUFFER_FLAGS) orelse {
|
||||
checkGLError();
|
||||
@panic("bind camera_ubo");
|
||||
}));
|
||||
const camera_matrices = camera_matrices_c[0..MAX_FRAMES_QUEUED];
|
||||
g_mem.camera_ubo = camera_ubo;
|
||||
g_mem.camera_matrices = camera_matrices;
|
||||
}
|
||||
|
||||
// Point lights ubo
|
||||
{
|
||||
var point_lights_ubo: gl.GLuint = 0;
|
||||
gl.createBuffers(1, &point_lights_ubo);
|
||||
|
||||
gl.namedBufferStorage(
|
||||
point_lights_ubo,
|
||||
@sizeOf(RenderPointLightArray) * MAX_FRAMES_QUEUED,
|
||||
null,
|
||||
PERSISTENT_BUFFER_FLAGS,
|
||||
);
|
||||
const point_lights_c: [*c]RenderPointLightArray = @alignCast(@ptrCast(gl.mapNamedBufferRange(
|
||||
point_lights_ubo,
|
||||
0,
|
||||
@sizeOf(RenderPointLightArray) * MAX_FRAMES_QUEUED,
|
||||
PERSISTENT_BUFFER_FLAGS,
|
||||
) orelse {
|
||||
checkGLError();
|
||||
@panic("bind point_lights_ubo");
|
||||
}));
|
||||
const point_lights = point_lights_c[0..MAX_FRAMES_QUEUED];
|
||||
g_mem.point_lights_ubo = point_lights_ubo;
|
||||
g_mem.point_lights = point_lights;
|
||||
}
|
||||
|
||||
_ = g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(0, 1, 0) },
|
||||
.flags = .{ .point_light = true },
|
||||
.point_light = .{ .color = Vec4.new(1.0, 0.5, 0.2, 1.0) },
|
||||
});
|
||||
|
||||
// 10 bunnies
|
||||
{
|
||||
for (0..10) |i| {
|
||||
_ = g_mem.world.addEntity(.{
|
||||
.transform = .{ .pos = Vec3.new(@floatFromInt(i * 1), 0, 0) },
|
||||
|
||||
.flags = .{ .mesh = true },
|
||||
.mesh = .{ .handle = a.Meshes.bunny },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move this out into a renderer
|
||||
// Should be std140
|
||||
const CameraMatrices = extern struct {
|
||||
projection: za.Mat4,
|
||||
view: za.Mat4,
|
||||
pub const CameraMatrices = extern struct {
|
||||
projection: Mat4,
|
||||
view: Mat4,
|
||||
};
|
||||
pub const RenderPointLight = extern struct {
|
||||
pos: Vec4, // it's vec3, but glsl std140 requires 16 byte alignment anyway
|
||||
// color: Vec4,
|
||||
};
|
||||
|
||||
pub const RenderPointLightArray = extern struct {
|
||||
lights: [MAX_POINT_LIGHTS]RenderPointLight,
|
||||
};
|
||||
|
||||
export fn game_update() bool {
|
||||
const ginit = g_init;
|
||||
const gmem = g_mem;
|
||||
// std.debug.print("FPS: {d}\n", .{1.0 / g_mem.delta_time});
|
||||
|
||||
g_mem.frame_fba.reset();
|
||||
gmem.frame_fba.reset();
|
||||
var event: c.SDL_Event = undefined;
|
||||
|
||||
var move = Vec3.zero();
|
||||
@ -295,16 +454,16 @@ export fn game_update() bool {
|
||||
return false;
|
||||
},
|
||||
c.SDL_MOUSEMOTION => {
|
||||
if (g_mem.mouse_focus) {
|
||||
if (gmem.mouse_focus) {
|
||||
look.xMut().* += @floatFromInt(event.motion.xrel);
|
||||
look.yMut().* += @floatFromInt(event.motion.yrel);
|
||||
}
|
||||
},
|
||||
c.SDL_MOUSEBUTTONUP => {
|
||||
if (!g_mem.mouse_focus) {
|
||||
if (!gmem.mouse_focus) {
|
||||
_ = c.SDL_SetRelativeMouseMode(c.SDL_TRUE);
|
||||
|
||||
g_mem.mouse_focus = true;
|
||||
gmem.mouse_focus = true;
|
||||
}
|
||||
},
|
||||
c.SDL_KEYUP, c.SDL_KEYDOWN => {
|
||||
@ -312,31 +471,31 @@ export fn game_update() bool {
|
||||
switch (event.key.keysym.scancode) {
|
||||
c.SDL_SCANCODE_ESCAPE => {
|
||||
if (event.type == c.SDL_KEYUP) {
|
||||
if (g_mem.mouse_focus) {
|
||||
if (gmem.mouse_focus) {
|
||||
_ = c.SDL_SetRelativeMouseMode(c.SDL_FALSE);
|
||||
g_mem.mouse_focus = false;
|
||||
gmem.mouse_focus = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
c.SDL_SCANCODE_W => {
|
||||
g_mem.input_state.forward = pressed;
|
||||
gmem.input_state.forward = pressed;
|
||||
},
|
||||
c.SDL_SCANCODE_S => {
|
||||
g_mem.input_state.backward = pressed;
|
||||
gmem.input_state.backward = pressed;
|
||||
},
|
||||
c.SDL_SCANCODE_A => {
|
||||
g_mem.input_state.left = pressed;
|
||||
gmem.input_state.left = pressed;
|
||||
},
|
||||
c.SDL_SCANCODE_D => {
|
||||
g_mem.input_state.right = pressed;
|
||||
gmem.input_state.right = pressed;
|
||||
},
|
||||
c.SDL_SCANCODE_SPACE => {
|
||||
g_mem.input_state.up = pressed;
|
||||
gmem.input_state.up = pressed;
|
||||
},
|
||||
c.SDL_SCANCODE_LSHIFT => {
|
||||
g_mem.input_state.down = pressed;
|
||||
gmem.input_state.down = pressed;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@ -344,11 +503,11 @@ export fn game_update() bool {
|
||||
c.SDL_WINDOWEVENT => {
|
||||
switch (event.window.event) {
|
||||
c.SDL_WINDOWEVENT_SIZE_CHANGED => {
|
||||
g_init.width = event.window.data1;
|
||||
g_init.height = event.window.data2;
|
||||
std.log.debug("w: {}, h: {}\n", .{ g_init.width, g_init.height });
|
||||
ginit.width = event.window.data1;
|
||||
ginit.height = event.window.data2;
|
||||
std.log.debug("w: {}, h: {}\n", .{ ginit.width, ginit.height });
|
||||
|
||||
gl.viewport(0, 0, g_init.width, g_init.height);
|
||||
gl.viewport(0, 0, ginit.width, ginit.height);
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
@ -358,85 +517,164 @@ export fn game_update() bool {
|
||||
}
|
||||
|
||||
const now = c.SDL_GetPerformanceCounter();
|
||||
g_mem.delta_time = @as(f32, @floatFromInt((now - g_mem.last_frame_time))) / @as(f32, @floatFromInt(g_mem.performance_frequency));
|
||||
g_mem.last_frame_time = now;
|
||||
gmem.delta_time = @as(f32, @floatFromInt((now - gmem.last_frame_time))) / @as(f32, @floatFromInt(gmem.performance_frequency));
|
||||
gmem.last_frame_time = now;
|
||||
|
||||
const MOVEMENT_SPEED = 0.5;
|
||||
if (g_mem.input_state.forward) {
|
||||
if (gmem.input_state.forward) {
|
||||
//const y = &move.data[1];
|
||||
move.yMut().* += 1;
|
||||
}
|
||||
if (g_mem.input_state.backward) {
|
||||
if (gmem.input_state.backward) {
|
||||
move.yMut().* -= 1;
|
||||
}
|
||||
if (g_mem.input_state.left) {
|
||||
if (gmem.input_state.left) {
|
||||
move.xMut().* -= 1;
|
||||
}
|
||||
if (g_mem.input_state.right) {
|
||||
if (gmem.input_state.right) {
|
||||
move.xMut().* += 1;
|
||||
}
|
||||
if (g_mem.input_state.up) {
|
||||
if (gmem.input_state.up) {
|
||||
move.zMut().* += 1;
|
||||
}
|
||||
if (g_mem.input_state.down) {
|
||||
if (gmem.input_state.down) {
|
||||
move.zMut().* -= 1;
|
||||
}
|
||||
|
||||
move = move.scale(MOVEMENT_SPEED * g_mem.delta_time);
|
||||
move = move.scale(MOVEMENT_SPEED * gmem.delta_time);
|
||||
|
||||
g_mem.free_cam.update(move, look.scale(0.008));
|
||||
gmem.free_cam.update(move, look.scale(0.008));
|
||||
|
||||
// RENDER
|
||||
// gl.fenceSync(_condition: GLenum, _flags: GLbitfield)
|
||||
|
||||
const f_width: f32 = @floatFromInt(g_init.width);
|
||||
const f_height: f32 = @floatFromInt(g_init.height);
|
||||
g_mem.current_camera_matrix = (g_mem.current_camera_matrix + 1) % g_mem.camera_matrices.len;
|
||||
const camera_matrix = &g_mem.camera_matrices[g_mem.current_camera_matrix];
|
||||
const f_width: f32 = @floatFromInt(ginit.width);
|
||||
const f_height: f32 = @floatFromInt(ginit.height);
|
||||
gmem.tripple_buffer_index = (gmem.tripple_buffer_index + 1) % MAX_FRAMES_QUEUED;
|
||||
|
||||
camera_matrix.* = .{
|
||||
.projection = Mat4.perspective(
|
||||
30,
|
||||
f_width / f_height,
|
||||
0.1,
|
||||
100.0,
|
||||
),
|
||||
.view = g_mem.free_cam.view_matrix,
|
||||
};
|
||||
gl.enable(gl.CULL_FACE);
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||||
|
||||
gl.useProgram(g_assetman.resolveShaderProgram(a.ShaderPrograms.mesh).program);
|
||||
gl.bindVertexArray(g_mem.mesh_vao);
|
||||
gl.bindVertexArray(gmem.mesh_vao);
|
||||
|
||||
gl.bindBufferRange(
|
||||
gl.UNIFORM_BUFFER,
|
||||
UBO.CameraMatrices.value(),
|
||||
g_mem.camera_ubo,
|
||||
g_mem.current_camera_matrix * @sizeOf(CameraMatrices),
|
||||
@sizeOf(CameraMatrices),
|
||||
);
|
||||
g_mem.rotation += 0.5 * g_mem.delta_time;
|
||||
gl.uniformMatrix4fv(1, 1, gl.FALSE, @ptrCast(&Mat4.fromRotation(g_mem.rotation, Vec3.up()).data));
|
||||
if (gmem.gl_fences[gmem.tripple_buffer_index]) |fence| {
|
||||
const syncResult = gl.clientWaitSync(fence, gl.SYNC_FLUSH_COMMANDS_BIT, 9999999);
|
||||
|
||||
const mesh = g_assetman.resolveMesh(a.Meshes.bunny);
|
||||
mesh.positions.bind(Attrib.Position.value());
|
||||
mesh.normals.bind(Attrib.Normal.value());
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer);
|
||||
gl.drawElements(
|
||||
gl.TRIANGLES,
|
||||
mesh.indices.count,
|
||||
mesh.indices.type,
|
||||
@ptrFromInt(mesh.indices.offset),
|
||||
);
|
||||
switch (syncResult) {
|
||||
gl.ALREADY_SIGNALED => {
|
||||
// awesome
|
||||
},
|
||||
gl.TIMEOUT_EXPIRED => {
|
||||
// oh no, driver will crash soon :(
|
||||
std.log.err("OpenGL clientWaitSync timeout expired D:\n", .{});
|
||||
},
|
||||
gl.CONDITION_SATISFIED => {
|
||||
// awesome
|
||||
},
|
||||
gl.WAIT_FAILED => {
|
||||
checkGLError();
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
gl.deleteSync(fence);
|
||||
gmem.gl_fences[gmem.tripple_buffer_index] = null;
|
||||
}
|
||||
|
||||
c.SDL_GL_SwapWindow(g_init.window);
|
||||
DwmFlush();
|
||||
gmem.gl_fences[gmem.tripple_buffer_index] = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
{
|
||||
const camera_matrix = &gmem.camera_matrices[gmem.tripple_buffer_index];
|
||||
|
||||
camera_matrix.* = .{
|
||||
.projection = Mat4.perspective(
|
||||
60,
|
||||
f_width / f_height,
|
||||
0.1,
|
||||
100.0,
|
||||
),
|
||||
.view = gmem.free_cam.view_matrix,
|
||||
};
|
||||
|
||||
gl.bindBufferRange(
|
||||
gl.UNIFORM_BUFFER,
|
||||
UBO.CameraMatrices.value(),
|
||||
gmem.camera_ubo,
|
||||
gmem.tripple_buffer_index * @sizeOf(CameraMatrices),
|
||||
@sizeOf(CameraMatrices),
|
||||
);
|
||||
}
|
||||
|
||||
// Collect point lights
|
||||
{
|
||||
const point_lights = &gmem.point_lights[gmem.tripple_buffer_index];
|
||||
var point_lights_count: usize = 0;
|
||||
|
||||
for (0..gmem.world.entity_count) |i| {
|
||||
const ent = &gmem.world.entities[i];
|
||||
if (!ent.flags.active) continue;
|
||||
|
||||
if (ent.flags.point_light) {
|
||||
const new_pos = Mat4.fromRotation(
|
||||
gmem.rotation,
|
||||
Vec3.up(),
|
||||
).mulByVec4(Vec4.new(2, 1, 0, 1));
|
||||
ent.transform.pos = Vec3.new(new_pos.x(), new_pos.y(), new_pos.z());
|
||||
|
||||
point_lights.lights[point_lights_count] = .{
|
||||
.pos = new_pos,
|
||||
// .color = ent.point_light.color,
|
||||
};
|
||||
point_lights_count += 1;
|
||||
if (point_lights_count == point_lights.lights.len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gl.flushMappedNamedBufferRange(
|
||||
// gmem.point_lights_ubo,
|
||||
// gmem.tripple_buffer_index * @sizeOf(RenderPointLightArray),
|
||||
// @sizeOf(RenderPointLightArray),
|
||||
// );
|
||||
|
||||
gl.bindBufferRange(
|
||||
gl.UNIFORM_BUFFER,
|
||||
UBO.PointLights.value(),
|
||||
gmem.point_lights_ubo,
|
||||
gmem.tripple_buffer_index * @sizeOf(RenderPointLightArray),
|
||||
@sizeOf(RenderPointLightArray),
|
||||
);
|
||||
}
|
||||
|
||||
gmem.rotation += 60 * gmem.delta_time;
|
||||
|
||||
// Render meshes
|
||||
for (0..gmem.world.entity_count) |i| {
|
||||
const ent = &gmem.world.entities[i];
|
||||
if (!ent.flags.active or !ent.flags.mesh) continue;
|
||||
|
||||
gl.uniformMatrix4fv(1, 1, gl.FALSE, @ptrCast(&ent.transform.matrix().data));
|
||||
|
||||
const mesh = g_assetman.resolveMesh(ent.mesh.handle);
|
||||
mesh.positions.bind(Attrib.Position.value());
|
||||
mesh.normals.bind(Attrib.Normal.value());
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.indices.buffer);
|
||||
gl.drawElements(
|
||||
gl.TRIANGLES,
|
||||
mesh.indices.count,
|
||||
mesh.indices.type,
|
||||
@ptrFromInt(mesh.indices.offset),
|
||||
);
|
||||
}
|
||||
|
||||
c.SDL_GL_SwapWindow(ginit.window);
|
||||
// DwmFlush();
|
||||
// const vblank_event: D3DKMT_WAITFORVERTICALBLANKEVENT = .{
|
||||
// .hAdapter = 0,
|
||||
// .hDevice = g_init.syswm_info.info.win.hdc.*,
|
||||
// .hDevice = ginit.syswm_info.info.win.hdc.*,
|
||||
// .VidPnSourceId = 0,
|
||||
// };
|
||||
// switch (D3DKMTWaitForVerticalBlankEvent(&vblank_event)) {
|
||||
@ -455,9 +693,10 @@ export fn game_update() bool {
|
||||
}
|
||||
|
||||
export fn game_shutdown() void {
|
||||
const gmem = g_mem;
|
||||
std.log.debug("game_shutdown\n", .{});
|
||||
g_mem.global_allocator.free(g_mem.frame_fba.buffer);
|
||||
g_mem.global_allocator.destroy(g_mem);
|
||||
gmem.global_allocator.free(gmem.frame_fba.buffer);
|
||||
gmem.global_allocator.destroy(gmem);
|
||||
}
|
||||
|
||||
export fn game_shutdown_window() void {
|
||||
|
Loading…
x
Reference in New Issue
Block a user