Implement depth interpolation, not working yet

This commit is contained in:
Patrick Walton 2019-02-18 13:42:30 -08:00
parent 661a865508
commit 9af3bac11f
8 changed files with 185 additions and 26 deletions

View File

@ -634,10 +634,13 @@ fn build_scene(scene: &Scene, build_options: BuildOptions, jobs: Option<usize>)
},
};
let built_options = render_options.prepare(scene.bounds);
let quad = built_options.quad();
let built_objects = panic::catch_unwind(|| {
match jobs {
Some(1) => scene.build_objects_sequentially(render_options, &z_buffer),
_ => scene.build_objects(render_options, &z_buffer),
Some(1) => scene.build_objects_sequentially(built_options, &z_buffer),
_ => scene.build_objects(built_options, &z_buffer),
}
});
@ -650,7 +653,7 @@ fn build_scene(scene: &Scene, build_options: BuildOptions, jobs: Option<usize>)
}
};
let mut built_scene = BuiltScene::new(scene.view_box);
let mut built_scene = BuiltScene::new(scene.view_box, &quad);
built_scene.shaders = scene.build_shaders();
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, scene.view_box);
@ -832,4 +835,4 @@ fn create_grid_vertex_positions() -> Vec<(u8, u8)> {
]);
}
positions
}
}

View File

