From 1742b909dc7b1a7cb9af2d03d4759b4a7274bd1a Mon Sep 17 00:00:00 2001 From: luboslenco Date: Wed, 26 Mar 2025 20:56:40 +0100 Subject: [PATCH] kong test --- base/assets/shader_datas.arm | Bin 14253 -> 14713 bytes base/shaders/deferred_light.frag.glsl | 75 ------- base/shaders/deferred_light.kong | 257 ++++++++++++++++++++++++ base/shaders/prefilter_envmap.frag.glsl | 54 ----- base/shaders/prefilter_envmap.kong | 87 ++++++++ base/sources/ts/import_envmap.ts | 10 +- base/sources/ts/iron/shader_data.ts | 39 ++-- base/sources/ts/iron/uniforms.ts | 54 ++++- 8 files changed, 420 insertions(+), 156 deletions(-) delete mode 100644 base/shaders/deferred_light.frag.glsl create mode 100644 base/shaders/deferred_light.kong delete mode 100644 base/shaders/prefilter_envmap.frag.glsl create mode 100644 base/shaders/prefilter_envmap.kong diff --git a/base/assets/shader_datas.arm b/base/assets/shader_datas.arm index 1b0d07d5b17bd013c7b5561f05c1b9be91fe21c9..a37c9ebeac1ca2f435473af3ee5634f693836699 100644 GIT binary patch delta 377 zcmZ3R|FdYrMLl5=1_p-sl+?7;qN3E4_?*o2jFQO@^`uzA;+y~LEn#HjoxH^0)#O`- z_a*N$16AK<0TOwMxv96=fQ;gd%%UQL$?wf%CUYC{r~o;MDVd3R$*Bgo6dPhuY=}#- v5f;TpxD*>>QEZG$u?ZH%Cb$%vVo_|0OR*VDF*hPK%qANu32#1Q^pFJrig|aM delta 102 zcmexav^IakMLhvQ1_p+L#Ny)kvdq--qQuI{1uRl5!a%{z%=$|h8QCYVFnFcG3gj1O zWEK_OW&yHFDhpC?vjG`tIr)ht#bB|V%)IQ|LX+){MJG2KzME{QB)oZs$wL+Zndl)J diff --git a/base/shaders/deferred_light.frag.glsl b/base/shaders/deferred_light.frag.glsl deleted file mode 100644 index cff91314..00000000 --- a/base/shaders/deferred_light.frag.glsl +++ /dev/null @@ -1,75 +0,0 @@ -#version 450 - -uniform sampler2D gbufferD; -uniform sampler2D gbuffer0; -uniform sampler2D gbuffer1; -uniform vec4 envmap_data; // angle, sin(angle), cos(angle), strength -uniform vec4 shirr[7]; -uniform sampler2D senvmap_brdf; -uniform sampler2D senvmap_radiance; -#ifdef SPIRV -uniform float envmap_num_mipmaps; -#else -uniform int envmap_num_mipmaps; -#endif -uniform sampler2D ssaotex; -uniform vec2 camera_proj; -uniform vec3 eye; -uniform vec3 eye_look; - -#include "std/gbuffer.glsl" -#include "std/brdf.glsl" -#include "std/math.glsl" -#include "std/shirr.glsl" - -in vec2 tex_coord; -in vec3 view_ray; -out vec4 frag_color; - -void main() { - vec4 g0 = textureLod(gbuffer0, tex_coord, 0.0); // Normal.xy, roughness, metallic/matid - - vec3 n; - n.z = 1.0 - abs(g0.x) - abs(g0.y); - n.xy = n.z >= 0.0 ? g0.xy : octahedron_wrap(g0.xy); - n = normalize(n); - - float roughness = g0.b; - float metallic; - uint matid; - unpack_f32_i16(g0.a, metallic, matid); - vec4 g1 = textureLod(gbuffer1, tex_coord, 0.0); // Basecolor.rgb, occ - float occ = g1.a; - vec3 albedo = surface_albedo(g1.rgb, metallic); // g1.rgb - basecolor - vec3 f0 = surface_f0(g1.rgb, metallic); - - float depth = textureLod(gbufferD, tex_coord, 0.0).r * 2.0 - 1.0; - vec3 p = get_pos(eye, eye_look, normalize(view_ray), depth, camera_proj); - vec3 v = normalize(eye - p); - float dotnv = max(0.0, dot(n, v)); - - occ = mix(1.0, occ, dotnv); // AO Fresnel - - // Envmap - vec3 envl = sh_irradiance(vec3(n.x * envmap_data.z - n.y * envmap_data.y, n.x * envmap_data.y + n.y * envmap_data.z, n.z), shirr); - envl /= PI; - - vec3 reflection_world = reflect(-v, n); - float lod = mip_from_roughness(roughness, float(envmap_num_mipmaps)); - vec3 prefiltered_color = textureLod(senvmap_radiance, envmap_equirect(reflection_world, envmap_data.x), lod).rgb; - - envl.rgb *= albedo; - // Indirect specular - vec2 env_brdf = texelFetch(senvmap_brdf, ivec2(vec2(roughness, 1.0 - dotnv) * 256.0), 0).xy; - envl.rgb += prefiltered_color * (f0 * env_brdf.x + env_brdf.y) * 1.5; - envl.rgb *= envmap_data.w * occ; - frag_color.rgb = envl; - frag_color.rgb *= textureLod(ssaotex, tex_coord, 0.0).r; - - if (matid == uint(1)) { // Emission - frag_color.rgb += g1.rgb; // materialid - albedo = vec3(0.0, 0.0, 0.0); - } - - frag_color.a = 1.0; // Mark as opaque -} diff --git a/base/shaders/deferred_light.kong b/base/shaders/deferred_light.kong new file mode 100644 index 00000000..43e4d6a9 --- /dev/null +++ b/base/shaders/deferred_light.kong @@ -0,0 +1,257 @@ + +#[set(everything)] +const gbufferD: tex2d; + +#[set(everything)] +const gbufferD_sampler: sampler; + +#[set(everything)] +const gbuffer0: tex2d; + +#[set(everything)] +const gbuffer0_sampler: sampler; + +#[set(everything)] +const gbuffer1: tex2d; + +#[set(everything)] +const gbuffer1_sampler: sampler; + +#[set(everything)] +const senvmap_brdf: tex2d; + +#[set(everything)] +const senvmap_brdf_sampler: sampler; + +#[set(everything)] +const senvmap_radiance: tex2d; + +#[set(everything)] +const senvmap_radiance_sampler: sampler; + +#[set(everything)] +const ssaotex: tex2d; + +#[set(everything)] +const ssaotex_sampler: sampler; + +#[set(everything)] +const constants: { + invVP: float4x4; + eye: float3; + envmap_data: float4; // angle, sin(angle), cos(angle), strength + envmap_num_mipmaps: int; + camera_proj: float2; + eye_look: float3; + shirr0: float4; + shirr1: float4; + shirr2: float4; + shirr3: float4; + shirr4: float4; + shirr5: float4; + shirr6: float4; +}; + +const PI: float = 3.14159265358979; +const PI2: float = 6.28318530718; + +struct vert_in { + pos: float2; +} + +struct vert_out { + pos: float4; + tex: float2; + view_ray: float3; +} + +fun deferred_light_vert(input: vert_in): vert_out { + var output: vert_out; + output.tex = input.pos.xy * 0.5 + 0.5; + output.tex.y = 1.0 - output.tex.y; + output.pos = float4(input.pos.xy, 0.0, 1.0); + + // NDC (at the back of cube) + var v: float4 = float4(input.pos.xy, 1.0, 1.0); + v = constants.invVP * v; + v.xyz /= v.w; + output.view_ray = float3(v.xyz - constants.eye); + + return output; +} + +fun octahedron_wrap(v: float2): float2 { + var a: float2; + if (v.x >= 0.0) { + a.x = 1.0; + } + else { + a.x = -1.0; + } + + if (v.y >= 0.0) { + a.y = 1.0; + } + else { + a.y = -1.0; + } + + var r: float2; + r.x = abs(v.y); + r.y = abs(v.x); + r.x = 1.0 - r.x; + r.y = 1.0 - r.y; + return r * a; + + // return (1.0 - abs(v.yx)) * (float2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0)); +} + +// fun unpack_f32_i16(val: float, out f: float, out i: uint) { +// // Constant optimize by compiler +// const num_bit_target: int = 16; +// const num_bit_i: int = 4; +// const prec: float = float(1 << num_bit_target); +// const maxi: float = float(1 << num_bit_i); +// const prec_minus_one: float = prec - 1.0; +// const t1: float = ((prec / maxi) - 1.0) / prec_minus_one; +// const t2: float = (prec / maxi) / prec_minus_one; +// // Code +// // extract integer part +// // + rcp(prec_minus_one) to deal with precision issue +// i = uint((val / t2) + (1.0 / prec_minus_one)); +// // Now that we have i, solve formula in pack_f32_i16 for f +// //f = (val - t2 * float(i)) / t1 => convert in mads form +// f = clamp((-t2 * float(i) + val) / t1, 0.0, 1.0); // Saturate in case of precision issue +// } + +fun surface_albedo(base_color: float3, metalness: float): float3 { + return lerp(base_color, float3(0.0, 0.0, 0.0), metalness); +} + +fun surface_f0(base_color: float3, metalness: float): float3 { + return lerp(float3(0.04, 0.04, 0.04), base_color, metalness); +} + +fun get_pos(eye: float3, eye_look: float3, view_ray: float3, depth: float, camera_proj: float2): float3 { + // eye_look, view_ray should be normalized + var linear_depth: float = camera_proj.y / ((depth * 0.5 + 0.5) - camera_proj.x); + var view_z_dist: float = dot(eye_look, view_ray); + var wposition: float3 = eye + view_ray * (linear_depth / view_z_dist); + return wposition; +} + +const c1: float = 0.429043; +const c2: float = 0.511664; +const c3: float = 0.743125; +const c4: float = 0.886227; +const c5: float = 0.247708; + +fun sh_irradiance(nor: float3): float3 { + // TODO: Use padding for 4th component and pass shirr[].xyz directly + var cl00: float3 = float3(constants.shirr0.x, constants.shirr0.y, constants.shirr0.z); + var cl1m1: float3 = float3(constants.shirr0.w, constants.shirr1.x, constants.shirr1.y); + var cl10: float3 = float3(constants.shirr1.z, constants.shirr1.w, constants.shirr2.x); + var cl11: float3 = float3(constants.shirr2.y, constants.shirr2.z, constants.shirr2.w); + var cl2m2: float3 = float3(constants.shirr3.x, constants.shirr3.y, constants.shirr3.z); + var cl2m1: float3 = float3(constants.shirr3.w, constants.shirr4.x, constants.shirr4.y); + var cl20: float3 = float3(constants.shirr4.z, constants.shirr4.w, constants.shirr5.x); + var cl21: float3 = float3(constants.shirr5.y, constants.shirr5.z, constants.shirr5.w); + var cl22: float3 = float3(constants.shirr6.x, constants.shirr6.y, constants.shirr6.z); + return ( + c1 * cl22 * (nor.y * nor.y - (-nor.z) * (-nor.z)) + + c3 * cl20 * nor.x * nor.x + + c4 * cl00 - + c5 * cl20 + + 2.0 * c1 * cl2m2 * nor.y * (-nor.z) + + 2.0 * c1 * cl21 * nor.y * nor.x + + 2.0 * c1 * cl2m1 * (-nor.z) * nor.x + + 2.0 * c2 * cl11 * nor.y + + 2.0 * c2 * cl1m1 * (-nor.z) + + 2.0 * c2 * cl10 * nor.x + ); +} + +fun mip_from_roughness(roughness: float, num_mipmaps: float): float { + // First mipmap level = roughness 0, last = roughness = 1 + return roughness * num_mipmaps; +} + +fun envmap_equirect(normal: float3, angle: float): float2 { + var phi: float = acos(normal.z); + var theta: float = atan2(normal.x, -normal.y) + PI + angle; + return float2(theta / PI2, phi / PI); +} + +fun deferred_light_frag(input: vert_out): float4 { + // normal.xy, roughness, metallic/matid + var g0: float4 = sample_lod(gbuffer0, gbuffer0_sampler, input.tex, 0.0); + + var n: float3; + n.z = 1.0 - abs(g0.x) - abs(g0.y); + if (n.z >= 0.0) { + n.xy = g0.xy; + } + else { + n.xy = octahedron_wrap(g0.xy); + } + n = normalize(n); + + var roughness: float = g0.b; + var metallic: float; + var matid: uint; + // unpack_f32_i16(g0.a, metallic, matid); + matid = uint((g0.a / 0.06250047610269868710814625956118106842041015625) + (1.0 / 65535.0)); + metallic = clamp((-0.06250047610269868710814625956118106842041015625 * float(matid) + g0.a) / 0.062485207147583624058737396240234375, 0.0, 1.0); + + var g1: float4 = sample_lod(gbuffer1, gbuffer1_sampler, input.tex, 0.0); // basecolor.rgb, occ + var occ: float = g1.a; + var albedo: float3 = surface_albedo(g1.rgb, metallic); + var f0: float3 = surface_f0(g1.rgb, metallic); + + var depth: float = sample_lod(gbufferD, gbufferD_sampler, input.tex, 0.0).r * 2.0 - 1.0; + var p: float3 = get_pos(constants.eye, constants.eye_look, normalize(input.view_ray), depth, constants.camera_proj); + var v: float3 = normalize(constants.eye - p); + var dotnv: float = max(0.0, dot(n, v)); + + occ = lerp(1.0, occ, dotnv); // ao fresnel + + // Envmap + var envl: float3 = sh_irradiance( + float3( + n.x * constants.envmap_data.z - n.y * constants.envmap_data.y, + n.x * constants.envmap_data.y + n.y * constants.envmap_data.z, + n.z + ) + ); + envl /= PI; + + var reflection_world: float3 = reflect(-v, n); + var lod: float = mip_from_roughness(roughness, float(constants.envmap_num_mipmaps)); + var prefiltered_color: float3 = sample_lod(senvmap_radiance, senvmap_radiance_sampler, envmap_equirect(reflection_world, constants.envmap_data.x), lod).rgb; + + envl.rgb = envl.rgb * albedo; + // Indirect specular + // var env_brdf: float2 = senvmap_brdf[uint2(roughness * 256.0, (1.0 - dotnv) * 256.0)].xy; + var env_brdf: float4 = senvmap_brdf[uint2(roughness * 256.0, (1.0 - dotnv) * 256.0)]; + envl.rgb += prefiltered_color * (f0 * env_brdf.x + env_brdf.y) * 1.5; + envl.rgb *= constants.envmap_data.w * occ; + + var color: float4; + color.rgb = envl; + color.rgb = color.rgb * sample_lod(ssaotex, ssaotex_sampler, input.tex, 0.0).r; + + if (matid == uint(1)) { // Emission + color.rgb += g1.rgb; // materialid + albedo = float3(0.0, 0.0, 0.0); + } + + color.a = 1.0; // Mark as opaque + + return color; +} + +#[pipe] +struct pipe { + vertex = deferred_light_vert; + fragment = deferred_light_frag; +} diff --git a/base/shaders/prefilter_envmap.frag.glsl b/base/shaders/prefilter_envmap.frag.glsl deleted file mode 100644 index 2ea04ec4..00000000 --- a/base/shaders/prefilter_envmap.frag.glsl +++ /dev/null @@ -1,54 +0,0 @@ -#version 450 - -uniform sampler2D radiance; -uniform vec4 params; - -in vec2 tex_coord; -out vec4 frag_color; - -const float PI = 3.14159265358979; -const float PI2 = PI * 2.0; -#ifdef METAL -const int samples = 1024 * 2; // Prevent gpu hang -#else -const int samples = 1024 * 16; -#endif - -float rand(vec2 co) { - return fract(sin(mod(dot(co.xy, vec2(12.9898, 78.233)), 3.14)) * 43758.5453); -} - -vec2 equirect(vec3 normal) { - float phi = acos(normal.z); - float theta = atan2(normal.x, -normal.y) + PI; - return vec2(theta / PI2, phi / PI); -} - -vec3 reverse_equirect(vec2 co) { - float theta = co.x * PI2 - PI; - float phi = co.y * PI; - return vec3(sin(phi) * cos(theta), -(sin(phi) * sin(theta)), cos(phi)); -} - -vec3 cos_weighted_hemisphere_direction(vec3 n, vec2 co, uint seed) { - vec2 r = vec2(rand(co * seed), rand(co * seed * 2)); - vec3 uu = normalize(cross(n, vec3(0.0, 1.0, 1.0))); - vec3 vv = cross(uu, n); - float ra = sqrt(r.y); - float rx = ra * cos(PI2 * r.x); - float ry = ra * sin(PI2 * r.x); - float rz = sqrt(1.0 - r.y); - vec3 rr = vec3(rx * uu + ry * vv + rz * n); - return normalize(rr); -} - -void main() { - frag_color = vec4(0.0, 0.0, 0.0, 1.0); - vec3 n = reverse_equirect(tex_coord); - for (int i = 0; i < samples; i++) { - vec3 dir = normalize(mix(n, cos_weighted_hemisphere_direction(n, tex_coord, i), params.x)); - frag_color.rgb += texture(radiance, equirect(dir)).rgb; - } - frag_color.rgb /= float(samples); - frag_color.rgb = pow(frag_color.rgb, vec3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); -} diff --git a/base/shaders/prefilter_envmap.kong b/base/shaders/prefilter_envmap.kong new file mode 100644 index 00000000..5d4dcb41 --- /dev/null +++ b/base/shaders/prefilter_envmap.kong @@ -0,0 +1,87 @@ + +#[set(everything)] +const radiance: tex2d; + +#[set(everything)] +const radiance_sampler: sampler; + +#[set(everything)] +const constants: { + params: float4; +}; + +const PI: float = 3.14159265358979; +const PI2: float = 6.28318530718; +// #ifdef METAL +// const samples = 1024 * 2; // Prevent gpu hang +// #else +// const samples: float = 1024 * 16; +const samples: float = 16384; +// #endif + +struct vert_in { + pos: float2; +} + +struct vert_out { + pos: float4; + tex: float2; +} + +fun prefilter_envmap_vert(input: vert_in): vert_out { + var output: vert_out; + output.tex = input.pos.xy * 0.5 + 0.5; + output.tex.y = 1.0 - output.tex.y; + output.pos = float4(input.pos.xy, 0.0, 1.0); + return output; +} + +fun rand(co: float2): float { + return frac(sin(dot(co.xy, float2(12.9898, 78.233)) % 3.14) * 43758.5453); +} + +fun equirect(normal: float3): float2 { + var phi: float = acos(normal.z); + var theta: float = atan2(normal.x, -normal.y) + PI; + return float2(theta / PI2, phi / PI); +} + +fun reverse_equirect(co: float2): float3 { + var theta: float = co.x * PI2 - PI; + var phi: float = co.y * PI; + return float3(sin(phi) * cos(theta), -(sin(phi) * sin(theta)), cos(phi)); +} + +// fun cos_weighted_hemisphere_direction(n: float3, co: float2, seed: uint): float3 { +fun cos_weighted_hemisphere_direction(n: float3, co: float2, seed: float): float3 { + var r: float2 = float2(rand(co * seed), rand(co * seed * 2.0)); + var uu: float3 = normalize(cross(n, float3(0.0, 1.0, 1.0))); + var vv: float3 = cross(uu, n); + var ra: float = sqrt(r.y); + var rx: float = ra * cos(PI2 * r.x); + var ry: float = ra * sin(PI2 * r.x); + var rz: float = sqrt(1.0 - r.y); + var rr: float3 = float3(rx * uu + ry * vv + rz * n); + return normalize(rr); +} + +fun prefilter_envmap_frag(input: vert_out): float4 { + var color: float4 = float4(0.0, 0.0, 0.0, 1.0); + var n: float3 = reverse_equirect(input.tex); + for (var i: uint = 0; i < samples; i += 1) { + var dir: float3 = normalize(lerp(n, cos_weighted_hemisphere_direction(n, input.tex, i), constants.params.x)); + color.rgb += sample(radiance, radiance_sampler, equirect(dir)).rgb; + } + color.rgb /= float(samples); + // color.rgb = pow(color.rgb, float3(1.0 / 2.2, 1.0 / 2.2, 1.0 / 2.2)); + color.r = pow(color.r, 1.0 / 2.2); + color.g = pow(color.g, 1.0 / 2.2); + color.b = pow(color.b, 1.0 / 2.2); + return color; +} + +#[pipe] +struct pipe { + vertex = prefilter_envmap_vert; + fragment = prefilter_envmap_frag; +} diff --git a/base/sources/ts/import_envmap.ts b/base/sources/ts/import_envmap.ts index f9212878..d48867a6 100644 --- a/base/sources/ts/import_envmap.ts +++ b/base/sources/ts/import_envmap.ts @@ -13,16 +13,24 @@ function import_envmap_run(path: string, image: iron_gpu_texture_t) { // Init if (import_envmap_pipeline == null) { import_envmap_pipeline = gpu_create_pipeline(); - import_envmap_pipeline.vertex_shader = sys_get_shader("pass.vert"); + import_envmap_pipeline.vertex_shader = sys_get_shader("prefilter_envmap.vert"); import_envmap_pipeline.fragment_shader = sys_get_shader("prefilter_envmap.frag"); let vs: iron_gpu_vertex_structure_t = gpu_vertex_struct_create(); gpu_vertex_struct_add(vs, "pos", vertex_data_t.F32_2X); import_envmap_pipeline.input_layout = vs; import_envmap_pipeline.color_attachment_count = 1; ARRAY_ACCESS(import_envmap_pipeline.color_attachment, 0) = tex_format_t.RGBA128; + + import_envmap_pipeline.kong = true; gpu_compile_pipeline(import_envmap_pipeline); + import_envmap_params_loc = gpu_get_constant_location(import_envmap_pipeline, "params"); + let ptr: gpu_constant_location_impl_t = ADDRESS(import_envmap_params_loc.impl); + ptr.vertexOffset = -1; + ptr.fragmentOffset = 0; + import_envmap_radiance_loc = gpu_get_texture_unit(import_envmap_pipeline, "radiance"); + ARRAY_ACCESS(import_envmap_radiance_loc.stages, IRON_GPU_SHADER_TYPE_FRAGMENT) = 0; import_envmap_radiance = gpu_create_render_target(1024, 512, tex_format_t.RGBA128); diff --git a/base/sources/ts/iron/shader_data.ts b/base/sources/ts/iron/shader_data.ts index 003a7458..bc8ce446 100644 --- a/base/sources/ts/iron/shader_data.ts +++ b/base/sources/ts/iron/shader_data.ts @@ -165,34 +165,25 @@ function shader_context_compile(raw: shader_context_t): shader_context_t { return shader_context_finish_compile(raw); } -function shader_context_type_offset(t: string): i32 { - ///if IRON_DIRECT3D12 - if (t == "int") return 16; - if (t == "float") return 16; - if (t == "vec2") return 16; - if (t == "vec3") return 16; - if (t == "vec4") return 16; - if (t == "mat3") return 48; - if (t == "mat4") return 64; - ///end - ///if IRON_VULKAN - if (t == "int") return 4; - if (t == "float") return 4; - if (t == "vec2") return 8; - if (t == "vec3") return 16; - if (t == "vec4") return 16; - if (t == "mat3") return 48; - if (t == "mat4") return 64; - ///end - ///if IRON_METAL +function shader_context_type_size(t: string): i32 { if (t == "int") return 4; if (t == "float") return 4; if (t == "vec2") return 8; if (t == "vec3") return 12; if (t == "vec4") return 16; - if (t == "mat3") return 36; + if (t == "mat3") return 48; if (t == "mat4") return 64; - ///end +} + +function shader_context_type_pad(offset: i32, size: i32): i32 { + let r: i32 = offset % 16; + if (r == 0) { + return 0; + } + if (size >= 16 || r + size > 16) { + return 16 - r; + } + return 0; } function shader_context_finish_compile(raw: shader_context_t): shader_context_t { @@ -202,8 +193,10 @@ function shader_context_finish_compile(raw: shader_context_t): shader_context_t let offset: i32 = 0; for (let i: i32 = 0; i < raw.constants.length; ++i) { let c: shader_const_t = raw.constants[i]; + let size: i32 = shader_context_type_size(c.type); + offset += shader_context_type_pad(offset, size); shader_context_add_const(raw, c, offset); - offset += shader_context_type_offset(c.type); + offset += size; } } diff --git a/base/sources/ts/iron/uniforms.ts b/base/sources/ts/iron/uniforms.ts index 9ac5d77b..f3c7bdd0 100644 --- a/base/sources/ts/iron/uniforms.ts +++ b/base/sources/ts/iron/uniforms.ts @@ -196,10 +196,58 @@ function uniforms_set_context_const(location: iron_gpu_constant_location_t, c: s } else if (c.type == "vec4") { let v: vec4_t = vec4_nan(); - // if (c.link == "") {} - // else { + 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);