use alpha mask even when unlit (#6047)
# Objective - Alpha mask was previously ignored when using an unlit material. - Fixes https://github.com/bevyengine/bevy/issues/4479 ## Solution - Extract the alpha discard to a separate function and use it when unlit is true ## Notes I tried calling `alpha_discard()` before the `if` in pbr.wgsl, but I had errors related to having a `discard` at the beginning before doing the texture sampling. I'm not sure if there's a way to fix that instead of having the function being called in 2 places.
This commit is contained in:
		
							parent
							
								
									8073362039
								
							
						
					
					
						commit
						197392a2cd
					
				| @ -89,6 +89,8 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> { | |||||||
|         pbr_input.V = calculate_view(in.world_position, pbr_input.is_orthographic); |         pbr_input.V = calculate_view(in.world_position, pbr_input.is_orthographic); | ||||||
| 
 | 
 | ||||||
|         output_color = tone_mapping(pbr(pbr_input)); |         output_color = tone_mapping(pbr(pbr_input)); | ||||||
|  |     } else { | ||||||
|  |         output_color = alpha_discard(material, output_color); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return output_color; |     return output_color; | ||||||
|  | |||||||
| @ -1,5 +1,23 @@ | |||||||
| #define_import_path bevy_pbr::pbr_functions | #define_import_path bevy_pbr::pbr_functions | ||||||
| 
 | 
 | ||||||
|  | fn alpha_discard(material: StandardMaterial, output_color: vec4<f32>) -> vec4<f32>{ | ||||||
|  |     var color = output_color; | ||||||
|  |     if ((material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE) != 0u) { | ||||||
|  |         // NOTE: If rendering as opaque, alpha should be ignored so set to 1.0 | ||||||
|  |         color.a = 1.0; | ||||||
|  |     } else if ((material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK) != 0u) { | ||||||
|  |         if (color.a >= material.alpha_cutoff) { | ||||||
|  |             // NOTE: If rendering as masked alpha and >= the cutoff, render as fully opaque | ||||||
|  |             color.a = 1.0; | ||||||
|  |         } else { | ||||||
|  |             // NOTE: output_color.a < in.material.alpha_cutoff should not is not rendered | ||||||
|  |             // NOTE: This and any other discards mean that early-z testing cannot be done! | ||||||
|  |             discard; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return color; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // NOTE: This ensures that the world_normal is normalized and if | // NOTE: This ensures that the world_normal is normalized and if | ||||||
| // vertex tangents and normal maps then normal mapping may be applied. | // vertex tangents and normal maps then normal mapping may be applied. | ||||||
| fn prepare_normal( | fn prepare_normal( | ||||||
| @ -142,19 +160,7 @@ fn pbr( | |||||||
| 
 | 
 | ||||||
|     let occlusion = in.occlusion; |     let occlusion = in.occlusion; | ||||||
| 
 | 
 | ||||||
|     if ((in.material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE) != 0u) { |     output_color = alpha_discard(in.material, output_color); | ||||||
|         // NOTE: If rendering as opaque, alpha should be ignored so set to 1.0 |  | ||||||
|         output_color.a = 1.0; |  | ||||||
|     } else if ((in.material.flags & STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK) != 0u) { |  | ||||||
|         if (output_color.a >= in.material.alpha_cutoff) { |  | ||||||
|             // NOTE: If rendering as masked alpha and >= the cutoff, render as fully opaque |  | ||||||
|             output_color.a = 1.0; |  | ||||||
|         } else { |  | ||||||
|             // NOTE: output_color.a < in.material.alpha_cutoff should not is not rendered |  | ||||||
|             // NOTE: This and any other discards mean that early-z testing cannot be done! |  | ||||||
|             discard; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" |     // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" | ||||||
|     let NdotV = max(dot(in.N, in.V), 0.0001); |     let NdotV = max(dot(in.N, in.V), 0.0001); | ||||||
| @ -247,3 +253,4 @@ fn tone_mapping(in: vec4<f32>) -> vec4<f32> { | |||||||
|     // Not needed with sRGB buffer |     // Not needed with sRGB buffer | ||||||
|     // output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); |     // output_color.rgb = pow(output_color.rgb, vec3(1.0 / 2.2)); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -44,6 +44,21 @@ fn setup( | |||||||
|         transform: Transform::from_xyz(1.0, 0.5, -1.5), |         transform: Transform::from_xyz(1.0, 0.5, -1.5), | ||||||
|         ..default() |         ..default() | ||||||
|     }); |     }); | ||||||
|  |     // transparent unlit sphere, uses `alpha_mode: Mask(f32)`
 | ||||||
|  |     commands.spawn(PbrBundle { | ||||||
|  |         mesh: meshes.add(Mesh::from(shape::Icosphere { | ||||||
|  |             radius: 0.5, | ||||||
|  |             subdivisions: 3, | ||||||
|  |         })), | ||||||
|  |         material: materials.add(StandardMaterial { | ||||||
|  |             base_color: Color::rgba(0.2, 0.7, 0.1, 0.0), | ||||||
|  |             alpha_mode: AlphaMode::Mask(0.5), | ||||||
|  |             unlit: true, | ||||||
|  |             ..default() | ||||||
|  |         }), | ||||||
|  |         transform: Transform::from_xyz(-1.0, 0.5, -1.5), | ||||||
|  |         ..default() | ||||||
|  |     }); | ||||||
|     // transparent cube, uses `alpha_mode: Blend`
 |     // transparent cube, uses `alpha_mode: Blend`
 | ||||||
|     commands.spawn(PbrBundle { |     commands.spawn(PbrBundle { | ||||||
|         mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), |         mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })), | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Charles
						Charles