Generate edge descriptors for instanced rendering when Levien AA is in use

This commit is contained in:
Patrick Walton 2017-07-07 14:19:33 -07:00
parent 0edb604612
commit 9a9ef90cc9
4 changed files with 81 additions and 16 deletions

View File

@ -6,7 +6,7 @@ use partitioner::Partitioner;
use tessellator::{QuadTessLevels, Tessellator};
use std::mem;
use std::slice;
use {AntialiasingMode, BQuad, ControlPoints, Endpoint, Subpath, Vertex};
use {AntialiasingMode, BQuad, ControlPoints, EdgeInstance, Endpoint, Subpath, Vertex};
#[derive(Clone, Copy)]
#[repr(C)]
@ -138,14 +138,14 @@ pub unsafe extern fn pf_tessellator_msaa_indices<'a>(tessellator: *mut Tessellat
}
#[no_mangle]
pub unsafe extern fn pf_tessellator_levien_indices<'a>(tessellator: *mut Tessellator<'a>,
out_levien_index_count: *mut u32)
-> *const u32 {
let levien_indices = (*tessellator).levien_indices();
if !out_levien_index_count.is_null() {
*out_levien_index_count = levien_indices.len() as u32
pub unsafe extern fn pf_tessellator_edge_instances<'a>(tessellator: *mut Tessellator<'a>,
out_edge_instance_count: *mut u32)
-> *const EdgeInstance {
let edge_instances = (*tessellator).edge_instances();
if !out_edge_instance_count.is_null() {
*out_edge_instance_count = edge_instances.len() as u32
}
levien_indices.as_ptr()
edge_instances.as_ptr()
}
#[no_mangle]

View File

@ -82,3 +82,25 @@ impl Vertex {
}
}
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct EdgeInstance {
pub prev_endpoint_index: u32,
pub next_endpoint_index: u32,
pub prev_time: f32,
pub next_time: f32,
}
impl EdgeInstance {
#[inline]
pub fn new(prev_endpoint_index: u32, next_endpoint_index: u32, prev_time: f32, next_time: f32)
-> EdgeInstance {
EdgeInstance {
prev_endpoint_index: prev_endpoint_index,
next_endpoint_index: next_endpoint_index,
prev_time: prev_time,
next_time: next_time,
}
}
}

View File

@ -38,6 +38,15 @@ struct pf_vertex {
typedef struct pf_vertex pf_vertex_t;
struct pf_edge_instance {
uint32_t prev_endpoint_index;
uint32_t next_endpoint_index;
float prev_time;
float next_time;
};
typedef struct pf_edge_instance pf_edge_instance_t;
struct pf_quad_tess_levels {
pf_float16_t outer[4];
pf_float16_t inner[2];
@ -125,8 +134,8 @@ const pf_vertex_t *pf_tessellator_vertices(const pf_tessellator_t *tessellator,
const uint32_t *pf_tessellator_msaa_indices(const pf_tessellator_t *tessellator,
uint32_t *out_msaa_index_count);
const uint32_t *pf_tessellator_levien_indices(const pf_tessellator_t *tessellator,
uint32_t *out_levien_index_count);
const pf_edge_instance_t *pf_tessellator_edge_instances(const pf_tessellator_t *tessellator,
uint32_t *out_edge_instance_count);
uint32_t pf_init_env_logger();

View File

@ -6,7 +6,7 @@ use euclid::{Length, Transform2D};
use half::{f16, self};
use std::cmp;
use std::u32;
use {AntialiasingMode, BQuad, ControlPoints, Endpoint, Vertex};
use {AntialiasingMode, BQuad, ControlPoints, EdgeInstance, Endpoint, Vertex};
const TOLERANCE: f32 = 0.25;
@ -19,7 +19,7 @@ pub struct Tessellator<'a> {
tess_levels: Vec<QuadTessLevels>,
vertices: Vec<Vertex>,
msaa_indices: Vec<u32>,
levien_indices: Vec<u32>,
edge_instances: Vec<EdgeInstance>,
}
// NB: This must match the layout of `MTLQuadTessellationFactorsHalf` in Metal in order for the
@ -55,7 +55,7 @@ impl<'a> Tessellator<'a> {
tess_levels: vec![QuadTessLevels::new(); b_quads.len()],
vertices: vec![],
msaa_indices: vec![],
levien_indices: vec![],
edge_instances: vec![],
}
}
@ -124,6 +124,41 @@ impl<'a> Tessellator<'a> {
first_lower_vertex_index + index + 0,
].into_iter())
}
// If Levien-style antialiasing is in use, then emit edge instances.
if self.antialiasing_mode == AntialiasingMode::Levien {
let upper_left_endpoint_time: Length<f32, ()> = Length::new(b_quad.upper_left_time);
let upper_right_endpoint_time: Length<f32, ()> =
Length::new(b_quad.upper_right_time);
let lower_left_endpoint_time: Length<f32, ()> = Length::new(b_quad.lower_left_time);
let lower_right_endpoint_time: Length<f32, ()> =
Length::new(b_quad.lower_right_time);
for index in 0..tess_level {
let left_tess_coord = index as f32 / tess_level as f32;
let right_tess_coord = (index + 1) as f32 / tess_level as f32;
let upper_left_time = upper_left_endpoint_time.lerp(upper_right_endpoint_time,
left_tess_coord).get();
let upper_right_time = upper_left_endpoint_time.lerp(upper_right_endpoint_time,
right_tess_coord).get();
let lower_left_time = lower_left_endpoint_time.lerp(lower_right_endpoint_time,
left_tess_coord).get();
let lower_right_time = lower_left_endpoint_time.lerp(lower_right_endpoint_time,
right_tess_coord).get();
self.edge_instances.extend([
EdgeInstance::new(b_quad.upper_prev_endpoint,
b_quad.upper_next_endpoint,
upper_left_time,
upper_right_time),
EdgeInstance::new(b_quad.lower_prev_endpoint,
b_quad.lower_next_endpoint,
lower_left_time,
lower_right_time),
].into_iter())
}
}
}
}
@ -143,10 +178,9 @@ impl<'a> Tessellator<'a> {
}
#[inline]
pub fn levien_indices(&self) -> &[u32] {
&self.levien_indices
pub fn edge_instances(&self) -> &[EdgeInstance] {
&self.edge_instances
}
}
// http://antigrain.com/research/adaptive_bezier/