mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-08 17:19:10 -10:00
Fix OpenGL shader error: flatten colored_lights to avoid ARB_arrays_of_arrays (#6267)
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
1 parent
904ef97e51
commit
7affb5b478
5 files changed
+51
-9
No files matched your search
@@ -73,4 +73,4 @@ workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
horizon-items = { path = "../horizon-items", features = ["test-support"] }
|
||||
naga = { version = "30.0.1", features = ["wgsl-in", "hlsl-out", "msl-out", "spv-out"] }
|
||||
naga = { version = "30.0.1", features = ["wgsl-in", "hlsl-out", "glsl-out", "msl-out", "spv-out"] }
|
||||
@@ -13,7 +13,8 @@ use std::collections::HashMap;
|
||||
|
||||
/// Lights the shaders read: `Globals.dynamic_lights` in gfx.rs, terrain.wgsl and entity.wgsl.
|
||||
pub const MAX: usize = 16;
|
||||
/// Camera-relative position and radius; RGB intensity in a second vec4.
|
||||
/// Camera-relative position and radius; RGB intensity in a second vec4. The shaders read it as a flat
|
||||
/// `array<vec4<f32>, 32>` (nested arrays need ARB_arrays_of_arrays, absent from GL below 4.3).
|
||||
pub type Colored = [[f32; 4]; 2];
|
||||
|
||||
/// Nearest validated native visual lights; never enters gameplay lighting.
|
||||
|
||||
@@ -22,7 +22,7 @@ struct Globals {
|
||||
outline_params: vec4<f32>,
|
||||
// Horizon Extras' dynamic lights: camera-relative position and level (dynamic_light.rs).
|
||||
dynamic_lights: array<vec4<f32>, 16>,
|
||||
colored_lights: array<array<vec4<f32>, 2>, 16>,
|
||||
colored_lights: array<vec4<f32>, 32>,
|
||||
colored_count: vec4<u32>,
|
||||
emissive_layers: array<vec4<u32>, 32>,
|
||||
emissive_count: vec4<u32>,
|
||||
@@ -97,8 +97,8 @@ fn dynamic_block_light(pos: vec3<f32>) -> f32 {
|
||||
fn native_colored_light(pos: vec3<f32>) -> vec3<f32> {
|
||||
var rgb = vec3(0.0);
|
||||
for (var i = 0u; i < min(globals.colored_count.x, 16u); i++) {
|
||||
let at = globals.colored_lights[i][0];
|
||||
let color = globals.colored_lights[i][1];
|
||||
let at = globals.colored_lights[i * 2u];
|
||||
let color = globals.colored_lights[i * 2u + 1u];
|
||||
rgb += color.rgb * max(0.0, 1.0 - distance(pos, at.xyz) / at.w) * color.a;
|
||||
}
|
||||
return min(rgb, vec3(1.0));
|
||||
|
||||
@@ -8807,7 +8807,7 @@ mod tests {
|
||||
/// Every WGSL shader file translates to HLSL as wgpu's DirectX 12 backend
|
||||
/// writes it for FXC (shader model 5.1), entry point by entry point.
|
||||
#[test]
|
||||
fn shaders_translate_to_hlsl_for_directx_12() {
|
||||
fn shaders_translate_to_hlsl_for_directx_12_and_glsl_for_opengl() {
|
||||
fn wgsl_files(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
|
||||
for entry in std::fs::read_dir(dir).unwrap() {
|
||||
let path = entry.unwrap().path();
|
||||
@@ -8848,6 +8848,7 @@ mod tests {
|
||||
sources.push((path, text));
|
||||
}
|
||||
}
|
||||
let mut glsl_checked = 0;
|
||||
for (path, text) in sources {
|
||||
// entity.wgsl comes after the overlay's constants (entity_shader).
|
||||
let module = naga::front::wgsl::parse_str(&text)
|
||||
@@ -8880,8 +8881,48 @@ mod tests {
|
||||
.write(&module, &info, None)
|
||||
.unwrap_or_else(|e| panic!("{} {}: {e}", path.display(), entry.name));
|
||||
assert!(!hlsl.is_empty());
|
||||
// OpenGL below 4.3 lacks ARB_arrays_of_arrays (#6267): no nested array may reach it.
|
||||
// Compute and storage-buffer shaders (culling, frame generation) never run on GL.
|
||||
if entry.stage == naga::ShaderStage::Compute
|
||||
|| text.contains("var<storage")
|
||||
|| text.contains("var<workgroup>")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for version in [330, 400] {
|
||||
let mut glsl = String::new();
|
||||
let glsl_result = naga::back::glsl::Writer::new(
|
||||
&mut glsl,
|
||||
&module,
|
||||
&info,
|
||||
&naga::back::glsl::Options {
|
||||
version: naga::back::glsl::Version::Desktop(version),
|
||||
..Default::default()
|
||||
},
|
||||
&naga::back::glsl::PipelineOptions {
|
||||
shader_stage: entry.stage,
|
||||
entry_point: entry.name.clone(),
|
||||
multiview: None,
|
||||
},
|
||||
Default::default(),
|
||||
)
|
||||
.and_then(|mut w| w.write());
|
||||
// Some shaders use features GLSL cannot express (depth textureLoad): GL does
|
||||
// not run them. The ones it does run must translate, checked below.
|
||||
if glsl_result.is_err() {
|
||||
continue;
|
||||
}
|
||||
glsl_checked += 1;
|
||||
assert!(
|
||||
!glsl.contains("ARB_arrays_of_arrays"),
|
||||
"{} {} needs ARB_arrays_of_arrays on GLSL {version}",
|
||||
path.display(),
|
||||
entry.name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(glsl_checked >= 10, "{glsl_checked} GLSL translations");
|
||||
}
|
||||
#[test]
|
||||
fn gl_sprite_arrays_are_neither_2d_textures_nor_cube_maps() {
|
||||
|
||||
@@ -24,7 +24,7 @@ struct Globals {
|
||||
outline_params: vec4<f32>,
|
||||
// Horizon Extras' dynamic lights: camera-relative position and level (dynamic_light.rs).
|
||||
dynamic_lights: array<vec4<f32>, 16>,
|
||||
colored_lights: array<array<vec4<f32>, 2>, 16>,
|
||||
colored_lights: array<vec4<f32>, 32>,
|
||||
colored_count: vec4<u32>,
|
||||
emissive_layers: array<vec4<u32>, 32>,
|
||||
emissive_count: vec4<u32>,
|
||||
@@ -249,8 +249,8 @@ fn dynamic_block_light(pos: vec3<f32>) -> f32 {
|
||||
fn native_colored_light(pos: vec3<f32>) -> vec3<f32> {
|
||||
var rgb = vec3(0.0);
|
||||
for (var i = 0u; i < min(globals.colored_count.x, 16u); i++) {
|
||||
let at = globals.colored_lights[i][0];
|
||||
let color = globals.colored_lights[i][1];
|
||||
let at = globals.colored_lights[i * 2u];
|
||||
let color = globals.colored_lights[i * 2u + 1u];
|
||||
rgb += color.rgb * max(0.0, 1.0 - distance(pos, at.xyz) / at.w) * color.a;
|
||||
}
|
||||
return min(rgb, vec3(1.0));
|
||||
|
||||
Reference in new issue
Block a user