Use radix sort for sorting draw commands, add ambient light, tweak lighting
This commit is contained in:
parent
9a6ba0dc7f
commit
37f603dc8a
@ -299,7 +299,7 @@ vec3 microfacetModel(EvalMaterial mat, int light_idx, vec3 P, vec3 N) {
|
||||
|
||||
shadow_mult = sum / 16.0;
|
||||
}
|
||||
shadow_mult = clamp(shadow_mult, 0.3, 1.0);
|
||||
shadow_mult = clamp(shadow_mult, 0.0, 1.0);
|
||||
|
||||
vec3 specBrdf = 0.25 * ggxDistribution(mat, NDotH) * schlickFresnel(mat, LDotH) * geomSmith(mat, NDotL) * geomSmith(mat, NDotV);
|
||||
|
||||
@ -327,6 +327,11 @@ void main() {
|
||||
finalColor += microfacetModel(material, i, VertexOut.vPos, N);
|
||||
}
|
||||
|
||||
float ambient_a = dot(VertexOut.wNormal, vec3(0, 1, 0)) * 0.5 + 0.5;
|
||||
|
||||
// ambient
|
||||
finalColor += material.albedo.rgb * mix(vec3(0.0116, 0.0127, 0.0200), vec3(0.185, 0.198, 0.250), ambient_a);
|
||||
|
||||
FragColor = vec4(finalColor, material.albedo.a);
|
||||
}
|
||||
|
||||
|
124
src/Render.zig
124
src/Render.zig
@ -428,6 +428,12 @@ pub const LightCommand = union(LightKind) {
|
||||
point: PointLight,
|
||||
};
|
||||
|
||||
const DrawCommandKey = packed struct {
|
||||
transparent: u1 = 0,
|
||||
distance: u15 = 0,
|
||||
mesh: u16 = 0,
|
||||
};
|
||||
|
||||
pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
||||
self.lights[self.light_count] = cmd;
|
||||
self.light_count += 1;
|
||||
@ -435,9 +441,99 @@ pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
||||
|
||||
pub fn draw(self: *Render, cmd: DrawCommand) void {
|
||||
self.command_buffer[self.command_count] = cmd;
|
||||
// TODO: don't load the whole mesh here
|
||||
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
||||
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
|
||||
const view_origin = self.camera.view_mat.extractTranslation();
|
||||
const max_value = @as(f32, @floatFromInt(std.math.maxInt(u15)));
|
||||
const dist: u15 = @intFromFloat(std.math.clamp(view_origin.distance(cmd.transform.extractTranslation()) / max_value, 0.0, max_value));
|
||||
const key = DrawCommandKey{
|
||||
.transparent = if (material.blend_mode == .AlphaBlend) 1 else 0,
|
||||
.distance = if (material.blend_mode == .AlphaBlend) ~dist else dist, // TODO: calculate distance. Opaque should be front to back, transparent back to front
|
||||
.mesh = @intCast(cmd.mesh.id % std.math.maxInt(u16)),
|
||||
};
|
||||
self.command_buffer[self.command_count].key = key;
|
||||
self.command_count += 1;
|
||||
}
|
||||
|
||||
// Multipass radix sort for u32
|
||||
fn sortCommands(self: *Render, in_cmds: []DrawCommand) void {
|
||||
var cmds = in_cmds;
|
||||
var aux = self.frame_arena.alloc(DrawCommand, cmds.len) catch @panic("OOM");
|
||||
|
||||
var cnt1: [256]usize = std.mem.zeroes([256]usize);
|
||||
var cnt2: [256]usize = std.mem.zeroes([256]usize);
|
||||
var cnt3: [256]usize = std.mem.zeroes([256]usize);
|
||||
var cnt4: [256]usize = std.mem.zeroes([256]usize);
|
||||
|
||||
// Find counts
|
||||
for (cmds) |*cmd| {
|
||||
const key: u32 = @bitCast(cmd.key);
|
||||
|
||||
cnt1[(key >> 0) & 0xFF] += 1;
|
||||
cnt2[(key >> 8) & 0xFF] += 1;
|
||||
cnt3[(key >> 16) & 0xFF] += 1;
|
||||
cnt4[(key >> 24) & 0xFF] += 1;
|
||||
}
|
||||
|
||||
var a1: usize = 0;
|
||||
var a2: usize = 0;
|
||||
var a3: usize = 0;
|
||||
var a4: usize = 0;
|
||||
for (0..256) |i| {
|
||||
const b1 = cnt1[i];
|
||||
const b2 = cnt2[i];
|
||||
const b3 = cnt3[i];
|
||||
const b4 = cnt4[i];
|
||||
|
||||
cnt1[i] = a1;
|
||||
cnt2[i] = a2;
|
||||
cnt3[i] = a3;
|
||||
cnt4[i] = a4;
|
||||
|
||||
a1 += b1;
|
||||
a2 += b2;
|
||||
a3 += b3;
|
||||
a4 += b4;
|
||||
}
|
||||
|
||||
for (0..cmds.len) |i| {
|
||||
const key: u32 = @bitCast(cmds[i].key);
|
||||
const k = (key >> 0) & 0xFF;
|
||||
const dst = cnt1[k];
|
||||
cnt1[k] += 1;
|
||||
aux[dst] = cmds[i];
|
||||
}
|
||||
std.mem.swap([]DrawCommand, &cmds, &aux);
|
||||
|
||||
for (0..cmds.len) |i| {
|
||||
const key: u32 = @bitCast(cmds[i].key);
|
||||
const k = (key >> 8) & 0xFF;
|
||||
const dst = cnt2[k];
|
||||
cnt2[k] += 1;
|
||||
aux[dst] = cmds[i];
|
||||
}
|
||||
std.mem.swap([]DrawCommand, &cmds, &aux);
|
||||
|
||||
for (0..cmds.len) |i| {
|
||||
const key: u32 = @bitCast(cmds[i].key);
|
||||
const k = (key >> 16) & 0xFF;
|
||||
const dst = cnt3[k];
|
||||
cnt3[k] += 1;
|
||||
aux[dst] = cmds[i];
|
||||
}
|
||||
std.mem.swap([]DrawCommand, &cmds, &aux);
|
||||
|
||||
for (0..cmds.len) |i| {
|
||||
const key: u32 = @bitCast(cmds[i].key);
|
||||
const k = (key >> 24) & 0xFF;
|
||||
const dst = cnt4[k];
|
||||
cnt4[k] += 1;
|
||||
aux[dst] = cmds[i];
|
||||
}
|
||||
std.mem.swap([]DrawCommand, &cmds, &aux);
|
||||
}
|
||||
|
||||
pub fn finish(self: *Render) void {
|
||||
const zone = tracy.initZone(@src(), .{ .name = "Render.finish" });
|
||||
defer zone.deinit();
|
||||
@ -450,32 +546,7 @@ pub fn finish(self: *Render) void {
|
||||
const zoneSort = tracy.initZone(@src(), .{ .name = "Render.finish_sortDraws" });
|
||||
defer zoneSort.deinit();
|
||||
|
||||
const cmds = self.command_buffer[0..self.command_count];
|
||||
std.mem.sortUnstable(DrawCommand, cmds, self, struct {
|
||||
pub fn lessThan(render: *const Render, lhs: DrawCommand, rhs: DrawCommand) bool {
|
||||
const lhs_mesh = render.assetman.resolveMesh(lhs.mesh);
|
||||
const rhs_mesh = render.assetman.resolveMesh(rhs.mesh);
|
||||
const lhs_material: Material = if (lhs.material_override) |mat| mat else lhs_mesh.material;
|
||||
const rhs_material: Material = if (rhs.material_override) |mat| mat else rhs_mesh.material;
|
||||
|
||||
const lhs_blend_num = @intFromEnum(lhs_material.blend_mode);
|
||||
const rhs_blend_num = @intFromEnum(rhs_material.blend_mode);
|
||||
|
||||
if (lhs_material.blend_mode == .Opaque and rhs_material.blend_mode == .Opaque) {
|
||||
return lhs.mesh.id < rhs.mesh.id;
|
||||
}
|
||||
|
||||
if (lhs_material.blend_mode == .AlphaBlend and rhs_material.blend_mode == .AlphaBlend) {
|
||||
const lhs_view_pos = render.camera.view_mat.mulByVec4(lhs.transform.extractTranslation().toVec4(1));
|
||||
const rhs_view_pos = render.camera.view_mat.mulByVec4(rhs.transform.extractTranslation().toVec4(1));
|
||||
|
||||
// Back to front sorting. View pos has negative Z
|
||||
return lhs_view_pos.z() < rhs_view_pos.z();
|
||||
}
|
||||
|
||||
return lhs_blend_num < rhs_blend_num;
|
||||
}
|
||||
}.lessThan);
|
||||
self.sortCommands(self.command_buffer[0..self.command_count]);
|
||||
}
|
||||
|
||||
if (self.update_view_frustum) {
|
||||
@ -1129,6 +1200,7 @@ pub fn checkGLError() void {
|
||||
}
|
||||
|
||||
pub const DrawCommand = struct {
|
||||
key: DrawCommandKey = .{},
|
||||
mesh: AssetManager.Handle.Mesh,
|
||||
material_override: ?Material,
|
||||
transform: Mat4,
|
||||
|
@ -191,7 +191,7 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
|
||||
_ = globals.g_mem.world.addEntity(.{
|
||||
.flags = .{ .dir_light = true, .rotate = true },
|
||||
.transform = .{ .rot = Quat.fromEulerAngles(Vec3.new(70, 0, 0)) },
|
||||
.light = .{ .color_intensity = Vec4.new(std.math.pow(f32, 1, 2.2), std.math.pow(f32, 0.9568627450980393, 2.2), std.math.pow(f32, 0.9176470588235294, 2.2), 1.0) },
|
||||
.light = .{ .color_intensity = Vec4.new(1.00, 0.885, 0.570, 1.0) },
|
||||
.rotate = .{ .axis = Vec3.up(), .rate = -10 },
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user