Explicitly specify color texture coordinates for alpha and solid tiles.

This is groundwork for gradients and images.

This commit also refactors the interface for vertex attributes to use named
parameters (via structs), for clarity.
This commit is contained in:
Patrick Walton 2019-05-14 14:28:21 -07:00
parent a54378f931
commit 7a02b78b3d
15 changed files with 333 additions and 239 deletions

View File

@ -11,7 +11,7 @@
//! GPU rendering code specifically for the demo. //! GPU rendering code specifically for the demo.
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BufferTarget, Device, VertexAttrType}; use pathfinder_gpu::{BufferTarget, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
pub struct GroundProgram<D> pub struct GroundProgram<D>
where where
@ -67,7 +67,14 @@ where
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&ground_program.program); device.use_program(&ground_program.program);
device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0); device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::U8,
stride: 0,
offset: 0,
divisor: 0,
});
GroundVertexArray { vertex_array } GroundVertexArray { vertex_array }
} }

View File

@ -18,7 +18,8 @@ use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams}; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams};
use pathfinder_gpu::{DepthFunc, Device, Primitive, RenderState, ShaderKind, StencilFunc}; use pathfinder_gpu::{DepthFunc, Device, Primitive, RenderState, ShaderKind, StencilFunc};
use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrType}; use pathfinder_gpu::{TextureFormat, UniformData, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use rustache::{HashBuilder, Render}; use rustache::{HashBuilder, Render};
use std::ffi::CString; use std::ffi::CString;
@ -327,40 +328,33 @@ impl Device for GLDevice {
} }
} }
fn configure_float_vertex_attr(&self, fn configure_vertex_attr(&self, attr: &GLVertexAttr, descriptor: &VertexAttrDescriptor) {
attr: &GLVertexAttr,
size: usize,
attr_type: VertexAttrType,
normalized: bool,
stride: usize,
offset: usize,
divisor: u32) {
unsafe { unsafe {
gl::VertexAttribPointer(attr.attr, let attr_type = descriptor.attr_type.to_gl_type();
size as GLint, match descriptor.class {
attr_type.to_gl_type(), VertexAttrClass::Float | VertexAttrClass::FloatNorm => {
if normalized { gl::TRUE } else { gl::FALSE }, let normalized = if descriptor.class == VertexAttrClass::FloatNorm {
stride as GLint, gl::TRUE
offset as *const GLvoid); ck(); } else {
gl::VertexAttribDivisor(attr.attr, divisor); ck(); gl::FALSE
gl::EnableVertexAttribArray(attr.attr); ck(); };
} gl::VertexAttribPointer(attr.attr,
} descriptor.size as GLint,
attr_type,
normalized,
descriptor.stride as GLint,
descriptor.offset as *const GLvoid); ck();
}
VertexAttrClass::Int => {
gl::VertexAttribIPointer(attr.attr,
descriptor.size as GLint,
attr_type,
descriptor.stride as GLint,
descriptor.offset as *const GLvoid); ck();
}
}
fn configure_int_vertex_attr(&self, gl::VertexAttribDivisor(attr.attr, descriptor.divisor); ck();
attr: &GLVertexAttr,
size: usize,
attr_type: VertexAttrType,
stride: usize,
offset: usize,
divisor: u32) {
unsafe {
gl::VertexAttribIPointer(attr.attr,
size as GLint,
attr_type.to_gl_type(),
stride as GLint,
offset as *const GLvoid); ck();
gl::VertexAttribDivisor(attr.attr, divisor); ck();
gl::EnableVertexAttribArray(attr.attr); ck(); gl::EnableVertexAttribArray(attr.attr); ck();
} }
} }

View File

