make pbr shader std140 compatible (#1798)

In shaders, `vec3` should be avoided for `std140` layout, as they take the size of a `vec4` and won't support manual padding by adding an additional `float`.

This change is needed for 3D to work in WebGL2. With it, I get PBR to render
<img width="1407" alt="Screenshot 2021-04-02 at 02 57 14" src="https://user-images.githubusercontent.com/8672791/113368551-5a3c2780-935f-11eb-8c8d-e9ba65b5ee98.png">

Without it, nothing renders... @cart Could this be considered for 0.5 release?

Also, I learned shaders 2 days ago, so don't hesitate to correct any issue or misunderstanding I may have

bevy_webgl2 PR in progress for Bevy 0.5 is here if you want to test: https://github.com/rparrett/bevy_webgl2/pull/1
This commit is contained in:
François 2021-04-03 23:30:28 +00:00
parent 276a81cc30
commit 9098df3034
2 changed files with 16 additions and 17 deletions

View file

@ -38,10 +38,8 @@ const int MAX_LIGHTS = 10;
struct Light {
mat4 proj;
vec3 pos;
float inverseRadiusSquared;
vec3 color;
float unused; // unused 4th element of vec4;
vec4 pos;
vec4 color;
};
layout(location = 0) in vec3 v_WorldPosition;
@ -57,12 +55,12 @@ layout(location = 0) out vec4 o_Target;
layout(set = 0, binding = 0) uniform CameraViewProj {
mat4 ViewProj;
};
layout(set = 0, binding = 1) uniform CameraPosition {
vec3 CameraPos;
layout(std140, set = 0, binding = 1) uniform CameraPosition {
vec4 CameraPos;
};
layout(set = 1, binding = 0) uniform Lights {
vec3 AmbientColor;
layout(std140, set = 1, binding = 0) uniform Lights {
vec4 AmbientColor;
uvec4 NumLights;
Light SceneLights[MAX_LIGHTS];
};
@ -351,7 +349,7 @@ void main() {
vec3 L = normalize(lightDir);
float rangeAttenuation =
getDistanceAttenuation(lightDir, light.inverseRadiusSquared);
getDistanceAttenuation(lightDir, light.pos.w);
vec3 H = normalize(L + V);
float NoL = saturate(dot(N, L));
@ -380,7 +378,7 @@ void main() {
vec3 specular_ambient = EnvBRDFApprox(F0, perceptual_roughness, NdotV);
output_color.rgb = light_accum;
output_color.rgb += (diffuse_ambient + specular_ambient) * AmbientColor * occlusion;
output_color.rgb += (diffuse_ambient + specular_ambient) * AmbientColor.xyz * occlusion;
output_color.rgb += emissive.rgb * output_color.a;
// tone_mapping

View file

@ -69,7 +69,7 @@ pub struct CameraNodeState {
}
const MATRIX_SIZE: usize = std::mem::size_of::<[[f32; 4]; 4]>();
const VEC3_SIZE: usize = std::mem::size_of::<[f32; 3]>();
const VEC4_SIZE: usize = std::mem::size_of::<[f32; 4]>();
pub fn camera_node_system(
mut state: Local<CameraNodeState>,
@ -101,7 +101,7 @@ pub fn camera_node_system(
// View
MATRIX_SIZE +
// Position
VEC3_SIZE,
VEC4_SIZE,
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
mapped_at_creation: true,
});
@ -144,7 +144,7 @@ pub fn camera_node_system(
if bindings.get(CAMERA_POSITION).is_none() {
let buffer = render_resource_context.create_buffer(BufferInfo {
size: VEC3_SIZE,
size: VEC4_SIZE,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
@ -152,7 +152,7 @@ pub fn camera_node_system(
CAMERA_POSITION,
RenderResourceBinding::Buffer {
buffer,
range: 0..VEC3_SIZE as u64,
range: 0..VEC4_SIZE as u64,
dynamic_index: None,
},
);
@ -200,11 +200,12 @@ pub fn camera_node_system(
if let Some(RenderResourceBinding::Buffer { buffer, .. }) = bindings.get(CAMERA_POSITION) {
let position: [f32; 3] = global_transform.translation.into();
let position: [f32; 4] = [position[0], position[1], position[2], 0.0];
render_resource_context.write_mapped_buffer(
staging_buffer,
offset..(offset + VEC3_SIZE as u64),
offset..(offset + VEC4_SIZE as u64),
&mut |data, _renderer| {
data[0..VEC3_SIZE].copy_from_slice(position.as_bytes());
data[0..VEC4_SIZE].copy_from_slice(position.as_bytes());
},
);
state.command_queue.copy_buffer_to_buffer(
@ -212,7 +213,7 @@ pub fn camera_node_system(
offset,
*buffer,
0,
VEC3_SIZE as u64,
VEC4_SIZE as u64,
);
}