@ -84,6 +84,12 @@ impl Point2DF32 {
self.x() * other.y() - self.y() * other.x()
}
#[inline]
pub fn dot(&self, other: Point2DF32) -> f32 {
let xy = self.0 * other.0;
xy.x() + xy.y()
}
#[inline]
pub fn scale(&self, x: f32) -> Point2DF32 {
Point2DF32(self.0 * F32x4::splat(x))

View File

@ -132,12 +132,12 @@ impl Renderer {
self.upload_shaders(&built_scene.shaders);
self.upload_solid_tiles(&built_scene.solid_tiles);
self.draw_solid_tiles(&built_scene.solid_tiles);
self.draw_solid_tiles(&built_scene);
for batch in &built_scene.batches {
self.upload_batch(batch);
self.draw_batch_fills(batch);
self.draw_batch_mask_tiles(batch);
self.draw_batch_mask_tiles(&built_scene, batch);
}
if self.postprocessing_needed() {
@ -245,7 +245,7 @@ impl Renderer {
}
}
fn draw_batch_mask_tiles(&mut self, batch: &Batch) {
fn draw_batch_mask_tiles(&mut self, built_scene: &BuiltScene, batch: &Batch) {
unsafe {
self.bind_draw_framebuffer();
self.set_main_viewport();
@ -270,6 +270,22 @@ impl Renderer {
FILL_COLORS_TEXTURE_HEIGHT as GLfloat);
// FIXME(pcwalton): Fill this in properly!
gl::Uniform2f(self.mask_tile_program.view_box_origin_uniform.location, 0.0, 0.0);
gl::Uniform3f(self.mask_tile_program.quad_p0_uniform.location,
built_scene.quad[0].x(),
built_scene.quad[0].y(),
built_scene.quad[0].z());
gl::Uniform3f(self.mask_tile_program.quad_p1_uniform.location,
built_scene.quad[1].x(),
built_scene.quad[1].y(),
built_scene.quad[1].z());
gl::Uniform3f(self.mask_tile_program.quad_p2_uniform.location,
built_scene.quad[2].x(),
built_scene.quad[2].y(),
built_scene.quad[2].z());
gl::Uniform3f(self.mask_tile_program.quad_p3_uniform.location,
built_scene.quad[3].x(),
built_scene.quad[3].y(),
built_scene.quad[3].z());
self.enable_blending();
self.enable_depth_test();
gl::DrawArraysInstanced(gl::TRIANGLE_FAN, 0, 4, batch.mask_tiles.len() as GLint);
@ -277,7 +293,7 @@ impl Renderer {
}
}
fn draw_solid_tiles(&mut self, solid_tiles: &[SolidTileScenePrimitive]) {
fn draw_solid_tiles(&mut self, built_scene: &BuiltScene) {
unsafe {
self.bind_draw_framebuffer();
self.set_main_viewport();
@ -297,11 +313,28 @@ impl Renderer {
FILL_COLORS_TEXTURE_HEIGHT as GLfloat);
// FIXME(pcwalton): Fill this in properly!
gl::Uniform2f(self.solid_tile_program.view_box_origin_uniform.location, 0.0, 0.0);
gl::Uniform3f(self.solid_tile_program.quad_p0_uniform.location,
built_scene.quad[0].x(),
built_scene.quad[0].y(),
built_scene.quad[0].z());
gl::Uniform3f(self.solid_tile_program.quad_p1_uniform.location,
built_scene.quad[1].x(),
built_scene.quad[1].y(),
built_scene.quad[1].z());
gl::Uniform3f(self.solid_tile_program.quad_p2_uniform.location,
built_scene.quad[2].x(),
built_scene.quad[2].y(),
built_scene.quad[2].z());
gl::Uniform3f(self.solid_tile_program.quad_p3_uniform.location,
built_scene.quad[3].x(),
built_scene.quad[3].y(),
built_scene.quad[3].z());
gl::Disable(gl::BLEND);
gl::DepthMask(gl::FALSE);
gl::Enable(gl::DEPTH_TEST);
gl::Disable(gl::STENCIL_TEST);
gl::DrawArraysInstanced(gl::TRIANGLE_FAN, 0, 4, solid_tiles.len() as GLint);
let count = built_scene.solid_tiles.len();
gl::DrawArraysInstanced(gl::TRIANGLE_FAN, 0, 4, count as GLint);
}
}
@ -539,6 +572,10 @@ struct SolidTileProgram {
fill_colors_texture_uniform: Uniform,
fill_colors_texture_size_uniform: Uniform,
view_box_origin_uniform: Uniform,
quad_p0_uniform: Uniform,
quad_p1_uniform: Uniform,
quad_p2_uniform: Uniform,
quad_p3_uniform: Uniform,
}
impl SolidTileProgram {
@ -549,6 +586,10 @@ impl SolidTileProgram {
let fill_colors_texture_uniform = Uniform::new(&program, "FillColorsTexture");
let fill_colors_texture_size_uniform = Uniform::new(&program, "FillColorsTextureSize");
let view_box_origin_uniform = Uniform::new(&program, "ViewBoxOrigin");
let quad_p0_uniform = Uniform::new(&program, "QuadP0");
let quad_p1_uniform = Uniform::new(&program, "QuadP1");
let quad_p2_uniform = Uniform::new(&program, "QuadP2");
let quad_p3_uniform = Uniform::new(&program, "QuadP3");
SolidTileProgram {
program,
framebuffer_size_uniform,
@ -556,6 +597,10 @@ impl SolidTileProgram {
fill_colors_texture_uniform,
fill_colors_texture_size_uniform,
view_box_origin_uniform,
quad_p0_uniform,
quad_p1_uniform,
quad_p2_uniform,
quad_p3_uniform,
}
}
}
@ -569,6 +614,10 @@ struct MaskTileProgram {
fill_colors_texture_uniform: Uniform,
fill_colors_texture_size_uniform: Uniform,
view_box_origin_uniform: Uniform,
quad_p0_uniform: Uniform,
quad_p1_uniform: Uniform,
quad_p2_uniform: Uniform,
quad_p3_uniform: Uniform,
}
impl MaskTileProgram {
@ -581,6 +630,10 @@ impl MaskTileProgram {
let fill_colors_texture_uniform = Uniform::new(&program, "FillColorsTexture");
let fill_colors_texture_size_uniform = Uniform::new(&program, "FillColorsTextureSize");
let view_box_origin_uniform = Uniform::new(&program, "ViewBoxOrigin");
let quad_p0_uniform = Uniform::new(&program, "QuadP0");
let quad_p1_uniform = Uniform::new(&program, "QuadP1");
let quad_p2_uniform = Uniform::new(&program, "QuadP2");
let quad_p3_uniform = Uniform::new(&program, "QuadP3");
MaskTileProgram {
program,
framebuffer_size_uniform,
@ -590,6 +643,10 @@ impl MaskTileProgram {
fill_colors_texture_uniform,
fill_colors_texture_size_uniform,
view_box_origin_uniform,
quad_p0_uniform,
quad_p1_uniform,
quad_p2_uniform,
quad_p3_uniform,
}
}
}

View File

@ -15,7 +15,7 @@ use crate::gpu_data::{MaskTileBatchPrimitive, SolidTileScenePrimitive};
use crate::scene;
use crate::tiles;
use crate::z_buffer::ZBuffer;
use pathfinder_geometry::basic::point::Point2DF32;
use pathfinder_geometry::basic::point::{Point2DF32, Point3DF32};
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
use pathfinder_geometry::basic::transform2d::Transform2DF32;
use pathfinder_geometry::basic::transform3d::Perspective;
@ -173,17 +173,47 @@ impl RenderTransform {
for point in &mut points {
*point = perspective.transform.transform_point(*point);
}
//println!("... PERSPECTIVE quad={:?}", points);
println!("... PERSPECTIVE quad={:?}", points);
// Compute depth.
let quad = [
points[0].perspective_divide(),
points[1].perspective_divide(),
points[2].perspective_divide(),
points[3].perspective_divide(),
];
println!("barycentric(0, 0) = {:?}", compute_barycentric(&[
quad[0].to_2d(),
quad[1].to_2d(),
quad[2].to_2d(),
quad[3].to_2d(),
], Point2DF32::new(0.0, 0.0)));
points = PolygonClipper3D::new(points).clip();
//println!("... CLIPPED quad={:?}", points);
for point in &mut points {
*point = point.perspective_divide()
}
let inverse_transform = perspective.transform.inverse();
let clip_polygon = points.into_iter().map(|point| {
inverse_transform.transform_point(point).perspective_divide().to_2d()
}).collect();
PreparedRenderTransform::Perspective { perspective, clip_polygon }
return PreparedRenderTransform::Perspective { perspective, clip_polygon, quad };
fn compute_barycentric(quad: &[Point2DF32], point: Point2DF32) -> [f32; 4] {
let (s0, s1) = (quad[0] - point, quad[1] - point);
let (s2, s3) = (quad[2] - point, quad[3] - point);
let (a0, a1, a2, a3) = (s0.det(s1), s1.det(s2), s2.det(s3), s3.det(s0));
let (d0, d1, d2, d3) = (s0.dot(s1), s1.dot(s2), s2.dot(s3), s3.dot(s0));
let (r0, r1, r2, r3) = (s0.length(), s1.length(), s2.length(), s3.length());
let (t0, t1) = ((r0 * r1 - d0) / a0, (r1 * r2 - d1) / a1);
let (t2, t3) = ((r2 * r3 - d2) / a2, (r3 * r0 - d3) / a3);
let (u0, u1) = ((t3 + t0) / r0, (t2 + t1) / r1);
let (u2, u3) = ((t0 + t2) / r2, (t0 + t3) / r3);
let sum = u0 + u1 + u2 + u3;
[u0 / sum, u1 / sum, u2 / sum, u3 / sum]
}
}
}
@ -192,8 +222,19 @@ pub struct PreparedRenderOptions {
pub dilation: Point2DF32,
}
impl PreparedRenderOptions {
#[inline]
pub fn quad(&self) -> [Point3DF32; 4] {
match self.transform {
PreparedRenderTransform::Perspective { quad, .. } => quad,
_ => [Point3DF32::default(); 4],
}
}
}
pub enum PreparedRenderTransform {
None,
Transform2D(Transform2DF32),
Perspective { perspective: Perspective, clip_polygon: Vec<Point2DF32> }
Perspective { perspective: Perspective, clip_polygon: Vec<Point2DF32>, quad: [Point3DF32; 4] }
}

View File

@ -14,7 +14,7 @@ use crate::paint::{ObjectShader, ShaderId};
use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH};
use fixedbitset::FixedBitSet;
use pathfinder_geometry::basic::line_segment::{LineSegmentF32, LineSegmentU4, LineSegmentU8};
use pathfinder_geometry::basic::point::Point2DF32;
use pathfinder_geometry::basic::point::{Point2DF32, Point3DF32};
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
use pathfinder_geometry::util;
use pathfinder_simd::default::{F32x4, I32x4};
@ -32,6 +32,7 @@ pub struct BuiltObject {
#[derive(Debug)]
pub struct BuiltScene {
pub view_box: RectF32,
pub quad: [Point3DF32; 4],
pub batches: Vec<Batch>,
pub solid_tiles: Vec<SolidTileScenePrimitive>,
pub shaders: Vec<ObjectShader>,
@ -249,8 +250,8 @@ impl BuiltObject {
impl BuiltScene {
#[inline]
pub fn new(view_box: RectF32) -> BuiltScene {
BuiltScene { view_box, batches: vec![], solid_tiles: vec![], shaders: vec![] }
pub fn new(view_box: RectF32, quad: &[Point3DF32; 4]) -> BuiltScene {
BuiltScene { view_box, quad: *quad, batches: vec![], solid_tiles: vec![], shaders: vec![] }
}
}

View File

@ -10,7 +10,7 @@
//! A set of paths to be rendered.
use crate::builder::{PreparedRenderOptions, PreparedRenderTransform, RenderOptions};
use crate::builder::{PreparedRenderOptions, PreparedRenderTransform};
use crate::gpu_data::BuiltObject;
use crate::paint::{ObjectShader, Paint, PaintId, ShaderId};
use crate::tiles::Tiler;
@ -63,9 +63,10 @@ impl Scene {
.collect()
}
pub fn build_objects_sequentially(&self, options: RenderOptions, z_buffer: &ZBuffer)
pub fn build_objects_sequentially(&self,
built_options: PreparedRenderOptions,
z_buffer: &ZBuffer)
-> Vec<BuiltObject> {
let built_options = options.prepare(self.bounds);
self.objects
.iter()
.enumerate()
@ -84,8 +85,8 @@ impl Scene {
.collect()
}
pub fn build_objects(&self, options: RenderOptions, z_buffer: &ZBuffer) -> Vec<BuiltObject> {
let built_options = options.prepare(self.bounds);
pub fn build_objects(&self, built_options: PreparedRenderOptions, z_buffer: &ZBuffer)
-> Vec<BuiltObject> {
self.objects
.par_iter()
.enumerate()
@ -108,7 +109,7 @@ impl Scene {
-> Outline {
let mut outline;
match options.transform {
PreparedRenderTransform::Perspective { ref perspective, ref clip_polygon } => {
PreparedRenderTransform::Perspective { ref perspective, ref clip_polygon, .. } => {
if original_outline.is_outside_polygon(clip_polygon) {
outline = Outline::new();
} else {

View File

@ -18,6 +18,10 @@ uniform vec2 uStencilTextureSize;
uniform sampler2D uFillColorsTexture;
uniform vec2 uFillColorsTextureSize;
uniform vec2 uViewBoxOrigin;
uniform vec3 uQuadP0;
uniform vec3 uQuadP1;
uniform vec3 uQuadP2;
uniform vec3 uQuadP3;
in vec2 aTessCoord;
in vec2 aTileOrigin;
@ -28,6 +32,21 @@ out vec2 vTexCoord;
out float vBackdrop;
out vec4 vColor;
float wedge(vec2 a, vec2 b) {
return a.x * b.y - a.y * b.x;
}
// From "A Quadrilateral Rendering Primitive", Hormann and Tarini 2004.
vec4 barycentricQuad(vec2 p) {
vec2 s0 = uQuadP0.xy - p, s1 = uQuadP1.xy - p, s2 = uQuadP2.xy - p, s3 = uQuadP3.xy - p;
vec4 a = vec4(wedge(s0, s1), wedge(s1, s2), wedge(s2, s3), wedge(s3, s0));
vec4 d = vec4(dot(s0, s1), dot(s1, s2), dot(s2, s3), dot(s3, s0));
vec4 r = vec4(length(s0), length(s1), length(s2), length(s3));
vec4 t = (r * r.yzwx - d) / a;
vec4 u = (t.wxyz + t) / r;
return u / dot(u, vec4(1.0));
}
vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) {
uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x);
uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow);
@ -41,11 +60,17 @@ vec2 computeFillColorTexCoord(uint object, vec2 textureSize) {
void main() {
uint tileIndex = uint(gl_InstanceID);
vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0);
vec4 depths = vec4(uQuadP0.z, uQuadP1.z, uQuadP2.z, uQuadP3.z);
float depth = dot(barycentricQuad(position), depths);
vec2 texCoord = computeTileOffset(tileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize;
vec2 colorTexCoord = computeFillColorTexCoord(aObject, uFillColorsTextureSize);
vTexCoord = texCoord / uStencilTextureSize;
vBackdrop = float(aBackdrop);
vColor = texture(uFillColorsTexture, colorTexCoord);
gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);
gl_Position = vec4(position, depth, 1.0);
}

View File

@ -17,6 +17,10 @@ uniform vec2 uTileSize;
uniform sampler2D uFillColorsTexture;
uniform vec2 uFillColorsTextureSize;
uniform vec2 uViewBoxOrigin;
uniform vec3 uQuadP0;
uniform vec3 uQuadP1;
uniform vec3 uQuadP2;
uniform vec3 uQuadP3;
in vec2 aTessCoord;
in vec2 aTileOrigin;
@ -24,14 +28,35 @@ in uint aObject;
out vec4 vColor;
float wedge(vec2 a, vec2 b) {
return a.x * b.y - a.y * b.x;
}
// From "A Quadrilateral Rendering Primitive", Hormann and Tarini 2004.
vec4 barycentricQuad(vec2 p) {
vec2 s0 = uQuadP0.xy - p, s1 = uQuadP1.xy - p, s2 = uQuadP2.xy - p, s3 = uQuadP3.xy - p;
vec4 a = vec4(wedge(s0, s1), wedge(s1, s2), wedge(s2, s3), wedge(s3, s0));
vec4 d = vec4(dot(s0, s1), dot(s1, s2), dot(s2, s3), dot(s3, s0));
vec4 r = vec4(length(s0), length(s1), length(s2), length(s3));
vec4 t = (r * r.yzwx - d) / a;
vec4 u = (t.wxyz + t) / r;
return u / dot(u, vec4(1.0));
}
vec2 computeFillColorTexCoord(uint object, vec2 textureSize) {
uint width = uint(textureSize.x);
return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize;
}
void main() {
vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0);
vec4 depths = vec4(uQuadP0.z, uQuadP1.z, uQuadP2.z, uQuadP3.z);
float depth = dot(barycentricQuad(position), depths);
vec2 colorTexCoord = computeFillColorTexCoord(aObject, uFillColorsTextureSize);
vColor = texture(uFillColorsTexture, colorTexCoord);
gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);
gl_Position = vec4(position, depth, 1.0);
}