@ -52,25 +52,7 @@ pub trait Device {
fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Self::VertexAttr; fn get_vertex_attr(&self, program: &Self::Program, name: &str) -> Self::VertexAttr;
fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform; fn get_uniform(&self, program: &Self::Program, name: &str) -> Self::Uniform;
fn use_program(&self, program: &Self::Program); fn use_program(&self, program: &Self::Program);
fn configure_float_vertex_attr( fn configure_vertex_attr(&self, attr: &Self::VertexAttr, descriptor: &VertexAttrDescriptor);
&self,
attr: &Self::VertexAttr,
size: usize,
attr_type: VertexAttrType,
normalized: bool,
stride: usize,
offset: usize,
divisor: u32,
);
fn configure_int_vertex_attr(
&self,
attr: &Self::VertexAttr,
size: usize,
attr_type: VertexAttrType,
stride: usize,
offset: usize,
divisor: u32,
);
fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData); fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData);
fn create_framebuffer(&self, texture: Self::Texture) -> Self::Framebuffer; fn create_framebuffer(&self, texture: Self::Texture) -> Self::Framebuffer;
fn create_buffer(&self) -> Self::Buffer; fn create_buffer(&self) -> Self::Buffer;
@ -340,6 +322,23 @@ impl UniformData {
} }
} }
#[derive(Clone, Copy, Debug)]
pub struct VertexAttrDescriptor {
pub size: usize,
pub class: VertexAttrClass,
pub attr_type: VertexAttrType,
pub stride: usize,
pub offset: usize,
pub divisor: u32,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum VertexAttrClass {
Float,
FloatNorm,
Int,
}
fn load_shader_include(resources: &dyn ResourceLoader, include_name: &str) -> String { fn load_shader_include(resources: &dyn ResourceLoader, include_name: &str) -> String {
let resource = resources let resource = resources
.slurp(&format!("shaders/{}.inc.glsl", include_name)) .slurp(&format!("shaders/{}.inc.glsl", include_name))

View File

@ -20,7 +20,8 @@ use pathfinder_geometry::color::ColorF;
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams}; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, ClearParams};
use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc}; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc};
use pathfinder_gpu::{StencilState, TextureFormat, UniformData, VertexAttrType}; use pathfinder_gpu::{StencilState, TextureFormat, UniformData, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_simd::default::{F32x4, I32x4}; use pathfinder_simd::default::{F32x4, I32x4};
use std::cmp; use std::cmp;
use std::collections::VecDeque; use std::collections::VecDeque;
@ -37,8 +38,8 @@ const MASK_FRAMEBUFFER_HEIGHT: i32 = TILE_HEIGHT as i32 * 256;
// TODO(pcwalton): Replace with `mem::size_of` calls? // TODO(pcwalton): Replace with `mem::size_of` calls?
const FILL_INSTANCE_SIZE: usize = 8; const FILL_INSTANCE_SIZE: usize = 8;
const SOLID_TILE_INSTANCE_SIZE: usize = 6; const SOLID_TILE_INSTANCE_SIZE: usize = 10;
const MASK_TILE_INSTANCE_SIZE: usize = 8; const MASK_TILE_INSTANCE_SIZE: usize = 12;
const MAX_FILLS_PER_BATCH: usize = 0x4000; const MAX_FILLS_PER_BATCH: usize = 0x4000;
@ -918,55 +919,57 @@ where
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&fill_program.program); device.use_program(&fill_program.program);
device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&tess_coord_attr, 2, VertexAttrType::U8, false, 0, 0, 0); device.configure_vertex_attr(&tess_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::U8,
stride: 0,
offset: 0,
divisor: 0,
});
device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex);
device.configure_int_vertex_attr( device.configure_vertex_attr(&from_px_attr, &VertexAttrDescriptor {
&from_px_attr, size: 1,
1, class: VertexAttrClass::Int,
VertexAttrType::U8, attr_type: VertexAttrType::U8,
FILL_INSTANCE_SIZE, stride: FILL_INSTANCE_SIZE,
0, offset: 0,
1, divisor: 1,
); });
device.configure_int_vertex_attr( device.configure_vertex_attr(&to_px_attr, &VertexAttrDescriptor {
&to_px_attr, size: 1,
1, class: VertexAttrClass::Int,
VertexAttrType::U8, attr_type: VertexAttrType::U8,
FILL_INSTANCE_SIZE, stride: FILL_INSTANCE_SIZE,
1, offset: 1,
1, divisor: 1,
); });
device.configure_float_vertex_attr( device.configure_vertex_attr(&from_subpx_attr, &VertexAttrDescriptor {
&from_subpx_attr, size: 2,
2, class: VertexAttrClass::FloatNorm,
VertexAttrType::U8, attr_type: VertexAttrType::U8,
true, stride: FILL_INSTANCE_SIZE,
FILL_INSTANCE_SIZE, offset: 2,
2, divisor: 1,
1, });
); device.configure_vertex_attr(&to_subpx_attr, &VertexAttrDescriptor {
device.configure_float_vertex_attr( size: 2,
&to_subpx_attr, class: VertexAttrClass::FloatNorm,
2, attr_type: VertexAttrType::U8,
VertexAttrType::U8, stride: FILL_INSTANCE_SIZE,
true, offset: 4,
FILL_INSTANCE_SIZE, divisor: 1,
4, });
1, device.configure_vertex_attr(&tile_index_attr, &VertexAttrDescriptor {
); size: 1,
device.configure_int_vertex_attr( class: VertexAttrClass::Int,
&tile_index_attr, attr_type: VertexAttrType::U16,
1, stride: FILL_INSTANCE_SIZE,
VertexAttrType::U16, offset: 6,
FILL_INSTANCE_SIZE, divisor: 1,
6, });
1,
);
FillVertexArray { FillVertexArray { vertex_array, vertex_buffer }
vertex_array,
vertex_buffer,
}
} }
} }
@ -994,51 +997,65 @@ where
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop"); let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop");
let object_attr = device.get_vertex_attr(&alpha_tile_program.program, "Object"); let object_attr = device.get_vertex_attr(&alpha_tile_program.program, "Object");
let tile_index_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileIndex"); let tile_index_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileIndex");
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"ColorTexCoord");
// NB: The object must be of type `I16`, not `U16`, to work around a macOS Radeon // NB: The object must be of type `I16`, not `U16`, to work around a macOS Radeon
// driver bug. // driver bug.
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&alpha_tile_program.program); device.use_program(&alpha_tile_program.program);
device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&tess_coord_attr, 2, VertexAttrType::U8, false, 0, 0, 0); device.configure_vertex_attr(&tess_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::U8,
stride: 0,
offset: 0,
divisor: 0,
});
device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex);
device.configure_int_vertex_attr( device.configure_vertex_attr(&tile_origin_attr, &VertexAttrDescriptor {
&tile_origin_attr, size: 3,
3, class: VertexAttrClass::Int,
VertexAttrType::U8, attr_type: VertexAttrType::U8,
MASK_TILE_INSTANCE_SIZE, stride: MASK_TILE_INSTANCE_SIZE,
0, offset: 0,
1, divisor: 1,
); });
device.configure_int_vertex_attr( device.configure_vertex_attr(&backdrop_attr, &VertexAttrDescriptor {
&backdrop_attr, size: 1,
1, class: VertexAttrClass::Int,
VertexAttrType::I8, attr_type: VertexAttrType::I8,
MASK_TILE_INSTANCE_SIZE, stride: MASK_TILE_INSTANCE_SIZE,
3, offset: 3,
1, divisor: 1,
); });
device.configure_int_vertex_attr( device.configure_vertex_attr(&object_attr, &VertexAttrDescriptor {
&object_attr, size: 1,
1, class: VertexAttrClass::Int,
VertexAttrType::I16, attr_type: VertexAttrType::I16,
MASK_TILE_INSTANCE_SIZE, stride: MASK_TILE_INSTANCE_SIZE,
4, offset: 4,
1, divisor: 1,
); });
device.configure_int_vertex_attr( device.configure_vertex_attr(&tile_index_attr, &VertexAttrDescriptor {
&tile_index_attr, size: 1,
1, class: VertexAttrClass::Int,
VertexAttrType::I16, attr_type: VertexAttrType::I16,
MASK_TILE_INSTANCE_SIZE, stride: MASK_TILE_INSTANCE_SIZE,
6, offset: 6,
1, divisor: 1,
); });
device.configure_vertex_attr(&color_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_INSTANCE_SIZE,
offset: 8,
divisor: 1,
});
AlphaTileVertexArray { AlphaTileVertexArray { vertex_array, vertex_buffer }
vertex_array,
vertex_buffer,
}
} }
} }
@ -1064,36 +1081,49 @@ where
let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord"); let tess_coord_attr = device.get_vertex_attr(&solid_tile_program.program, "TessCoord");
let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin"); let tile_origin_attr = device.get_vertex_attr(&solid_tile_program.program, "TileOrigin");
let object_attr = device.get_vertex_attr(&solid_tile_program.program, "Object"); let object_attr = device.get_vertex_attr(&solid_tile_program.program, "Object");
let color_tex_coord_attr = device.get_vertex_attr(&solid_tile_program.program,
"ColorTexCoord");
// NB: The object must be of type short, not unsigned short, to work around a macOS // NB: The object must be of type short, not unsigned short, to work around a macOS
// Radeon driver bug. // Radeon driver bug.
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&solid_tile_program.program); device.use_program(&solid_tile_program.program);
device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&tess_coord_attr, 2, VertexAttrType::U8, false, 0, 0, 0); device.configure_vertex_attr(&tess_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::U8,
stride: 0,
offset: 0,
divisor: 0,
});
device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr( device.configure_vertex_attr(&tile_origin_attr, &VertexAttrDescriptor {
&tile_origin_attr, size: 2,
2, class: VertexAttrClass::Float,
VertexAttrType::I16, attr_type: VertexAttrType::I16,
false, stride: SOLID_TILE_INSTANCE_SIZE,
SOLID_TILE_INSTANCE_SIZE, offset: 0,
0, divisor: 1,
1, });
); device.configure_vertex_attr(&color_tex_coord_attr, &VertexAttrDescriptor {
device.configure_int_vertex_attr( size: 2,
&object_attr, class: VertexAttrClass::FloatNorm,
1, attr_type: VertexAttrType::U16,
VertexAttrType::I16, stride: SOLID_TILE_INSTANCE_SIZE,
SOLID_TILE_INSTANCE_SIZE, offset: 4,
4, divisor: 1,
1, });
); device.configure_vertex_attr(&object_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: SOLID_TILE_INSTANCE_SIZE,
offset: 8,
divisor: 1,
});
SolidTileVertexArray { SolidTileVertexArray { vertex_array, vertex_buffer }
vertex_array,
vertex_buffer,
}
} }
} }
@ -1361,7 +1391,14 @@ where
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&postprocess_program.program); device.use_program(&postprocess_program.program);
device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0); device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::U8,
stride: 0,
offset: 0,
divisor: 0,
});
PostprocessVertexArray { vertex_array } PostprocessVertexArray { vertex_array }
} }
@ -1404,20 +1441,16 @@ where
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&stencil_program.program); device.use_program(&stencil_program.program);
device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr( device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor {
&position_attr, size: 3,
3, class: VertexAttrClass::Float,
VertexAttrType::F32, attr_type: VertexAttrType::F32,
false, stride: 4 * 4,
4 * 4, offset: 0,
0, divisor: 0,
0, });
);
StencilVertexArray { StencilVertexArray { vertex_array, vertex_buffer }
vertex_array,
vertex_buffer,
}
} }
} }
@ -1473,7 +1506,14 @@ where
device.bind_vertex_array(&vertex_array); device.bind_vertex_array(&vertex_array);
device.use_program(&reprojection_program.program); device.use_program(&reprojection_program.program);
device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex);
device.configure_float_vertex_attr(&position_attr, 2, VertexAttrType::U8, false, 0, 0, 0); device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Float,
attr_type: VertexAttrType::U8,
stride: 0,
offset: 0,
divisor: 0,
});
ReprojectionVertexArray { vertex_array } ReprojectionVertexArray { vertex_array }
} }

