Refactor lights
This commit is contained in:
parent
f1123a1e15
commit
6b4fe69505
198
src/Render.zig
198
src/Render.zig
@ -16,8 +16,9 @@ const Quat = za.Quat;
|
|||||||
const Vec2_i32 = za.Vec2_i32;
|
const Vec2_i32 = za.Vec2_i32;
|
||||||
|
|
||||||
pub const MAX_FRAMES_QUEUED = 3;
|
pub const MAX_FRAMES_QUEUED = 3;
|
||||||
pub const MAX_POINT_LIGHTS = 8;
|
pub const MAX_LIGHTS = 8;
|
||||||
pub const MAX_DRAW_COMMANDS = 4096;
|
pub const MAX_DRAW_COMMANDS = 4096;
|
||||||
|
pub const MAX_LIGHT_COMMANDS = 2048;
|
||||||
|
|
||||||
pub const Render = @This();
|
pub const Render = @This();
|
||||||
|
|
||||||
@ -33,7 +34,9 @@ gl_fences: [MAX_FRAMES_QUEUED]?gl.GLsync = [_]?gl.GLsync{null} ** MAX_FRAMES_QUE
|
|||||||
camera_ubo: gl.GLuint = 0,
|
camera_ubo: gl.GLuint = 0,
|
||||||
camera_matrices: []u8 = &.{},
|
camera_matrices: []u8 = &.{},
|
||||||
point_lights_ubo: gl.GLuint = 0,
|
point_lights_ubo: gl.GLuint = 0,
|
||||||
point_lights: []u8 = &.{},
|
point_lights: []u8 = &.{}, // TODO: remove
|
||||||
|
lights: [MAX_LIGHT_COMMANDS]LightCommand = undefined,
|
||||||
|
light_count: usize = 0,
|
||||||
command_buffer: [MAX_DRAW_COMMANDS]DrawCommand = undefined,
|
command_buffer: [MAX_DRAW_COMMANDS]DrawCommand = undefined,
|
||||||
command_count: usize = 0,
|
command_count: usize = 0,
|
||||||
ubo_align: usize = 0,
|
ubo_align: usize = 0,
|
||||||
@ -136,7 +139,7 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
|
|||||||
gl.createBuffers(1, &render.point_lights_ubo);
|
gl.createBuffers(1, &render.point_lights_ubo);
|
||||||
std.debug.assert(render.camera_ubo != 0);
|
std.debug.assert(render.camera_ubo != 0);
|
||||||
|
|
||||||
const buf_size = render.uboAlignedSizeOf(PointLightArray) * MAX_FRAMES_QUEUED;
|
const buf_size = render.uboAlignedSizeOf(LightArray) * MAX_FRAMES_QUEUED;
|
||||||
gl.namedBufferStorage(
|
gl.namedBufferStorage(
|
||||||
render.point_lights_ubo,
|
render.point_lights_ubo,
|
||||||
@intCast(buf_size),
|
@intCast(buf_size),
|
||||||
@ -193,7 +196,7 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
|
|||||||
checkGLError();
|
checkGLError();
|
||||||
std.debug.assert(render.cube_shadow_texture_array != 0);
|
std.debug.assert(render.cube_shadow_texture_array != 0);
|
||||||
|
|
||||||
gl.textureStorage3D(render.cube_shadow_texture_array, 1, gl.DEPTH_COMPONENT16, 512, 512, MAX_POINT_LIGHTS * 6);
|
gl.textureStorage3D(render.cube_shadow_texture_array, 1, gl.DEPTH_COMPONENT16, 512, 512, MAX_LIGHTS * 6);
|
||||||
checkGLError();
|
checkGLError();
|
||||||
|
|
||||||
gl.textureParameteri(render.cube_shadow_texture_array, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
|
gl.textureParameteri(render.cube_shadow_texture_array, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
|
||||||
@ -346,6 +349,7 @@ fn updateScreenBufferSize(self: *Render, width: c_int, height: c_int) void {
|
|||||||
|
|
||||||
pub fn begin(self: *Render) void {
|
pub fn begin(self: *Render) void {
|
||||||
self.command_count = 0;
|
self.command_count = 0;
|
||||||
|
self.light_count = 0;
|
||||||
self.tripple_buffer_index = (self.tripple_buffer_index + 1) % MAX_FRAMES_QUEUED;
|
self.tripple_buffer_index = (self.tripple_buffer_index + 1) % MAX_FRAMES_QUEUED;
|
||||||
|
|
||||||
gl.enable(gl.CULL_FACE);
|
gl.enable(gl.CULL_FACE);
|
||||||
@ -375,10 +379,11 @@ pub fn begin(self: *Render) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getPointLights(self: *Render) *PointLightArray {
|
fn getLightBuffer(self: *Render) *LightArray {
|
||||||
return @alignCast(@ptrCast(self.point_lights[self.tripple_buffer_index * self.uboAlignedSizeOf(PointLightArray) ..].ptr));
|
return @alignCast(@ptrCast(self.point_lights[self.tripple_buffer_index * self.uboAlignedSizeOf(LightArray) ..].ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: get rid of this
|
||||||
pub fn flushUBOs(self: *Render) void {
|
pub fn flushUBOs(self: *Render) void {
|
||||||
const idx = self.tripple_buffer_index;
|
const idx = self.tripple_buffer_index;
|
||||||
|
|
||||||
@ -387,12 +392,37 @@ pub fn flushUBOs(self: *Render) void {
|
|||||||
gl.UNIFORM_BUFFER,
|
gl.UNIFORM_BUFFER,
|
||||||
UBO.PointLights.value(),
|
UBO.PointLights.value(),
|
||||||
self.point_lights_ubo,
|
self.point_lights_ubo,
|
||||||
idx * self.uboAlignedSizeOf(PointLightArray),
|
idx * self.uboAlignedSizeOf(LightArray),
|
||||||
@intCast(self.uboAlignedSizeOf(PointLightArray)),
|
@intCast(self.uboAlignedSizeOf(LightArray)),
|
||||||
);
|
);
|
||||||
checkGLError();
|
checkGLError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const LightKind = enum {
|
||||||
|
directional,
|
||||||
|
point,
|
||||||
|
// Spot, // TODO
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PointLight = struct {
|
||||||
|
color: Vec3,
|
||||||
|
pos: Vec3,
|
||||||
|
radius: f32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const LightCommand = union(LightKind) {
|
||||||
|
directional: struct {
|
||||||
|
color: Vec3,
|
||||||
|
dir: Vec3,
|
||||||
|
},
|
||||||
|
point: PointLight,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
||||||
|
self.lights[self.light_count] = cmd;
|
||||||
|
self.light_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw(self: *Render, cmd: DrawCommand) void {
|
pub fn draw(self: *Render, cmd: DrawCommand) void {
|
||||||
self.command_buffer[self.command_count] = cmd;
|
self.command_buffer[self.command_count] = cmd;
|
||||||
self.command_count += 1;
|
self.command_count += 1;
|
||||||
@ -401,79 +431,64 @@ pub fn draw(self: *Render, cmd: DrawCommand) void {
|
|||||||
pub fn finish(self: *Render) void {
|
pub fn finish(self: *Render) void {
|
||||||
const ginit = globals.g_init;
|
const ginit = globals.g_init;
|
||||||
|
|
||||||
const lights = self.getPointLights();
|
const lights = self.lights[0..self.light_count];
|
||||||
|
|
||||||
|
// Sort lights: directional first
|
||||||
|
{
|
||||||
|
std.mem.sortUnstable(LightCommand, lights, {}, struct {
|
||||||
|
pub fn lessThan(_: void, lhs: LightCommand, rhs: LightCommand) bool {
|
||||||
|
_ = rhs; // autofix
|
||||||
|
return switch (lhs) {
|
||||||
|
.directional => true,
|
||||||
|
.point => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}.lessThan);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lights_buf = self.getLightBuffer();
|
||||||
|
lights_buf.count = 0;
|
||||||
|
|
||||||
// Light shadow maps
|
// Light shadow maps
|
||||||
{
|
{
|
||||||
gl.bindVertexArray(self.shadow_vao);
|
gl.bindVertexArray(self.shadow_vao);
|
||||||
|
|
||||||
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, self.shadow_framebuffer);
|
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, self.shadow_framebuffer);
|
||||||
|
|
||||||
for (lights.lights[0..lights.count], 0..) |*light, i| {
|
var finished_dir_lights = false;
|
||||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.shadow).program);
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.shadow).program);
|
||||||
// Directional light
|
|
||||||
if (std.math.approxEqAbs(f32, light.pos.w(), 0, std.math.floatEps(f32))) {
|
|
||||||
gl.namedFramebufferTextureLayer(self.shadow_framebuffer, gl.DEPTH_ATTACHMENT, self.shadow_texture_array, 0, 0);
|
|
||||||
const check_fbo_status = gl.checkNamedFramebufferStatus(self.shadow_framebuffer, gl.DRAW_FRAMEBUFFER);
|
|
||||||
if (check_fbo_status != gl.FRAMEBUFFER_COMPLETE) {
|
|
||||||
std.log.debug("Shadow Framebuffer Incomplete: {}\n", .{check_fbo_status});
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.viewport(0, 0, 2048, 2048);
|
for (lights) |light_cmd| {
|
||||||
|
const i = lights_buf.count;
|
||||||
|
if (i == lights_buf.lights.len) break;
|
||||||
|
|
||||||
const camera_matrix = &self.shadow_matrices;
|
const light = &lights_buf.lights[i];
|
||||||
camera_matrix.* = .{
|
lights_buf.count += 1;
|
||||||
.projection = math.orthographic(-4, 4, -4, 4, -5, 5),
|
|
||||||
.view = Mat4.lookAt(
|
|
||||||
Vec3.new(light.pos.x(), light.pos.y(), light.pos.z()).scale(-1),
|
|
||||||
Vec3.zero(),
|
|
||||||
Vec3.up(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
const shadow_view_proj = camera_matrix.projection.mul(camera_matrix.view);
|
switch (light_cmd) {
|
||||||
const light_frustum = math.Frustum.new(shadow_view_proj);
|
.directional => |dir_light| {
|
||||||
light.shadow_vp = shadow_view_proj;
|
light.pos = dir_light.dir.toVec4(0);
|
||||||
|
light.color_radius = dir_light.color.toVec4(0);
|
||||||
gl.namedBufferSubData(self.shadow_matrices_buffer, 0, @sizeOf(CameraMatrices), std.mem.asBytes(&self.shadow_matrices));
|
gl.namedFramebufferTextureLayer(self.shadow_framebuffer, gl.DEPTH_ATTACHMENT, self.shadow_texture_array, 0, 0);
|
||||||
checkGLError();
|
|
||||||
|
|
||||||
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
||||||
gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer);
|
|
||||||
|
|
||||||
self.renderShadow(&light_frustum);
|
|
||||||
} else {
|
|
||||||
// Point Light
|
|
||||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.cube_shadow).program);
|
|
||||||
|
|
||||||
const pos = Vec3.new(light.pos.x(), light.pos.y(), light.pos.z());
|
|
||||||
light.shadow_vp = Mat4.fromTranslate(pos.negate());
|
|
||||||
// For each cube face
|
|
||||||
for (cube_camera_dirs, 0..) |cam_dir, face| {
|
|
||||||
gl.namedFramebufferTextureLayer(self.shadow_framebuffer, gl.DEPTH_ATTACHMENT, self.cube_shadow_texture_array, 0, @intCast(i * 6 + face));
|
|
||||||
const check_fbo_status = gl.checkNamedFramebufferStatus(self.shadow_framebuffer, gl.DRAW_FRAMEBUFFER);
|
const check_fbo_status = gl.checkNamedFramebufferStatus(self.shadow_framebuffer, gl.DRAW_FRAMEBUFFER);
|
||||||
if (check_fbo_status != gl.FRAMEBUFFER_COMPLETE) {
|
if (check_fbo_status != gl.FRAMEBUFFER_COMPLETE) {
|
||||||
std.log.debug("Shadow Framebuffer Incomplete: {}\n", .{check_fbo_status});
|
std.log.debug("Shadow Framebuffer Incomplete: {}\n", .{check_fbo_status});
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.viewport(0, 0, 512, 512);
|
gl.viewport(0, 0, 2048, 2048);
|
||||||
|
|
||||||
const near_far = Vec2.new(0.1, 10);
|
|
||||||
const camera_matrix = &self.shadow_matrices;
|
const camera_matrix = &self.shadow_matrices;
|
||||||
camera_matrix.* = .{
|
camera_matrix.* = .{
|
||||||
.projection = math.perspective(90, 1, near_far.x(), near_far.y()),
|
.projection = math.orthographic(-4, 4, -4, 4, -5, 5),
|
||||||
.view = Mat4.lookAt(
|
.view = Mat4.lookAt(
|
||||||
pos,
|
dir_light.dir.scale(-1),
|
||||||
pos.add(cam_dir.target),
|
Vec3.zero(),
|
||||||
cam_dir.up,
|
Vec3.up(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const shadow_view_proj = camera_matrix.projection.mul(camera_matrix.view);
|
const shadow_view_proj = camera_matrix.projection.mul(camera_matrix.view);
|
||||||
const light_frustum = math.Frustum.new(shadow_view_proj);
|
const light_frustum = math.Frustum.new(shadow_view_proj);
|
||||||
//light.shadow_vp = shadow_view_proj;
|
light.shadow_vp = shadow_view_proj;
|
||||||
light.near_far = near_far;
|
|
||||||
gl.uniform2f(Uniform.NearFarPlanes.value(), near_far.x(), near_far.y());
|
|
||||||
|
|
||||||
gl.namedBufferSubData(self.shadow_matrices_buffer, 0, @sizeOf(CameraMatrices), std.mem.asBytes(&self.shadow_matrices));
|
gl.namedBufferSubData(self.shadow_matrices_buffer, 0, @sizeOf(CameraMatrices), std.mem.asBytes(&self.shadow_matrices));
|
||||||
checkGLError();
|
checkGLError();
|
||||||
@ -482,13 +497,62 @@ pub fn finish(self: *Render) void {
|
|||||||
gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer);
|
gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer);
|
||||||
|
|
||||||
self.renderShadow(&light_frustum);
|
self.renderShadow(&light_frustum);
|
||||||
}
|
},
|
||||||
|
.point => |point_light| {
|
||||||
|
if (!finished_dir_lights) {
|
||||||
|
finished_dir_lights = true;
|
||||||
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.cube_shadow).program);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pos = point_light.pos;
|
||||||
|
light.pos = pos.toVec4(1);
|
||||||
|
light.color_radius = point_light.color.toVec4(point_light.radius);
|
||||||
|
|
||||||
|
light.shadow_vp = Mat4.fromTranslate(pos.negate());
|
||||||
|
// For each cube face
|
||||||
|
for (cube_camera_dirs, 0..) |cam_dir, face| {
|
||||||
|
gl.namedFramebufferTextureLayer(self.shadow_framebuffer, gl.DEPTH_ATTACHMENT, self.cube_shadow_texture_array, 0, @intCast(i * 6 + face));
|
||||||
|
const check_fbo_status = gl.checkNamedFramebufferStatus(self.shadow_framebuffer, gl.DRAW_FRAMEBUFFER);
|
||||||
|
if (check_fbo_status != gl.FRAMEBUFFER_COMPLETE) {
|
||||||
|
std.log.debug("Shadow Framebuffer Incomplete: {}\n", .{check_fbo_status});
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.viewport(0, 0, 512, 512);
|
||||||
|
|
||||||
|
const range = pointLightRange(&point_light);
|
||||||
|
|
||||||
|
const near_far = Vec2.new(0.1, range);
|
||||||
|
const camera_matrix = &self.shadow_matrices;
|
||||||
|
camera_matrix.* = .{
|
||||||
|
.projection = math.perspective(90, 1, near_far.x(), near_far.y()),
|
||||||
|
.view = Mat4.lookAt(
|
||||||
|
pos,
|
||||||
|
pos.add(cam_dir.target),
|
||||||
|
cam_dir.up,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const shadow_view_proj = camera_matrix.projection.mul(camera_matrix.view);
|
||||||
|
const light_frustum = math.Frustum.new(shadow_view_proj);
|
||||||
|
light.shadow_vp = shadow_view_proj;
|
||||||
|
light.near_far = near_far;
|
||||||
|
gl.uniform2f(Uniform.NearFarPlanes.value(), near_far.x(), near_far.y());
|
||||||
|
|
||||||
|
gl.namedBufferSubData(self.shadow_matrices_buffer, 0, @sizeOf(CameraMatrices), std.mem.asBytes(&self.shadow_matrices));
|
||||||
|
checkGLError();
|
||||||
|
|
||||||
|
gl.clear(gl.DEPTH_BUFFER_BIT);
|
||||||
|
gl.bindBufferBase(gl.UNIFORM_BUFFER, UBO.CameraMatrices.value(), self.shadow_matrices_buffer);
|
||||||
|
|
||||||
|
self.renderShadow(&light_frustum);
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Light world space to view space
|
// Light world space to view space
|
||||||
for (lights.lights[0..lights.count]) |*light| {
|
for (lights_buf.lights[0..lights_buf.count]) |*light| {
|
||||||
light.pos = self.camera.view_mat.mulByVec4(light.pos);
|
light.pos = self.camera.view_mat.mulByVec4(light.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,6 +772,14 @@ pub fn finish(self: *Render) void {
|
|||||||
//c.SDL_Delay(1);
|
//c.SDL_Delay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pointLightRange(self: *const PointLight) f32 {
|
||||||
|
const color = self.color;
|
||||||
|
const light_intensity = @max(color.x(), color.y(), color.z());
|
||||||
|
|
||||||
|
const cutoff = 0.005;
|
||||||
|
return self.radius * (@sqrt(light_intensity / cutoff) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
const CubeCameraDir = struct {
|
const CubeCameraDir = struct {
|
||||||
face: gl.GLenum,
|
face: gl.GLenum,
|
||||||
target: Vec3,
|
target: Vec3,
|
||||||
@ -869,7 +941,7 @@ const CameraMatrices = extern struct {
|
|||||||
projection: Mat4 = Mat4.identity(),
|
projection: Mat4 = Mat4.identity(),
|
||||||
view: Mat4 = Mat4.identity(),
|
view: Mat4 = Mat4.identity(),
|
||||||
};
|
};
|
||||||
pub const PointLight = extern struct {
|
pub const Light = extern struct {
|
||||||
pos: Vec4, // x, y, z, w - vPos
|
pos: Vec4, // x, y, z, w - vPos
|
||||||
color_radius: Vec4, // x, y, z - color, w - radius
|
color_radius: Vec4, // x, y, z - color, w - radius
|
||||||
shadow_vp: Mat4 = Mat4.identity(),
|
shadow_vp: Mat4 = Mat4.identity(),
|
||||||
@ -877,8 +949,8 @@ pub const PointLight = extern struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: rename
|
// TODO: rename
|
||||||
pub const PointLightArray = extern struct {
|
pub const LightArray = extern struct {
|
||||||
lights: [MAX_POINT_LIGHTS]PointLight,
|
lights: [MAX_LIGHTS]Light,
|
||||||
count: c_uint,
|
count: c_uint,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
65
src/game.zig
65
src/game.zig
@ -434,44 +434,6 @@ export fn game_update() bool {
|
|||||||
|
|
||||||
// Collect point lights
|
// Collect point lights
|
||||||
{
|
{
|
||||||
const point_lights = gmem.render.getPointLights();
|
|
||||||
point_lights.count = 0;
|
|
||||||
|
|
||||||
for (0..gmem.world.entity_count) |i| {
|
|
||||||
const ent = &gmem.world.entities[i];
|
|
||||||
if (!ent.data.flags.active) continue;
|
|
||||||
|
|
||||||
if (ent.data.flags.point_light) {
|
|
||||||
const pos = ent.globalMatrix(&gmem.world).extractTranslation();
|
|
||||||
var pos4 = Vec4.new(pos.x(), pos.y(), pos.z(), 1.0);
|
|
||||||
|
|
||||||
const color = ent.data.light.premultipliedColor();
|
|
||||||
point_lights.lights[point_lights.count] = .{
|
|
||||||
.pos = Vec4.new(pos4.x(), pos4.y(), pos4.z(), 1),
|
|
||||||
.color_radius = Vec4.new(color.x(), color.y(), color.z(), ent.data.point_light.radius),
|
|
||||||
};
|
|
||||||
point_lights.count += 1;
|
|
||||||
if (point_lights.count == Render.MAX_POINT_LIGHTS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ent.data.flags.dir_light) {
|
|
||||||
const dir4 = ent.globalMatrix(&gmem.world).mulByVec4(Vec4.forward());
|
|
||||||
const color = ent.data.light.premultipliedColor();
|
|
||||||
point_lights.lights[point_lights.count] = .{
|
|
||||||
.pos = dir4,
|
|
||||||
.color_radius = Vec4.new(color.x(), color.y(), color.z(), 1),
|
|
||||||
};
|
|
||||||
point_lights.count += 1;
|
|
||||||
if (point_lights.count == Render.MAX_POINT_LIGHTS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gmem.render.flushUBOs();
|
|
||||||
|
|
||||||
// Render meshes and lights
|
|
||||||
for (0..gmem.world.entity_count) |i| {
|
for (0..gmem.world.entity_count) |i| {
|
||||||
const ent = &gmem.world.entities[i];
|
const ent = &gmem.world.entities[i];
|
||||||
if (!ent.data.flags.active) continue;
|
if (!ent.data.flags.active) continue;
|
||||||
@ -490,7 +452,34 @@ export fn game_update() bool {
|
|||||||
.transform = ent.globalMatrix(&gmem.world).*,
|
.transform = ent.globalMatrix(&gmem.world).*,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ent.data.flags.point_light) {
|
||||||
|
const pos = ent.globalMatrix(&gmem.world).extractTranslation();
|
||||||
|
const color = ent.data.light.premultipliedColor();
|
||||||
|
|
||||||
|
gmem.render.drawLight(.{
|
||||||
|
.point = .{
|
||||||
|
.pos = pos,
|
||||||
|
.radius = ent.data.point_light.radius,
|
||||||
|
.color = color,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (ent.data.flags.dir_light) {
|
||||||
|
const dir4 = ent.globalMatrix(&gmem.world).mulByVec4(Vec4.forward());
|
||||||
|
const color = ent.data.light.premultipliedColor();
|
||||||
|
|
||||||
|
gmem.render.drawLight(.{
|
||||||
|
.directional = .{
|
||||||
|
.dir = dir4.toVec3(),
|
||||||
|
.color = color,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: get rid of this
|
||||||
|
gmem.render.flushUBOs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user