| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- type render_target_t = {
- name?: string;
- width?: i32;
- height?: i32;
- // Opt
- format?: string;
- scale?: f32;
- // Runtime
- _image?: gpu_texture_t;
- };
- type cached_shader_context_t = {
- context?: shader_context_t;
- };
- enum draw_order_t {
- DIST, // Early-z
- SHADER, // Less state changes
- }
- let render_path_commands: () => void = null;
- let render_path_render_targets: map_t<string, render_target_t> = map_create();
- let render_path_current_w: i32;
- let render_path_current_h: i32;
- let _render_path_frame_time: f32 = 0.0;
- let _render_path_frame: i32 = 0;
- let _render_path_current_target: render_target_t = null;
- let _render_path_current_image: gpu_texture_t = null;
- let _render_path_draw_order: draw_order_t = draw_order_t.DIST;
- let _render_path_paused: bool = false;
- let _render_path_last_w: i32 = 0;
- let _render_path_last_h: i32 = 0;
- let _render_path_bind_params: string[];
- let _render_path_meshes_sorted: bool;
- let _render_path_last_frame_time: f32 = 0.0;
- let _render_path_loading: i32 = 0;
- let _render_path_cached_shader_contexts: map_t<string, cached_shader_context_t> = map_create();
- function render_path_ready(): bool {
- return _render_path_loading == 0;
- }
- function render_path_render_frame() {
- if (!render_path_ready() || _render_path_paused) {
- return;
- }
- if (_render_path_last_w > 0 && (_render_path_last_w != sys_w() || _render_path_last_h != sys_h())) {
- render_path_resize();
- }
- _render_path_last_w = sys_w();
- _render_path_last_h = sys_h();
- _render_path_frame_time = sys_time() - _render_path_last_frame_time;
- _render_path_last_frame_time = sys_time();
- render_path_current_w = sys_w();
- render_path_current_h = sys_h();
- _render_path_meshes_sorted = false;
- render_path_commands();
- _render_path_frame++;
- }
- function render_path_set_target(target: string, additional: string[] = null, depth_buffer: string = null, flags: gpu_clear_t = gpu_clear_t.NONE,
- color: i32 = 0, depth: f32 = 0.0) {
- if (_render_path_current_image != null) {
- render_path_end();
- }
- if (target == "") { // Framebuffer
- _render_path_current_target = null;
- render_path_current_w = sys_w();
- render_path_current_h = sys_h();
- _gpu_begin(null, null, null, flags, color, depth);
- gpu_viewport(sys_x(), render_path_current_h - (sys_h() - sys_y()), sys_w(), sys_h());
- }
- else { // Render target
- let rt: render_target_t = map_get(render_path_render_targets, target);
- _render_path_current_target = rt;
- let additional_images: gpu_texture_t[] = null;
- if (additional != null) {
- additional_images = [];
- for (let i: i32 = 0; i < additional.length; ++i) {
- let s: string = additional[i];
- let t: render_target_t = map_get(render_path_render_targets, s);
- array_push(additional_images, t._image);
- }
- }
- render_path_current_w = rt._image.width;
- render_path_current_h = rt._image.height;
- let db: render_target_t = map_get(render_path_render_targets, depth_buffer);
- _render_path_current_image = rt._image;
- _gpu_begin(rt._image, additional_images, db != null ? db._image : null, flags, color, depth);
- }
- _render_path_bind_params = null;
- }
- function render_path_end() {
- gpu_end();
- _render_path_current_image = null;
- _render_path_bind_params = null;
- }
- function _render_path_sort_dist(a: any_ptr, b: any_ptr): i32 {
- let ma: mesh_object_t = DEREFERENCE(a);
- let mb: mesh_object_t = DEREFERENCE(b);
- return ma.camera_dist >= mb.camera_dist ? 1 : -1;
- }
- function render_path_sort_meshes_dist(meshes: mesh_object_t[]) {
- array_sort(meshes, _render_path_sort_dist);
- }
- function _render_path_sort_shader(a: any_ptr, b: any_ptr): i32 {
- let ma: mesh_object_t = DEREFERENCE(a);
- let mb: mesh_object_t = DEREFERENCE(b);
- return strcmp(ma.material.name, mb.material.name);
- }
- function render_path_sort_meshes_shader(meshes: mesh_object_t[]) {
- array_sort(meshes, _render_path_sort_shader);
- }
- function render_path_draw_meshes(context: string) {
- render_path_submit_draw(context);
- render_path_end();
- }
- function render_path_submit_draw(context: string) {
- let camera: camera_object_t = scene_camera;
- let meshes: mesh_object_t[] = scene_meshes;
- _mesh_object_last_pipeline = null;
- if (!_render_path_meshes_sorted && camera != null) { // Order max once per frame for now
- let cam_x: f32 = transform_world_x(camera.base.transform);
- let cam_y: f32 = transform_world_y(camera.base.transform);
- let cam_z: f32 = transform_world_z(camera.base.transform);
- for (let i: i32 = 0; i < meshes.length; ++i) {
- let mesh: mesh_object_t = meshes[i];
- mesh_object_compute_camera_dist(mesh, cam_x, cam_y, cam_z);
- }
- if (_render_path_draw_order == draw_order_t.SHADER) {
- render_path_sort_meshes_shader(meshes);
- }
- else {
- render_path_sort_meshes_dist(meshes);
- }
- _render_path_meshes_sorted = true;
- }
- for (let i: i32 = 0; i < meshes.length; ++i) {
- let mesh: mesh_object_t = meshes[i];
- mesh_object_render(mesh, context, _render_path_bind_params);
- }
- }
- function render_path_draw_skydome(handle: string) {
- if (const_data_skydome_vb == null) {
- const_data_create_skydome_data();
- }
- let cc: cached_shader_context_t = map_get(_render_path_cached_shader_contexts, handle);
- if (cc.context == null) {
- return; // World data not specified
- }
- gpu_set_pipeline(cc.context._.pipe);
- uniforms_set_context_consts(cc.context, _render_path_bind_params);
- uniforms_set_obj_consts(cc.context, null); // External hosek
- gpu_set_vertex_buffer(const_data_skydome_vb);
- gpu_set_index_buffer(const_data_skydome_ib);
- gpu_draw();
- render_path_end();
- }
- function render_path_bind_target(target: string, uniform: string) {
- if (_render_path_bind_params != null) {
- array_push(_render_path_bind_params, target);
- array_push(_render_path_bind_params, uniform);
- }
- else {
- _render_path_bind_params = [ target, uniform ];
- }
- }
- // Full-screen triangle
- function render_path_draw_shader(handle: string) {
- // file/data_name/context
- let cc: cached_shader_context_t = map_get(_render_path_cached_shader_contexts, handle);
- if (const_data_screen_aligned_vb == null) {
- const_data_create_screen_aligned_data();
- }
- gpu_set_pipeline(cc.context._.pipe);
- uniforms_set_context_consts(cc.context, _render_path_bind_params);
- uniforms_set_obj_consts(cc.context, null);
- gpu_set_vertex_buffer(const_data_screen_aligned_vb);
- gpu_set_index_buffer(const_data_screen_aligned_ib);
- gpu_draw();
- render_path_end();
- }
- function render_path_load_shader(handle: string) {
- _render_path_loading++;
- let cc: cached_shader_context_t = map_get(_render_path_cached_shader_contexts, handle);
- if (cc != null) {
- _render_path_loading--;
- return;
- }
- cc = {};
- map_set(_render_path_cached_shader_contexts, handle, cc);
- // file/data_name/context
- let shader_path: string[] = string_split(handle, "/");
- let res: shader_data_t = data_get_shader(shader_path[0], shader_path[1]);
- cc.context = shader_data_get_context(res, shader_path[2]);
- _render_path_loading--;
- }
- function render_path_unload_shader(handle: string) {
- map_delete(_render_path_cached_shader_contexts, handle);
- // file/data_name/context
- let shader_path: string[] = string_split(handle, "/");
- // Todo: Handle context overrides (see data_get_shader())
- map_delete(data_cached_shaders, shader_path[1]);
- }
- function render_path_unload() {
- let render_targets_keys: string[] = map_keys(render_path_render_targets);
- for (let i: i32 = 0; i < render_targets_keys.length; ++i) {
- let rt: render_target_t = map_get(render_path_render_targets, render_targets_keys[i]);
- render_target_unload(rt);
- }
- }
- function render_path_resize() {
- if (iron_window_width() == 0 || iron_window_height() == 0) {
- return;
- }
- let render_targets_keys: string[] = map_keys(render_path_render_targets);
- for (let i: i32 = 0; i < render_targets_keys.length; ++i) {
- let rt: render_target_t = map_get(render_path_render_targets, render_targets_keys[i]);
- if (rt != null && rt.width == 0) {
- gpu_delete_texture(rt._image);
- rt._image = render_path_create_image(rt);
- }
- }
- }
- function render_path_create_render_target(t: render_target_t): render_target_t {
- t._image = render_path_create_image(t);
- map_set(render_path_render_targets, t.name, t);
- return t;
- }
- function render_path_create_image(t: render_target_t): gpu_texture_t {
- let width: i32 = t.width == 0 ? sys_w() : t.width;
- let height: i32 = t.height == 0 ? sys_h() : t.height;
- width = math_floor(width * t.scale);
- height = math_floor(height * t.scale);
- if (width < 1) {
- width = 1;
- }
- if (height < 1) {
- height = 1;
- }
- return gpu_create_render_target(width, height, t.format != null ? render_path_get_tex_format(t.format) : gpu_texture_format_t.RGBA32);
- }
- function render_path_get_tex_format(s: string): gpu_texture_format_t {
- if (s == "RGBA32") {
- return gpu_texture_format_t.RGBA32;
- }
- if (s == "RGBA64") {
- return gpu_texture_format_t.RGBA64;
- }
- if (s == "RGBA128") {
- return gpu_texture_format_t.RGBA128;
- }
- if (s == "R32") {
- return gpu_texture_format_t.R32;
- }
- if (s == "R16") {
- return gpu_texture_format_t.R16;
- }
- if (s == "R8") {
- return gpu_texture_format_t.R8;
- }
- if (s == "D32") {
- return gpu_texture_format_t.D32;
- }
- return gpu_texture_format_t.RGBA32;
- }
- function render_target_create(): render_target_t {
- let raw: render_target_t = {};
- raw.scale = 1.0;
- return raw;
- }
- function render_target_unload(raw: render_target_t) {
- if (raw._image != null) {
- gpu_delete_texture(raw._image);
- }
- }
|