View File

@ -72,6 +72,8 @@ pub struct FillBatchPrimitive {
pub struct SolidTileBatchPrimitive { pub struct SolidTileBatchPrimitive {
pub tile_x: i16, pub tile_x: i16,
pub tile_y: i16, pub tile_y: i16,
pub origin_u: u16,
pub origin_v: u16,
pub object_index: u16, pub object_index: u16,
} }
@ -84,6 +86,8 @@ pub struct AlphaTileBatchPrimitive {
pub backdrop: i8, pub backdrop: i8,
pub object_index: u16, pub object_index: u16,
pub tile_index: u16, pub tile_index: u16,
pub origin_u: u16,
pub origin_v: u16,
} }
impl Debug for RenderCommand { impl Debug for RenderCommand {

View File

@ -17,6 +17,7 @@ pub mod concurrent;
pub mod gpu; pub mod gpu;
pub mod gpu_data; pub mod gpu_data;
pub mod options; pub mod options;
pub mod paint;
pub mod post; pub mod post;
pub mod scene; pub mod scene;

37
renderer/src/paint.rs Normal file
View File

@ -0,0 +1,37 @@
// pathfinder/renderer/src/paint.rs
//
// Copyright © 2019 The Pathfinder Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use crate::gpu_data::PaintData;
use crate::scene::Scene;
use pathfinder_geometry::basic::point::Point2DI32;
const PAINT_TEXTURE_WIDTH: i32 = 256;
const PAINT_TEXTURE_HEIGHT: i32 = 256;
impl Scene {
pub fn build_paint_data(&self) -> PaintData {
let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT);
let mut texels = vec![0; size.x() as usize * size.y() as usize * 4];
for (path_object_index, path_object) in self.paths.iter().enumerate() {
let paint = &self.paints[path_object.paint().0 as usize];
texels[path_object_index * 4 + 0] = paint.color.r;
texels[path_object_index * 4 + 1] = paint.color.g;
texels[path_object_index * 4 + 2] = paint.color.b;
texels[path_object_index * 4 + 3] = paint.color.a;
}
PaintData { size, texels }
}
}
pub(crate) fn object_index_to_paint_coords(object_index: u16) -> Point2DI32 {
let tex_coords = Point2DI32::new(object_index as i32 % PAINT_TEXTURE_WIDTH,
object_index as i32 / PAINT_TEXTURE_WIDTH);
tex_coords.scale(256) + Point2DI32::new(128, 128)
}

View File

@ -12,24 +12,20 @@
use crate::builder::SceneBuilder; use crate::builder::SceneBuilder;
use crate::concurrent::executor::Executor; use crate::concurrent::executor::Executor;
use crate::gpu_data::PaintData;
use crate::options::{PreparedRenderOptions, PreparedRenderTransform}; use crate::options::{PreparedRenderOptions, PreparedRenderTransform};
use crate::options::{RenderCommandListener, RenderOptions}; use crate::options::{RenderCommandListener, RenderOptions};
use hashbrown::HashMap; use hashbrown::HashMap;
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; use pathfinder_geometry::basic::point::Point2DF32;
use pathfinder_geometry::basic::rect::RectF32; use pathfinder_geometry::basic::rect::RectF32;
use pathfinder_geometry::basic::transform2d::Transform2DF32; use pathfinder_geometry::basic::transform2d::Transform2DF32;
use pathfinder_geometry::color::ColorU; use pathfinder_geometry::color::ColorU;
use pathfinder_geometry::outline::Outline; use pathfinder_geometry::outline::Outline;
use std::io::{self, Write}; use std::io::{self, Write};
const PAINT_TEXTURE_WIDTH: i32 = 256;
const PAINT_TEXTURE_HEIGHT: i32 = 256;
#[derive(Clone)] #[derive(Clone)]
pub struct Scene { pub struct Scene {
pub(crate) paths: Vec<PathObject>, pub(crate) paths: Vec<PathObject>,
paints: Vec<Paint>, pub(crate) paints: Vec<Paint>,
paint_cache: HashMap<Paint, PaintId>, paint_cache: HashMap<Paint, PaintId>,
bounds: RectF32, bounds: RectF32,
view_box: RectF32, view_box: RectF32,
@ -89,19 +85,6 @@ impl Scene {
self.view_box = new_view_box; self.view_box = new_view_box;
} }
pub fn build_paint_data(&self) -> PaintData {
let size = Point2DI32::new(PAINT_TEXTURE_WIDTH, PAINT_TEXTURE_HEIGHT);
let mut texels = vec![0; size.x() as usize * size.y() as usize * 4];
for (path_object_index, path_object) in self.paths.iter().enumerate() {
let paint = &self.paints[path_object.paint.0 as usize];
texels[path_object_index * 4 + 0] = paint.color.r;
texels[path_object_index * 4 + 1] = paint.color.g;
texels[path_object_index * 4 + 2] = paint.color.b;
texels[path_object_index * 4 + 3] = paint.color.a;
}
PaintData { size, texels }
}
pub(crate) fn apply_render_options( pub(crate) fn apply_render_options(
&self, &self,
original_outline: &Outline, original_outline: &Outline,
@ -233,6 +216,11 @@ impl PathObject {
pub fn outline(&self) -> &Outline { pub fn outline(&self) -> &Outline {
&self.outline &self.outline
} }
#[inline]
pub(crate) fn paint(&self) -> PaintId {
self.paint
}
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]

View File

@ -10,6 +10,7 @@
use crate::builder::SceneBuilder; use crate::builder::SceneBuilder;
use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive}; use crate::gpu_data::{AlphaTileBatchPrimitive, BuiltObject, TileObjectPrimitive};
use crate::paint;
use crate::sorted_vector::SortedVector; use crate::sorted_vector::SortedVector;
use pathfinder_geometry::basic::line_segment::LineSegmentF32; use pathfinder_geometry::basic::line_segment::LineSegmentF32;
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32}; use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32};
@ -114,11 +115,14 @@ impl<'a> Tiler<'a> {
continue; continue;
} }
let origin_uv = paint::object_index_to_paint_coords(self.object_index);
let alpha_tile = AlphaTileBatchPrimitive::new( let alpha_tile = AlphaTileBatchPrimitive::new(
tile_coords, tile_coords,
tile.backdrop, tile.backdrop,
self.object_index, self.object_index,
tile.alpha_tile_index as u16, tile.alpha_tile_index as u16,
origin_uv,
); );
self.built_object.alpha_tiles.push(alpha_tile); self.built_object.alpha_tiles.push(alpha_tile);
@ -521,7 +525,8 @@ impl AlphaTileBatchPrimitive {
fn new(tile_coords: Point2DI32, fn new(tile_coords: Point2DI32,
backdrop: i8, backdrop: i8,
object_index: u16, object_index: u16,
tile_index: u16) tile_index: u16,
origin_uv: Point2DI32)
-> AlphaTileBatchPrimitive { -> AlphaTileBatchPrimitive {
AlphaTileBatchPrimitive { AlphaTileBatchPrimitive {
tile_x_lo: (tile_coords.x() & 0xff) as u8, tile_x_lo: (tile_coords.x() & 0xff) as u8,
@ -530,6 +535,8 @@ impl AlphaTileBatchPrimitive {
backdrop, backdrop,
object_index, object_index,
tile_index, tile_index,
origin_u: origin_uv.x() as u16,
origin_v: origin_uv.y() as u16,
} }
} }

View File

@ -11,6 +11,7 @@
//! Software occlusion culling. //! Software occlusion culling.
use crate::gpu_data::SolidTileBatchPrimitive; use crate::gpu_data::SolidTileBatchPrimitive;
use crate::paint;
use crate::tile_map::DenseTileMap; use crate::tile_map::DenseTileMap;
use crate::tiles; use crate::tiles;
use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::point::Point2DI32;
@ -67,13 +68,27 @@ impl ZBuffer {
if object_index < object_range.start || object_index >= object_range.end { if object_index < object_range.start || object_index >= object_range.end {
continue; continue;
} }
solid_tiles.push(SolidTileBatchPrimitive {
tile_x: (tile_coords.x() + self.buffer.rect.min_x()) as i16, let origin_uv = paint::object_index_to_paint_coords(object_index as u16);
tile_y: (tile_coords.y() + self.buffer.rect.min_y()) as i16,
object_index: object_index as u16, solid_tiles.push(SolidTileBatchPrimitive::new(tile_coords + self.buffer.rect.origin(),
}); object_index as u16,
origin_uv));
} }
solid_tiles solid_tiles
} }
} }
impl SolidTileBatchPrimitive {
fn new(tile_coords: Point2DI32, object_index: u16, origin_uv: Point2DI32)
-> SolidTileBatchPrimitive {
SolidTileBatchPrimitive {
tile_x: tile_coords.x() as i16,
tile_y: tile_coords.y() as i16,
object_index: object_index,
origin_u: origin_uv.x() as u16,
origin_v: origin_uv.y() as u16,
}
}
}

