use gfx;
use gfx::traits::FactoryExt;
use polygon::*;
use vertex::Vertex;
gfx_pipeline!(z_fail_polyhedron_pipeline {
mvp: gfx::Global<[[f32; 4]; 4]> = "u_mvp",
vertex_buffer: gfx::VertexBuffer<Vertex> = (),
out_color: gfx::BlendTarget<gfx::format::Srgba8> = (
"o_color",
gfx::state::ColorMask::all(),
gfx::preset::blend::ALPHA,
),
out_depth_stencil: gfx::DepthStencilTarget<gfx::format::DepthStencil> = (
gfx::preset::depth::LESS_EQUAL_TEST,
gfx::state::Stencil {
front: gfx::state::StencilSide {
fun: gfx::state::Comparison::Always,
mask_read: 255,
mask_write: 255,
op_fail: gfx::state::StencilOp::Keep,
op_depth_fail: gfx::state::StencilOp::DecrementWrap,
op_pass: gfx::state::StencilOp::Keep,
},
back: gfx::state::StencilSide {
fun: gfx::state::Comparison::Always,
mask_read: 255,
mask_write: 255,
op_fail: gfx::state::StencilOp::Keep,
op_depth_fail: gfx::state::StencilOp::IncrementWrap,
op_pass: gfx::state::StencilOp::Keep,
},
},
),
});
gfx_pipeline!(z_fail_bounding_box_pipeline {
out_color: gfx::BlendTarget<gfx::format::Srgba8> = (
"o_color",
gfx::state::ColorMask::all(),
gfx::preset::blend::ALPHA,
),
mvp: gfx::Global<[[f32; 4]; 4]> = "u_mvp",
color: gfx::Global<[f32; 4]> = "u_color",
vertex_buffer: gfx::VertexBuffer<Vertex> = (),
out_depth_stencil: gfx::DepthStencilTarget<gfx::format::DepthStencil> = (
gfx::preset::depth::PASS_TEST,
gfx::state::Stencil::new(
gfx::state::Comparison::NotEqual,
255,
(
gfx::state::StencilOp::Keep,
gfx::state::StencilOp::Keep,
gfx::state::StencilOp::Replace,
),
),
),
});
#[derive(Clone, Debug)]
pub struct DrapingRenderer<R: gfx::Resources> {
polyhedron_pso: gfx::pso::PipelineState<R, z_fail_polyhedron_pipeline::Meta>,
bounding_box_pso: gfx::pso::PipelineState<R, z_fail_bounding_box_pipeline::Meta>,
}
impl<R: gfx::Resources> DrapingRenderer<R> {
pub fn new<F: gfx::Factory<R>>(factory: &mut F) -> DrapingRenderer<R> {
DrapingRenderer {
polyhedron_pso: Self::polyhedron_pso(factory),
bounding_box_pso: Self::bounding_box_pso(factory),
}
}
pub fn render<C: gfx::CommandBuffer<R>>(
&self,
encoder: &mut gfx::Encoder<R, C>,
render_target: gfx::handle::RenderTargetView<R, gfx::format::Srgba8>,
depth_stencil_target: gfx::handle::DepthStencilView<R, gfx::format::DepthStencil>,
mvp: [[f32; 4]; 4],
color: [f32; 4],
buffer: &RenderablePolygonBuffer<R>,
indices: &RenderablePolygonIndices<R>,
) {
let polyhedron_bundle = gfx::Bundle {
pso: self.polyhedron_pso.clone(),
slice: indices.polyhedron_slice.clone(),
data: z_fail_polyhedron_pipeline::Data {
mvp: mvp,
out_color: render_target.clone(),
out_depth_stencil: (depth_stencil_target.clone(), (0, 0)),
vertex_buffer: buffer.polyhedron_vertex_buffer.clone(),
},
};
let bounding_box_bundle = gfx::Bundle {
pso: self.bounding_box_pso.clone(),
slice: indices.bounding_box_slice.clone(),
data: z_fail_bounding_box_pipeline::Data {
color: color,
mvp: mvp,
out_color: render_target.clone(),
out_depth_stencil: (depth_stencil_target.clone(), (0, 0)),
vertex_buffer: buffer.bounding_box_vertex_buffer.clone(),
},
};
polyhedron_bundle.encode(encoder);
bounding_box_bundle.encode(encoder);
}
fn polyhedron_pso<F: gfx::Factory<R>>(
factory: &mut F,
) -> gfx::pso::PipelineState<R, z_fail_polyhedron_pipeline::Meta> {
let shaders = factory
.create_shader_set(
include_bytes!("shaders/polyhedron.vert"),
include_bytes!("shaders/polyhedron.frag"),
)
.unwrap();
let rasterizer = gfx::state::Rasterizer::new_fill();
factory
.create_pipeline_state(
&shaders,
gfx::Primitive::TriangleList,
rasterizer,
z_fail_polyhedron_pipeline::new(),
)
.unwrap()
}
fn bounding_box_pso<F: gfx::Factory<R>>(
factory: &mut F,
) -> gfx::pso::PipelineState<R, z_fail_bounding_box_pipeline::Meta> {
let shaders = factory
.create_shader_set(
include_bytes!("shaders/bounding_box.vert"),
include_bytes!("shaders/bounding_box.frag"),
)
.unwrap();
let rasterizer = gfx::state::Rasterizer {
cull_face: gfx::state::CullFace::Front,
..gfx::state::Rasterizer::new_fill()
};
factory
.create_pipeline_state(
&shaders,
gfx::Primitive::TriangleList,
rasterizer,
z_fail_bounding_box_pipeline::new(),
)
.unwrap()
}
}
#[derive(Clone, Debug)]
pub struct RenderablePolygonBuffer<R: gfx::Resources> {
polyhedron_vertex_buffer: gfx::handle::Buffer<R, Vertex>,
bounding_box_vertex_buffer: gfx::handle::Buffer<R, Vertex>,
}
impl<R: gfx::Resources> RenderablePolygonBuffer<R> {
pub fn new<F: gfx::Factory<R>>(
factory: &mut F,
buffer: &PolygonBuffer,
) -> RenderablePolygonBuffer<R> {
RenderablePolygonBuffer {
polyhedron_vertex_buffer: factory.create_vertex_buffer(&buffer.polyhedron_vertices),
bounding_box_vertex_buffer: factory.create_vertex_buffer(&buffer.bounding_box_vertices),
}
}
}
#[derive(Clone, Debug)]
pub struct RenderablePolygonIndices<R: gfx::Resources> {
polyhedron_slice: gfx::Slice<R>,
bounding_box_slice: gfx::Slice<R>,
}
impl<R: gfx::Resources> RenderablePolygonIndices<R> {
pub fn new<F: gfx::Factory<R>>(
factory: &mut F,
indices: &PolygonBufferIndices,
) -> RenderablePolygonIndices<R> {
RenderablePolygonIndices {
polyhedron_slice: Self::create_slice(factory, &indices.polyhedron_indices),
bounding_box_slice: Self::create_slice(factory, &indices.bounding_box_indices),
}
}
fn create_slice<F: gfx::Factory<R>>(factory: &mut F, indices: &[u32]) -> gfx::Slice<R> {
gfx::Slice {
start: 0,
end: indices.len() as u32,
base_vertex: 0,
instances: None,
buffer: factory.create_index_buffer(indices),
}
}
}