work on editor
This commit is contained in:
parent
8668157060
commit
1bfe79fc6b
@ -24,149 +24,4 @@ VK_KHR_deferred_host_operations
|
||||
VK_KHR_acceleration_structure
|
||||
VK_KHR_ray_query
|
||||
|
||||
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
|
||||
_______________
|
||||
Vulkan Version:
|
||||
- available: 1.4.309
|
||||
- requesting: 1.3.0
|
||||
______________________
|
||||
Used Instance Layers :
|
||||
VK_LAYER_KHRONOS_validation
|
||||
|
||||
Used Instance Extensions :
|
||||
____________________
|
||||
Devices : 1
|
||||
0: AMD Radeon RX 6950 XT
|
||||
- Compatible
|
||||
Compatible physical devices found : 1
|
||||
Using Device:
|
||||
- Device Name : AMD Radeon RX 6950 XT
|
||||
- Vendor : AMD
|
||||
- Driver Version : 2.0.341
|
||||
- API Version : 1.4.308
|
||||
- Device Type : Discrete GPU
|
||||
________________________
|
||||
Used Device Extensions :
|
||||
VK_KHR_deferred_host_operations
|
||||
VK_KHR_acceleration_structure
|
||||
VK_KHR_ray_query
|
||||
|
||||
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
|
||||
_______________
|
||||
Vulkan Version:
|
||||
- available: 1.4.309
|
||||
- requesting: 1.3.0
|
||||
______________________
|
||||
Used Instance Layers :
|
||||
VK_LAYER_KHRONOS_validation
|
||||
|
||||
Used Instance Extensions :
|
||||
____________________
|
||||
Devices : 1
|
||||
0: AMD Radeon RX 6950 XT
|
||||
- Compatible
|
||||
Compatible physical devices found : 1
|
||||
Using Device:
|
||||
- Device Name : AMD Radeon RX 6950 XT
|
||||
- Vendor : AMD
|
||||
- Driver Version : 2.0.341
|
||||
- API Version : 1.4.308
|
||||
- Device Type : Discrete GPU
|
||||
________________________
|
||||
Used Device Extensions :
|
||||
VK_KHR_deferred_host_operations
|
||||
VK_KHR_acceleration_structure
|
||||
VK_KHR_ray_query
|
||||
|
||||
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
|
||||
_______________
|
||||
Vulkan Version:
|
||||
- available: 1.4.309
|
||||
- requesting: 1.3.0
|
||||
______________________
|
||||
Used Instance Layers :
|
||||
VK_LAYER_KHRONOS_validation
|
||||
|
||||
Used Instance Extensions :
|
||||
____________________
|
||||
Devices : 1
|
||||
0: AMD Radeon RX 6950 XT
|
||||
- Compatible
|
||||
Compatible physical devices found : 1
|
||||
Using Device:
|
||||
- Device Name : AMD Radeon RX 6950 XT
|
||||
- Vendor : AMD
|
||||
- Driver Version : 2.0.341
|
||||
- API Version : 1.4.308
|
||||
- Device Type : Discrete GPU
|
||||
________________________
|
||||
Used Device Extensions :
|
||||
VK_KHR_deferred_host_operations
|
||||
VK_KHR_acceleration_structure
|
||||
VK_KHR_ray_query
|
||||
|
||||
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
|
||||
_______________
|
||||
Vulkan Version:
|
||||
- available: 1.4.309
|
||||
- requesting: 1.3.0
|
||||
______________________
|
||||
Used Instance Layers :
|
||||
VK_LAYER_KHRONOS_validation
|
||||
|
||||
Used Instance Extensions :
|
||||
____________________
|
||||
Devices : 1
|
||||
0: AMD Radeon RX 6950 XT
|
||||
- Compatible
|
||||
Compatible physical devices found : 1
|
||||
Using Device:
|
||||
- Device Name : AMD Radeon RX 6950 XT
|
||||
- Vendor : AMD
|
||||
- Driver Version : 2.0.341
|
||||
- API Version : 1.4.308
|
||||
- Device Type : Discrete GPU
|
||||
________________________
|
||||
Used Device Extensions :
|
||||
VK_KHR_deferred_host_operations
|
||||
VK_KHR_acceleration_structure
|
||||
VK_KHR_ray_query
|
||||
|
||||
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
|
||||
_______________
|
||||
Vulkan Version:
|
||||
- available: 1.4.309
|
||||
- requesting: 1.3.0
|
||||
______________________
|
||||
Used Instance Layers :
|
||||
VK_LAYER_KHRONOS_validation
|
||||
|
||||
Used Instance Extensions :
|
||||
____________________
|
||||
Devices : 1
|
||||
0: AMD Radeon RX 6950 XT
|
||||
- Compatible
|
||||
Compatible physical devices found : 1
|
||||
Using Device:
|
||||
- Device Name : AMD Radeon RX 6950 XT
|
||||
- Vendor : AMD
|
||||
- Driver Version : 2.0.341
|
||||
- API Version : 1.4.308
|
||||
- Device Type : Discrete GPU
|
||||
________________________
|
||||
Used Device Extensions :
|
||||
VK_KHR_deferred_host_operations
|
||||
VK_KHR_acceleration_structure
|
||||
VK_KHR_ray_query
|
||||
|
||||
BLAS Compaction: 0.7MB -> 0.2MB (0.4MB saved, 66.0% smaller)
|
||||
_______________
|
||||
Vulkan Version:
|
||||
- available: 1.4.309
|
||||
- requesting: 1.3.0
|
||||
______________________
|
||||
Used Instance Layers :
|
||||
VK_LAYER_KHRONOS_validation
|
||||
|
||||
Used Instance Extensions :
|
||||
__________________
|
||||
BLAS Compaction: 1.9MB -> 0.6MB (1.2MB saved, 66.1% smaller)
|
||||
|
||||
@ -20,6 +20,34 @@ cameraCenter : Vector2;
|
||||
|
||||
trile_preview_disabled : bool = false;
|
||||
|
||||
Level_Editor_Tool_Mode :: enum {
|
||||
POINT;
|
||||
BRUSH;
|
||||
AREA;
|
||||
LINE;
|
||||
}
|
||||
|
||||
current_tool_mode : Level_Editor_Tool_Mode = .POINT;
|
||||
brush_radius : int = 2;
|
||||
brush_height : int = 0;
|
||||
|
||||
area_active : bool;
|
||||
area_start_x : int;
|
||||
area_start_y : int;
|
||||
area_start_z : int;
|
||||
|
||||
line_active : bool;
|
||||
line_start_x : int;
|
||||
line_start_y : int;
|
||||
line_start_z : int;
|
||||
|
||||
current_orientation_face : u8 = 0;
|
||||
current_orientation_twist : u8 = 0;
|
||||
|
||||
get_current_orientation :: () -> u8 {
|
||||
return current_orientation_face * 4 + current_orientation_twist;
|
||||
}
|
||||
|
||||
#scope_export
|
||||
|
||||
toggle_preview :: () {
|
||||
@ -248,7 +276,74 @@ editMode : Edit_Mode;
|
||||
|
||||
draw_tools_tab :: (theme: *GR.Overall_Theme, total_r: GR.Rect) {
|
||||
r := total_r;
|
||||
r.h = ui_h(3,0);
|
||||
r.h = ui_h(4, 0);
|
||||
|
||||
// Tool mode buttons
|
||||
if GR.button(r, "Point", *t_button_selectable(theme, current_tool_mode == .POINT)) {
|
||||
current_tool_mode = .POINT;
|
||||
}
|
||||
r.y += r.h;
|
||||
if GR.button(r, "Brush", *t_button_selectable(theme, current_tool_mode == .BRUSH)) {
|
||||
current_tool_mode = .BRUSH;
|
||||
}
|
||||
r.y += r.h;
|
||||
if GR.button(r, "Area", *t_button_selectable(theme, current_tool_mode == .AREA)) {
|
||||
current_tool_mode = .AREA;
|
||||
area_active = false;
|
||||
}
|
||||
r.y += r.h;
|
||||
if GR.button(r, "Line", *t_button_selectable(theme, current_tool_mode == .LINE)) {
|
||||
current_tool_mode = .LINE;
|
||||
line_active = false;
|
||||
}
|
||||
r.y += r.h;
|
||||
|
||||
// Brush radius/height (only for brush mode)
|
||||
if current_tool_mode == .BRUSH {
|
||||
r.h = ui_h(3, 2);
|
||||
GR.label(r, "Brush Radius", *t_label_left(theme));
|
||||
r.y += r.h;
|
||||
r.h = ui_h(4, 0);
|
||||
GR.slider(r, *brush_radius, 1, 8, 1, *theme.slider_theme);
|
||||
r.y += r.h;
|
||||
r.h = ui_h(3, 2);
|
||||
GR.label(r, "Brush Height (±Y layers)", *t_label_left(theme));
|
||||
r.y += r.h;
|
||||
r.h = ui_h(4, 0);
|
||||
GR.slider(r, *brush_height, 0, 8, 1, *theme.slider_theme);
|
||||
r.y += r.h * 2;
|
||||
} else {
|
||||
r.y += r.h;
|
||||
}
|
||||
|
||||
// Status hints for multi-click tools
|
||||
r.h = ui_h(3, 2);
|
||||
if current_tool_mode == .AREA {
|
||||
if area_active {
|
||||
GR.label(r, "Click second corner to fill", *t_label_left(theme));
|
||||
} else {
|
||||
GR.label(r, "Click first corner to start", *t_label_left(theme));
|
||||
}
|
||||
r.y += r.h;
|
||||
} else if current_tool_mode == .LINE {
|
||||
if line_active {
|
||||
GR.label(r, "Click endpoint to draw line", *t_label_left(theme));
|
||||
} else {
|
||||
GR.label(r, "Click start of line", *t_label_left(theme));
|
||||
}
|
||||
r.y += r.h;
|
||||
}
|
||||
|
||||
// Orientation controls
|
||||
r.y += r.h;
|
||||
r.h = ui_h(3, 2);
|
||||
GR.label(r, "-- Orientation --", *t_label_left(theme));
|
||||
r.y += r.h;
|
||||
twist_angle := current_orientation_twist * 90;
|
||||
GR.label(r, tprint("Face: % Twist: %°", current_orientation_face, twist_angle), *t_label_left(theme));
|
||||
r.y += r.h;
|
||||
GR.label(r, "Q/E: twist R: face", *t_label_left(theme));
|
||||
r.y += r.h;
|
||||
}
|
||||
|
||||
handle_tool_click :: (x: int, y: int, z: int, delete: bool = false) {
|
||||
@ -256,10 +351,53 @@ handle_tool_click :: (x: int, y: int, z: int, delete: bool = false) {
|
||||
if delete {
|
||||
remove_trile(cast(s32)x, cast(s32)y, cast(s32)z);
|
||||
} else {
|
||||
if editor_current_trile != null then add_trile(editor_current_trile.name, cast(s32)x, cast(s32)y, cast(s32)z);
|
||||
if editor_current_trile != null then add_trile(editor_current_trile.name, cast(s32)x, cast(s32)y, cast(s32)z, get_current_orientation());
|
||||
}
|
||||
}
|
||||
|
||||
apply_brush :: (cx: int, cy: int, cz: int, delete: bool) {
|
||||
for dy: -brush_height..brush_height {
|
||||
for dx: -brush_radius..brush_radius {
|
||||
for dz: -brush_radius..brush_radius {
|
||||
dist := sqrt(cast(float)(dx*dx + dz*dz));
|
||||
if dist <= cast(float)brush_radius {
|
||||
handle_tool_click(cx + dx, cy + dy, cz + dz, delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply_area :: (x2: int, y2: int, z2: int, delete: bool) {
|
||||
for x: min(area_start_x, x2)..max(area_start_x, x2) {
|
||||
for y: min(area_start_y, y2)..max(area_start_y, y2) {
|
||||
for z: min(area_start_z, z2)..max(area_start_z, z2) {
|
||||
handle_tool_click(x, y, z, delete);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply_line :: (x2: int, y2: int, z2: int, delete: bool) {
|
||||
x1 := line_start_x; y1 := line_start_y; z1 := line_start_z;
|
||||
dx := abs(x2 - x1); dy := abs(y2 - y1); dz := abs(z2 - z1);
|
||||
sx := ifx x1 < x2 then 1 else -1;
|
||||
sy := ifx y1 < y2 then 1 else -1;
|
||||
sz := ifx z1 < z2 then 1 else -1;
|
||||
// 3D Bresenham: drive along the longest axis
|
||||
dm := max(dx, max(dy, dz));
|
||||
x := x1; y := y1; z := z1;
|
||||
ex := dm / 2; ey := dm / 2; ez := dm / 2;
|
||||
count := 0;
|
||||
while count <= dm && count < 2000 {
|
||||
handle_tool_click(x, y, z, delete);
|
||||
ex -= dx; if ex < 0 { x += sx; ex += dm; }
|
||||
ey -= dy; if ey < 0 { y += sy; ey += dm; }
|
||||
ez -= dz; if ez < 0 { z += sz; ez += dm; }
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
add_trile :: (name: string, x: s32, y: s32, z: s32, orientation: u8 = 0) {
|
||||
curworld := get_current_world();
|
||||
|
||||
@ -316,9 +454,25 @@ remove_trile :: (x: s32, y: s32, z: s32) {
|
||||
tick_level_editor :: () {
|
||||
#if HAS_TACOMA { rdm_bake_tick(); }
|
||||
tick_level_editor_camera();
|
||||
|
||||
if !console_open_ignore_input {
|
||||
if input_button_states[#char "Q"] & .START {
|
||||
lastInputTime = get_time();
|
||||
current_orientation_twist = (current_orientation_twist + 1) % 4;
|
||||
}
|
||||
if input_button_states[#char "E"] & .START {
|
||||
lastInputTime = get_time();
|
||||
current_orientation_twist = (current_orientation_twist + 3) % 4;
|
||||
}
|
||||
if input_button_states[#char "R"] & .START {
|
||||
lastInputTime = get_time();
|
||||
current_orientation_face = (current_orientation_face + 1) % 6;
|
||||
}
|
||||
}
|
||||
|
||||
ray := get_mouse_ray(*get_level_editor_camera());
|
||||
hit, point := ray_plane_collision_point(ray, xx editY, 20);
|
||||
|
||||
|
||||
show_trile_preview = false;
|
||||
if hit {
|
||||
show_trile_preview = true;
|
||||
@ -326,20 +480,138 @@ tick_level_editor :: () {
|
||||
trile_preview_y = editY;
|
||||
trile_preview_z = xx floor(point.y);
|
||||
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
|
||||
handle_tool_click(xx floor(point.x), xx editY, xx floor(point.y));
|
||||
}
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
|
||||
handle_tool_click(xx floor(point.x), xx editY, xx floor(point.y), true);
|
||||
px := trile_preview_x;
|
||||
py := trile_preview_y;
|
||||
pz := trile_preview_z;
|
||||
|
||||
if current_tool_mode == .POINT {
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
|
||||
handle_tool_click(px, py, pz);
|
||||
}
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
|
||||
handle_tool_click(px, py, pz, true);
|
||||
}
|
||||
} else if current_tool_mode == .BRUSH {
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .DOWN {
|
||||
apply_brush(px, py, pz, false);
|
||||
}
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .DOWN {
|
||||
apply_brush(px, py, pz, true);
|
||||
}
|
||||
} else if current_tool_mode == .AREA {
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
|
||||
if !area_active {
|
||||
area_active = true;
|
||||
area_start_x = px;
|
||||
area_start_y = py;
|
||||
area_start_z = pz;
|
||||
} else {
|
||||
apply_area(px, py, pz, false);
|
||||
area_active = false;
|
||||
}
|
||||
}
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
|
||||
if area_active then area_active = false;
|
||||
else handle_tool_click(px, py, pz, true);
|
||||
}
|
||||
} else if current_tool_mode == .LINE {
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_LEFT) & .START {
|
||||
if !line_active {
|
||||
line_active = true;
|
||||
line_start_x = px;
|
||||
line_start_y = py;
|
||||
line_start_z = pz;
|
||||
} else {
|
||||
apply_line(px, py, pz, false);
|
||||
line_active = false;
|
||||
}
|
||||
}
|
||||
if get_mouse_state(Key_Code.MOUSE_BUTTON_RIGHT) & .START {
|
||||
if line_active then line_active = false;
|
||||
else handle_tool_click(px, py, pz, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create_level_editor_preview_tasks :: () {
|
||||
curworld := get_current_world();
|
||||
if !curworld.valid then return;
|
||||
if !editor_current_trile then return;
|
||||
|
||||
positions: [..]Vector4;
|
||||
positions.allocator = temp;
|
||||
ori := cast(float) get_current_orientation();
|
||||
|
||||
px := trile_preview_x; py := trile_preview_y; pz := trile_preview_z;
|
||||
|
||||
if current_tool_mode == .POINT {
|
||||
array_add(*positions, .{cast(float)px, cast(float)py, cast(float)pz, ori});
|
||||
} else if current_tool_mode == .BRUSH {
|
||||
for dy: -brush_height..brush_height {
|
||||
for dx: -brush_radius..brush_radius {
|
||||
for dz: -brush_radius..brush_radius {
|
||||
dist := sqrt(cast(float)(dx*dx + dz*dz));
|
||||
if dist <= cast(float)brush_radius {
|
||||
array_add(*positions, .{cast(float)(px+dx), cast(float)(py+dy), cast(float)(pz+dz), ori});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if current_tool_mode == .AREA {
|
||||
if area_active {
|
||||
for x: min(area_start_x, px)..max(area_start_x, px) {
|
||||
for y: min(area_start_y, py)..max(area_start_y, py) {
|
||||
for z: min(area_start_z, pz)..max(area_start_z, pz) {
|
||||
array_add(*positions, .{cast(float)x, cast(float)y, cast(float)z, ori});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
array_add(*positions, .{cast(float)px, cast(float)py, cast(float)pz, ori});
|
||||
}
|
||||
} else if current_tool_mode == .LINE {
|
||||
if line_active {
|
||||
x1 := line_start_x; y1 := line_start_y; z1 := line_start_z;
|
||||
x2 := px; y2 := py; z2 := pz;
|
||||
dx := abs(x2-x1); dy := abs(y2-y1); dz := abs(z2-z1);
|
||||
sx := ifx x1 < x2 then 1 else -1;
|
||||
sy := ifx y1 < y2 then 1 else -1;
|
||||
sz := ifx z1 < z2 then 1 else -1;
|
||||
dm := max(dx, max(dy, dz));
|
||||
x := x1; y := y1; z := z1;
|
||||
ex := dm/2; ey := dm/2; ez := dm/2;
|
||||
count := 0;
|
||||
while count <= dm && count < 2000 {
|
||||
array_add(*positions, .{cast(float)x, cast(float)y, cast(float)z, ori});
|
||||
ex -= dx; if ex < 0 { x += sx; ex += dm; }
|
||||
ey -= dy; if ey < 0 { y += sy; ey += dm; }
|
||||
ez -= dz; if ez < 0 { z += sz; ez += dm; }
|
||||
count += 1;
|
||||
}
|
||||
} else {
|
||||
array_add(*positions, .{cast(float)px, cast(float)py, cast(float)pz, ori});
|
||||
}
|
||||
}
|
||||
|
||||
if positions.count == 0 then return;
|
||||
|
||||
task: Rendering_Task_Trile;
|
||||
task.trile = editor_current_trile.name;
|
||||
task.positions = positions;
|
||||
task.worldConf = *curworld.world.conf;
|
||||
task.is_preview = true;
|
||||
add_rendering_task(task);
|
||||
}
|
||||
|
||||
draw_level_editor :: () {
|
||||
curworld := get_current_world();
|
||||
if !curworld.valid then return;
|
||||
create_set_cam_rendering_task(get_level_editor_camera(), effective_plane_height(*curworld.world.conf));
|
||||
create_world_rendering_tasks(*curworld.world);
|
||||
if show_trile_preview && !trile_preview_disabled {
|
||||
create_level_editor_preview_tasks();
|
||||
}
|
||||
}
|
||||
|
||||
draw_level_editor_ui :: (theme: *GR.Overall_Theme) {
|
||||
|
||||
@ -74,6 +74,59 @@ get_trile_roughness_set :: (trile_name: string) -> u8 {
|
||||
return mask;
|
||||
}
|
||||
|
||||
// Predicted pixel dimensions of a single RDM entry at a given roughness level.
|
||||
// roughness 0 → 512×768, roughness 1 → 256×384, ..., roughness 7 → 4×6.
|
||||
rdm_entry_predicted_size :: (roughness: s32) -> (w: s32, h: s32) {
|
||||
size : s32 = cast(s32)(1 << (8 - roughness));
|
||||
return 2 * size, 3 * size;
|
||||
}
|
||||
|
||||
// Simulate shelf-pack of jobs into a canvas of given width; return total height used.
|
||||
rdm_simulate_pack_height :: (jobs: []RDM_Bake_Job, canvas_w: s32) -> s32 {
|
||||
cx : s32 = 0;
|
||||
cy : s32 = 0;
|
||||
rh : s32 = 0;
|
||||
for job: jobs {
|
||||
w, h := rdm_entry_predicted_size(job.roughness);
|
||||
if cx + w > canvas_w { cy += rh; cx = 0; rh = 0; }
|
||||
cx += w;
|
||||
if h > rh rh = h;
|
||||
}
|
||||
cy += rh;
|
||||
return cy;
|
||||
}
|
||||
|
||||
// Simulate shelf-packing for a chunk's sorted job list and return minimum
|
||||
// power-of-2 atlas dimensions, capped at RDM_ATLAS_SIZE.
|
||||
rdm_calc_chunk_atlas_size :: (jobs: []RDM_Bake_Job) -> (s32, s32) {
|
||||
if jobs.count == 0 return 16, 16;
|
||||
|
||||
// Estimate canvas width from sqrt(total pixel area).
|
||||
total_area : s64 = 0;
|
||||
for job: jobs {
|
||||
w, h := rdm_entry_predicted_size(job.roughness);
|
||||
total_area += cast(s64) w * cast(s64) h;
|
||||
}
|
||||
target_w : s32 = 16;
|
||||
sqrt_area := cast(s32) sqrt(cast(float) total_area) + 1;
|
||||
while target_w < sqrt_area target_w *= 2;
|
||||
|
||||
// Widen until the packed height fits within the width (roughly square).
|
||||
while target_w < RDM_ATLAS_SIZE {
|
||||
if rdm_simulate_pack_height(jobs, target_w) <= target_w break;
|
||||
target_w *= 2;
|
||||
}
|
||||
|
||||
// Round height up to next power of 2.
|
||||
final_height := rdm_simulate_pack_height(jobs, target_w);
|
||||
target_h : s32 = 16;
|
||||
while target_h < final_height target_h *= 2;
|
||||
|
||||
if target_w > RDM_ATLAS_SIZE target_w = RDM_ATLAS_SIZE;
|
||||
if target_h > RDM_ATLAS_SIZE target_h = RDM_ATLAS_SIZE;
|
||||
return target_w, target_h;
|
||||
}
|
||||
|
||||
// Build the Tacoma scene from the world, and emit bake jobs for selected chunks.
|
||||
// If chunk_keys is null, all chunks are queued.
|
||||
rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys: []Chunk_Key = .[]) {
|
||||
@ -205,15 +258,38 @@ rdm_bake_start :: (world: World, quality: s32, include_water: bool, chunk_keys:
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-allocate per-chunk atlas CPU buffers.
|
||||
atlas_bytes := cast(s64) RDM_ATLAS_SIZE * cast(s64) RDM_ATLAS_SIZE * 4 * size_of(float);
|
||||
for job: rdm_bake.jobs {
|
||||
chunk_key := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
|
||||
if !table_contains(*rdm_chunk_bakes, chunk_key) {
|
||||
// Pre-allocate per-chunk atlas CPU buffers with optimal (minimum) sizes.
|
||||
{
|
||||
// Collect unique chunk keys.
|
||||
unique_chunk_keys : [..]Chunk_Key;
|
||||
unique_chunk_keys.allocator = temp;
|
||||
for job: rdm_bake.jobs {
|
||||
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
|
||||
already := false;
|
||||
for unique_chunk_keys { if it == ck { already = true; break; } }
|
||||
if !already array_add(*unique_chunk_keys, ck);
|
||||
}
|
||||
|
||||
for chunk_key: unique_chunk_keys {
|
||||
// Collect this chunk's jobs (already sorted by roughness ascending).
|
||||
this_jobs : [..]RDM_Bake_Job;
|
||||
this_jobs.allocator = temp;
|
||||
for job: rdm_bake.jobs {
|
||||
ck := world_to_chunk_coord(cast(s32) job.world_pos.x, cast(s32) job.world_pos.y, cast(s32) job.world_pos.z);
|
||||
if ck == chunk_key array_add(*this_jobs, job);
|
||||
}
|
||||
|
||||
atlas_w, atlas_h := rdm_calc_chunk_atlas_size(this_jobs);
|
||||
print("RDM atlas for chunk %: %x% (%.1f MB, was % MB)\n",
|
||||
chunk_key, atlas_w, atlas_h,
|
||||
cast(float)(cast(s64) atlas_w * atlas_h * 4 * size_of(float)) / (1024.0 * 1024.0),
|
||||
RDM_ATLAS_SIZE * RDM_ATLAS_SIZE * 4 * size_of(float) / (1024 * 1024));
|
||||
|
||||
atlas_bytes := cast(s64) atlas_w * cast(s64) atlas_h * 4 * size_of(float);
|
||||
bake : RDM_Chunk_Bake;
|
||||
bake.width = RDM_ATLAS_SIZE;
|
||||
bake.height = RDM_ATLAS_SIZE;
|
||||
bake.data = cast(*float) alloc(atlas_bytes);
|
||||
bake.width = atlas_w;
|
||||
bake.height = atlas_h;
|
||||
bake.data = cast(*float) alloc(atlas_bytes);
|
||||
memset(bake.data, 0, atlas_bytes);
|
||||
table_set(*rdm_chunk_bakes, chunk_key, bake);
|
||||
}
|
||||
|
||||
@ -53,6 +53,7 @@ Render_Command_Draw_Trile_Positions :: struct {
|
||||
chunk_key : Chunk_Key;
|
||||
amount : s32;
|
||||
conf : *World_Config;
|
||||
is_preview : bool = false;
|
||||
}
|
||||
|
||||
Render_Command_Update_Trixels :: struct {
|
||||
|
||||
@ -20,7 +20,7 @@ backend_handle_command :: (cmd: *Render_Command) {
|
||||
backend_add_trile_positions(add_command.positions);
|
||||
case .DRAW_TRILE_POSITIONS;
|
||||
draw_command := cast(*Render_Command_Draw_Trile_Positions)cmd;
|
||||
backend_draw_trile_positions(draw_command.trile, draw_command.amount, draw_command.conf, draw_command.chunk_key);
|
||||
backend_draw_trile_positions(draw_command.trile, draw_command.amount, draw_command.conf, draw_command.chunk_key, draw_command.is_preview);
|
||||
case .DRAW_SKY;
|
||||
sky_command := cast(*Render_Command_Sky)cmd;
|
||||
backend_draw_sky(sky_command.worldConfig);
|
||||
@ -115,11 +115,11 @@ backend_add_trile_positions :: (positions : []Vector4) {
|
||||
array_add(*trile_offsets, offset);
|
||||
}
|
||||
|
||||
backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key) {
|
||||
backend_draw_trile_positions :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, is_preview: bool = false) {
|
||||
if in_gbuffer_pass {
|
||||
backend_draw_trile_positions_gbuffer(trile, amount, worldConf);
|
||||
} else {
|
||||
backend_draw_trile_positions_main(trile, amount, worldConf, chunk_key);
|
||||
backend_draw_trile_positions_main(trile, amount, worldConf, chunk_key, is_preview);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ backend_draw_trile_positions_gbuffer :: (trile : string, amount : s32, worldConf
|
||||
sg_draw(0, cast(s32) trilegfx.vertex_count, amount);
|
||||
}
|
||||
|
||||
backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key) {
|
||||
backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *World_Config, chunk_key: Chunk_Key, is_preview: bool = false) {
|
||||
start_frame_profiling_group("Draw trile positions");
|
||||
mvp : Matrix4;
|
||||
if !in_shadowmap_pass {
|
||||
@ -220,6 +220,7 @@ backend_draw_trile_positions_main :: (trile : string, amount : s32, worldConf: *
|
||||
fs_params.rdm_diff_scale = lc.rdm_diff_scale;
|
||||
fs_params.rdm_spec_scale = lc.rdm_spec_scale;
|
||||
fs_params.ambient_color = lc.ambient_color.component;
|
||||
fs_params.is_preview = ifx is_preview then cast(s32)1 else cast(s32)0;
|
||||
fs_params.rdm_tint = lc.rdm_tint.component;
|
||||
|
||||
sg_apply_bindings(*bindings);
|
||||
|
||||
@ -56,6 +56,7 @@ Rendering_Task_Trile :: struct {
|
||||
chunk_key : Chunk_Key;
|
||||
positions : []Vector4;
|
||||
worldConf : *World_Config;
|
||||
is_preview : bool = false;
|
||||
}
|
||||
|
||||
Rendering_Task_Trixels :: struct {
|
||||
@ -113,10 +114,15 @@ tasks_to_commands :: () {
|
||||
drawPositionsCmd.chunk_key = trileTask.chunk_key;
|
||||
drawPositionsCmd.amount = cast(s32)trileTask.positions.count;
|
||||
drawPositionsCmd.conf = trileTask.worldConf;
|
||||
array_add(*render_command_buckets.reflection, drawPositionsCmd);
|
||||
array_add(*render_command_buckets.main, drawPositionsCmd);
|
||||
array_add(*render_command_buckets.gbuffer, drawPositionsCmd);
|
||||
array_add(*render_command_buckets.shadow, drawPositionsCmd);
|
||||
drawPositionsCmd.is_preview = trileTask.is_preview;
|
||||
if trileTask.is_preview {
|
||||
array_add(*render_command_buckets.main, drawPositionsCmd);
|
||||
} else {
|
||||
array_add(*render_command_buckets.reflection, drawPositionsCmd);
|
||||
array_add(*render_command_buckets.main, drawPositionsCmd);
|
||||
array_add(*render_command_buckets.gbuffer, drawPositionsCmd);
|
||||
array_add(*render_command_buckets.shadow, drawPositionsCmd);
|
||||
}
|
||||
case .SKY;
|
||||
command := New(Render_Command_Sky,, temp);
|
||||
command.worldConfig = (cast(*Rendering_Task_Sky)it).worldConfig;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,24 @@ in vec4 instance;
|
||||
out vec3 view_space_pos;
|
||||
out vec3 view_space_normal;
|
||||
|
||||
mat3 gbuf_rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
|
||||
mat3 gbuf_rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
|
||||
mat3 gbuf_rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
|
||||
|
||||
mat3 gbuf_get_orientation_matrix(int ori) {
|
||||
int face = ori / 4;
|
||||
int twist = ori % 4;
|
||||
float PI = 3.1415927;
|
||||
mat3 base;
|
||||
if (face == 0) base = mat3(1.0);
|
||||
else if (face == 1) base = gbuf_rot_x(PI);
|
||||
else if (face == 2) base = gbuf_rot_z(-PI*0.5);
|
||||
else if (face == 3) base = gbuf_rot_z( PI*0.5);
|
||||
else if (face == 4) base = gbuf_rot_x( PI*0.5);
|
||||
else base = gbuf_rot_x(-PI*0.5);
|
||||
return base * gbuf_rot_y(float(twist) * PI * 0.5);
|
||||
}
|
||||
|
||||
void main() {
|
||||
if (isGround == 1) {
|
||||
vec4 world_pos = vec4(position.x * 100.0, planeHeight, position.z * 100.0, 1.0);
|
||||
@ -22,12 +40,15 @@ void main() {
|
||||
view_space_pos = view_pos_4.xyz;
|
||||
view_space_normal = mat3(view_matrix) * normal.xyz;
|
||||
} else {
|
||||
vec4 world_pos = vec4(position.xyz + instance.xyz, 1.0);
|
||||
vec4 view_pos_4 = view_matrix * world_pos;
|
||||
gl_Position = mvp * world_pos;
|
||||
view_space_pos = view_pos_4.xyz;
|
||||
view_space_normal = mat3(view_matrix) * normal.xyz;
|
||||
|
||||
int ori = int(round(instance.w));
|
||||
mat3 rot = gbuf_get_orientation_matrix(ori);
|
||||
vec3 local = position.xyz - 0.5;
|
||||
vec3 rotated = rot * local + 0.5;
|
||||
vec4 world_pos = vec4(rotated + instance.xyz, 1.0);
|
||||
vec4 view_pos_4 = view_matrix * world_pos;
|
||||
gl_Position = mvp * world_pos;
|
||||
view_space_pos = view_pos_4.xyz;
|
||||
view_space_normal = mat3(view_matrix) * (rot * normal.xyz);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
@ -16,18 +16,43 @@ out vec3 to_center;
|
||||
out vec3 vpos; // The actual position;
|
||||
out vec3 ipos; // Trile space position;
|
||||
out vec4 fnormal;
|
||||
out vec3 orig_normal; // Unrotated object-space normal, used for trixel lookup
|
||||
out vec3 trileCenter;
|
||||
out vec3 cv;
|
||||
|
||||
mat3 rot_x(float a) { float c=cos(a),s=sin(a); return mat3(1,0,0, 0,c,-s, 0,s,c); }
|
||||
mat3 rot_z(float a) { float c=cos(a),s=sin(a); return mat3(c,-s,0, s,c,0, 0,0,1); }
|
||||
mat3 rot_y(float a) { float c=cos(a),s=sin(a); return mat3(c,0,s, 0,1,0, -s,0,c); }
|
||||
|
||||
mat3 get_orientation_matrix(int ori) {
|
||||
int face = ori / 4;
|
||||
int twist = ori % 4;
|
||||
float PI = 3.1415927;
|
||||
mat3 base;
|
||||
if (face == 0) base = mat3(1.0);
|
||||
else if (face == 1) base = rot_x(PI);
|
||||
else if (face == 2) base = rot_z(-PI*0.5);
|
||||
else if (face == 3) base = rot_z( PI*0.5);
|
||||
else if (face == 4) base = rot_x( PI*0.5);
|
||||
else base = rot_x(-PI*0.5);
|
||||
return base * rot_y(float(twist) * PI * 0.5);
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_Position = mvp * vec4(position.xyz + instance.xyz, 1.0);
|
||||
fnormal = normal;
|
||||
to_center = centre.xyz - position.xyz;
|
||||
vpos = position.xyz + instance.xyz;
|
||||
ipos = position.xyz;
|
||||
cam = camera;
|
||||
cv = normalize(camera - vpos);
|
||||
trileCenter = vpos - ipos + vec3(0.5);
|
||||
int ori = int(round(instance.w));
|
||||
mat3 rot = get_orientation_matrix(ori);
|
||||
vec3 local = position.xyz - 0.5;
|
||||
vec3 rotated = rot * local + 0.5;
|
||||
|
||||
gl_Position = mvp * vec4(rotated + instance.xyz, 1.0);
|
||||
fnormal = vec4(rot * normal.xyz, 0.0);
|
||||
orig_normal = normal.xyz; // unrotated, for trixel lookup
|
||||
to_center = centre.xyz - position.xyz; // unrotated, for trixel lookup
|
||||
vpos = rotated + instance.xyz;
|
||||
ipos = position.xyz;
|
||||
cam = camera;
|
||||
cv = normalize(camera - vpos);
|
||||
trileCenter = instance.xyz + vec3(0.5);
|
||||
}
|
||||
@end
|
||||
|
||||
@ -59,6 +84,7 @@ in vec3 to_center;
|
||||
in vec3 vpos;
|
||||
in vec3 ipos;
|
||||
in vec4 fnormal;
|
||||
in vec3 orig_normal;
|
||||
in vec3 trileCenter;
|
||||
in vec3 cv;
|
||||
out vec4 frag_color;
|
||||
@ -74,6 +100,7 @@ layout(binding=3) uniform trile_fs_params {
|
||||
float rdm_diff_scale;
|
||||
float rdm_spec_scale;
|
||||
vec3 ambient_color;
|
||||
int is_preview;
|
||||
vec3 rdm_tint;
|
||||
};
|
||||
|
||||
@ -447,7 +474,7 @@ void main() {
|
||||
}
|
||||
|
||||
// Trixel material sampling
|
||||
vec3 pos_after_adjust = ipos - fnormal.xyz * 0.02;
|
||||
vec3 pos_after_adjust = ipos - orig_normal * 0.02;
|
||||
int count = 0;
|
||||
vec4 trixel_material;
|
||||
while (count < 5) {
|
||||
@ -543,6 +570,9 @@ void main() {
|
||||
}
|
||||
|
||||
frag_color = vec4(mix(deepColor, light + emissive, smoothstep(0.0, planeHeight, vpos.y)), 1.0);
|
||||
if (is_preview == 1) {
|
||||
frag_color.rgb = mix(frag_color.rgb, vec3(0.3, 0.7, 1.0), 0.5);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user