Switch to using [0, 1] depth in NDC like DirectX and Vulkan

This commit is contained in:
sergeypdev 2024-03-04 22:39:57 +04:00
parent 83b9d64235
commit 2e8ae535a8
4 changed files with 50 additions and 6 deletions

View File

@ -220,7 +220,8 @@ vec3 microfacetModel(Material mat, int light_idx, Light light, vec3 P, vec3 N) {
vec4 shadow_pos = light.shadow_vp * vec4(VertexOut.wPos, 1.0);
shadow_pos.xy = (light.shadow_vp * (vec4(VertexOut.wPos, 1.0) + shadow_offset)).xy;
shadow_pos /= shadow_pos.w;
shadow_pos.xyz = shadow_pos.xyz * 0.5 + 0.5; // [-1, 1] to [0, 1]
shadow_pos.xy = shadow_pos.xy * 0.5 + 0.5; // [-1, 1] to [0, 1]
shadow_pos.z = min(shadow_pos.z, 1);
shadow_pos.z -= constant_bias;

View File

@ -53,6 +53,8 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
.assetman = assetman,
};
gl.clipControl(gl.LOWER_LEFT, gl.ZERO_TO_ONE); // use [0, 1] depth in NDC
var buffer_align_int: gl.GLint = 0;
gl.getIntegerv(gl.UNIFORM_BUFFER_OFFSET_ALIGNMENT, &buffer_align_int);
@ -151,11 +153,15 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
gl.textureParameteri(render.shadow_texture_array, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
gl.textureParameteri(render.shadow_texture_array, gl.TEXTURE_COMPARE_FUNC, gl.LESS);
var border = [_]f32{1} ** 4;
gl.textureParameterfv(render.shadow_texture_array, gl.TEXTURE_BORDER_COLOR, &border);
checkGLError();
gl.textureParameteri(render.shadow_texture_array, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_BORDER);
gl.textureParameteri(render.shadow_texture_array, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_BORDER);
gl.textureParameteri(render.shadow_texture_array, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.textureParameteri(render.shadow_texture_array, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.textureParameterfv(render.shadow_texture_array, gl.TEXTURE_BORDER_COLOR, @ptrCast(&Vec4.one().data));
}
// First shadow texture handle
@ -199,6 +205,8 @@ pub fn init(allocator: std.mem.Allocator, frame_arena: std.mem.Allocator, assetm
gl.createFramebuffers(1, &render.shadow_framebuffer);
checkGLError();
std.debug.assert(render.shadow_framebuffer != 0);
gl.namedFramebufferDrawBuffer(render.shadow_framebuffer, gl.NONE);
gl.namedFramebufferReadBuffer(render.shadow_framebuffer, gl.NONE);
}
gl.namedFramebufferTextureLayer(render.shadow_framebuffer, gl.DEPTH_ATTACHMENT, render.shadow_texture_array, 0, 0);
@ -311,7 +319,7 @@ pub fn finish(self: *Render) void {
const camera_matrix = &self.shadow_matrices;
camera_matrix.* = .{
.projection = Mat4.orthographic(-2, 2, -2, 2, -5, 5),
.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(),
@ -349,7 +357,7 @@ pub fn finish(self: *Render) void {
const near_far = Vec2.new(0.1, 10);
const camera_matrix = &self.shadow_matrices;
camera_matrix.* = .{
.projection = Mat4.perspective(90, 1, near_far.x(), near_far.y()),
.projection = math.perspective(90, 1, near_far.x(), near_far.y()),
.view = Mat4.lookAt(
pos,
pos.add(cam_dir.target),
@ -359,6 +367,7 @@ pub fn finish(self: *Render) void {
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());
@ -646,7 +655,7 @@ pub const Camera = struct {
view_mat: Mat4 = Mat4.identity(),
pub fn projection(self: *const Camera) Mat4 {
return Mat4.perspective(self.fovy, self.aspect, self.near, self.far);
return math.perspective(self.fovy, self.aspect, self.near, self.far);
}
};

View File

@ -113,7 +113,7 @@ fn loadGL() void {
@panic("gl.load");
};
gl.debugMessageCallback(glDebugCallback, null);
// gl.enable(gl.DEBUG_OUTPUT);
gl.enable(gl.DEBUG_OUTPUT);
gl.enable(gl.DEBUG_OUTPUT_SYNCHRONOUS);
}

View File

@ -170,3 +170,37 @@ pub fn checkAABBIntersectionNDC(aabb: *const AABB, mvp: *const Mat4) bool {
return !(outside_left_plane or outside_right_plane or outside_bottom_plane or outside_top_plane or outside_near_plane or outside_far_plane);
}
/// Formulas from D3DXMatrixPerspectiveFovRH
/// Maps z to [0, 1]
pub fn perspective(fovy_in_degrees: f32, aspect_ratio: f32, z_near: f32, z_far: f32) Mat4 {
var result = Mat4.identity();
const f = 1 / @tan(za.toRadians(fovy_in_degrees) * 0.5);
result.data[0][0] = f / aspect_ratio;
result.data[1][1] = f;
result.data[2][2] = z_far / (z_near - z_far);
result.data[2][3] = -1;
result.data[3][2] = z_far * z_near / (z_near - z_far);
result.data[3][3] = 0;
return result;
}
/// Formulas from D3DXMatrixOrthoOffCenterRH
/// Maps z to [0, 1]
pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, z_near: f32, z_far: f32) Mat4 {
var result = Mat4.zero();
result.data[0][0] = 2 / (right - left);
result.data[1][1] = 2 / (top - bottom);
result.data[2][2] = 2 / (z_near - z_far);
result.data[3][3] = 1;
result.data[3][0] = (left + right) / (left - right);
result.data[3][1] = (bottom + top) / (bottom - top);
result.data[3][2] = z_near / (z_near - z_far);
return result;
}