Start implementing alpha mask instead of alpha blend for everything,
add debug bounds rendering
This commit is contained in:
parent
8031b77c8a
commit
8e9cb3fa5b
29
assets/shaders/debug.glsl
Normal file
29
assets/shaders/debug.glsl
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// UBOs
|
||||||
|
layout(std140, binding = 0) uniform Matrices {
|
||||||
|
mat4 projection;
|
||||||
|
mat4 view;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(location = 2) uniform vec3 color;
|
||||||
|
|
||||||
|
// Input, output blocks
|
||||||
|
|
||||||
|
#if VERTEX_SHADER
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 aPos;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = projection * view * vec4(aPos.xyz, 1.0);
|
||||||
|
}
|
||||||
|
#endif // VERTEX_SHADER
|
||||||
|
|
||||||
|
#if FRAGMENT_SHADER
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
FragColor = vec4(vec3(1.0), 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FRAGMNET_SHADER
|
5
assets/shaders/debug.prog
Normal file
5
assets/shaders/debug.prog
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"shader": "debug.glsl",
|
||||||
|
"vertex": true,
|
||||||
|
"fragment": true
|
||||||
|
}
|
@ -341,6 +341,10 @@ vec3 ibl(int matIdx, vec3 N, vec3 V) {
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
int matIdx = draw_data[DrawID].materialIdx;
|
int matIdx = draw_data[DrawID].materialIdx;
|
||||||
|
if (getAlbedo(matIdx).a < 0.5) {
|
||||||
|
FragColor = vec4(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sampler2D normal_map = materials[matIdx].normal_map;
|
sampler2D normal_map = materials[matIdx].normal_map;
|
||||||
vec2 normal_map_uv_scale = materials[matIdx].normal_map_uv_scale;
|
vec2 normal_map_uv_scale = materials[matIdx].normal_map_uv_scale;
|
||||||
|
|
||||||
@ -354,7 +358,8 @@ void main() {
|
|||||||
vec3 finalColor = vec3(0);
|
vec3 finalColor = vec3(0);
|
||||||
|
|
||||||
int n_lights = clamp(int(lights_count), 0, MAX_POINT_LIGHTS);
|
int n_lights = clamp(int(lights_count), 0, MAX_POINT_LIGHTS);
|
||||||
for (int i = 0; i < n_lights; i++) {
|
for (int i = 0; i < MAX_POINT_LIGHTS; i++) {
|
||||||
|
if (i > lights_count) break;
|
||||||
finalColor += microfacetModel(matIdx, i, VertexOut.vPos, N);
|
finalColor += microfacetModel(matIdx, i, VertexOut.vPos, N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ void main() {
|
|||||||
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
//gl_FragDepth = gl_FragCoord.z / gl_FragCoord.w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#extension GL_ARB_bindless_texture : enable
|
||||||
|
|
||||||
struct DrawCmdData {
|
struct DrawCmdData {
|
||||||
mat4 transform;
|
mat4 transform;
|
||||||
@ -15,21 +16,63 @@ layout(std430, binding = 3) readonly buffer DrawCmdDatas {
|
|||||||
DrawCmdData draw_data[];
|
DrawCmdData draw_data[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VERTEX_EXPORT flat uint DrawID;
|
||||||
|
|
||||||
|
VERTEX_EXPORT VertexData {
|
||||||
|
vec2 uv;
|
||||||
|
} VertexOut;
|
||||||
|
|
||||||
#if VERTEX_SHADER
|
#if VERTEX_SHADER
|
||||||
|
|
||||||
layout(location = 0) in vec3 aPos;
|
layout(location = 0) in vec3 aPos;
|
||||||
|
layout(location = 2) in vec2 aUV;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
mat4 model = draw_data[gl_BaseInstance + gl_InstanceID].transform;
|
DrawID = gl_BaseInstance + gl_InstanceID;
|
||||||
mat4 viewModel = view * model;
|
mat4 model = draw_data[DrawID].transform;
|
||||||
vec4 vPos = viewModel * vec4(aPos.xyz, 1.0);
|
mat4 viewModel = view * model;
|
||||||
gl_Position = projection * vPos;
|
vec4 vPos = viewModel * vec4(aPos.xyz, 1.0);
|
||||||
|
gl_Position = projection * vPos;
|
||||||
|
VertexOut.uv = aUV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FRAGMENT_SHADER
|
#if FRAGMENT_SHADER
|
||||||
|
|
||||||
void main() {}
|
struct Material {
|
||||||
|
vec4 albedo;
|
||||||
|
sampler2D albedo_map;
|
||||||
|
vec2 albedo_map_uv_scale;
|
||||||
|
sampler2D normal_map;
|
||||||
|
vec2 normal_map_uv_scale;
|
||||||
|
float metallic;
|
||||||
|
sampler2D metallic_map;
|
||||||
|
vec2 metallic_map_uv_scale;
|
||||||
|
float roughness;
|
||||||
|
sampler2D roughness_map;
|
||||||
|
vec2 roughness_map_uv_scale;
|
||||||
|
vec3 emission;
|
||||||
|
sampler2D emission_map;
|
||||||
|
vec2 emission_map_uv_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 2) readonly buffer Materials {
|
||||||
|
uint materials_count;
|
||||||
|
Material materials[];
|
||||||
|
};
|
||||||
|
|
||||||
|
vec4 getAlbedo(int materialIdx) {
|
||||||
|
return textureSize(materials[materialIdx].albedo_map, 0) == ivec2(0) ? vec4(pow(materials[materialIdx].albedo.rgb, vec3(2.2)), materials[materialIdx].albedo.a) : texture(materials[materialIdx].albedo_map, VertexOut.uv * materials[materialIdx].albedo_map_uv_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
int matIdx = draw_data[DrawID].materialIdx;
|
||||||
|
if (getAlbedo(matIdx).a < 0.5) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,7 @@ const checkGLError = @import("Render.zig").checkGLError;
|
|||||||
const BuddyAllocator = @import("BuddyAllocator.zig");
|
const BuddyAllocator = @import("BuddyAllocator.zig");
|
||||||
const Vec2 = @import("zalgebra").Vec2;
|
const Vec2 = @import("zalgebra").Vec2;
|
||||||
const Vec3 = @import("zalgebra").Vec3;
|
const Vec3 = @import("zalgebra").Vec3;
|
||||||
|
const Mat4 = @import("zalgebra").Mat4;
|
||||||
const sdl = @import("sdl.zig");
|
const sdl = @import("sdl.zig");
|
||||||
const tracy = @import("tracy");
|
const tracy = @import("tracy");
|
||||||
|
|
||||||
@ -689,6 +690,35 @@ const LoadedScene = struct {
|
|||||||
pub const AABB = struct {
|
pub const AABB = struct {
|
||||||
min: Vec3 = Vec3.zero(),
|
min: Vec3 = Vec3.zero(),
|
||||||
max: Vec3 = Vec3.zero(),
|
max: Vec3 = Vec3.zero(),
|
||||||
|
|
||||||
|
pub fn distance(self: *const AABB, point: Vec3) f32 {
|
||||||
|
const center = self.min.add(self.max).scale(0.5);
|
||||||
|
const extent = self.max.sub(self.min).scale(0.5);
|
||||||
|
|
||||||
|
var center_to_point = point.sub(center);
|
||||||
|
center_to_point.data = @abs(center_to_point.data);
|
||||||
|
var d = center_to_point.sub(extent);
|
||||||
|
d.data = @max(d.data, @as(@Vector(3, f32), @splat(0.0)));
|
||||||
|
|
||||||
|
const sq_dist_to_side = d.dot(d);
|
||||||
|
|
||||||
|
if (std.math.approxEqAbs(f32, sq_dist_to_side, 0.0, 0.0001)) {
|
||||||
|
const diff = point.sub(center);
|
||||||
|
return diff.dot(diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sq_dist_to_side;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transformBy(self: *const AABB, matrix: Mat4) AABB {
|
||||||
|
var center = self.min.add(self.max).scale(0.5).toVec4(1.0);
|
||||||
|
var extent = self.max.sub(self.min).scale(0.5).toVec4(0.0);
|
||||||
|
|
||||||
|
center = matrix.mulByVec4(center);
|
||||||
|
extent = matrix.mulByVec4(extent);
|
||||||
|
|
||||||
|
return AABB{ .min = center.sub(extent).toVec3(), .max = center.add(extent).toVec3() };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BufferSlice = struct {
|
pub const BufferSlice = struct {
|
||||||
|
144
src/Render.zig
144
src/Render.zig
@ -7,6 +7,7 @@ const globals = @import("globals.zig");
|
|||||||
pub const Material = @import("formats.zig").Material;
|
pub const Material = @import("formats.zig").Material;
|
||||||
const math = @import("math.zig");
|
const math = @import("math.zig");
|
||||||
const formats = @import("formats.zig");
|
const formats = @import("formats.zig");
|
||||||
|
const AABB = AssetManager.AABB; // TODO: move AABB out of formats pls
|
||||||
const tracy = @import("tracy");
|
const tracy = @import("tracy");
|
||||||
|
|
||||||
const za = @import("zalgebra");
|
const za = @import("zalgebra");
|
||||||
@ -39,6 +40,7 @@ frame_arena: std.mem.Allocator,
|
|||||||
assetman: *AssetManager,
|
assetman: *AssetManager,
|
||||||
camera: *Camera = &default_camera,
|
camera: *Camera = &default_camera,
|
||||||
mesh_vao: gl.GLuint = 0,
|
mesh_vao: gl.GLuint = 0,
|
||||||
|
z_prepass_vao: gl.GLuint = 0,
|
||||||
tripple_buffer_index: usize = MAX_FRAMES_QUEUED - 1,
|
tripple_buffer_index: usize = MAX_FRAMES_QUEUED - 1,
|
||||||
gl_fences: [MAX_FRAMES_QUEUED]?gl.GLsync = [_]?gl.GLsync{null} ** MAX_FRAMES_QUEUED,
|
gl_fences: [MAX_FRAMES_QUEUED]?gl.GLsync = [_]?gl.GLsync{null} ** MAX_FRAMES_QUEUED,
|
||||||
camera_ubo: gl.GLuint = 0,
|
camera_ubo: gl.GLuint = 0,
|
||||||
@ -85,6 +87,10 @@ camera_view_proj: Mat4 = Mat4.identity(),
|
|||||||
world_camera_frustum: math.Frustum = .{},
|
world_camera_frustum: math.Frustum = .{},
|
||||||
world_view_frustum_corners: [CSM_SPLITS][8]Vec3 = undefined,
|
world_view_frustum_corners: [CSM_SPLITS][8]Vec3 = undefined,
|
||||||
|
|
||||||
|
// Debug Draw
|
||||||
|
debug_drawer: DebugDrawer = undefined,
|
||||||
|
debug_lines_vao: gl.GLuint = 0,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetman: *AssetManager) Render {
|
pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetman: *AssetManager) Render {
|
||||||
var render = Render{
|
var render = Render{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
@ -137,6 +143,38 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
|
|||||||
gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0);
|
gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Z Prepass Mesh VAO
|
||||||
|
var vao: gl.GLuint = 0;
|
||||||
|
gl.createVertexArrays(1, &vao);
|
||||||
|
std.debug.assert(vao != 0);
|
||||||
|
render.z_prepass_vao = vao;
|
||||||
|
|
||||||
|
// positions
|
||||||
|
// gl.vertexArrayVertexBuffer(vao, 0, vertices, 0, @sizeOf(formats.Vector3));
|
||||||
|
gl.enableVertexArrayAttrib(vao, Attrib.Position.value());
|
||||||
|
gl.vertexArrayAttribBinding(vao, Attrib.Position.value(), 0);
|
||||||
|
gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0);
|
||||||
|
|
||||||
|
// uvs
|
||||||
|
gl.enableVertexArrayAttrib(vao, Attrib.UV.value());
|
||||||
|
gl.vertexArrayAttribBinding(vao, Attrib.UV.value(), 2);
|
||||||
|
gl.vertexArrayAttribFormat(vao, Attrib.UV.value(), 2, gl.FLOAT, gl.FALSE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Debug Lines VAO
|
||||||
|
var vao: gl.GLuint = 0;
|
||||||
|
gl.createVertexArrays(1, &vao);
|
||||||
|
std.debug.assert(vao != 0);
|
||||||
|
render.debug_lines_vao = vao;
|
||||||
|
|
||||||
|
// positions
|
||||||
|
gl.enableVertexArrayAttrib(vao, Attrib.Position.value());
|
||||||
|
gl.vertexArrayAttribBinding(vao, Attrib.Position.value(), 0);
|
||||||
|
gl.vertexArrayAttribFormat(vao, Attrib.Position.value(), 3, gl.FLOAT, gl.FALSE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
const PERSISTENT_BUFFER_FLAGS: gl.GLbitfield = gl.MAP_PERSISTENT_BIT | gl.MAP_WRITE_BIT | gl.MAP_COHERENT_BIT;
|
const PERSISTENT_BUFFER_FLAGS: gl.GLbitfield = gl.MAP_PERSISTENT_BIT | gl.MAP_WRITE_BIT | gl.MAP_COHERENT_BIT;
|
||||||
|
|
||||||
// Camera matrices ubo
|
// Camera matrices ubo
|
||||||
@ -372,6 +410,8 @@ pub fn begin(self: *Render) void {
|
|||||||
self.light_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;
|
||||||
|
|
||||||
|
self.debug_drawer = DebugDrawer.init(self.frame_arena);
|
||||||
|
|
||||||
gl.enable(gl.CULL_FACE);
|
gl.enable(gl.CULL_FACE);
|
||||||
gl.enable(gl.DEPTH_TEST);
|
gl.enable(gl.DEPTH_TEST);
|
||||||
if (self.gl_fences[self.tripple_buffer_index]) |fence| {
|
if (self.gl_fences[self.tripple_buffer_index]) |fence| {
|
||||||
@ -429,9 +469,8 @@ pub const LightCommand = union(LightKind) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DrawCommandKey = packed struct {
|
const DrawCommandKey = packed struct {
|
||||||
mesh: u16 = 0,
|
distance: u30 = 0,
|
||||||
distance: u15 = 0,
|
blend: u2 = 0,
|
||||||
transparent: u1 = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
||||||
@ -439,18 +478,78 @@ pub fn drawLight(self: *Render, cmd: LightCommand) void {
|
|||||||
self.light_count += 1;
|
self.light_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn invLerp(aa: f32, b: f32, v: f32) f32 {
|
||||||
|
return (v - aa) / (b - aa);
|
||||||
|
}
|
||||||
|
|
||||||
|
const DebugDrawer = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
// Wasting frame arena memory here, maybe redo this
|
||||||
|
line_list: std.ArrayListUnmanaged([2][3]f32) = .{},
|
||||||
|
|
||||||
|
pub fn init(allocator: std.mem.Allocator) Self {
|
||||||
|
return Self{ .allocator = allocator };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawAABB(self: *Self, in_aabb: AABB) void {
|
||||||
|
var aabb = in_aabb;
|
||||||
|
var new_lines: [12][2][3]f32 = undefined;
|
||||||
|
|
||||||
|
var min: [3]f32 = .{ aabb.min.x(), aabb.min.y(), aabb.min.z() };
|
||||||
|
var max: [3]f32 = .{ aabb.max.x(), aabb.max.y(), aabb.max.z() };
|
||||||
|
|
||||||
|
for (0..2) |i| {
|
||||||
|
new_lines[i * 6 + 0] = .{ min, .{ max[0], min[1], min[2] } };
|
||||||
|
new_lines[i * 6 + 1] = .{ min, .{ min[0], max[1], min[2] } };
|
||||||
|
new_lines[i * 6 + 2] = .{ min, .{ min[0], min[1], max[2] } };
|
||||||
|
|
||||||
|
new_lines[i * 6 + 3] = .{ max, .{ min[0], max[1], max[2] } };
|
||||||
|
new_lines[i * 6 + 4] = .{ max, .{ max[0], min[1], max[2] } };
|
||||||
|
new_lines[i * 6 + 5] = .{ max, .{ max[0], max[1], min[2] } };
|
||||||
|
|
||||||
|
std.mem.swap(f32, &min[1], &max[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.line_list.appendSlice(self.allocator, &new_lines) catch {};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uploadLinesBuffer(self: *const Self) gl.GLuint {
|
||||||
|
var buf: gl.GLuint = 0;
|
||||||
|
gl.createBuffers(1, &buf);
|
||||||
|
std.debug.assert(buf != 0);
|
||||||
|
|
||||||
|
gl.namedBufferStorage(buf, @intCast(@sizeOf(f32) * 3 * 2 * self.line_list.items.len), self.line_list.items.ptr, 0);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
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;
|
||||||
// TODO: don't load the whole mesh here
|
// TODO: don't load the whole mesh here
|
||||||
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
||||||
|
const aabb = mesh.aabb.transformBy(cmd.transform);
|
||||||
|
|
||||||
|
self.debug_drawer.drawAABB(aabb);
|
||||||
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
|
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
|
||||||
const view_origin = self.camera.view_mat.extractTranslation();
|
const view_origin = self.camera.view_mat.extractTranslation();
|
||||||
const max_value = @as(f32, @floatFromInt(std.math.maxInt(u15)));
|
const distance = view_origin.distance(aabb.min.add(aabb.max).scale(0.5));
|
||||||
const dist: u15 = @intFromFloat(std.math.clamp(view_origin.distance(cmd.transform.extractTranslation()) / max_value, 0.0, max_value));
|
const alpha = std.math.clamp(invLerp(self.camera.near, self.camera.far, distance), 0.0, 1.0);
|
||||||
|
|
||||||
|
const max_value = @as(f32, @floatFromInt(std.math.maxInt(u30)));
|
||||||
|
const quantized_dist: u30 = @intFromFloat(alpha * max_value);
|
||||||
|
const inv_quantized_dist: u30 = @intFromFloat((1.0 - alpha) * max_value);
|
||||||
const key = DrawCommandKey{
|
const key = DrawCommandKey{
|
||||||
.transparent = if (material.blend_mode == .AlphaBlend) 1 else 0,
|
.blend = switch (material.blend_mode) {
|
||||||
.distance = if (material.blend_mode == .AlphaBlend) dist else dist, // TODO: calculate distance. Opaque should be front to back, transparent back to front
|
.Opaque => 0,
|
||||||
.mesh = @intCast(cmd.mesh.id % std.math.maxInt(u16)),
|
.AlphaMask => 1,
|
||||||
|
.AlphaBlend => 2,
|
||||||
|
},
|
||||||
|
.distance = if (material.blend_mode == .AlphaBlend) inv_quantized_dist else quantized_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_buffer[self.command_count].key = key;
|
||||||
self.command_count += 1;
|
self.command_count += 1;
|
||||||
@ -846,11 +945,11 @@ pub fn finish(self: *Render) void {
|
|||||||
var materials_count: usize = 0;
|
var materials_count: usize = 0;
|
||||||
for (self.command_buffer[0..self.command_count]) |*cmd| {
|
for (self.command_buffer[0..self.command_count]) |*cmd| {
|
||||||
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
||||||
// const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max);
|
const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max);
|
||||||
|
|
||||||
// if (!self.world_camera_frustum.intersectAABB(aabb.transform(cmd.transform))) {
|
if (!self.world_camera_frustum.intersectAABB(aabb.transform(cmd.transform))) {
|
||||||
// continue;
|
continue;
|
||||||
// }
|
}
|
||||||
|
|
||||||
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
|
const material: Material = if (cmd.material_override) |mat| mat else mesh.material;
|
||||||
|
|
||||||
@ -919,11 +1018,13 @@ pub fn finish(self: *Render) void {
|
|||||||
// Z Prepass
|
// Z Prepass
|
||||||
{
|
{
|
||||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.z_prepass).program);
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.z_prepass).program);
|
||||||
gl.bindVertexArray(self.shadow_vao);
|
gl.bindVertexArray(self.z_prepass_vao);
|
||||||
gl.depthFunc(gl.LESS);
|
gl.depthFunc(gl.LESS);
|
||||||
|
|
||||||
self.assetman.vertex_heap.vertices.bind(Render.Attrib.Position.value());
|
self.assetman.vertex_heap.vertices.bind(Render.Attrib.Position.value());
|
||||||
checkGLError();
|
checkGLError();
|
||||||
|
self.assetman.vertex_heap.uvs.bind(Render.Attrib.UV.value());
|
||||||
|
checkGLError();
|
||||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer);
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer);
|
||||||
checkGLError();
|
checkGLError();
|
||||||
|
|
||||||
@ -936,6 +1037,7 @@ pub fn finish(self: *Render) void {
|
|||||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
|
||||||
gl.bindVertexArray(self.mesh_vao);
|
gl.bindVertexArray(self.mesh_vao);
|
||||||
gl.depthFunc(gl.EQUAL);
|
gl.depthFunc(gl.EQUAL);
|
||||||
|
defer gl.depthFunc(gl.LEQUAL);
|
||||||
|
|
||||||
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(Uniform.EnvBRDF.value(), self.assetman.resolveTexture(a.Textures.@"ibl_brdf_lut.norm").handle);
|
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(Uniform.EnvBRDF.value(), self.assetman.resolveTexture(a.Textures.@"ibl_brdf_lut.norm").handle);
|
||||||
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(Uniform.ShadowMap2D.value(), self.shadow_texture_handle);
|
gl.GL_ARB_bindless_texture.uniformHandleui64ARB(Uniform.ShadowMap2D.value(), self.shadow_texture_handle);
|
||||||
@ -978,8 +1080,20 @@ pub fn finish(self: *Render) void {
|
|||||||
defer gl.polygonMode(gl.FRONT_AND_BACK, gl.FILL);
|
defer gl.polygonMode(gl.FRONT_AND_BACK, gl.FILL);
|
||||||
gl.lineWidth(4);
|
gl.lineWidth(4);
|
||||||
|
|
||||||
|
const debug_lines_buffer = self.debug_drawer.uploadLinesBuffer();
|
||||||
|
defer gl.deleteBuffers(1, &debug_lines_buffer);
|
||||||
|
|
||||||
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.debug).program);
|
||||||
|
gl.bindVertexArray(self.debug_lines_vao);
|
||||||
|
|
||||||
|
gl.uniform3f(Uniform.Color.value(), 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
gl.bindVertexBuffer(Render.Attrib.Position.value(), debug_lines_buffer, 0, @intCast(@sizeOf(f32) * 3));
|
||||||
|
|
||||||
|
gl.drawArrays(gl.LINES, 0, @intCast(self.debug_drawer.line_list.items.len * 2));
|
||||||
|
|
||||||
// Frustum debug stuff, drawn only when view frustum is fixed
|
// Frustum debug stuff, drawn only when view frustum is fixed
|
||||||
if (!self.update_view_frustum) {
|
if (false and !self.update_view_frustum) {
|
||||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.unlit).program);
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.unlit).program);
|
||||||
|
|
||||||
// Draw wire frustum cubes
|
// Draw wire frustum cubes
|
||||||
@ -1162,9 +1276,9 @@ const cube_camera_dirs = [6]CubeCameraDir{
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn renderShadow(self: *Render, frustum: *const math.Frustum) void {
|
fn renderShadow(self: *Render, frustum: *const math.Frustum) void {
|
||||||
|
_ = frustum; // autofix
|
||||||
const zone = tracy.initZone(@src(), .{ .name = "Render.renderShadow" });
|
const zone = tracy.initZone(@src(), .{ .name = "Render.renderShadow" });
|
||||||
defer zone.deinit();
|
defer zone.deinit();
|
||||||
_ = frustum; // autofix
|
|
||||||
self.assetman.vertex_heap.vertices.bind(Render.Attrib.Position.value());
|
self.assetman.vertex_heap.vertices.bind(Render.Attrib.Position.value());
|
||||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer);
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.assetman.vertex_heap.indices.buffer);
|
||||||
|
|
||||||
|
@ -369,8 +369,8 @@ test "write and read scene" {
|
|||||||
pub const Material = extern struct {
|
pub const Material = extern struct {
|
||||||
pub const BlendMode = enum(u8) {
|
pub const BlendMode = enum(u8) {
|
||||||
Opaque = 0,
|
Opaque = 0,
|
||||||
AlphaBlend = 1,
|
AlphaMask = 1,
|
||||||
AlphaMask = 2,
|
AlphaBlend = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
albedo: Vec4 = Vec4.one(),
|
albedo: Vec4 = Vec4.one(),
|
||||||
|
16
src/math.zig
16
src/math.zig
@ -84,19 +84,14 @@ pub const AABB = struct {
|
|||||||
return AABB{ .origin = origin, .extents = extents };
|
return AABB{ .origin = origin, .extents = extents };
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: optimize
|
|
||||||
pub fn transform(self: *const AABB, matrix: Mat4) AABB {
|
pub fn transform(self: *const AABB, matrix: Mat4) AABB {
|
||||||
var min = Vec3.new(std.math.floatMax(f32), std.math.floatMax(f32), std.math.floatMax(f32));
|
var origin = self.origin.toVec4(1.0);
|
||||||
var max = Vec3.new(std.math.floatMin(f32), std.math.floatMin(f32), std.math.floatMin(f32));
|
var extents = self.extents.toVec4(0.0);
|
||||||
|
|
||||||
inline for (box_corners) |corner| {
|
origin = matrix.mulByVec4(origin);
|
||||||
const corner_pos = matrix.mulByVec4(self.origin.add(self.extents.mul(corner)).toVec4(1));
|
extents = matrix.mulByVec4(extents);
|
||||||
const corner_pos3 = corner_pos.toVec3();
|
|
||||||
min = corner_pos3.min(min);
|
|
||||||
max = corner_pos3.max(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
return AABB.fromMinMax(min, max);
|
return AABB{ .origin = origin.toVec3(), .extents = extents.toVec3() };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toSphere(self: *const AABB) BoundingSphere {
|
pub fn toSphere(self: *const AABB) BoundingSphere {
|
||||||
@ -232,6 +227,7 @@ pub const Frustum = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn intersectAABB(self: *const Frustum, aabb: AABB) bool {
|
pub fn intersectAABB(self: *const Frustum, aabb: AABB) bool {
|
||||||
|
@setRuntimeSafety(false);
|
||||||
return self.intersectAABBInternal(aabb, false);
|
return self.intersectAABBInternal(aabb, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,10 +218,8 @@ fn processScene(allocator: std.mem.Allocator, input: []const u8, output_dir: std
|
|||||||
// TODO: rgba
|
// TODO: rgba
|
||||||
mat_output.albedo = Vec4.new(base_color.r, base_color.g, base_color.b, base_color.a);
|
mat_output.albedo = Vec4.new(base_color.r, base_color.g, base_color.b, base_color.a);
|
||||||
|
|
||||||
if (std.math.approxEqAbs(f32, base_color.a, 0.0, std.math.floatEps(f32))) {
|
if (base_color.a < 1.0) {
|
||||||
mat_output.blend_mode = .AlphaMask;
|
mat_output.blend_mode = .AlphaMask;
|
||||||
} else if (base_color.a < 1.0) {
|
|
||||||
mat_output.blend_mode = .AlphaBlend;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +229,7 @@ fn processScene(allocator: std.mem.Allocator, input: []const u8, output_dir: std
|
|||||||
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs, &has_alpha);
|
const entry = mat_texture.path.resolveAssetListEntry(texture_outputs, &has_alpha);
|
||||||
mat_output.albedo_map.id = entry.getAssetId();
|
mat_output.albedo_map.id = entry.getAssetId();
|
||||||
if (has_alpha) {
|
if (has_alpha) {
|
||||||
mat_output.blend_mode = .AlphaBlend;
|
mat_output.blend_mode = .AlphaMask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user