View File

@ -23,7 +23,7 @@ out vec2 vTexCoord;
out float vBackdrop; out float vBackdrop;
out vec4 vColor; out vec4 vColor;
vec4 getColor(uint object); vec4 getColor();
vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) {
uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x);
@ -35,11 +35,12 @@ void computeVaryings() {
vec2 origin = vec2(aTileOrigin.xy) + vec2(aTileOrigin.z & 15u, aTileOrigin.z >> 4u) * 256.0; vec2 origin = vec2(aTileOrigin.xy) + vec2(aTileOrigin.z & 15u, aTileOrigin.z >> 4u) * 256.0;
vec2 pixelPosition = (origin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 pixelPosition = (origin + aTessCoord) * uTileSize + uViewBoxOrigin;
vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0);
vec2 texCoord = computeTileOffset(aTileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize; vec2 maskTexCoordOrigin = computeTileOffset(aTileIndex, uStencilTextureSize.x);
vec2 maskTexCoord = maskTexCoordOrigin + aTessCoord * uTileSize;
vTexCoord = texCoord / uStencilTextureSize; vTexCoord = maskTexCoord / uStencilTextureSize;
vBackdrop = float(aBackdrop); vBackdrop = float(aBackdrop);
vColor = getColor(aObject); vColor = getColor();
gl_Position = vec4(position, 0.0, 1.0); gl_Position = vec4(position, 0.0, 1.0);
} }

