Files
armorpaint/base/sources/ts/iron/uniforms.ts
T
luboslenco 1742b909dc kong test
2025-03-26 20:56:40 +01:00

627 lines
18 KiB
TypeScript

let _uniforms_mat: mat4_t = mat4_identity();
let _uniforms_mat2: mat4_t = mat4_identity();
let _uniforms_mat3: mat3_t = mat3_identity();
let _uniforms_vec: vec4_t = vec4_create();
let _uniforms_vec2: vec4_t = vec4_create();
let _uniforms_quat: quat_t = quat_create();
let uniforms_tex_links: (o: object_t, md: material_data_t, s: string)=>iron_gpu_texture_t = null;
let uniforms_mat4_links: (o: object_t, md: material_data_t, s: string)=>mat4_t = null;
let uniforms_vec4_links: (o: object_t, md: material_data_t, s: string)=>vec4_t = null;
let uniforms_vec3_links: (o: object_t, md: material_data_t, s: string)=>vec4_t = null;
let uniforms_vec2_links: (o: object_t, md: material_data_t, s: string)=>vec2_t = null;
let uniforms_f32_links: (o: object_t, md: material_data_t, s: string)=>f32 = null;
let uniforms_f32_array_links: (o: object_t, md: material_data_t, s: string)=>f32_array_t = null;
let uniforms_i32_links: (o: object_t, md: material_data_t, s: string)=>i32 = null;
let uniforms_pos_unpack: f32 = 1.0;
let uniforms_tex_unpack: f32 = 1.0;
function uniforms_set_context_consts(context: shader_context_t, bind_params: string[]) {
if (context.constants != null) {
for (let i: i32 = 0; i < context.constants.length; ++i) {
let c: shader_const_t = context.constants[i];
uniforms_set_context_const(context._.constants[i], c);
}
}
// Texture context constants
if (bind_params != null) { // Bind targets
for (let i: i32 = 0; i < math_floor(bind_params.length / 2); ++i) {
let pos: i32 = i * 2; // bind params = [texture, sampler_id]
let rt_id: string = bind_params[pos];
let sampler_id: string = bind_params[pos + 1];
let attach_depth: bool = false; // Attach texture depth if "_" is prepended
let c: string = char_at(rt_id, 0);
if (c == "_") {
attach_depth = true;
rt_id = substring(rt_id, 1, rt_id.length);
}
let rt: render_target_t;
if (attach_depth) {
rt = map_get(_render_path_depth_to_render_target, rt_id);
}
else {
rt = map_get(render_path_render_targets, rt_id);
}
uniforms_bind_render_target(rt, context, sampler_id, attach_depth);
}
}
// Texture links
if (context.texture_units != null) {
for (let j: i32 = 0; j < context.texture_units.length; ++j) {
let tulink: string = context.texture_units[j].link;
if (tulink == null) {
continue;
}
if (char_at(tulink, 0) == "$") { // Link to embedded data
gpu_set_texture(context._.tex_units[j], map_get(scene_embedded, substring(tulink, 1, tulink.length)));
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.REPEAT, tex_addressing_t.REPEAT, tex_filter_t.LINEAR, tex_filter_t.LINEAR, mip_map_filter_t.NONE);
}
else if (tulink == "_envmap_radiance") {
let w: world_data_t = scene_world;
if (w != null) {
gpu_set_texture(context._.tex_units[j], w._.radiance);
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.REPEAT, tex_addressing_t.REPEAT, tex_filter_t.LINEAR, tex_filter_t.LINEAR, mip_map_filter_t.LINEAR);
}
}
else if (tulink == "_envmap") {
let w: world_data_t = scene_world;
if (w != null) {
gpu_set_texture(context._.tex_units[j], w._.envmap);
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.REPEAT, tex_addressing_t.REPEAT, tex_filter_t.LINEAR, tex_filter_t.LINEAR, mip_map_filter_t.NONE);
}
}
}
}
}
function uniforms_set_obj_consts(context: shader_context_t, object: object_t) {
if (context.constants != null) {
for (let i: i32 = 0; i < context.constants.length; ++i) {
let c: shader_const_t = context.constants[i];
uniforms_set_obj_const(object, context._.constants[i], c);
}
}
// Texture object constants
// External
if (uniforms_tex_links != null) {
if (context.texture_units != null) {
for (let j: i32 = 0; j < context.texture_units.length; ++j) {
let tu: tex_unit_t = context.texture_units[j];
if (tu.link == null) {
continue;
}
let image: iron_gpu_texture_t = uniforms_tex_links(object, current_material(object), tu.link);
if (image != null) {
ends_with(tu.link, "_depth") ?
gpu_set_texture_depth(context._.tex_units[j], image) :
gpu_set_texture(context._.tex_units[j], image);
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.REPEAT, tex_addressing_t.REPEAT, tex_filter_t.LINEAR, tex_filter_t.LINEAR, mip_map_filter_t.NONE);
}
}
}
}
}
function uniforms_bind_render_target(rt: render_target_t, context: shader_context_t, sampler_id: string, attach_depth: bool) {
if (rt == null) {
return;
}
let tus: tex_unit_t[] = context.texture_units;
for (let j: i32 = 0; j < tus.length; ++j) { // Set texture
if (sampler_id == tus[j].name) {
if (attach_depth) {
gpu_set_texture_depth(context._.tex_units[j], rt._image); // sampler2D
}
else {
gpu_set_texture(context._.tex_units[j], rt._image); // sampler2D
}
if (rt.mipmaps) {
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.CLAMP, tex_addressing_t.CLAMP, tex_filter_t.LINEAR, tex_filter_t.LINEAR, mip_map_filter_t.LINEAR);
continue;
}
if (starts_with(rt.name, "bloom")) {
// Use bilinear filter for bloom mips to get correct blur
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.CLAMP, tex_addressing_t.CLAMP, tex_filter_t.LINEAR, tex_filter_t.LINEAR, mip_map_filter_t.NONE);
continue;
}
if (attach_depth) {
gpu_set_texture_parameters(context._.tex_units[j], tex_addressing_t.CLAMP, tex_addressing_t.CLAMP, tex_filter_t.POINT, tex_filter_t.POINT, mip_map_filter_t.NONE);
continue;
}
// No filtering when sampling render targets
let oc: _shader_override_t = context._.override_context;
let allow_params: bool = oc == null || oc.shared_sampler == null || oc.shared_sampler == sampler_id;
if (allow_params) {
let addressing: tex_addressing_t = (oc != null && oc.addressing == "repeat") ? tex_addressing_t.REPEAT : tex_addressing_t.CLAMP;
let filter: tex_filter_t = (oc != null && oc.filter == "point") ? tex_filter_t.POINT : tex_filter_t.LINEAR;
gpu_set_texture_parameters(context._.tex_units[j], addressing, addressing, filter, filter, mip_map_filter_t.NONE);
}
}
}
}
function uniforms_set_context_const(location: iron_gpu_constant_location_t, c: shader_const_t): bool {
if (c.link == null) {
return true;
}
let camera: camera_object_t = scene_camera;
if (c.type == "mat4") {
let m: mat4_t = mat4_nan();
if (c.link == "_view_matrix") {
m = camera.v;
}
else if (c.link == "_proj_matrix") {
m = camera.p;
}
else if (c.link == "_inv_proj_matrix") {
m = mat4_inv(camera.p);
}
else if (c.link == "_view_proj_matrix") {
m = camera.vp;
}
else if (c.link == "_inv_view_proj_matrix") {
m = mat4_mult_mat(camera.v, camera.p);
m = mat4_inv(m);
}
else if (c.link == "_skydome_matrix") {
let tr: transform_t = camera.base.transform;
let v: vec4_t = vec4_create(transform_world_x(tr), transform_world_y(tr), transform_world_z(tr));
let bounds: f32 = camera.data.far_plane * 0.9;
let v2: vec4_t = vec4_create(bounds, bounds, bounds);
m = mat4_compose(v, _uniforms_quat, v2);
m = mat4_mult_mat(m, camera.v);
m = mat4_mult_mat(m, camera.p);
}
else { // Unknown uniform
return false;
}
gpu_set_matrix4(location, m);
return true;
}
else if (c.type == "vec4") {
let v: vec4_t = vec4_nan();
if (c.link == "_envmap_irradiance0") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[0];
v.y = fa[1];
v.z = fa[2];
v.w = fa[3];
}
else if (c.link == "_envmap_irradiance1") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[4];
v.y = fa[5];
v.z = fa[6];
v.w = fa[7];
}
else if (c.link == "_envmap_irradiance2") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[8];
v.y = fa[9];
v.z = fa[10];
v.w = fa[11];
}
else if (c.link == "_envmap_irradiance3") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[12];
v.y = fa[13];
v.z = fa[14];
v.w = fa[15];
}
else if (c.link == "_envmap_irradiance4") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[16];
v.y = fa[17];
v.z = fa[18];
v.w = fa[19];
}
else if (c.link == "_envmap_irradiance5") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[20];
v.y = fa[21];
v.z = fa[22];
v.w = fa[23];
}
else if (c.link == "_envmap_irradiance6") {
let fa: f32_array_t = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
v.x = fa[24];
v.y = fa[25];
v.z = fa[26];
v.w = fa[27];
}
else {
return false;
}
if (!vec4_isnan(v)) {
gpu_set_float4(location, v.x, v.y, v.z, v.w);
}
else {
gpu_set_float4(location, 0, 0, 0, 0);
}
return true;
}
else if (c.type == "vec3") {
let v: vec4_t = vec4_nan();
if (c.link == "_camera_pos") {
v = vec4_create(transform_world_x(camera.base.transform), transform_world_y(camera.base.transform), transform_world_z(camera.base.transform));
}
else if (c.link == "_camera_look") {
v = vec4_norm(camera_object_look_world(camera));
}
else {
return false;
}
if (!vec4_isnan(v)) {
gpu_set_float3(location, v.x, v.y, v.z);
}
else {
gpu_set_float3(location, 0.0, 0.0, 0.0);
}
return true;
}
else if (c.type == "vec2") {
let v: vec4_t = vec4_nan();
if (c.link == "_vec2x") {
v.x = 1.0;
v.y = 0.0;
}
else if (c.link == "_vec2x_inv") {
v.x = 1.0 / render_path_current_w;
v.y = 0.0;
}
else if (c.link == "_vec2x2") {
v.x = 2.0;
v.y = 0.0;
}
else if (c.link == "_vec2x2_inv") {
v.x = 2.0 / render_path_current_w;
v.y = 0.0;
}
else if (c.link == "_vec2y") {
v.x = 0.0;
v.y = 1.0;
}
else if (c.link == "_vec2y_inv") {
v.x = 0.0;
v.y = 1.0 / render_path_current_h;
}
else if (c.link == "_vec2y2") {
v.x = 0.0;
v.y = 2.0;
}
else if (c.link == "_vec2y2_inv") {
v.x = 0.0;
v.y = 2.0 / render_path_current_h;
}
else if (c.link == "_vec2y3") {
v.x = 0.0;
v.y = 3.0;
}
else if (c.link == "_vec2y3_inv") {
v.x = 0.0;
v.y = 3.0 / render_path_current_h;
}
else if (c.link == "_screen_size") {
v.x = render_path_current_w;
v.y = render_path_current_h;
}
else if (c.link == "_screen_size_inv") {
v.x = 1.0 / render_path_current_w;
v.y = 1.0 / render_path_current_h;
}
else if (c.link == "_camera_plane_proj") {
let znear: f32 = camera.data.near_plane;
let zfar: f32 = camera.data.far_plane;
v.x = zfar / (zfar - znear);
v.y = (-zfar * znear) / (zfar - znear);
}
else {
return false;
}
if (!vec4_isnan(v)) {
gpu_set_float2(location, v.x, v.y);
}
else {
gpu_set_float2(location, 0.0, 0.0);
}
return true;
}
else if (c.type == "float") {
let f: f32 = 0.0;
if (c.link == "_time") {
f = sys_time();
}
else if (c.link == "_aspect_ratio_window") {
f = sys_w() / sys_h();
}
else {
return false;
}
gpu_set_float(location, f);
return true;
}
else if (c.type == "floats") {
let fa: f32_array_t = null;
if (c.link == "_envmap_irradiance") {
fa = scene_world == null ? world_data_get_empty_irradiance() : scene_world._.irradiance;
}
if (fa != null) {
gpu_set_floats(location, fa);
return true;
}
}
else if (c.type == "int") {
let i: i32 = 0;
if (c.link == "_envmap_num_mipmaps") {
let w: world_data_t = scene_world;
i = w != null ? w.radiance_mipmaps + 1 - 2 : 1; // Include basecolor and exclude 2 scaled mips
}
else {
return false;
}
gpu_set_int(location, i);
return true;
}
return false;
}
function uniforms_set_obj_const(obj: object_t, loc: iron_gpu_constant_location_t, c: shader_const_t) {
if (c.link == null) {
return;
}
let camera: camera_object_t = scene_camera;
if (c.type == "mat4") {
let m: mat4_t = mat4_nan();
if (c.link == "_world_matrix") {
m = obj.transform.world_unpack;
}
else if (c.link == "_inv_world_matrix") {
m = mat4_inv(obj.transform.world_unpack);
}
else if (c.link == "_world_view_proj_matrix") {
m = mat4_mult_mat(obj.transform.world_unpack, camera.v);
m = mat4_mult_mat(m, camera.p);
}
else if (c.link == "_world_wiew_matrix") {
m = mat4_mult_mat(obj.transform.world_unpack, camera.v);
}
else if (c.link == "_prev_world_view_proj_matrix") {
let mo: mesh_object_t = obj.ext;
m = mat4_mult_mat(mo.prev_matrix, camera.prev_v);
// m = mat4_mult_mat(m, camera.prev_p);
m = mat4_mult_mat(m, camera.p);
}
else if (uniforms_mat4_links != null) {
m = uniforms_mat4_links(obj, current_material(obj), c.link);
}
if (mat4_isnan(m)) {
return;
}
gpu_set_matrix4(loc, m);
}
else if (c.type == "mat3") {
let m: mat3_t = mat3_nan();
if (c.link == "_normal_matrix") {
let m4: mat4_t = mat4_inv(obj.transform.world);
m4 = mat4_transpose3x3(m4);
m = mat3_set_from4(m4);
}
else if (c.link == "_view_matrix3") {
m = mat3_set_from4(camera.v);
}
if (mat3_isnan(m)) {
return;
}
gpu_set_matrix3(loc, m);
}
else if (c.type == "vec4") {
let v: vec4_t = vec4_nan();
if (uniforms_vec4_links != null) {
v = uniforms_vec4_links(obj, current_material(obj), c.link);
}
if (vec4_isnan(v)) {
return;
}
gpu_set_float4(loc, v.x, v.y, v.z, v.w);
}
else if (c.type == "vec3") {
let v: vec4_t = vec4_nan();
if (c.link == "_dim") { // Model space
let d: vec4_t = obj.transform.dim;
let s: vec4_t = obj.transform.scale;
v = vec4_create((d.x / s.x), (d.y / s.y), (d.z / s.z));
}
else if (c.link == "_half_dim") { // Model space
let d: vec4_t = obj.transform.dim;
let s: vec4_t = obj.transform.scale;
v = vec4_create((d.x / s.x) / 2, (d.y / s.y) / 2, (d.z / s.z) / 2);
}
else if (uniforms_vec3_links != null) {
v = uniforms_vec3_links(obj, current_material(obj), c.link);
}
if (vec4_isnan(v)) {
return;
}
gpu_set_float3(loc, v.x, v.y, v.z);
}
else if (c.type == "vec2") {
let v: vec2_t = vec2_nan();
if (uniforms_vec2_links != null) {
v = uniforms_vec2_links(obj, current_material(obj), c.link);
}
if (vec2_isnan(v)) {
return;
}
gpu_set_float2(loc, v.x, v.y);
}
else if (c.type == "float") {
let f: f32 = f32_nan();
if (c.link == "_object_info_index") {
f = obj.uid;
}
else if (c.link == "_object_info_material_index") {
f = current_material(obj)._.uid;
}
else if (c.link == "_object_info_random") {
f = obj.urandom;
}
else if (c.link == "_pos_unpack") {
f = uniforms_pos_unpack;
}
else if (c.link == "_tex_unpack") {
f = uniforms_tex_unpack;
}
else if (uniforms_f32_links != null) {
f = uniforms_f32_links(obj, current_material(obj), c.link);
}
if (f32_isnan(f)) {
return;
}
gpu_set_float(loc, f);
}
else if (c.type == "floats") {
let fa: f32_array_t = null;
if (c.link == "_skin_bones") {
///if arm_skin
if (obj.animation != null) {
fa = obj.animation.ext.skin_buffer;
}
///end
}
else if (uniforms_f32_array_links != null) {
fa = uniforms_f32_array_links(obj, current_material(obj), c.link);
}
if (fa == null) {
return;
}
gpu_set_floats(loc, fa);
}
else if (c.type == "int") {
let i: i32 = INT_MAX;
if (c.link == "_uid") {
i = obj.uid;
}
else if (uniforms_i32_links != null) {
i = uniforms_i32_links(obj, current_material(obj), c.link);
}
if (i == INT_MAX) {
return;
}
gpu_set_int(loc, i);
}
}
function uniforms_set_material_consts(context: shader_context_t, material_context: material_context_t) {
if (material_context.bind_constants != null) {
for (let i: i32 = 0; i < material_context.bind_constants.length; ++i) {
let matc: bind_const_t = material_context.bind_constants[i];
let pos: i32 = -1;
for (let i: i32 = 0; i < context.constants.length; ++i) {
let name: string = context.constants[i].name;
if (name == matc.name) {
pos = i;
break;
}
}
if (pos == -1) {
continue;
}
let c: shader_const_t = context.constants[pos];
uniforms_set_material_const(context._.constants[pos], c, matc);
}
}
if (material_context._.textures != null) {
for (let i: i32 = 0; i < material_context._.textures.length; ++i) {
let mname: string = material_context.bind_textures[i].name;
for (let j: i32 = 0; j < context._.tex_units.length; ++j) {
let sname: string = context.texture_units[j].name;
if (mname == sname) {
gpu_set_texture(context._.tex_units[j], material_context._.textures[i]);
// After texture sampler have been assigned, set texture parameters
material_context_set_tex_params(material_context, i, context, j);
break;
}
}
}
}
}
function current_material(object: object_t): material_data_t {
if (object != null && object.ext != null) {
let mo: mesh_object_t = object.ext;
if (mo.materials != null) {
return mo.materials[mo.material_index];
}
}
return null;
}
function uniforms_set_material_const(location: iron_gpu_constant_location_t, shader_const: shader_const_t, material_const: bind_const_t) {
if (shader_const.type == "vec4") {
gpu_set_float4(location, material_const.vec[0], material_const.vec[1], material_const.vec[2], material_const.vec[3]);
}
else if (shader_const.type == "vec3") {
gpu_set_float3(location, material_const.vec[0], material_const.vec[1], material_const.vec[2]);
}
else if (shader_const.type == "vec2") {
gpu_set_float2(location, material_const.vec[0], material_const.vec[1]);
}
else if (shader_const.type == "float") {
gpu_set_float(location, material_const.vec[0]);
}
else if (shader_const.type == "bool") {
gpu_set_bool(location, material_const.vec[0] > 0.0);
}
else if (shader_const.type == "int") {
gpu_set_int(location, math_floor(material_const.vec[0]));
}
}