Fix WebGL not rendering StandardMaterial (#12110)

# Objective

- Fixes #12081

## Solution

Passing the `Affine2` as a neatly packed `mat3x2` breaks WebGL with
`drawElementsInstanced: Buffer for uniform block is smaller than
UNIFORM_BLOCK_DATA_SIZE.`
I fixed this by using a `mat3x3` instead.
Alternative solutions that come to mind:
- Pass in a `mat3x2` on non-webgl targets and a `mat3x3` otherwise. I
guess I could use `#ifdef SIXTEEN_BYTE_ALIGNMENT` for this, but it
doesn't seem quite right? This would be more efficient, but decrease
code quality.
- Do something about `UNIFORM_BLOCK_DATA_SIZE`. I don't know how, so I'd
need some guidance here.

@superdump let me know if you'd like me to implement other variants.
Otherwise, I vote for merging this as a quick fix for `main` and then
improving the packing in subsequent PRs :)

## Additional notes

Ideally we should merge this before @JMS55 rebases #10164 so that they
don't have to rebase everything a second time.
This commit is contained in:
Jan Hohenheim 2024-02-25 23:42:28 +01:00 committed by GitHub
parent 5e63f6815b
commit ad5d790e9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 8 additions and 16 deletions

View file

@ -1,5 +1,5 @@
use bevy_asset::Asset;
use bevy_math::{Affine2, Vec2, Vec4};
use bevy_math::{Affine2, Mat3, Vec4};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{mesh::MeshVertexBufferLayout, render_asset::RenderAssets, render_resource::*};
@ -596,12 +596,8 @@ pub struct StandardMaterialUniform {
pub emissive: Vec4,
/// Color white light takes after travelling through the attenuation distance underneath the material surface
pub attenuation_color: Vec4,
/// The x-axis of the mat2 of the transform applied to the UVs corresponding to ATTRIBUTE_UV_0 on the mesh before sampling. Default is [1, 0].
pub uv_transform_x_axis: Vec2,
/// The y-axis of the mat2 of the transform applied to the UVs corresponding to ATTRIBUTE_UV_0 on the mesh before sampling. Default is [0, 1].
pub uv_transform_y_axis: Vec2,
/// The translation of the transform applied to the UVs corresponding to ATTRIBUTE_UV_0 on the mesh before sampling. Default is [0, 0].
pub uv_transform_translation: Vec2,
/// The transform applied to the UVs corresponding to ATTRIBUTE_UV_0 on the mesh before sampling. Default is identity.
pub uv_transform: Mat3,
/// Linear perceptual roughness, clamped to [0.089, 1.0] in the shader
/// Defaults to minimum of 0.089
pub roughness: f32,
@ -736,9 +732,7 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
lightmap_exposure: self.lightmap_exposure,
max_relief_mapping_search_steps: self.parallax_mapping_method.max_steps(),
deferred_lighting_pass_id: self.deferred_lighting_pass_id as u32,
uv_transform_x_axis: self.uv_transform.matrix2.x_axis,
uv_transform_y_axis: self.uv_transform.matrix2.y_axis,
uv_transform_translation: self.uv_transform.translation,
uv_transform: self.uv_transform.into(),
}
}
}

View file

@ -11,7 +11,6 @@
parallax_mapping::parallaxed_uv,
lightmap::lightmap,
}
#import bevy_render::maths::affine2_to_square
#ifdef SCREEN_SPACE_AMBIENT_OCCLUSION
#import bevy_pbr::mesh_view_bindings::screen_space_ambient_occlusion_texture
@ -74,7 +73,7 @@ fn pbr_input_from_standard_material(
let NdotV = max(dot(pbr_input.N, pbr_input.V), 0.0001);
#ifdef VERTEX_UVS
let uv_transform = affine2_to_square(pbr_bindings::material.uv_transform);
let uv_transform = pbr_bindings::material.uv_transform;
var uv = (uv_transform * vec3(in.uv, 1.0)).xy;
#ifdef VERTEX_TANGENTS

View file

@ -7,7 +7,6 @@
pbr_bindings,
pbr_types,
}
#import bevy_render::maths::affine2_to_square
// Cutoff used for the premultiplied alpha modes BLEND and ADD.
const PREMULTIPLIED_ALPHA_CUTOFF = 0.05;
@ -19,7 +18,7 @@ fn prepass_alpha_discard(in: VertexOutput) {
var output_color: vec4<f32> = pbr_bindings::material.base_color;
#ifdef VERTEX_UVS
let uv_transform = affine2_to_square(pbr_bindings::material.uv_transform);
let uv_transform = pbr_bindings::material.uv_transform;
let uv = (uv_transform * vec3(in.uv, 1.0)).xy;
if (pbr_bindings::material.flags & pbr_types::STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT) != 0u {
output_color = output_color * textureSampleBias(pbr_bindings::base_color_texture, pbr_bindings::base_color_sampler, uv, view.mip_bias);

View file

@ -6,7 +6,7 @@ struct StandardMaterial {
base_color: vec4<f32>,
emissive: vec4<f32>,
attenuation_color: vec4<f32>,
uv_transform: mat3x2<f32>,
uv_transform: mat3x3<f32>,
perceptual_roughness: f32,
metallic: f32,
reflectance: f32,
@ -78,7 +78,7 @@ fn standard_material_new() -> StandardMaterial {
material.max_relief_mapping_search_steps = 5u;
material.deferred_lighting_pass_id = 1u;
// scale 1, translation 0, rotation 0
material.uv_transform = mat3x2<f32>(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
material.uv_transform = mat3x3<f32>(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0);
return material;
}