View File

@ -10,6 +10,6 @@
uniform vec4 uColor; uniform vec4 uColor;
vec4 getColor(uint object) { vec4 getColor() {
return uColor; return uColor;
} }

View File

@ -11,12 +11,8 @@
uniform sampler2D uPaintTexture; uniform sampler2D uPaintTexture;
uniform vec2 uPaintTextureSize; uniform vec2 uPaintTextureSize;
vec2 computePaintTexCoord(uint object, vec2 textureSize) { in vec2 aColorTexCoord;
uint width = uint(textureSize.x);
return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize;
}
vec4 getColor(uint object) { vec4 getColor() {
vec2 colorTexCoord = computePaintTexCoord(object, uPaintTextureSize); return texture(uPaintTexture, aColorTexCoord);
return texture(uPaintTexture, colorTexCoord);
} }

View File

@ -18,12 +18,13 @@ in uint aObject;
out vec4 vColor; out vec4 vColor;
vec4 getColor(uint object); vec4 getColor();
void computeVaryings() { void computeVaryings() {
vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin;
vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0);
vColor = getColor(aObject); vColor = getColor();
//vColor = vec4(1.0, 0.0, 0.0, 1.0);
gl_Position = vec4(position, 0.0, 1.0); gl_Position = vec4(position, 0.0, 1.0);
} }

