mod common;
use glsl_to_spirv::ShaderType;
use image::{DynamicImage, ImageBuffer, Rgba};
use std::sync::{Arc, Mutex};
use truck_platform::*;
use truck_rendimpl::*;
use wgpu::*;
const PICTURE_SIZE: (u32, u32) = (256, 256);
struct BGCheckShapeInstance<'a> {
shape: ShapeInstance,
fragment_shader: &'a str,
}
impl<'a> Rendered for BGCheckShapeInstance<'a> {
derive_render_id!(shape);
derive_vertex_buffer!(shape);
derive_bind_group_layout!(shape);
derive_bind_group!(shape);
#[inline(always)]
fn pipeline(
&self,
device_handler: &DeviceHandler,
layout: &PipelineLayout,
sample_count: u32,
) -> Arc<RenderPipeline> {
let vertex_shader = include_str!("shaders/shape-bindgroup.vert");
let vertex_spirv = common::compile_shader(vertex_shader, ShaderType::Vertex);
let vertex_module = wgpu::util::make_spirv(&vertex_spirv);
let fragment_spirv = common::compile_shader(self.fragment_shader, ShaderType::Fragment);
let fragment_module = wgpu::util::make_spirv(&fragment_spirv);
self.shape.pipeline_with_shader(
vertex_module,
fragment_module,
device_handler,
layout,
sample_count,
)
}
}
fn test_shape() -> Shell {
let v = builder::vertex(Point3::new(-1.0, -1.0, 0.0));
let e = builder::tsweep(&v, Vector3::unit_x());
let face0 = builder::tsweep(&e, Vector3::unit_y() * 2.0);
let edge = face0.boundaries()[0][1].clone();
let face1 = builder::tsweep(&edge, Vector3::new(1.0, 0.0, 1.0)).inverse();
vec![face0, face1].into()
}
fn exec_shape_bgtest(
scene: &mut Scene,
instance: &ShapeInstance,
shader: &str,
answer: &Vec<u8>,
pngpath: &str,
) -> bool {
let sc_desc = scene.sc_desc();
let tex_desc = common::texture_descriptor(&sc_desc);
let texture = scene.device().create_texture(&tex_desc);
let bgc_instance = BGCheckShapeInstance {
shape: instance.clone_instance(),
fragment_shader: shader,
};
common::render_one(scene, &texture, &bgc_instance);
let buffer = common::read_texture(scene.device_handler(), &texture);
common::save_buffer(pngpath, &buffer, PICTURE_SIZE);
common::same_buffer(&answer, &buffer)
}
fn nontex_inst_desc() -> ShapeInstanceDescriptor {
ShapeInstanceDescriptor {
instance_state: InstanceState {
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,
},
texture: None,
backface_culling: true,
},
mesh_precision: 0.01,
}
}
fn exec_shape_nontex_bind_group_test(backend: BackendBit, out_dir: &str) {
let out_dir = out_dir.to_string();
std::fs::create_dir_all(&out_dir).unwrap();
let instance = Instance::new(backend);
let (device, queue) = common::init_device(&instance);
let sc_desc = Arc::new(Mutex::new(common::swap_chain_descriptor(PICTURE_SIZE)));
let handler = DeviceHandler::new(device, queue, sc_desc);
let mut scene = Scene::new(handler, &Default::default());
let answer = common::nontex_answer_texture(&mut scene);
let answer = common::read_texture(scene.device_handler(), &answer);
let inst_desc = nontex_inst_desc();
let shell = test_shape();
let instance = scene
.instance_creator()
.create_shape_instance(&shell, &inst_desc);
let shader = include_str!("shaders/shape-nontex-bindgroup.frag");
let pngpath = out_dir.clone() + "shape-nontex-bindgroup.png";
assert!(exec_shape_bgtest(
&mut scene, &instance, shader, &answer, &pngpath,
));
let shader = include_str!("shaders/anti-shape-nontex-bindgroup.frag");
let pngpath = out_dir + "anti-shape-nontex-bindgroup.png";
assert!(!exec_shape_bgtest(
&mut scene, &instance, shader, &answer, &pngpath
));
}
#[test]
fn shape_nontex_bind_group_test() { common::os_alt_exec_test(exec_shape_nontex_bind_group_test) }
fn exec_shape_tex_bind_group_test(backend: BackendBit, out_dir: &str) {
let out_dir = out_dir.to_string();
std::fs::create_dir_all(&out_dir).unwrap();
let instance = Instance::new(backend);
let (device, queue) = common::init_device(&instance);
let sc_desc = Arc::new(Mutex::new(common::swap_chain_descriptor(PICTURE_SIZE)));
let handler = DeviceHandler::new(device, queue, sc_desc);
let mut scene = Scene::new(handler, &Default::default());
let answer = common::random_texture(&mut scene);
let buffer = common::read_texture(scene.device_handler(), &answer);
let mut inst_desc = nontex_inst_desc();
let image_buffer =
ImageBuffer::<Rgba<_>, _>::from_raw(PICTURE_SIZE.0, PICTURE_SIZE.1, buffer.clone())
.unwrap();
let attach = image2texture::image2texture(
scene.device_handler(),
&DynamicImage::ImageRgba8(image_buffer),
);
inst_desc.instance_state.texture = Some(Arc::new(attach));
let shell = test_shape();
let instance = scene
.instance_creator()
.create_shape_instance(&shell, &inst_desc);
let shader = include_str!("shaders/shape-tex-bindgroup.frag");
let pngpath = out_dir.clone() + "shape-tex-bindgroup.png";
assert!(exec_shape_bgtest(
&mut scene, &instance, shader, &buffer, &pngpath
));
let shader = include_str!("shaders/anti-shape-tex-bindgroup.frag");
let pngpath = out_dir + "anti-shape-tex-bindgroup.png";
assert!(!exec_shape_bgtest(
&mut scene, &instance, shader, &buffer, &pngpath
));
}
#[test]
fn shape_tex_bind_group_test() { common::os_alt_exec_test(exec_shape_tex_bind_group_test) }