glTF alphaMode BLEND: blend over opaque surfaces in production and live (eyes behind the cornea; Tim t1016u/t1017u); GPU probe case blend-over
@@ -683,6 +683,7 @@ fn extract_mesh(
683
683
flat_normals: !mesh.vertex_normal.exists,
684
684
specular: 0.,
685
685
shiny: None,
686
blend: false,
686
687
});
687
688
}
688
689
}
@@ -683,6 +683,7 @@ fn extract_mesh(683
flat_normals: !mesh.vertex_normal.exists,683
flat_normals: !mesh.vertex_normal.exists,684
specular: 0.,684
specular: 0.,685
shiny: None,685
shiny: None,686
blend: false,686
});687
});687
}688
}688
}689
}@@ -825,4 +825,6 @@ pub const TABLE: &[(&str, &str)] = &[
825
825
("voorste materiaal niet als texture × factor getekend: {surface_front:?}", "front material not drawn as texture × factor: {surface_front:?}"),
826
826
("materiaal per primitive verwisseld: {surface_swap:?}", "material per primitive swapped: {surface_swap:?}"),
827
827
("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}", "GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}"),
828
("BLEND-laag niet over het ondoorzichtige oppervlak gemengd: {blend_over:?}", "BLEND layer not blended over the opaque surface: {blend_over:?}"),
829
("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}, blend-over={blend_over:?}", "GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}, blend-over={blend_over:?}"),
828
830
];
@@ -825,4 +825,6 @@ pub const TABLE: &[(&str, &str)] = &[825
("voorste materiaal niet als texture × factor getekend: {surface_front:?}", "front material not drawn as texture × factor: {surface_front:?}"),825
("voorste materiaal niet als texture × factor getekend: {surface_front:?}", "front material not drawn as texture × factor: {surface_front:?}"),826
("materiaal per primitive verwisseld: {surface_swap:?}", "material per primitive swapped: {surface_swap:?}"),826
("materiaal per primitive verwisseld: {surface_swap:?}", "material per primitive swapped: {surface_swap:?}"),827
("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}", "GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}"),827
("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}", "GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}"),828
("BLEND-laag niet over het ondoorzichtige oppervlak gemengd: {blend_over:?}", "BLEND layer not blended over the opaque surface: {blend_over:?}"),829
("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}, blend-over={blend_over:?}", "GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}, blend-over={blend_over:?}"),828
];830
];@@ -159,6 +159,8 @@ pub struct BodySurface {
159
159
/// the extension) and its strength texture (alpha copied into RGB).
160
160
pub specular: f32,
161
161
pub shiny: Option<std::sync::Arc<crate::equipment::Texture>>,
162
/// glTF alphaMode BLEND: composited over the opaque surfaces (t1016u).
163
pub blend: bool,
162
164
}
163
165
164
166
#[derive(Debug, Clone)]
@@ -468,6 +470,7 @@ impl StaticAcc {
468
470
flat_normals,
469
471
specular: 0.,
470
472
shiny: None,
473
blend: false,
471
474
});
472
475
Ok(())
473
476
}
@@ -693,6 +696,7 @@ fn load_gltf_file_unguarded(path: &Path) -> Result<PreviewCharacter, String> {
693
696
cutoff: prim.cutoff,
694
697
specular: prim.specular,
695
698
shiny: prim.shiny,
699
blend: prim.blend,
696
700
});
697
701
}
698
702
}
@@ -809,6 +813,7 @@ struct GltfPrimitive {
809
813
cutoff: f32,
810
814
specular: f32,
811
815
shiny: Option<std::sync::Arc<crate::equipment::Texture>>,
816
blend: bool,
812
817
flat_normals: bool,
813
818
}
814
819
@@ -915,6 +920,7 @@ fn read_gltf_primitive(
915
920
},
916
921
specular,
917
922
shiny,
923
blend: material.alpha_mode() == gltf::material::AlphaMode::Blend,
918
924
})
919
925
}
920
926
@@ -159,6 +159,8 @@ pub struct BodySurface {159
/// the extension) and its strength texture (alpha copied into RGB).159
/// the extension) and its strength texture (alpha copied into RGB).160
pub specular: f32,160
pub specular: f32,161
pub shiny: Option<std::sync::Arc<crate::equipment::Texture>>,161
pub shiny: Option<std::sync::Arc<crate::equipment::Texture>>,162
/// glTF alphaMode BLEND: composited over the opaque surfaces (t1016u).163
pub blend: bool,162
}164
}163
165
164
#[derive(Debug, Clone)]166
#[derive(Debug, Clone)]@@ -468,6 +470,7 @@ impl StaticAcc {468
flat_normals,470
flat_normals,469
specular: 0.,471
specular: 0.,470
shiny: None,472
shiny: None,473
blend: false,471
});474
});472
Ok(())475
Ok(())473
}476
}@@ -693,6 +696,7 @@ fn load_gltf_file_unguarded(path: &Path) -> Result<PreviewCharacter, String> {693
cutoff: prim.cutoff,696
cutoff: prim.cutoff,694
specular: prim.specular,697
specular: prim.specular,695
shiny: prim.shiny,698
shiny: prim.shiny,699
blend: prim.blend,696
});700
});697
}701
}698
}702
}@@ -809,6 +813,7 @@ struct GltfPrimitive {809
cutoff: f32,813
cutoff: f32,810
specular: f32,814
specular: f32,811
shiny: Option<std::sync::Arc<crate::equipment::Texture>>,815
shiny: Option<std::sync::Arc<crate::equipment::Texture>>,816
blend: bool,812
flat_normals: bool,817
flat_normals: bool,813
}818
}814
819
@@ -915,6 +920,7 @@ fn read_gltf_primitive(915
},920
},916
specular,921
specular,917
shiny,922
shiny,923
blend: material.alpha_mode() == gltf::material::AlphaMode::Blend,918
})924
})919
}925
}920
926
@@ -319,6 +319,7 @@ fn body_frame(
319
319
cutoff: s.cutoff,
320
320
specular: s.specular,
321
321
shiny: s.shiny.clone(),
322
blend: s.blend,
322
323
})
323
324
.collect();
324
325
PendingFrame {
@@ -407,6 +408,8 @@ struct SurfaceDraw {
407
408
cutoff: f32,
408
409
specular: f32,
409
410
shiny: Option<std::sync::Arc<crate::equipment::Texture>>,
411
/// glTF BLEND: drawn after the opaque ranges, blended, no depth write.
412
blend: bool,
410
413
}
411
414
412
415
impl PendingFrame {
@@ -582,7 +585,46 @@ impl GpuCache {
582
585
let albedo_enabled = gl.get_uniform_location(program, "u_albedo_enabled");
583
586
let shiny_enabled = gl.get_uniform_location(program, "u_shiny_enabled");
584
587
let specular = gl.get_uniform_location(program, "u_specular");
585
for (index, surface) in frame.surfaces.iter().enumerate() {
588
// glTF BLEND (design.md t1016u): opaque first, then BLEND blended
589
// without depth writes, then BLEND depth only.
590
let order: Vec<(usize, &SurfaceDraw, u8)> = (0..3u8)
591
.flat_map(|pass| {
592
frame
593
.surfaces
594
.iter()
595
.enumerate()
596
.filter(move |(_, s)| s.blend == (pass > 0))
597
.map(move |(i, s)| (i, s, pass))
598
})
599
.collect();
600
for (index, surface, pass) in order {
601
match pass {
602
0 => {
603
gl.disable(glow::BLEND);
604
gl.depth_mask(true);
605
gl.color_mask(true, true, true, true);
606
}
607
1 => {
608
gl.enable(glow::BLEND);
609
gl.blend_func_separate(
610
glow::SRC_ALPHA,
611
glow::ONE_MINUS_SRC_ALPHA,
612
glow::ZERO,
613
glow::ONE,
614
);
615
gl.depth_mask(false);
616
gl.color_mask(true, true, true, true);
617
}
618
_ => {
619
gl.disable(glow::BLEND);
620
gl.depth_mask(true);
621
gl.color_mask(false, false, false, false);
622
}
623
}
624
gl.uniform_1_i32(
625
gl.get_uniform_location(program, "u_blend").as_ref(),
626
i32::from(pass == 1),
627
);
586
628
let end = (surface.first + surface.count).min(self.index_count as usize);
587
629
if surface.first >= end {
588
630
continue;
@@ -612,6 +654,10 @@ impl GpuCache {
612
654
(surface.first * 4) as i32,
613
655
);
614
656
}
657
gl.disable(glow::BLEND);
658
gl.depth_mask(true);
659
gl.color_mask(true, true, true, true);
660
gl.uniform_1_i32(gl.get_uniform_location(program, "u_blend").as_ref(), 0);
615
661
}
616
662
gl.bind_vertex_array(None);
617
663
while self.layers.len() > frame.equipment.len() {
@@ -865,6 +911,7 @@ uniform vec3 u_eye;
865
911
in vec2 v_uv;
866
912
in vec3 v_world;
867
913
out vec4 frag;
914
uniform bool u_blend;
868
915
void main() {
869
916
vec3 n = normalize(v_normal);
870
917
vec3 light = normalize(vec3(0.35, 0.85, 0.4));
@@ -875,7 +922,7 @@ void main() {
875
922
float strength=u_specular;
876
923
if(u_shiny_enabled) strength*=dot(texture(u_shiny,v_uv).rgb,vec3(0.2126,0.7152,0.0722));
877
924
float highlight=pow(max(dot(reflect(-light,n),normalize(u_eye-v_world)),0.0),32.0)*strength;
878
frag = vec4(clamp(color.rgb * shade + highlight,0.0,1.0), 1.0);
925
frag = vec4(clamp(color.rgb * shade + highlight,0.0,1.0), u_blend ? color.a : 1.0);
879
926
}
880
927
"#;
881
928
@@ -1108,6 +1155,7 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {
1108
1155
cutoff: 0.001,
1109
1156
specular: 0.,
1110
1157
shiny: None,
1158
blend: false,
1111
1159
},
1112
1160
SurfaceDraw {
1113
1161
first: 3,
@@ -1117,6 +1165,7 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {
1117
1165
cutoff: 0.001,
1118
1166
specular: 0.,
1119
1167
shiny: None,
1168
blend: false,
1120
1169
},
1121
1170
];
1122
1171
cache.pending = Some(body.clone());
@@ -1165,6 +1214,7 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {
1165
1214
cutoff: 0.001,
1166
1215
specular: 0.,
1167
1216
shiny: None,
1217
blend: false,
1168
1218
}];
1169
1219
cache.pending = Some(body);
1170
1220
cache.paint(gl, &info, true);
@@ -1187,7 +1237,32 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {
1187
1237
"equipment-UV verkeerd georiënteerd: {equipment_uv:?}"
1188
1238
));
1189
1239
}
1190
println!("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}");
1240
// glTF BLEND (Tim t1016u): a nearly transparent front layer listed
1241
// first (the cornea) must not hide the opaque surface behind it.
1242
let mut body = make_frame(vec![0, 1, 2, 3, 4, 5], 17);
1243
let plain = |first, color: [f32; 4], blend| SurfaceDraw {
1244
first,
1245
count: 3,
1246
color,
1247
albedo: None,
1248
cutoff: 0.001,
1249
specular: 0.,
1250
shiny: None,
1251
blend,
1252
};
1253
body.surfaces = vec![
1254
plain(0, [1., 1., 1., 0.1], true),
1255
plain(3, [1., 0., 0., 1.], false),
1256
];
1257
cache.pending = Some(body);
1258
cache.paint(gl, &info, true);
1259
let blend_over = read();
1260
if blend_over[1] < 5 || blend_over[1] > 60 || blend_over[0] < 2 * blend_over[1] {
1261
return Err(format!(
1262
"BLEND-laag niet over het ondoorzichtige oppervlak gemengd: {blend_over:?}"
1263
));
1264
}
1265
println!("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}, blend-over={blend_over:?}");
1191
1266
Ok(())
1192
1267
})();
1193
1268
cache.destroy(gl);
@@ -319,6 +319,7 @@ fn body_frame(319
cutoff: s.cutoff,319
cutoff: s.cutoff,320
specular: s.specular,320
specular: s.specular,321
shiny: s.shiny.clone(),321
shiny: s.shiny.clone(),322
blend: s.blend,322
})323
})323
.collect();324
.collect();324
PendingFrame {325
PendingFrame {@@ -407,6 +408,8 @@ struct SurfaceDraw {407
cutoff: f32,408
cutoff: f32,408
specular: f32,409
specular: f32,409
shiny: Option<std::sync::Arc<crate::equipment::Texture>>,410
shiny: Option<std::sync::Arc<crate::equipment::Texture>>,411
/// glTF BLEND: drawn after the opaque ranges, blended, no depth write.412
blend: bool,410
}413
}411
414
412
impl PendingFrame {415
impl PendingFrame {@@ -582,7 +585,46 @@ impl GpuCache {582
let albedo_enabled = gl.get_uniform_location(program, "u_albedo_enabled");585
let albedo_enabled = gl.get_uniform_location(program, "u_albedo_enabled");583
let shiny_enabled = gl.get_uniform_location(program, "u_shiny_enabled");586
let shiny_enabled = gl.get_uniform_location(program, "u_shiny_enabled");584
let specular = gl.get_uniform_location(program, "u_specular");587
let specular = gl.get_uniform_location(program, "u_specular");585
for (index, surface) in frame.surfaces.iter().enumerate() {588
// glTF BLEND (design.md t1016u): opaque first, then BLEND blended589
// without depth writes, then BLEND depth only.590
let order: Vec<(usize, &SurfaceDraw, u8)> = (0..3u8)591
.flat_map(|pass| {592
frame593
.surfaces594
.iter()595
.enumerate()596
.filter(move |(_, s)| s.blend == (pass > 0))597
.map(move |(i, s)| (i, s, pass))598
})599
.collect();600
for (index, surface, pass) in order {601
match pass {602
0 => {603
gl.disable(glow::BLEND);604
gl.depth_mask(true);605
gl.color_mask(true, true, true, true);606
}607
1 => {608
gl.enable(glow::BLEND);609
gl.blend_func_separate(610
glow::SRC_ALPHA,611
glow::ONE_MINUS_SRC_ALPHA,612
glow::ZERO,613
glow::ONE,614
);615
gl.depth_mask(false);616
gl.color_mask(true, true, true, true);617
}618
_ => {619
gl.disable(glow::BLEND);620
gl.depth_mask(true);621
gl.color_mask(false, false, false, false);622
}623
}624
gl.uniform_1_i32(625
gl.get_uniform_location(program, "u_blend").as_ref(),626
i32::from(pass == 1),627
);586
let end = (surface.first + surface.count).min(self.index_count as usize);628
let end = (surface.first + surface.count).min(self.index_count as usize);587
if surface.first >= end {629
if surface.first >= end {588
continue;630
continue;@@ -612,6 +654,10 @@ impl GpuCache {612
(surface.first * 4) as i32,654
(surface.first * 4) as i32,613
);655
);614
}656
}657
gl.disable(glow::BLEND);658
gl.depth_mask(true);659
gl.color_mask(true, true, true, true);660
gl.uniform_1_i32(gl.get_uniform_location(program, "u_blend").as_ref(), 0);615
}661
}616
gl.bind_vertex_array(None);662
gl.bind_vertex_array(None);617
while self.layers.len() > frame.equipment.len() {663
while self.layers.len() > frame.equipment.len() {@@ -865,6 +911,7 @@ uniform vec3 u_eye;865
in vec2 v_uv;911
in vec2 v_uv;866
in vec3 v_world;912
in vec3 v_world;867
out vec4 frag;913
out vec4 frag;914
uniform bool u_blend;868
void main() {915
void main() {869
vec3 n = normalize(v_normal);916
vec3 n = normalize(v_normal);870
vec3 light = normalize(vec3(0.35, 0.85, 0.4));917
vec3 light = normalize(vec3(0.35, 0.85, 0.4));@@ -875,7 +922,7 @@ void main() {875
float strength=u_specular;922
float strength=u_specular;876
if(u_shiny_enabled) strength*=dot(texture(u_shiny,v_uv).rgb,vec3(0.2126,0.7152,0.0722));923
if(u_shiny_enabled) strength*=dot(texture(u_shiny,v_uv).rgb,vec3(0.2126,0.7152,0.0722));877
float highlight=pow(max(dot(reflect(-light,n),normalize(u_eye-v_world)),0.0),32.0)*strength;924
float highlight=pow(max(dot(reflect(-light,n),normalize(u_eye-v_world)),0.0),32.0)*strength;878
frag = vec4(clamp(color.rgb * shade + highlight,0.0,1.0), 1.0);925
frag = vec4(clamp(color.rgb * shade + highlight,0.0,1.0), u_blend ? color.a : 1.0);879
}926
}880
"#;927
"#;881
928
@@ -1108,6 +1155,7 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {1108
cutoff: 0.001,1155
cutoff: 0.001,1109
specular: 0.,1156
specular: 0.,1110
shiny: None,1157
shiny: None,1158
blend: false,1111
},1159
},1112
SurfaceDraw {1160
SurfaceDraw {1113
first: 3,1161
first: 3,@@ -1117,6 +1165,7 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {1117
cutoff: 0.001,1165
cutoff: 0.001,1118
specular: 0.,1166
specular: 0.,1119
shiny: None,1167
shiny: None,1168
blend: false,1120
},1169
},1121
];1170
];1122
cache.pending = Some(body.clone());1171
cache.pending = Some(body.clone());@@ -1165,6 +1214,7 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {1165
cutoff: 0.001,1214
cutoff: 0.001,1166
specular: 0.,1215
specular: 0.,1167
shiny: None,1216
shiny: None,1217
blend: false,1168
}];1218
}];1169
cache.pending = Some(body);1219
cache.pending = Some(body);1170
cache.paint(gl, &info, true);1220
cache.paint(gl, &info, true);@@ -1187,7 +1237,32 @@ pub unsafe fn depth_regression_probe(gl: &glow::Context) -> Result<(), String> {1187
"equipment-UV verkeerd georiënteerd: {equipment_uv:?}"1237
"equipment-UV verkeerd georiënteerd: {equipment_uv:?}"1188
));1238
));1189
}1239
}1190
println!("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}");1240
// glTF BLEND (Tim t1016u): a nearly transparent front layer listed1241
// first (the cornea) must not hide the opaque surface behind it.1242
let mut body = make_frame(vec![0, 1, 2, 3, 4, 5], 17);1243
let plain = |first, color: [f32; 4], blend| SurfaceDraw {1244
first,1245
count: 3,1246
color,1247
albedo: None,1248
cutoff: 0.001,1249
specular: 0.,1250
shiny: None,1251
blend,1252
};1253
body.surfaces = vec![1254
plain(0, [1., 1., 1., 0.1], true),1255
plain(3, [1., 0., 0., 1.], false),1256
];1257
cache.pending = Some(body);1258
cache.paint(gl, &info, true);1259
let blend_over = read();1260
if blend_over[1] < 5 || blend_over[1] > 60 || blend_over[0] < 2 * blend_over[1] {1261
return Err(format!(1262
"BLEND-laag niet over het ondoorzichtige oppervlak gemengd: {blend_over:?}"1263
));1264
}1265
println!("GPU depth PASS: native {native_bits}-bit, front={near:?}, next-frame={next:?}, reversed={reverse:?}, behind-layer={hidden:?}, textured-front={textured:?}, alpha-cutout={cutout:?}, shiny={shiny:?}, matte={matte:?}, body-surface texture×factor={surface_front:?}, body-surface factor-only={surface_swap:?}, body-uv-top={body_uv:?}, equipment-uv-bottom={equipment_uv:?}, blend-over={blend_over:?}");1191
Ok(())1266
Ok(())1192
})();1267
})();1193
cache.destroy(gl);1268
cache.destroy(gl);@@ -40,6 +40,8 @@ pub struct Draw {
40
40
pub specular: f32,
41
41
pub cutoff: f32,
42
42
pub flat_normals: bool,
43
/// glTF BLEND: drawn after the opaque draws, blended (design.md t1016u).
44
pub blend: bool,
43
45
}
44
46
#[derive(Clone)]
45
47
pub struct Scene {
@@ -312,6 +314,7 @@ pub fn scene(
312
314
specular: layer.specular,
313
315
cutoff: 0.5,
314
316
flat_normals: false,
317
blend: false,
315
318
});
316
319
}
317
320
} else {
@@ -353,6 +356,7 @@ pub fn scene(
353
356
specular: 0.,
354
357
cutoff: 0.001,
355
358
flat_normals: !body.source_normals_complete,
359
blend: false,
356
360
});
357
361
} else {
358
362
for surface in &body.surfaces {
@@ -368,6 +372,7 @@ pub fn scene(
368
372
specular: surface.specular,
369
373
cutoff: surface.cutoff,
370
374
flat_normals: surface.flat_normals,
375
blend: surface.blend,
371
376
});
372
377
}
373
378
}
@@ -645,7 +650,40 @@ impl GpuRenderer {
645
650
gl.enable_vertex_attrib_array(slot);
646
651
gl.vertex_attrib_pointer_f32(slot, size, glow::FLOAT, false, 12 * 4, offset * 4);
647
652
}
648
for draw in &scene.draws {
653
// glTF BLEND (design.md t1016u): opaque/mask first, then the
654
// BLEND draws blended without depth writes, then their depth only.
655
let order: Vec<(&Draw, u8)> = scene
656
.draws
657
.iter()
658
.filter(|d| !d.blend)
659
.map(|d| (d, 0))
660
.chain(scene.draws.iter().filter(|d| d.blend).map(|d| (d, 1)))
661
.chain(scene.draws.iter().filter(|d| d.blend).map(|d| (d, 2)))
662
.collect();
663
for (draw, pass) in order {
664
match pass {
665
0 => {
666
gl.disable(glow::BLEND);
667
gl.depth_mask(true);
668
gl.color_mask(true, true, true, true);
669
}
670
1 => {
671
gl.enable(glow::BLEND);
672
gl.blend_func_separate(
673
glow::SRC_ALPHA,
674
glow::ONE_MINUS_SRC_ALPHA,
675
glow::ONE,
676
glow::ONE_MINUS_SRC_ALPHA,
677
);
678
gl.depth_mask(false);
679
gl.color_mask(true, true, true, true);
680
}
681
_ => {
682
gl.disable(glow::BLEND);
683
gl.depth_mask(true);
684
gl.color_mask(false, false, false, false);
685
}
686
}
649
687
if draw.positions.len() != draw.normals.len()
650
688
|| draw
651
689
.indices
@@ -756,6 +794,9 @@ impl GpuRenderer {
756
794
gl.delete_texture(t);
757
795
}
758
796
}
797
gl.disable(glow::BLEND);
798
gl.depth_mask(true);
799
gl.color_mask(true, true, true, true);
759
800
let pixels = scene.width as usize * scene.height as usize;
760
801
let mut maps = Vec::new();
761
802
gl.pixel_store_i32(glow::PACK_ALIGNMENT, 1);
@@ -1936,6 +1977,7 @@ pub unsafe fn map_regression_probe(gl: &glow::Context) -> Result<(), String> {
1936
1977
specular,
1937
1978
cutoff: 0.001,
1938
1979
flat_normals: false,
1980
blend: false,
1939
1981
};
1940
1982
let mut renderer = GpuRenderer::default();
1941
1983
let mut scene = Scene {
@@ -40,6 +40,8 @@ pub struct Draw {40
pub specular: f32,40
pub specular: f32,41
pub cutoff: f32,41
pub cutoff: f32,42
pub flat_normals: bool,42
pub flat_normals: bool,43
/// glTF BLEND: drawn after the opaque draws, blended (design.md t1016u).44
pub blend: bool,43
}45
}44
#[derive(Clone)]46
#[derive(Clone)]45
pub struct Scene {47
pub struct Scene {@@ -312,6 +314,7 @@ pub fn scene(312
specular: layer.specular,314
specular: layer.specular,313
cutoff: 0.5,315
cutoff: 0.5,314
flat_normals: false,316
flat_normals: false,317
blend: false,315
});318
});316
}319
}317
} else {320
} else {@@ -353,6 +356,7 @@ pub fn scene(353
specular: 0.,356
specular: 0.,354
cutoff: 0.001,357
cutoff: 0.001,355
flat_normals: !body.source_normals_complete,358
flat_normals: !body.source_normals_complete,359
blend: false,356
});360
});357
} else {361
} else {358
for surface in &body.surfaces {362
for surface in &body.surfaces {@@ -368,6 +372,7 @@ pub fn scene(368
specular: surface.specular,372
specular: surface.specular,369
cutoff: surface.cutoff,373
cutoff: surface.cutoff,370
flat_normals: surface.flat_normals,374
flat_normals: surface.flat_normals,375
blend: surface.blend,371
});376
});372
}377
}373
}378
}@@ -645,7 +650,40 @@ impl GpuRenderer {645
gl.enable_vertex_attrib_array(slot);650
gl.enable_vertex_attrib_array(slot);646
gl.vertex_attrib_pointer_f32(slot, size, glow::FLOAT, false, 12 * 4, offset * 4);651
gl.vertex_attrib_pointer_f32(slot, size, glow::FLOAT, false, 12 * 4, offset * 4);647
}652
}648
for draw in &scene.draws {653
// glTF BLEND (design.md t1016u): opaque/mask first, then the654
// BLEND draws blended without depth writes, then their depth only.655
let order: Vec<(&Draw, u8)> = scene656
.draws657
.iter()658
.filter(|d| !d.blend)659
.map(|d| (d, 0))660
.chain(scene.draws.iter().filter(|d| d.blend).map(|d| (d, 1)))661
.chain(scene.draws.iter().filter(|d| d.blend).map(|d| (d, 2)))662
.collect();663
for (draw, pass) in order {664
match pass {665
0 => {666
gl.disable(glow::BLEND);667
gl.depth_mask(true);668
gl.color_mask(true, true, true, true);669
}670
1 => {671
gl.enable(glow::BLEND);672
gl.blend_func_separate(673
glow::SRC_ALPHA,674
glow::ONE_MINUS_SRC_ALPHA,675
glow::ONE,676
glow::ONE_MINUS_SRC_ALPHA,677
);678
gl.depth_mask(false);679
gl.color_mask(true, true, true, true);680
}681
_ => {682
gl.disable(glow::BLEND);683
gl.depth_mask(true);684
gl.color_mask(false, false, false, false);685
}686
}649
if draw.positions.len() != draw.normals.len()687
if draw.positions.len() != draw.normals.len()650
|| draw688
|| draw651
.indices689
.indices@@ -756,6 +794,9 @@ impl GpuRenderer {756
gl.delete_texture(t);794
gl.delete_texture(t);757
}795
}758
}796
}797
gl.disable(glow::BLEND);798
gl.depth_mask(true);799
gl.color_mask(true, true, true, true);759
let pixels = scene.width as usize * scene.height as usize;800
let pixels = scene.width as usize * scene.height as usize;760
let mut maps = Vec::new();801
let mut maps = Vec::new();761
gl.pixel_store_i32(glow::PACK_ALIGNMENT, 1);802
gl.pixel_store_i32(glow::PACK_ALIGNMENT, 1);@@ -1936,6 +1977,7 @@ pub unsafe fn map_regression_probe(gl: &glow::Context) -> Result<(), String> {1936
specular,1977
specular,1937
cutoff: 0.001,1978
cutoff: 0.001,1938
flat_normals: false,1979
flat_normals: false,1980
blend: false,1939
};1981
};1940
let mut renderer = GpuRenderer::default();1982
let mut renderer = GpuRenderer::default();1941
let mut scene = Scene {1983
let mut scene = Scene {