View File

@ -22,7 +22,8 @@ use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_geometry::color::ColorU; use pathfinder_geometry::color::ColorU;
use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::resources::ResourceLoader;
use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, Device, Primitive}; use pathfinder_gpu::{BlendState, BufferData, BufferTarget, BufferUploadMode, Device, Primitive};
use pathfinder_gpu::{RenderState, UniformData, VertexAttrType}; use pathfinder_gpu::{RenderState, UniformData, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use serde_json; use serde_json;
use std::mem; use std::mem;
@ -591,20 +592,22 @@ impl<D> DebugTextureVertexArray<D> where D: Device {
device.use_program(&debug_texture_program.program); device.use_program(&debug_texture_program.program);
device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex);
device.bind_buffer(&index_buffer, BufferTarget::Index); device.bind_buffer(&index_buffer, BufferTarget::Index);
device.configure_float_vertex_attr(&position_attr, device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor {
2, size: 2,
VertexAttrType::U16, class: VertexAttrClass::Float,
false, attr_type: VertexAttrType::U16,
DEBUG_TEXTURE_VERTEX_SIZE, stride: DEBUG_TEXTURE_VERTEX_SIZE,
0, offset: 0,
0); divisor: 0,
device.configure_float_vertex_attr(&tex_coord_attr, });
2, device.configure_vertex_attr(&tex_coord_attr, &VertexAttrDescriptor {
VertexAttrType::U16, size: 2,
false, class: VertexAttrClass::Float,
DEBUG_TEXTURE_VERTEX_SIZE, attr_type: VertexAttrType::U16,
4, stride: DEBUG_TEXTURE_VERTEX_SIZE,
0); offset: 4,
divisor: 0,
});
DebugTextureVertexArray { vertex_array, vertex_buffer, index_buffer } DebugTextureVertexArray { vertex_array, vertex_buffer, index_buffer }
} }
@ -626,13 +629,14 @@ impl<D> DebugSolidVertexArray<D> where D: Device {
device.use_program(&debug_solid_program.program); device.use_program(&debug_solid_program.program);
device.bind_buffer(&vertex_buffer, BufferTarget::Vertex); device.bind_buffer(&vertex_buffer, BufferTarget::Vertex);
device.bind_buffer(&index_buffer, BufferTarget::Index); device.bind_buffer(&index_buffer, BufferTarget::Index);
device.configure_float_vertex_attr(&position_attr, device.configure_vertex_attr(&position_attr, &VertexAttrDescriptor {
2, size: 2,
VertexAttrType::U16, class: VertexAttrClass::Float,
false, attr_type: VertexAttrType::U16,
DEBUG_SOLID_VERTEX_SIZE, stride: DEBUG_SOLID_VERTEX_SIZE,
0, offset: 0,
0); divisor: 0,
});
DebugSolidVertexArray { vertex_array, vertex_buffer, index_buffer } DebugSolidVertexArray { vertex_array, vertex_buffer, index_buffer }
} }