From 49db5d0cec0fedb6f5c7b7cb8dc6be1428662fd9 Mon Sep 17 00:00:00 2001 From: James Carl Date: Sat, 3 Dec 2022 17:37:53 -0500 Subject: [PATCH] Added ARRAY_TEXTURES support to shaders. --- .../src/render/mesh_vertex_output.wgsl | 3 ++ crates/bevy_pbr/src/render/pbr.wgsl | 28 ++++++++++++++++--- crates/bevy_pbr/src/render/pbr_bindings.wgsl | 24 ++++++++++++++++ crates/bevy_pbr/src/render/pbr_functions.wgsl | 9 +++++- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh_vertex_output.wgsl b/crates/bevy_pbr/src/render/mesh_vertex_output.wgsl index ba0c6b2237c0ae..ba623213e30f15 100644 --- a/crates/bevy_pbr/src/render/mesh_vertex_output.wgsl +++ b/crates/bevy_pbr/src/render/mesh_vertex_output.wgsl @@ -11,3 +11,6 @@ #ifdef VERTEX_COLORS @location(4) color: vec4, #endif +#ifdef ARRAY_TEXTURES + @location(5) texture_layer: i32, +#endif \ No newline at end of file diff --git a/crates/bevy_pbr/src/render/pbr.wgsl b/crates/bevy_pbr/src/render/pbr.wgsl index cfe825190d2a5a..1fc7179eb0036d 100644 --- a/crates/bevy_pbr/src/render/pbr.wgsl +++ b/crates/bevy_pbr/src/render/pbr.wgsl @@ -22,7 +22,11 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { #endif #ifdef VERTEX_UVS if ((material.flags & STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u) { - output_color = output_color * textureSample(base_color_texture, base_color_sampler, in.uv); + output_color = output_color * textureSample(base_color_texture, base_color_sampler, in.uv + #ifdef ARRAY_TEXTURES + , in.texture_layer + #endif + ); } #endif @@ -41,7 +45,12 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { var emissive: vec4 = material.emissive; #ifdef VERTEX_UVS if ((material.flags & STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT) != 0u) { - emissive = vec4(emissive.rgb * textureSample(emissive_texture, emissive_sampler, in.uv).rgb, 1.0); + emissive = vec4(emissive.rgb * textureSample(emissive_texture, emissive_sampler, in.uv +#ifdef ARRAY_TEXTURES + , in.texture_layer +#endif + ).rgb, 1.0 + ); } #endif pbr_input.material.emissive = emissive; @@ -50,7 +59,11 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { var perceptual_roughness: f32 = material.perceptual_roughness; #ifdef VERTEX_UVS if ((material.flags & STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT) != 0u) { - let metallic_roughness = textureSample(metallic_roughness_texture, metallic_roughness_sampler, in.uv); + let metallic_roughness = textureSample(metallic_roughness_texture, metallic_roughness_sampler, in.uv +#ifdef ARRAY_TEXTURES + , in.texture_layer +#endif + ); // Sampling from GLTF standard channels for now metallic = metallic * metallic_roughness.b; perceptual_roughness = perceptual_roughness * metallic_roughness.g; @@ -62,7 +75,11 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { var occlusion: f32 = 1.0; #ifdef VERTEX_UVS if ((material.flags & STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT) != 0u) { - occlusion = textureSample(occlusion_texture, occlusion_sampler, in.uv).r; + occlusion = textureSample(occlusion_texture, occlusion_sampler, in.uv +#ifdef ARRAY_TEXTURES + , in.texture_layer +#endif + ).r; } #endif pbr_input.occlusion = occlusion; @@ -87,6 +104,9 @@ fn fragment(in: FragmentInput) -> @location(0) vec4 { #endif #ifdef VERTEX_UVS in.uv, +#endif +#ifdef ARRAY_TEXTURES + in.texture_layer, #endif ); pbr_input.V = calculate_view(in.world_position, pbr_input.is_orthographic); diff --git a/crates/bevy_pbr/src/render/pbr_bindings.wgsl b/crates/bevy_pbr/src/render/pbr_bindings.wgsl index f4e4d34f3b4c21..c4110d2162e9e9 100644 --- a/crates/bevy_pbr/src/render/pbr_bindings.wgsl +++ b/crates/bevy_pbr/src/render/pbr_bindings.wgsl @@ -4,6 +4,8 @@ @group(1) @binding(0) var material: StandardMaterial; + +#ifndef ARRAY_TEXTURES @group(1) @binding(1) var base_color_texture: texture_2d; @group(1) @binding(2) @@ -24,3 +26,25 @@ var occlusion_sampler: sampler; var normal_map_texture: texture_2d; @group(1) @binding(10) var normal_map_sampler: sampler; +#else +@group(1) @binding(1) +var base_color_texture: texture_2d_array; +@group(1) @binding(2) +var base_color_sampler: sampler; +@group(1) @binding(3) +var emissive_texture: texture_2d_array; +@group(1) @binding(4) +var emissive_sampler: sampler; +@group(1) @binding(5) +var metallic_roughness_texture: texture_2d_array; +@group(1) @binding(6) +var metallic_roughness_sampler: sampler; +@group(1) @binding(7) +var occlusion_texture: texture_2d_array; +@group(1) @binding(8) +var occlusion_sampler: sampler; +@group(1) @binding(9) +var normal_map_texture: texture_2d_array; +@group(1) @binding(10) +var normal_map_sampler: sampler; +#endif \ No newline at end of file diff --git a/crates/bevy_pbr/src/render/pbr_functions.wgsl b/crates/bevy_pbr/src/render/pbr_functions.wgsl index 4f4c5495dbaa37..01e66423973c3f 100644 --- a/crates/bevy_pbr/src/render/pbr_functions.wgsl +++ b/crates/bevy_pbr/src/render/pbr_functions.wgsl @@ -50,6 +50,9 @@ fn apply_normal_mapping( #ifdef VERTEX_UVS uv: vec2, #endif +#ifdef ARRAY_TEXTURES + texture_layer: i32, +#endif ) -> vec3 { // NOTE: The mikktspace method of normal mapping explicitly requires that the world normal NOT // be re-normalized in the fragment shader. This is primarily to match the way mikktspace @@ -74,7 +77,11 @@ fn apply_normal_mapping( #ifdef VERTEX_UVS #ifdef STANDARDMATERIAL_NORMAL_MAP // Nt is the tangent-space normal. - var Nt = textureSample(normal_map_texture, normal_map_sampler, uv).rgb; + var Nt = textureSample(normal_map_texture, normal_map_sampler, uv +#ifdef ARRAY_TEXTURES + , texture_layer +#endif + ).rgb; if ((standard_material_flags & STANDARD_MATERIAL_FLAGS_TWO_COMPONENT_NORMAL_MAP) != 0u) { // Only use the xy components and derive z for 2-component normal maps. Nt = vec3(Nt.rg * 2.0 - 1.0, 0.0);