work on editor

This commit is contained in:
Tuomas Katajisto 2026-03-04 19:30:50 +02:00
parent 8668157060
commit 1bfe79fc6b
10 changed files with 5859 additions and 4265 deletions

View File

@ -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)

View File

@ -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) {

View File

@ -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);
}

View File

@ -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 {

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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