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

View File

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