mod common; use image::{DynamicImage, ImageBuffer, Rgba}; use std::sync::Arc; use truck_meshalgo::prelude::obj; use truck_platform::*; use truck_rendimpl::*; use wgpu::*; const PICTURE_SIZE: (u32, u32) = (256, 256); fn bgcheck_shaders(handler: &DeviceHandler) -> PolygonShaders { let source = include_str!("shaders/mesh-bindgroup.wgsl"); let module = Arc::new( handler .device() .create_shader_module(ShaderModuleDescriptor { source: ShaderSource::Wgsl(source.into()), label: None, }), ); PolygonShaders::new( Arc::clone(&module), "vs_main", Arc::clone(&module), "nontex_main", Arc::clone(&module), "tex_main", ) } fn bgcheck_anti_shaders(handler: &DeviceHandler) -> PolygonShaders { let source = include_str!("shaders/mesh-bindgroup.wgsl"); let module = Arc::new( handler .device() .create_shader_module(ShaderModuleDescriptor { source: ShaderSource::Wgsl(source.into()), label: None, }), ); PolygonShaders::new( Arc::clone(&module), "vs_main", Arc::clone(&module), "nontex_main_anti", Arc::clone(&module), "tex_main_anti", ) } const ATTRS_OBJ: &str = " v -1.0 2.0 -1.0\nv 1.0 2.0 -1.0\nv -1.0 2.0 1.0\nv 1.0 2.0 1.0 vt -1.0 -1.0\nvt 1.0 -1.0\nvt 1.0 1.0\nvt -1.0 1.0 vn -1.0 0.2 -1.0\nvn 1.0 0.2 -1.0\nvn -1.0 0.2 1.0\nvn 1.0 0.2 1.0 "; const TRIS_OBJ: &str = "f 1/1/1 2/2/3 3/4/2\nf 3/4/2 2/2/3 4/3/4\n"; const QUADS_OBJ: &str = "f 1/1/1 2/2/3 4/3/4 3/4/2\n"; fn test_polygons() -> [PolygonMesh; 2] { [ obj::read((ATTRS_OBJ.to_string() + TRIS_OBJ).as_bytes()).unwrap(), obj::read((ATTRS_OBJ.to_string() + QUADS_OBJ).as_bytes()).unwrap(), ] } fn nontex_inst_state() -> PolygonState { PolygonState { matrix: Matrix4::from_cols( [1.0, 2.0, 3.0, 4.0].into(), [5.0, 6.0, 7.0, 8.0].into(), [9.0, 10.0, 11.0, 12.0].into(), [13.0, 14.0, 15.0, 16.0].into(), ), material: Material { albedo: Vector4::new(0.2, 0.4, 0.6, 1.0), roughness: 0.31415, reflectance: 0.29613, ambient_ratio: 0.92, background_ratio: 0.32, alpha_blend: false, }, texture: None, backface_culling: true, } } fn exec_polygon_bgtest( scene: &mut Scene, instance: &PolygonInstance, answer: &[u8], id: usize, out_dir: String, ) -> bool { let buffer = common::render_one(scene, instance); let path = format!("{out_dir}polygon-bgtest-{id}.png"); common::save_buffer(path, &buffer, PICTURE_SIZE); common::same_buffer(answer, &buffer) } fn exec_polymesh_nontex_bind_group_test(backend: Backends, out_dir: &str) { let out_dir = out_dir.to_string(); std::fs::create_dir_all(&out_dir).unwrap(); let instance = wgpu::Instance::new(InstanceDescriptor { backends: backend, ..Default::default() }); let handler = common::init_device(&instance); let mut scene = Scene::new( handler, &SceneDescriptor { render_texture: RenderTextureConfig { canvas_size: PICTURE_SIZE, ..Default::default() }, ..Default::default() }, ); let answer = common::nontex_answer_texture(&mut scene); let inst_desc = nontex_inst_state(); test_polygons() .iter() .enumerate() .for_each(move |(i, polygon)| { let instance: PolygonInstance = polygon.to_instance( scene.device_handler(), &bgcheck_shaders(scene.device_handler()), &inst_desc, ); assert!(exec_polygon_bgtest( &mut scene, &instance, &answer, i, out_dir.clone() )); let instance: PolygonInstance = polygon.to_instance( scene.device_handler(), &bgcheck_anti_shaders(scene.device_handler()), &inst_desc, ); assert!(!exec_polygon_bgtest( &mut scene, &instance, &answer, i, out_dir.clone() )); }) } #[test] fn polymesh_nontex_bind_group_test() { common::os_alt_exec_test(exec_polymesh_nontex_bind_group_test) } fn exec_polymesh_tex_bind_group_test(backend: Backends, out_dir: &str) { let out_dir = out_dir.to_string(); std::fs::create_dir_all(&out_dir).unwrap(); let instance = wgpu::Instance::new(InstanceDescriptor { backends: backend, ..Default::default() }); let handler = common::init_device(&instance); let mut scene = Scene::new( handler, &SceneDescriptor { render_texture: RenderTextureConfig { canvas_size: PICTURE_SIZE, ..Default::default() }, ..Default::default() }, ); let buffer = common::random_texture(&mut scene); let pngpath = out_dir.clone() + "random-texture.png"; common::save_buffer(pngpath, &buffer, PICTURE_SIZE); let mut state = nontex_inst_state(); let image_buffer = ImageBuffer::, _>::from_raw(PICTURE_SIZE.0, PICTURE_SIZE.1, buffer.clone()) .unwrap(); let attach = image2texture::image2texture( scene.device_handler(), &DynamicImage::ImageRgba8(image_buffer), ); state.texture = Some(Arc::new(attach)); test_polygons() .iter() .enumerate() .for_each(move |(i, polygon)| { let instance: PolygonInstance = polygon.to_instance( scene.device_handler(), &bgcheck_shaders(scene.device_handler()), &state, ); assert!(exec_polygon_bgtest( &mut scene, &instance, &buffer, i + 3, out_dir.clone(), )); let instance: PolygonInstance = polygon.to_instance( scene.device_handler(), &bgcheck_anti_shaders(scene.device_handler()), &state, ); assert!(!exec_polygon_bgtest( &mut scene, &instance, &buffer, i + 3, out_dir.clone(), )); }) } #[test] fn polymesh_tex_bind_group_test() { common::os_alt_exec_test(exec_polymesh_tex_bind_group_test) }