2026-03-09 13:17:15 +01:00
|
|
|
|
|
|
|
|
#include "global.h"
|
|
|
|
|
|
2026-04-05 16:09:00 +02:00
|
|
|
f32 render_path_raytrace_uv_scale = 1.0;
|
|
|
|
|
mat4_t render_path_raytrace_transform;
|
|
|
|
|
gpu_buffer_t *render_path_raytrace_vb;
|
|
|
|
|
gpu_buffer_t *render_path_raytrace_ib;
|
|
|
|
|
|
2026-03-06 12:56:38 +01:00
|
|
|
void render_path_raytrace_init() {}
|
|
|
|
|
|
|
|
|
|
void render_path_raytrace_commands(bool use_live_layer) {
|
|
|
|
|
if (!render_path_raytrace_ready || render_path_raytrace_is_bake) {
|
|
|
|
|
render_path_raytrace_ready = true;
|
|
|
|
|
if (render_path_raytrace_is_bake) {
|
|
|
|
|
render_path_raytrace_is_bake = false;
|
|
|
|
|
render_path_raytrace_init_shader = true;
|
|
|
|
|
}
|
2026-03-07 21:12:59 +01:00
|
|
|
char *ext = "";
|
2026-05-04 20:30:49 +02:00
|
|
|
// if (g_context->tool == TOOL_TYPE_CURSOR) {
|
|
|
|
|
// ext = "forge_";
|
|
|
|
|
// }
|
2026-04-05 16:41:00 +02:00
|
|
|
char *mode = g_config->pathtrace_mode == PATHTRACE_MODE_FAST ? "core" : "full";
|
2026-03-10 21:00:00 +01:00
|
|
|
render_path_raytrace_raytrace_init(string("raytrace_brute_%s%s%s", ext, mode, render_path_raytrace_ext), true);
|
2026-03-06 12:56:38 +01:00
|
|
|
gc_unroot(render_path_raytrace_last_envmap);
|
2026-03-07 21:12:59 +01:00
|
|
|
render_path_raytrace_last_envmap = NULL;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-05 16:41:00 +02:00
|
|
|
if (!g_context->envmap_loaded) {
|
2026-03-06 12:56:38 +01:00
|
|
|
context_load_envmap();
|
|
|
|
|
context_update_envmap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
world_data_t *probe = scene_world;
|
2026-04-05 16:41:00 +02:00
|
|
|
gpu_texture_t *saved_envmap = g_context->show_envmap_blur ? probe->_->radiance_mipmaps->buffer[0] : g_context->saved_envmap;
|
2026-03-06 12:56:38 +01:00
|
|
|
|
|
|
|
|
////
|
|
|
|
|
if (render_path_raytrace_last_envmap != saved_envmap) {
|
|
|
|
|
gc_unroot(render_path_raytrace_last_envmap);
|
|
|
|
|
render_path_raytrace_last_envmap = saved_envmap;
|
|
|
|
|
gc_root(render_path_raytrace_last_envmap);
|
|
|
|
|
|
|
|
|
|
gpu_texture_t *bnoise_sobol = any_map_get(scene_embedded, "bnoise_sobol.k");
|
|
|
|
|
gpu_texture_t *bnoise_scramble = any_map_get(scene_embedded, "bnoise_scramble.k");
|
|
|
|
|
gpu_texture_t *bnoise_rank = any_map_get(scene_embedded, "bnoise_rank.k");
|
|
|
|
|
|
2026-03-10 21:00:00 +01:00
|
|
|
slot_layer_t *l = layers_flatten(true, NULL);
|
2026-03-06 12:56:38 +01:00
|
|
|
gpu_raytrace_set_textures(l->texpaint, l->texpaint_nor, l->texpaint_pack, saved_envmap, bnoise_sobol, bnoise_scramble, bnoise_rank);
|
|
|
|
|
}
|
|
|
|
|
////
|
|
|
|
|
|
2026-05-20 10:57:58 +02:00
|
|
|
if (g_context->pdirty > 0 || g_context->rtdirty > 0) {
|
2026-03-07 21:12:59 +01:00
|
|
|
layers_flatten(true, NULL);
|
2026-05-20 10:57:58 +02:00
|
|
|
g_context->rtdirty = 0;
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
camera_object_t *cam = scene_camera;
|
|
|
|
|
transform_t *ct = cam->base->transform;
|
2026-04-06 13:59:41 +02:00
|
|
|
render_path_raytrace_help_mat = cam->v;
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_help_mat = mat4_mult_mat(render_path_raytrace_help_mat, cam->p);
|
|
|
|
|
render_path_raytrace_help_mat = mat4_inv(render_path_raytrace_help_mat);
|
|
|
|
|
render_path_raytrace_f32a->buffer[0] = transform_world_x(ct);
|
|
|
|
|
render_path_raytrace_f32a->buffer[1] = transform_world_y(ct);
|
|
|
|
|
render_path_raytrace_f32a->buffer[2] = transform_world_z(ct);
|
|
|
|
|
render_path_raytrace_f32a->buffer[3] = render_path_raytrace_frame;
|
2026-03-10 21:00:00 +01:00
|
|
|
#ifdef IRON_METAL
|
2026-03-06 12:56:38 +01:00
|
|
|
// render_path_raytrace_frame = (render_path_raytrace_frame % (16)) + 1; // _PAINT
|
|
|
|
|
render_path_raytrace_frame = render_path_raytrace_frame + 1; // _RENDER
|
2026-03-10 21:00:00 +01:00
|
|
|
#else
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_frame = (render_path_raytrace_frame % 4) + 1; // _PAINT
|
2026-03-10 21:00:00 +01:00
|
|
|
// render_path_raytrace_frame = render_path_raytrace_frame + 1; // _RENDER
|
|
|
|
|
#endif
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_f32a->buffer[4] = render_path_raytrace_help_mat.m00;
|
2026-04-06 00:13:53 +02:00
|
|
|
render_path_raytrace_f32a->buffer[5] = render_path_raytrace_help_mat.m01;
|
|
|
|
|
render_path_raytrace_f32a->buffer[6] = render_path_raytrace_help_mat.m02;
|
|
|
|
|
render_path_raytrace_f32a->buffer[7] = render_path_raytrace_help_mat.m03;
|
|
|
|
|
render_path_raytrace_f32a->buffer[8] = render_path_raytrace_help_mat.m10;
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_f32a->buffer[9] = render_path_raytrace_help_mat.m11;
|
2026-04-06 00:13:53 +02:00
|
|
|
render_path_raytrace_f32a->buffer[10] = render_path_raytrace_help_mat.m12;
|
|
|
|
|
render_path_raytrace_f32a->buffer[11] = render_path_raytrace_help_mat.m13;
|
|
|
|
|
render_path_raytrace_f32a->buffer[12] = render_path_raytrace_help_mat.m20;
|
|
|
|
|
render_path_raytrace_f32a->buffer[13] = render_path_raytrace_help_mat.m21;
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_f32a->buffer[14] = render_path_raytrace_help_mat.m22;
|
2026-04-06 00:13:53 +02:00
|
|
|
render_path_raytrace_f32a->buffer[15] = render_path_raytrace_help_mat.m23;
|
|
|
|
|
render_path_raytrace_f32a->buffer[16] = render_path_raytrace_help_mat.m30;
|
|
|
|
|
render_path_raytrace_f32a->buffer[17] = render_path_raytrace_help_mat.m31;
|
|
|
|
|
render_path_raytrace_f32a->buffer[18] = render_path_raytrace_help_mat.m32;
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_f32a->buffer[19] = render_path_raytrace_help_mat.m33;
|
|
|
|
|
render_path_raytrace_f32a->buffer[20] = scene_world->strength;
|
2026-04-05 16:41:00 +02:00
|
|
|
if (!g_context->show_envmap) {
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_f32a->buffer[20] = -render_path_raytrace_f32a->buffer[20];
|
|
|
|
|
}
|
2026-04-05 16:41:00 +02:00
|
|
|
render_path_raytrace_f32a->buffer[21] = g_context->envmap_angle;
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_f32a->buffer[22] = render_path_raytrace_uv_scale;
|
|
|
|
|
|
|
|
|
|
if (render_path_base_buf_swapped) {
|
|
|
|
|
render_path_base_swap_buf("buf");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render_target_t *framebuffer = any_map_get(render_path_render_targets, "buf");
|
|
|
|
|
_gpu_raytrace_dispatch_rays(framebuffer->_image, render_path_raytrace_f32a);
|
|
|
|
|
|
2026-04-05 16:41:00 +02:00
|
|
|
if (g_context->ddirty == 1 || g_context->pdirty == 1) {
|
2026-03-10 21:00:00 +01:00
|
|
|
#ifdef IRON_METAL
|
2026-04-05 16:41:00 +02:00
|
|
|
g_context->rdirty = 128;
|
2026-03-10 21:00:00 +01:00
|
|
|
#else
|
2026-04-05 16:41:00 +02:00
|
|
|
g_context->rdirty = 4;
|
2026-03-10 21:00:00 +01:00
|
|
|
#endif
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
2026-04-05 16:41:00 +02:00
|
|
|
g_context->ddirty--;
|
|
|
|
|
g_context->pdirty--;
|
|
|
|
|
g_context->rdirty--;
|
2026-03-06 12:56:38 +01:00
|
|
|
|
2026-04-05 16:41:00 +02:00
|
|
|
// g_context->ddirty = 1; // _RENDER
|
2026-03-06 12:56:38 +01:00
|
|
|
}
|
|
|
|
|
|
2026-04-04 21:38:20 +02:00
|
|
|
void render_path_raytrace_build_data() {
|
2026-04-05 16:41:00 +02:00
|
|
|
if (g_context->merged_object == NULL) {
|
2026-04-04 21:38:20 +02:00
|
|
|
util_mesh_merge(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-05 16:41:00 +02:00
|
|
|
mesh_object_t *mo = !context_layer_filter_used() ? g_context->merged_object : g_context->paint_object;
|
2026-04-04 21:38:20 +02:00
|
|
|
|
2026-05-04 20:30:49 +02:00
|
|
|
// if (g_context->tool == TOOL_TYPE_CURSOR) {
|
|
|
|
|
// render_path_raytrace_transform = mo->base->transform->world_unpack;
|
|
|
|
|
// }
|
|
|
|
|
// else {
|
|
|
|
|
render_path_raytrace_transform = mat4_identity();
|
|
|
|
|
// }
|
2026-04-04 21:38:20 +02:00
|
|
|
|
|
|
|
|
f32 sc = mo->base->transform->scale.x * mo->data->scale_pos;
|
|
|
|
|
if (mo->base->parent != NULL) {
|
|
|
|
|
sc *= mo->base->parent->transform->scale.x;
|
|
|
|
|
}
|
2026-04-05 23:00:47 +02:00
|
|
|
render_path_raytrace_transform = mat4_scale(render_path_raytrace_transform, (vec4_t){sc, sc, sc, 1.0});
|
2026-04-04 21:38:20 +02:00
|
|
|
|
|
|
|
|
gc_unroot(render_path_raytrace_vb);
|
|
|
|
|
render_path_raytrace_vb = mo->data->_->vertex_buffer;
|
|
|
|
|
gc_root(render_path_raytrace_vb);
|
|
|
|
|
gc_unroot(render_path_raytrace_ib);
|
|
|
|
|
render_path_raytrace_ib = mo->data->_->index_buffer;
|
|
|
|
|
gc_root(render_path_raytrace_ib);
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-07 21:12:59 +01:00
|
|
|
void render_path_raytrace_raytrace_init(char *shader_name, bool build) {
|
2026-03-06 12:56:38 +01:00
|
|
|
if (render_path_raytrace_init_shader) {
|
|
|
|
|
render_path_raytrace_init_shader = false;
|
|
|
|
|
scene_embed_data("bnoise_sobol.k");
|
|
|
|
|
scene_embed_data("bnoise_scramble.k");
|
|
|
|
|
scene_embed_data("bnoise_rank.k");
|
|
|
|
|
|
|
|
|
|
buffer_t *shader = data_get_blob(shader_name);
|
|
|
|
|
_gpu_raytrace_init(shader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (build) {
|
|
|
|
|
render_path_raytrace_build_data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
_gpu_raytrace_as_init();
|
|
|
|
|
|
2026-05-04 20:30:49 +02:00
|
|
|
// if (g_context->tool == TOOL_TYPE_CURSOR) {
|
|
|
|
|
// for (i32 i = 0; i < project_paint_objects->length; ++i) {
|
|
|
|
|
// mesh_object_t *po = project_paint_objects->buffer[i];
|
|
|
|
|
// if (!po->base->visible) {
|
|
|
|
|
// continue;
|
|
|
|
|
// }
|
|
|
|
|
// _gpu_raytrace_as_add(po->data->_->vertex_buffer, po->data->_->index_buffer, po->base->transform->world_unpack);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// else {
|
|
|
|
|
_gpu_raytrace_as_add(render_path_raytrace_vb, render_path_raytrace_ib, render_path_raytrace_transform);
|
|
|
|
|
// }
|
2026-03-06 12:56:38 +01:00
|
|
|
|
2026-04-05 16:41:00 +02:00
|
|
|
gpu_buffer_t *vb_full = g_context->merged_object->data->_->vertex_buffer;
|
|
|
|
|
gpu_buffer_t *ib_full = g_context->merged_object->data->_->index_buffer;
|
2026-03-06 12:56:38 +01:00
|
|
|
|
|
|
|
|
_gpu_raytrace_as_build(vb_full, ib_full);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void render_path_raytrace_draw(bool use_live_layer) {
|
2026-04-05 16:41:00 +02:00
|
|
|
bool is_live = g_config->brush_live && render_path_paint_live_layer_drawn > 0;
|
|
|
|
|
if (g_context->ddirty > 1 || g_context->pdirty > 0 || is_live) {
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_frame = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-10 21:00:00 +01:00
|
|
|
#ifdef IRON_METAL
|
2026-03-06 12:56:38 +01:00
|
|
|
// Delay path tracing additional samples while painting
|
|
|
|
|
bool down = mouse_down("left") || pen_down("tip");
|
2026-04-14 15:10:04 +02:00
|
|
|
if (context_in_3d_view() && down && !ui_menu_show) {
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_raytrace_frame = 0;
|
|
|
|
|
}
|
2026-03-10 21:00:00 +01:00
|
|
|
#endif
|
2026-03-06 12:56:38 +01:00
|
|
|
|
|
|
|
|
render_path_raytrace_commands(use_live_layer);
|
2026-03-07 21:12:59 +01:00
|
|
|
render_path_set_target("buf", NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_draw_meshes("overlay");
|
2026-03-07 21:12:59 +01:00
|
|
|
render_path_set_target("buf", NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
|
2026-05-20 19:52:36 +02:00
|
|
|
render_compass();
|
2026-03-07 21:12:59 +01:00
|
|
|
render_path_set_target("last", NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_bind_target("buf", "tex");
|
|
|
|
|
render_path_draw_shader("Scene/compositor_pass/compositor_pass");
|
|
|
|
|
render_path_base_draw_bloom("buf", "last");
|
2026-05-20 19:26:15 +02:00
|
|
|
render_path_set_target("last", NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
|
|
|
|
|
render_envsphere();
|
2026-03-07 21:12:59 +01:00
|
|
|
render_path_set_target("", NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
|
2026-03-06 12:56:38 +01:00
|
|
|
render_path_bind_target("last", "tex");
|
|
|
|
|
render_path_draw_shader("Scene/copy_pass/copy_pass");
|
|
|
|
|
render_path_paint_commands_cursor();
|
|
|
|
|
}
|