Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions Lorr/Editor/Window/SceneBrowserWindow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,6 @@ static auto draw_hierarchy(SceneBrowserWindow &self) -> void {
created_entity.child_of(active_scene->get_root());
}

ImGui::Separator();

if (ImGui::MenuItem("Environment")) {
auto created_entity = active_scene->create_entity();
created_entity.set<lr::ECS::Transform>({});
created_entity.set<lr::ECS::Environment>({});
created_entity.child_of(active_scene->get_root());
}

ImGui::EndMenu();
}

Expand Down
2 changes: 1 addition & 1 deletion Lorr/Engine/Graphics/Slang/Compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ auto SlangCompiler::new_session(const SlangSessionInfo &info) -> ls::option<Slan
.format = SLANG_SPIRV,
.profile = impl->global_session->findProfile("spirv_1_5"),
.flags = SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY,
//.floatingPointMode = SLANG_FLOATING_POINT_MODE_FAST,
.floatingPointMode = SLANG_FLOATING_POINT_MODE_FAST,
.lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_STANDARD,
.forceGLSLScalarBufferLayout = true,
.compilerOptionEntries = entries,
Expand Down
55 changes: 31 additions & 24 deletions Lorr/Engine/Resources/shaders/passes/cull_meshes.slang
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@ import scene;
import cull;
import debug_drawer;

[[vk::binding(0)]] ConstantBuffer<Camera> camera;
[[vk::binding(1)]] StructuredBuffer<Mesh> meshes;
[[vk::binding(2)]] StructuredBuffer<Transform> transforms;
[[vk::binding(3)]] Image2D<f32> hiz_image;
[[vk::binding(4)]] Sampler hiz_sampler;
[[vk::binding(5)]] RWStructuredBuffer<MeshInstance> mesh_instances;
[[vk::binding(6)]] RWStructuredBuffer<MeshletInstance> meshlet_instances;
[[vk::binding(7)]] RWStructuredBuffer<u32> visible_meshlet_instances_count;
[[vk::binding(8)]] RWStructuredBuffer<DebugDrawer> debug_drawer;
[[vk::binding(0)]] StructuredBuffer<Mesh> meshes;
[[vk::binding(1)]] StructuredBuffer<Transform> transforms;
[[vk::binding(2)]] RWStructuredBuffer<MeshInstance> mesh_instances;
[[vk::binding(3)]] RWStructuredBuffer<MeshletInstance> meshlet_instances;
[[vk::binding(4)]] RWStructuredBuffer<u32> visible_meshlet_instances_count;
[[vk::binding(5)]] RWStructuredBuffer<DebugDrawer> debug_drawer;

#ifndef CULLING_MESHES_COUNT
#define CULLING_MESHES_COUNT 64
#ifndef CULLING_MESH_COUNT
#define CULLING_MESH_COUNT 64
#endif

