monolith: demo is prettier, debug rendering in progress

This commit is contained in:
a-day-old-bagel committed 2023-07-07 20:40:04 -06:00
1 parent f6252a8c41
commit d59a7fe371
5 files changed
+117 -31

No files matched your search

+2
View File
@@ -178,6 +178,7 @@ fn samplesCrossPlatform(b: *std.Build, options: Options) void {
const layers_wgpu = @import("samples/layers_wgpu/build.zig");
const gamepad_wgpu = @import("samples/gamepad_wgpu/build.zig");
const physics_test_wgpu = @import("samples/physics_test_wgpu/build.zig");
const monolith = @import("samples/monolith/build.zig");
install(b, minimal_gl.build(b, options), "minimal_gl");
install(b, triangle_wgpu.build(b, options), "triangle_wgpu");
@@ -190,6 +191,7 @@ fn samplesCrossPlatform(b: *std.Build, options: Options) void {
install(b, bullet_physics_test_wgpu.build(b, options), "bullet_physics_test_wgpu");
install(b, procedural_mesh_wgpu.build(b, options), "procedural_mesh_wgpu");
install(b, physics_test_wgpu.build(b, options), "physics_test_wgpu");
install(b, monolith.build(b, options), "monolith");
install(b, audio_experiments_wgpu.build(b, options), "audio_experiments_wgpu");
}
+51
View File
@@ -0,0 +1,51 @@
const std = @import("std");
const Options = @import("../../build.zig").Options;
const content_dir = "monolith_content/";
pub fn build(b: *std.Build, options: Options) *std.Build.CompileStep {
const exe = b.addExecutable(.{
.name = "monolith",
.root_source_file = .{ .path = thisDir() ++ "/src/monolith.zig" },
.target = options.target,
.optimize = options.optimize,
});
const zgui_pkg = @import("../../build.zig").zgui_pkg;
const zmath_pkg = @import("../../build.zig").zmath_pkg;
const zgpu_pkg = @import("../../build.zig").zgpu_pkg;
const zglfw_pkg = @import("../../build.zig").zglfw_pkg;
const zmesh_pkg = @import("../../build.zig").zmesh_pkg;
const zphysics_pkg = @import("../../libs/zphysics/build.zig").package(b, options.target, options.optimize, .{
.options = .{
.use_double_precision = false,
.enable_debug_renderer = true,
.enable_asserts = true,
},
});
zmath_pkg.link(exe);
zgui_pkg.link(exe);
zgpu_pkg.link(exe);
zglfw_pkg.link(exe);
zmesh_pkg.link(exe);
zphysics_pkg.link(exe);
const exe_options = b.addOptions();
exe.addOptions("build_options", exe_options);
exe_options.addOption([]const u8, "content_dir", content_dir);
const install_content_step = b.addInstallDirectory(.{
.source_dir = thisDir() ++ "/" ++ content_dir,
.install_dir = .{ .custom = "" },
.install_subdir = "bin/" ++ content_dir,
});
exe.step.dependOn(&install_content_step.step);
return exe;
}
inline fn thisDir() []const u8 {
return comptime std.fs.path.dirname(@src().file) orelse ".";
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8559132c89ad51d8a2ba5b171887a44a7ba93776e205f553573de228e64b45f8
size 162588
@@ -7,16 +7,18 @@ const zgui = @import("zgui");
const zm = @import("zmath");
const zphy = @import("zphysics");
const zmesh = @import("zmesh");
const wgsl = @import("physics_debug_rendering_wgsl.zig");
const wgsl = @import("monolith_wgsl.zig");
const content_dir = @import("build_options").content_dir;
const window_title = "zig-gamedev: physics test (wgpu)";
const FrameUniforms = extern struct {
world_to_clip: zm.Mat align(16),
floor_material: [4]f32 align(16),
box_rotation: [3][4]f32 align(16), // GPU will expect each element to be 16-aligned too, so extra f32 here to pad.
box_center: [4]f32 align(16), // Only [3]f32 logically, but [4]f32 in memory, so 3 or 4 works the same.
box_radius: [4]f32 align(16), // Only [3]f32 logically, but [4]f32 in memory, so 3 or 4 works the same.
box_inv_radius: [4]f32 align(16), // Only [3]f32 logically, but [4]f32 in memory, so 3 or 4 works the same.
camera_position: [3]f32 align(16), // Only [3]f32 logically, but [4]f32 in memory, so 3 or 4 works the same.
};
@@ -170,9 +172,9 @@ const DemoState = struct {
physics_debug_renderer: MyDebugRenderer,
camera: struct {
position: [3]f32 = .{ 0.0, 8.0, -32.0 },
position: [3]f32 = .{ 0.0, 32.0, -32.0 },
forward: [3]f32 = .{ 0.0, 0.0, 1.0 },
pitch: f32 = 0.1 * math.pi,
pitch: f32 = 0.16 * math.pi,
yaw: f32 = 0.0,
} = .{},
mouse: struct {
@@ -706,23 +708,24 @@ fn draw(demo: *DemoState) void {
);
pass.setPipeline(mesh_render_pipe);
const box_scale = zm.scaling(10, 30, 5);
const box_rotate = zm.mul(zm.rotationZ(0.4), zm.rotationY(0.5));
// const box_center = zm.f32x4(-25, 10, 50, 1);
const box_center = zm.f32x4(0, 10, 0, 1);
const box_scale = zm.scaling(10, 50, 5);
const box_rotate = zm.mul(zm.rotationZ(0.24), zm.rotationY(0.3));
const box_center = zm.f32x4(-15, 0, 30, 1);
const box_radius = zm.mul(box_scale, zm.f32x4(0.4999, 0.4999, 0.4999, 0)); // .4999 is anti-artifact bias
const box_translate = zm.transpose(zm.translationV(box_center));
const box_transform = zm.mul(box_translate, zm.mul(box_rotate, box_scale));
const box_radius = zm.mul(box_scale, zm.f32x4(0.499, 0.499, 0.499, 0)); // .499 is anti-artifacting
const box_rotate_t = zm.transpose(box_rotate);
const box_rotation: [3][4]f32 = .{ box_rotate_t[0], box_rotate_t[1], box_rotate_t[2] };
const floor_material = zm.f32x4(-0.9, -0.9, -0.9, 0.8);
{ // Update frame uniforms
const mem = gctx.uniformsAllocate(FrameUniforms, 1);
mem.slice[0] = .{
.world_to_clip = zm.transpose(cam_world_to_clip),
.floor_material = floor_material,
.box_rotation = .{ box_rotate_t[0], box_rotate_t[1], box_rotate_t[2] },
.box_center = box_center,
.box_radius = box_radius,
.box_rotation = box_rotation,
.box_inv_radius = .{ 1.0 / box_radius[0], 1.0 / box_radius[1], 1.0 / box_radius[2], 0 },
.camera_position = demo.camera.position,
};
pass.setBindGroup(0, uniform_bg, &.{mem.offset});
@@ -732,7 +735,8 @@ fn draw(demo: *DemoState) void {
const mem = gctx.uniformsAllocate(DrawUniforms, 1);
mem.slice[0] = .{
.object_to_world = zm.identity(),
.basecolor_roughness = .{ 0.9, 0.9, 0.9, -0.3 },
.basecolor_roughness = floor_material,
// .basecolor_roughness = .{ 0.9, 0.9, 0.9, -0.3 },
};
pass.setBindGroup(1, uniform_bg, &.{mem.offset});
pass.drawIndexed(
@@ -764,7 +768,11 @@ fn draw(demo: *DemoState) void {
const mem = gctx.uniformsAllocate(DrawUniforms, 1);
mem.slice[0] = .{
.object_to_world = box_transform,
.basecolor_roughness = .{ 0.9, 0.9, 0.9, -0.3 },
// .basecolor_roughness = .{ 0.03, 0.02, 0.04, -0.16 },
// .basecolor_roughness = .{ 0.3, 0.3, 0.3, -0.02 },
// .basecolor_roughness = .{ 0.92, 0.9, 0.94, -0.24 },
.basecolor_roughness = .{ 0.010, 0.010, 0.014, -0.05 },
// .basecolor_roughness = .{ 0.010, 0.010, 0.014, -0.3 },
};
pass.setBindGroup(1, uniform_bg, &.{mem.offset});
pass.drawIndexed(
@@ -8,9 +8,11 @@ const common =
\\
\\ struct FrameUniforms {
\\ world_to_clip: mat4x4<f32>,
\\ floor_material: vec4<f32>,
\\ box_rotation: mat3x3<f32>,
\\ box_center: vec3<f32>,
\\ box_radius: vec3<f32>,
\\ box_inv_radius: vec3<f32>,
\\ camera_position: vec3<f32>,
\\ }
\\ @group(0) @binding(0) var<uniform> frame_uniforms: FrameUniforms;
@@ -102,19 +104,26 @@ pub const mesh = struct {
\\ struct Box {
\\ center: vec3<f32>,
\\ radius: vec3<f32>,
\\ inv_radius: vec3<f32>,
\\ rotation: mat3x3<f32>,
\\ };
\\ struct Ray {
\\ origin: vec3<f32>,
\\ direction: vec3<f32>,
\\ };
\\ // Alexander Majercik, Cyril Crassin, Peter Shirley, and Morgan McGuire, A Ray-Box Intersection Algorithm and
\\ // Efficient Dynamic Voxel Rendering, Journal of Computer Graphics Techniques (JCGT), vol. 7, no. 3, 66-81, 2018
\\ // This wgsl implementation of the algorithm is customized to fit the assumptions of this use case.
\\ fn intersect_box(box: Box, ray: Ray, distance: ptr<function, f32>, normal: ptr<function, vec3<f32>>) -> bool {
\\ let r = Ray(
\\ (ray.origin - box.center) * box.rotation,
\\ ray.direction * box.rotation,
\\ );
\\ var winding: f32 = 1.0;
\\ let winding_vec = abs(r.origin) * box.inv_radius;
\\ if (max(max(winding_vec.x, winding_vec.y), winding_vec.z) < 1.0) { winding = -1.0; }
\\ var sgn: vec3<f32> = -sign(r.direction);
\\ var plane_dist: vec3<f32> = box.radius * sgn - r.origin;
\\ var plane_dist: vec3<f32> = box.radius * winding * sgn - r.origin;
\\ plane_dist = plane_dist / r.direction;
\\
\\ let test = vec3<bool>(
@@ -141,17 +150,22 @@ pub const mesh = struct {
\\ @location(1) normal: vec3<f32>,
\\ ) -> @location(0) vec4<f32> {
\\ let v = normalize(frame_uniforms.camera_position - position);
\\
\\ let r_x = rand2(floor(2 * position.xz));
\\ let r_z = rand2(floor(2 * position.zx));
\\ let r_vec = vec3(r_x, 0, r_z);
\\ let r_strength = 0.04;
\\ let n = normalize(normal + r_vec * r_strength);
\\
\\ let base_color = draw_uniforms.basecolor_roughness.xyz;
\\ var base_color = draw_uniforms.basecolor_roughness.xyz;
\\ var roughness = draw_uniforms.basecolor_roughness.a;
\\
\\ var n: vec3<f32>;
\\ if (base_color.x < 0.0) {
\\ let r_x = rand2(floor(2 * position.xz));
\\ let r_z = rand2(floor(2 * position.zx));
\\ let r_vec = vec3(r_x, 0, r_z);
\\ let r_strength = 0.04;
\\ n = normalize(normal + r_vec * r_strength);
\\ roughness += min(0, -dot(r_vec, r_vec) * 0.6 + 0.64);
\\ } else { n = normalize(normal); }
\\
\\ var metallic: f32;
\\ if (roughness < 0.0) { metallic = 0.95; } else { metallic = 0.0; }
\\ if (roughness < 0.0) { metallic = 0.95; } else { metallic = 0.05; }
\\ base_color = abs(base_color);
\\ roughness = abs(roughness);
\\
\\ let alpha = roughness * roughness;
@@ -177,26 +191,34 @@ pub const mesh = struct {
\\ vec3(0.70, 1.00, 0.70),
\\ );
\\
\\ let monolith = Box(
\\ frame_uniforms.box_center,
\\ frame_uniforms.box_radius,
\\ frame_uniforms.box_inv_radius,
\\ frame_uniforms.box_rotation,
\\ );
\\
\\ var lo = vec3(0.0);
\\ for (var light_index: i32 = 0; light_index < 9; light_index = light_index + 1) {
\\ let lvec = light_positions[light_index] - position;
\\
\\ let l = normalize(lvec);
\\ let h = normalize(l + v);
\\
\\ let box = Box(
\\ frame_uniforms.box_center,
\\ frame_uniforms.box_radius,
\\ frame_uniforms.box_rotation,
\\ );
\\ let pl_ray = Ray(position, l);
\\ var pl_hit_dist: f32;
\\ var pl_hit_norm: vec3<f32>;
\\ let pl_did_hit: bool = intersect_box(box, pl_ray, &pl_hit_dist, &pl_hit_norm);
\\ let pl_did_hit: bool = intersect_box(monolith, pl_ray, &pl_hit_dist, &pl_hit_norm);
\\ if (!pl_did_hit || pl_hit_dist > length(lvec)) {
\\ let distance_sq = dot(lvec, lvec);
\\ let attenuation = 1.0 / distance_sq;
\\ let radiance = 100 * light_colors[light_index] * attenuation;
\\ var radiance = 100 * light_colors[light_index] * attenuation;
\\
\\ if (position.y > 0.0001) { // reflection of floor lighting on monolith surface
\\ let mirror_cam = vec3<f32>(position.x, -position.y, position.z);
\\ let mirror_vec = light_positions[light_index] - mirror_cam;
\\ let t = -mirror_cam.y / (light_positions[light_index].y - mirror_cam.y);
\\ let mirror_pos = mirror_cam + t * mirror_vec;
\\ }
\\
\\ let f = fresnelSchlick(saturate(dot(h, v)), f0);
\\
@@ -220,7 +242,7 @@ pub const mesh = struct {
\\ let cl_ray = Ray(frame_uniforms.camera_position, cfn);
\\ var cl_hit_dist: f32;
\\ var cl_hit_norm: vec3<f32>;
\\ let cl_did_hit: bool = intersect_box(box, cl_ray, &cl_hit_dist, &cl_hit_norm);
\\ let cl_did_hit: bool = intersect_box(monolith, cl_ray, &cl_hit_dist, &cl_hit_norm);
\\ if (cl_did_hit && cl_hit_dist < length(cl)) { continue; }
\\ let negs = (dot(normalize(cl), cfn) - 1.0) * dot(cl, cl);
\\ let peak = 0.2;