This commit is contained in:
luboslenco
2025-08-12 23:26:06 +02:00
parent fcd65a71cc
commit c427d9751a
11 changed files with 129 additions and 234 deletions
+26 -70
View File
@@ -4,19 +4,15 @@ type mesh_object_t = {
data?: mesh_data_t;
materials?: material_data_t[];
camera_dist?: f32;
screen_size?: f32;
frustum_culling?: bool;
skip_context?: string; // Do not draw this context
force_context?: string; // Draw only this context
};
let _mesh_object_last_pipeline: gpu_pipeline_t = null;
let _mesh_object_material_contexts: material_context_t[] = [];
let _mesh_object_shader_contexts: shader_context_t[] = [];
function mesh_object_create(data: mesh_data_t, materials: material_data_t[]): mesh_object_t {
let raw: mesh_object_t = {};
raw.screen_size = 0.0;
raw.frustum_culling = true;
raw.base = object_create(false);
raw.base.ext = raw;
@@ -47,66 +43,35 @@ function mesh_object_setup_animation(raw: mesh_object_t, oactions: scene_t[] = n
///end
}
function mesh_object_set_culled(raw: mesh_object_t, b: bool): bool {
raw.base.culled = b;
return b;
}
function mesh_object_cull_material(raw: mesh_object_t, context: string): bool {
// Skip render if material does not contain current context
if (!mesh_object_valid_context(raw, raw.materials, context)) {
raw.base.culled = true;
return true;
}
if (!raw.base.visible) {
return mesh_object_set_culled(raw, true);
}
if (raw.skip_context == context) {
return mesh_object_set_culled(raw, true);
raw.base.culled = true;
return true;
}
if (raw.force_context != null && raw.force_context != context) {
return mesh_object_set_culled(raw, true);
raw.base.culled = true;
return true;
}
return mesh_object_set_culled(raw, false);
raw.base.culled = false;
return false;
}
function mesh_object_cull_mesh(raw: mesh_object_t, context: string, camera: camera_object_t): bool {
if (camera == null) {
return false;
}
if (camera.data.frustum_culling && raw.frustum_culling) {
let radius_scale: f32 = 1.0;
let frustum_planes: frustum_plane_t[] = camera.frustum_planes;
if (!camera_object_sphere_in_frustum(frustum_planes, raw.base.transform, radius_scale)) {
return mesh_object_set_culled(raw, true);
raw.base.culled = true;
return true;
}
}
raw.base.culled = false;
return raw.base.culled;
}
function mesh_object_get_contexts(raw: mesh_object_t, context: string, materials: material_data_t[], material_contexts: material_context_t[], shader_contexts: shader_context_t[]) {
for (let i: i32 = 0; i < materials.length; ++i) {
let mat: material_data_t = materials[i];
let found: bool = false;
for (let j: i32 = 0; j < mat.contexts.length; ++j) {
if (substring(mat.contexts[j].name, 0, context.length) == context) {
array_push(material_contexts, mat._.contexts[j]);
array_push(shader_contexts, shader_data_get_context(mat._.shader, context));
found = true;
break;
}
}
if (!found) {
array_push(material_contexts, null);
array_push(shader_contexts, null);
}
}
return false;
}
function mesh_object_render(raw: mesh_object_t, context: string, bind_params: string[]) {
@@ -120,29 +85,30 @@ function mesh_object_render(raw: mesh_object_t, context: string, bind_params: st
return;
}
// Get context
let material_contexts: material_context_t[] = _mesh_object_material_contexts;
let shader_contexts: shader_context_t[] = _mesh_object_shader_contexts;
material_contexts.length = 0;
shader_contexts.length = 0;
mesh_object_get_contexts(raw, context, raw.materials, material_contexts, shader_contexts);
uniforms_pos_unpack = raw.data.scale_pos;
uniforms_tex_unpack = raw.data.scale_tex;
transform_update(raw.base.transform);
// Render mesh
let scontext: shader_context_t = shader_contexts[0];
let scontext: shader_context_t = null;
let mcontext: material_context_t = null;
for (let i: i32 = 0; i < raw.materials.length; ++i) {
let mat: material_data_t = raw.materials[i];
for (let j: i32 = 0; j < mat.contexts.length; ++j) {
if (mat.contexts[j].name == context) {
scontext = shader_data_get_context(mat._.shader, context);
mcontext = mat.contexts[j];
break;
}
}
}
// Uniforms
if (scontext._.pipe_state != _mesh_object_last_pipeline) {
gpu_set_pipeline(scontext._.pipe_state);
_mesh_object_last_pipeline = scontext._.pipe_state;
if (scontext._.pipe != _mesh_object_last_pipeline) {
gpu_set_pipeline(scontext._.pipe);
_mesh_object_last_pipeline = scontext._.pipe;
}
uniforms_set_context_consts(scontext, bind_params);
uniforms_set_obj_consts(scontext, raw.base);
uniforms_set_material_consts(scontext, material_contexts[0]);
uniforms_set_material_consts(scontext, mcontext);
gpu_set_vertex_buffer(raw.data._.vertex_buffer);
gpu_set_index_buffer(raw.data._.index_buffer);
gpu_draw();
@@ -162,13 +128,3 @@ function mesh_object_compute_camera_dist(raw: mesh_object_t, cam_x: f32, cam_y:
// Render path mesh sorting
raw.camera_dist = vec4_fdist(cam_x, cam_y, cam_z, transform_world_x(raw.base.transform), transform_world_y(raw.base.transform), transform_world_z(raw.base.transform));
}
function mesh_object_compute_screen_size(raw: mesh_object_t, camera: camera_object_t) {
// Approx..
// let rp = camera_render_path;
// let screen_volume = rp.current_w * rp.current_h;
let tr: transform_t = raw.base.transform;
let volume: f32 = tr.dim.x * tr.dim.y * tr.dim.z;
raw.screen_size = volume * (1.0 / raw.camera_dist);
raw.screen_size = raw.screen_size > 1.0 ? 1.0 : raw.screen_size;
}