[[shader("compute")]]
[[numthreads(CULLING_MESHES_COUNT, 1, 1)]]
[[numthreads(CULLING_MESH_COUNT, 1, 1)]]
func cs_main(
uint3 thread_id : SV_DispatchThreadID,
uniform u32 mesh_instances_count,
uniform CullFlags cull_flags
uniform CullFlags cull_flags,
uniform f32x4x4 frustum_projection_view,
uniform f32x3 observer_position,
uniform f32 observer_max_resolution,
uniform f32 observer_acceptable_lod_error
) -> void {
let mesh_instance_index = thread_id.x;
if (mesh_instance_index >= mesh_instances_count) {
Expand All @@ -33,7 +34,7 @@ func cs_main(
let mesh_instance = &mesh_instances[mesh_instance_index];
let mesh = meshes[mesh_instance.mesh_index];
let transform = transforms[mesh_instance.transform_index];
let mvp = mul(camera.projection_view_mat, transform.world);
let mvp = mul(frustum_projection_view, transform.world);

let cull_frustum = (cull_flags & CullFlags::MeshFrustum) != 0;
if (cull_frustum && !test_frustum(mvp, mesh.bounds.aabb_center, mesh.bounds.aabb_extent)) {
Expand All @@ -45,33 +46,39 @@ func cs_main(
// Credits:
// - https://github.com/Sunset-Flock/Timberdoodle/blob/786f141e261dff4756e7f1a67dd7f7a5e1277956/src/scene/mesh_lod.hpp#L45
let aabb_center = mul(transform.world, f32x4(mesh.bounds.aabb_center, 1.0)).xyz;
let aabb_extent_x = length(transform.world[0]) * mesh.bounds.aabb_extent.x;
let aabb_extent_y = length(transform.world[1]) * mesh.bounds.aabb_extent.y;
let aabb_extent_z = length(transform.world[2]) * mesh.bounds.aabb_extent.z;
let aabb_rough_extent = max(max(aabb_extent_x, aabb_extent_y), aabb_extent_z);
let aabb_rough_camera_distance = max(length(aabb_center - camera.position) - 0.5 * aabb_rough_extent, 0.0);
let aabb_extent = mul(transform.world, f32x4(mesh.bounds.aabb_extent, 0.0)).xyz;
let aabb_rough_extent = max(aabb_extent.x, max(aabb_extent.y, aabb_extent.z));
let aabb_rough_camera_distance = max(length(aabb_center - observer_position) - 0.5 * aabb_rough_extent, 0.0);

// Avoiding the atan here
let rough_resolution = max(camera.resolution.x, camera.resolution.y);
let fov90_distance_to_screen_ratio = 2.0f;
let pixel_size_at_1m = fov90_distance_to_screen_ratio / rough_resolution;
let pixel_size_at_1m = fov90_distance_to_screen_ratio / observer_max_resolution;
let aabb_size_at_1m = (aabb_rough_extent / aabb_rough_camera_distance);
let rough_aabb_pixel_size = aabb_size_at_1m / pixel_size_at_1m;

for (var i = 1; i < mesh.lod_count; i++) {
let mesh_lod = mesh.lods[i];
let rough_pixel_error = rough_aabb_pixel_size * mesh_lod.error;
if (rough_pixel_error < camera.acceptable_lod_error) {
if (rough_pixel_error < observer_acceptable_lod_error) {
lod_index = i;
} else {
break;
}
}
#endif

#ifdef DEBUG_DRAW
var debug_aabb = DebugAABB();
debug_aabb.position = aabb_center;
debug_aabb.size = aabb_extent;
debug_aabb.color = f32x3(0.0, 0.0, 1.0);
debug_aabb.coord = DebugDrawCoord::World;
debug_draw_aabb(debug_drawer[0], debug_aabb);
#endif

mesh_instance.lod_index = lod_index;
let mesh_lod = mesh.lods[lod_index];
let meshlet_count = mesh_lod.meshlet_count;
var base_meshlet_instance_offset = __atomic_add(visible_meshlet_instances_count[2], meshlet_count, MemoryOrder::Relaxed);
var base_meshlet_instance_offset = __atomic_add(visible_meshlet_instances_count[0], meshlet_count, MemoryOrder::Relaxed);
for (u32 i = 0; i < meshlet_count; i++) {
let offset = base_meshlet_instance_offset + i;
meshlet_instances[offset].mesh_instance_index = mesh_instance_index;
Expand Down
76 changes: 34 additions & 42 deletions Lorr/Engine/Resources/shaders/passes/cull_meshlets.slang
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,20 @@ import std;
import gpu;
import scene;
import cull;
import debug_drawer;

#include <assert.slang>

[[vk::constant_id(0)]] const bool LATE = false;
[[vk::binding(0)]] ConstantBuffer<Camera> camera;
[[vk::binding(1)]] StructuredBuffer<MeshletInstance> meshlet_instances;
[[vk::binding(2)]] StructuredBuffer<MeshInstance> mesh_instances;
[[vk::binding(3)]] StructuredBuffer<Mesh> meshes;
[[vk::binding(4)]] StructuredBuffer<Transform> transforms;
[[vk::binding(5)]] Image2D<f32> hiz_image;
[[vk::binding(6)]] Sampler hiz_sampler;
[[vk::binding(7)]] RWStructuredBuffer<u32> visible_meshlet_instances_count;
[[vk::binding(8)]] RWStructuredBuffer<u32> visible_meshlet_instances_indices;
[[vk::binding(9)]] RWStructuredBuffer<u32> meshlet_instance_visibility_mask;
[[vk::binding(10)]] RWStructuredBuffer<DispatchIndirectCommand> cull_triangles_cmd;
[[vk::binding(11)]] RWStructuredBuffer<DebugDrawer> debug_drawer;
[[vk::binding(0)]] StructuredBuffer<MeshletInstance> meshlet_instances;
[[vk::binding(1)]] StructuredBuffer<MeshInstance> mesh_instances;
[[vk::binding(2)]] StructuredBuffer<Mesh> meshes;
[[vk::binding(3)]] StructuredBuffer<Transform> transforms;
[[vk::binding(4)]] Image2D<f32> hiz_image;
[[vk::binding(5)]] Sampler hiz_sampler;
[[vk::binding(6)]] StructuredBuffer<u32> visible_meshlet_instances_count;
[[vk::binding(7)]] RWStructuredBuffer<u32> early_visible_meshlet_instances_count;
[[vk::binding(8)]] RWStructuredBuffer<u32> late_visible_meshlet_instances_count;
[[vk::binding(9)]] RWStructuredBuffer<u32> visible_meshlet_instances_indices;
[[vk::binding(10)]] RWStructuredBuffer<u32> meshlet_instance_visibility_mask;
[[vk::binding(11)]] RWStructuredBuffer<DispatchIndirectCommand> cull_triangles_cmd;

#ifndef CULLING_MESHLET_COUNT
#define CULLING_MESHLET_COUNT 64
Expand All @@ -29,9 +26,11 @@ import debug_drawer;
func cs_main(
uint group_thread_id : SV_GroupThreadID,
uint global_thread_id : SV_DispatchThreadID,
uniform CullFlags cull_flags
uniform CullFlags cull_flags,
uniform f32 near_clip,
uniform f32x4x4 projection_view,
) -> void {
let meshlet_instance_count = visible_meshlet_instances_count[2];
let meshlet_instance_count = visible_meshlet_instances_count[0];
let meshlet_instance_index = global_thread_id;
if (meshlet_instance_index >= meshlet_instance_count) {
return;
Expand All @@ -40,7 +39,7 @@ func cs_main(
let meshlet_instance = meshlet_instances[meshlet_instance_index];
let mesh_instance = mesh_instances[meshlet_instance.mesh_instance_index];
let transform = transforms[mesh_instance.transform_index];
let mvp = mul(camera.projection_view_mat, transform.world);
let mvp = mul(projection_view, transform.world);

let mesh = meshes[mesh_instance.mesh_index];
let mesh_lod = mesh.lods[mesh_instance.lod_index];
Expand All @@ -49,42 +48,35 @@ func cs_main(
let cull_frustum = (cull_flags & CullFlags::MeshletFrustum) != 0;
let cull_occlusion = (cull_flags & CullFlags::MeshletOcclusion) != 0;

let meshlet_instance_visibility_index = mesh_instance.meshlet_instance_visibility_offset + meshlet_instance.meshlet_index;
let mask_index = meshlet_instance_visibility_index / 32;
let bit_index = meshlet_instance_visibility_index - mask_index * 32;
let visibility_bit = 1 << bit_index;
let was_visible = (meshlet_instance_visibility_mask[mask_index] & visibility_bit) != 0;
var visibility_mask_index = 0;
var visibility_bit = 0;
var was_visible = false;
if (cull_occlusion) {
let meshlet_instance_visibility_index = mesh_instance.meshlet_instance_visibility_offset + meshlet_instance.meshlet_index;
visibility_mask_index = meshlet_instance_visibility_index / 32;
let bit_index = meshlet_instance_visibility_index - visibility_mask_index * 32;
visibility_bit = 1 << bit_index;
was_visible = (meshlet_instance_visibility_mask[visibility_mask_index] & visibility_bit) != 0;
}

var visible = LATE ? true : was_visible;
if (visible && cull_frustum) {
visible = test_frustum(mvp, bounds.aabb_center, bounds.aabb_extent);
}

if (LATE && visible && cull_occlusion) {
if (let screen_aabb = project_aabb(mvp, camera.near_clip, bounds.aabb_center, bounds.aabb_extent)) {
if (let screen_aabb = project_aabb(mvp, near_clip, bounds.aabb_center, bounds.aabb_extent)) {
visible = !test_occlusion(screen_aabb, hiz_image, hiz_sampler);
#ifdef DEBUG_DRAW
if (visible) {
let ndc_aabb_max = screen_aabb.max.xy * 2.0 - 1.0;
let ndc_aabb_min = screen_aabb.min.xy * 2.0 - 1.0;
var debug_rect = DebugRect();
debug_rect.offset = f32x3((ndc_aabb_max + ndc_aabb_min) * 0.5, screen_aabb.max.z);
debug_rect.extent = ndc_aabb_max - ndc_aabb_min;
debug_rect.color = f32x3(1.0, 0.0, 0.0);
debug_rect.coord = DebugDrawCoord::NDC;
debug_draw_rect(debug_drawer[0], debug_rect);
}
#endif
}
}

if (visible && (!LATE || !was_visible)) {
var index = 0;
if (!LATE) {
index = __atomic_add(visible_meshlet_instances_count[0], 1, MemoryOrder::Relaxed);
index = __atomic_add(early_visible_meshlet_instances_count[0], 1, MemoryOrder::Relaxed);
} else {
let early_count = visible_meshlet_instances_count[0];
let late_offset = __atomic_add(visible_meshlet_instances_count[1], 1, MemoryOrder::Relaxed);
let early_count = early_visible_meshlet_instances_count[0];
let late_offset = __atomic_add(late_visible_meshlet_instances_count[0], 1, MemoryOrder::Relaxed);
index = early_count + late_offset;
}

Expand All @@ -93,11 +85,11 @@ func cs_main(
__atomic_add(cull_triangles_cmd[0].x, 1, MemoryOrder::Relaxed);
}

if (LATE) {
if (LATE && cull_occlusion) {
if (visible) {
__atomic_or(meshlet_instance_visibility_mask[mask_index], visibility_bit, MemoryOrder::Relaxed);
__atomic_or(meshlet_instance_visibility_mask[visibility_mask_index], visibility_bit, MemoryOrder::Relaxed);
} else {
__atomic_and(meshlet_instance_visibility_mask[mask_index], ~visibility_bit, MemoryOrder::Relaxed);
__atomic_and(meshlet_instance_visibility_mask[visibility_mask_index], ~visibility_bit, MemoryOrder::Relaxed);
}
}
}
32 changes: 15 additions & 17 deletions Lorr/Engine/Resources/shaders/passes/cull_triangles.slang
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
module cull_triangles;

import std;
import gpu;
import scene;

import passes.visbuffer;

[[vk::constant_id(0)]] const bool LATE = false;
[[vk::binding(0)]] ConstantBuffer<Camera> camera;
[[vk::binding(1)]] StructuredBuffer<u32> visible_meshlet_instances_count;
[[vk::binding(2)]] StructuredBuffer<u32> visible_meshlet_instances_indices;
[[vk::binding(3)]] StructuredBuffer<MeshletInstance> meshlet_instances;
[[vk::binding(4)]] StructuredBuffer<MeshInstance> mesh_instances;
[[vk::binding(5)]] StructuredBuffer<Mesh> meshes;
[[vk::binding(6)]] StructuredBuffer<Transform> transforms;
[[vk::binding(7)]] RWStructuredBuffer<DrawIndexedIndirectCommand> draw_cmd;
[[vk::binding(8)]] RWStructuredBuffer<u32> reordered_indices;
[[vk::binding(0)]] StructuredBuffer<u32> early_visible_meshlet_instances_count;
[[vk::binding(1)]] StructuredBuffer<u32> visible_meshlet_instances_indices;
[[vk::binding(2)]] StructuredBuffer<MeshletInstance> meshlet_instances;
[[vk::binding(3)]] StructuredBuffer<MeshInstance> mesh_instances;
[[vk::binding(4)]] StructuredBuffer<Mesh> meshes;
[[vk::binding(5)]] StructuredBuffer<Transform> transforms;
[[vk::binding(6)]] RWStructuredBuffer<DrawIndexedIndirectCommand> draw_cmd;
[[vk::binding(7)]] RWStructuredBuffer<u32> reordered_indices;

groupshared u32 base_index_shared;
groupshared u32 triangles_passed_shared;
Expand Down Expand Up @@ -111,11 +108,13 @@ func test_triangle(in f32x3x3 positions, in f32x2 resolution, CullFlags cull_fla
func cs_main(
uint3 group_id : SV_GroupID,
uint3 group_thread_id : SV_GroupThreadID,
uniform CullFlags cull_flags
uniform CullFlags cull_flags,
uniform f32x2 resolution,
uniform f32x4x4 projection_view
) -> void {
var visible_meshlet_instance_index = group_id.x;
if (LATE) {
visible_meshlet_instance_index += visible_meshlet_instances_count[0];
visible_meshlet_instance_index += early_visible_meshlet_instances_count[0];
}

let local_index = group_thread_id.x;
Expand All @@ -134,7 +133,7 @@ func cs_main(
meshlet_triangle_count_shared = meshlet.triangle_count;

let transform = transforms[mesh_instance.transform_index];
model_view_proj_shared = mul(camera.projection_view_mat, transform.world);
model_view_proj_shared = mul(projection_view, transform.world);
}

GroupMemoryBarrierWithGroupSync();
Expand All @@ -148,8 +147,7 @@ func cs_main(

let indices = meshlet.indices(mesh_lod, local_index);
let positions = meshlet.positions(mesh, indices);
triangle_passed = test_triangle(positions, camera.resolution, cull_flags, local_index);
triangle_passed = true;
triangle_passed = test_triangle(positions, resolution, cull_flags, local_index);
if (triangle_passed) {
active_triangle_index = __atomic_add(triangles_passed_shared, 1, MemoryOrder::Relaxed);
}
Expand All @@ -169,4 +167,4 @@ func cs_main(
reordered_indices[index_offset + 1] = (meshlet_instance_index << MESHLET_PRIMITIVE_BITS) | ((triangle_index + 1) & MESHLET_PRIMITIVE_MASK);
reordered_indices[index_offset + 2] = (meshlet_instance_index << MESHLET_PRIMITIVE_BITS) | ((triangle_index + 2) & MESHLET_PRIMITIVE_MASK);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import gpu;
[[shader("compute")]]
[[numthreads(1, 1, 1)]]
func cs_main() -> void {
cull_meshlets_cmd[0].x = (visible_meshlet_instances_count[2] + (CULLING_MESHLET_COUNT - 1)) / CULLING_MESHLET_COUNT;
cull_meshlets_cmd[0].x = (visible_meshlet_instances_count[0] + (CULLING_MESHLET_COUNT - 1)) / CULLING_MESHLET_COUNT;
}
10 changes: 5 additions & 5 deletions Lorr/Engine/Resources/shaders/passes/histogram_average.slang
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import scene;
#include <passes/histogram.slang>

struct ShaderParameters {
ConstantBuffer<Environment> environment;
ConstantBuffer<EyeAdaptation> eye_adaptation;
StructuredBuffer<u32> histogram_bin_indices;

RWStructuredBuffer<HistogramLuminance> luminance;
Expand Down Expand Up @@ -40,15 +40,15 @@ func cs_main(
}

if (gid == 0) {
let exposure_range = params.environment.eye_max_exposure - params.environment.eye_min_exposure;
let time_coeff = clamp(1.0 - exp(-params.environment.eye_adaptation_speed * delta_time), 0.0f, 1.0f);
let exposure_range = params.eye_adaptation.max_exposure - params.eye_adaptation.min_exposure;
let time_coeff = clamp(1.0 - exp(-params.eye_adaptation.adaptation_speed * delta_time), 0.0f, 1.0f);

let weighted_average_log2 = (histogram_shared[0] / max(pixel_count - count_for_this_bin, 1.0)) - 1.0;
let desired_luminance =
exp2(((weighted_average_log2 / (HISTOGRAM_BIN_COUNT - 1)) * exposure_range) + params.environment.eye_min_exposure);
exp2(((weighted_average_log2 / (HISTOGRAM_BIN_COUNT - 1)) * exposure_range) + params.eye_adaptation.min_exposure);
let last_luminance = params.luminance[0].adapted_luminance;
let adapted_luminance = last_luminance + (desired_luminance - last_luminance) * time_coeff;
let ev100 = ev100_from_luminance(adapted_luminance, params.environment.eye_ISO_K);
let ev100 = ev100_from_luminance(adapted_luminance, params.eye_adaptation.ISO_K);
let exposure = 1.0 / (exp2(ev100) * 1.2);
params.luminance[0] = HistogramLuminance(adapted_luminance, exposure);
}
Expand Down
5 changes: 2 additions & 3 deletions Lorr/Engine/Resources/shaders/passes/histogram_generate.slang
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import scene;

struct ShaderParameters {
Image2D<f32x4> src_image;

ConstantBuffer<Environment> environment;
ConstantBuffer<EyeAdaptation> eye_adaptation;

RWStructuredBuffer<u32> histogram_bin_indices;
};
Expand Down Expand Up @@ -40,7 +39,7 @@ func cs_main(
if (all(thread_id.xy < src_extent.xy)) {
const f32x3 color = params.src_image.Load(u32x3(thread_id.xy, 0)).rgb;
const f32 luminance = std::rec2020_to_xyz(color).y;
const u32 bin_index = bin_lum(luminance, params.environment.eye_max_exposure, params.environment.eye_min_exposure);
const u32 bin_index = bin_lum(luminance, params.eye_adaptation.max_exposure, params.eye_adaptation.min_exposure);
__atomic_add(histogram_shared[bin_index], 1, MemoryOrder::AcquireRelease);
}

Expand Down
Loading
Loading