Add a separate mask blit step, in preparation for supporting clips.

We can elide this in the future if there are no clips, but it isn't a huge
performance regression right now, so let's just unconditionally do it.
This commit is contained in:
Patrick Walton 2020-02-14 21:55:37 -08:00
parent 6a73a63336
commit 0883f54e2d
14 changed files with 297 additions and 79 deletions

View File

@ -11,7 +11,7 @@
//! Packs data onto the GPU.
use crate::concurrent::executor::Executor;
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, RenderCommand, TileObjectPrimitive};
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, RenderCommand, TileObjectPrimitive};
use crate::options::{PreparedBuildOptions, RenderCommandListener};
use crate::paint::{PaintInfo, PaintMetadata};
use crate::scene::Scene;
@ -106,9 +106,11 @@ impl<'a> SceneBuilder<'a> {
}
fn cull_tiles(&self, built_objects: Vec<BuiltObject>) -> CulledTiles {
let mut culled_tiles = CulledTiles { alpha_tiles: vec![] };
let mut culled_tiles = CulledTiles { mask_tiles: vec![], alpha_tiles: vec![] };
for built_object in built_objects {
culled_tiles.mask_tiles.extend_from_slice(&built_object.mask_tiles);
for alpha_tile in built_object.alpha_tiles {
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
if self.z_buffer.test(alpha_tile_coords,
@ -126,6 +128,9 @@ impl<'a> SceneBuilder<'a> {
let solid_tiles = self.z_buffer.build_solid_tiles(&self.scene.paths,
paint_metadata,
0..path_count);
if !culled_tiles.mask_tiles.is_empty() {
self.listener.send(RenderCommand::RenderMaskTiles(culled_tiles.mask_tiles));
}
if !solid_tiles.is_empty() {
self.listener.send(RenderCommand::DrawSolidTiles(solid_tiles));
}
@ -143,6 +148,11 @@ impl<'a> SceneBuilder<'a> {
}
}
struct CulledTiles {
mask_tiles: Vec<MaskTile>,
alpha_tiles: Vec<AlphaTile>,
}
#[derive(Clone, Copy, Debug, Default)]
pub struct TileStats {
pub solid_tile_count: u32,
@ -156,7 +166,7 @@ impl ObjectBuilder {
let tile_rect = tiles::round_rect_out_to_tile_bounds(bounds);
let tiles = DenseTileMap::new(tile_rect);
ObjectBuilder {
built_object: BuiltObject { alpha_tiles: vec![] },
built_object: BuiltObject { mask_tiles: vec![], alpha_tiles: vec![] },
bounds,
fills: vec![],
tiles,
@ -341,6 +351,7 @@ impl ObjectBuilder {
#[derive(Debug)]
pub(crate) struct BuiltObject {
pub mask_tiles: Vec<MaskTile>,
pub alpha_tiles: Vec<AlphaTile>,
}
@ -351,7 +362,3 @@ pub(crate) struct ObjectBuilder {
pub tiles: DenseTileMap<TileObjectPrimitive>,
pub bounds: RectF,
}
struct CulledTiles {
alpha_tiles: Vec<AlphaTile>,
}

View File

@ -11,10 +11,12 @@
use crate::gpu::debug::DebugUIPresenter;
use crate::gpu::options::{DestFramebuffer, RendererOptions};
use crate::gpu::shaders::{FillProgram, AlphaTileProgram, AlphaTileVertexArray, FillVertexArray};
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, PostprocessProgram, PostprocessVertexArray};
use crate::gpu::shaders::{ReprojectionProgram, ReprojectionVertexArray, SolidTileProgram};
use crate::gpu::shaders::{SolidTileVertexArray, StencilProgram, StencilVertexArray};
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, PaintData, RenderCommand, SolidTileVertex};
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MaskWindingTileProgram, MaskWindingTileVertexArray};
use crate::gpu::shaders::{PostprocessProgram, PostprocessVertexArray, ReprojectionProgram};
use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray};
use crate::gpu::shaders::{StencilProgram, StencilVertexArray};
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData};
use crate::gpu_data::{RenderCommand, SolidTileVertex};
use crate::post::DefringingKernel;
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
use pathfinder_color::{self as color, ColorF, ColorU};
@ -55,8 +57,10 @@ where
dest_framebuffer: DestFramebuffer<D>,
options: RendererOptions,
fill_program: FillProgram<D>,
mask_winding_tile_program: MaskWindingTileProgram<D>,
solid_tile_program: SolidTileProgram<D>,
alpha_tile_program: AlphaTileProgram<D>,
mask_winding_tile_vertex_array: MaskWindingTileVertexArray<D>,
solid_tile_vertex_array: SolidTileVertexArray<D>,
alpha_tile_vertex_array: AlphaTileVertexArray<D>,
area_lut_texture: D::Texture,
@ -65,6 +69,7 @@ where
quads_vertex_indices_buffer: D::Buffer,
quads_vertex_indices_length: usize,
fill_vertex_array: FillVertexArray<D>,
fill_framebuffer: D::Framebuffer,
mask_framebuffer: D::Framebuffer,
paint_texture: Option<D::Texture>,
@ -108,10 +113,9 @@ where
options: RendererOptions)
-> Renderer<D> {
let fill_program = FillProgram::new(&device, resources);
let mask_winding_tile_program = MaskWindingTileProgram::new(&device, resources);
let solid_tile_program = SolidTileProgram::new(&device, resources);
let alpha_tile_program = AlphaTileProgram::new(&device, resources);
let postprocess_program = PostprocessProgram::new(&device, resources);
let stencil_program = StencilProgram::new(&device, resources);
let reprojection_program = ReprojectionProgram::new(&device, resources);
@ -141,6 +145,11 @@ where
&quad_vertex_positions_buffer,
&quad_vertex_indices_buffer,
);
let mask_winding_tile_vertex_array = MaskWindingTileVertexArray::new(
&device,
&mask_winding_tile_program,
&quads_vertex_indices_buffer,
);
let alpha_tile_vertex_array = AlphaTileVertexArray::new(
&device,
&alpha_tile_program,
@ -165,10 +174,16 @@ where
&quad_vertex_indices_buffer,
);
let fill_framebuffer_size =
Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT);
let fill_framebuffer_texture =
device.create_texture(TextureFormat::R16F, fill_framebuffer_size);
let fill_framebuffer = device.create_framebuffer(fill_framebuffer_texture);
let mask_framebuffer_size =
Vector2I::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT);
let mask_framebuffer_texture =
device.create_texture(TextureFormat::R16F, mask_framebuffer_size);
device.create_texture(TextureFormat::R8, mask_framebuffer_size);
let mask_framebuffer = device.create_framebuffer(mask_framebuffer_texture);
let window_size = dest_framebuffer.window_size(&device);
@ -180,8 +195,10 @@ where
dest_framebuffer,
options,
fill_program,
mask_winding_tile_program,
solid_tile_program,
alpha_tile_program,
mask_winding_tile_vertex_array,
solid_tile_vertex_array,
alpha_tile_vertex_array,
area_lut_texture,
@ -190,6 +207,7 @@ where
quads_vertex_indices_buffer,
quads_vertex_indices_length: 0,
fill_vertex_array,
fill_framebuffer,
mask_framebuffer,
paint_texture: None,
@ -239,6 +257,11 @@ where
self.draw_buffered_fills();
self.begin_composite_timer_query();
}
RenderCommand::RenderMaskTiles(ref mask_tiles) => {
let count = mask_tiles.len();
self.upload_mask_tiles(mask_tiles);
self.draw_mask_tiles(count as u32);
}
RenderCommand::DrawSolidTiles(ref solid_tile_vertices) => {
let count = solid_tile_vertices.len() / 4;
self.stats.solid_tile_count += count;
@ -374,6 +397,16 @@ where
TextureDataRef::U8(texels));
}
fn upload_mask_tiles(&mut self, mask_tiles: &[MaskTile]) {
self.device.allocate_buffer(
&self.mask_winding_tile_vertex_array.vertex_buffer,
BufferData::Memory(&mask_tiles),
BufferTarget::Vertex,
BufferUploadMode::Dynamic,
);
self.ensure_index_buffer(mask_tiles.len());
}
fn upload_solid_tiles(&mut self, solid_tile_vertices: &[SolidTileVertex]) {
self.device.allocate_buffer(
&self.solid_tile_vertex_array.vertex_buffer,
@ -450,7 +483,7 @@ where
let mut clear_color = None;
if !self.framebuffer_flags.contains(
FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS) {
FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS) {
clear_color = Some(ColorF::default());
};
@ -459,7 +492,7 @@ where
debug_assert!(self.buffered_fills.len() <= u32::MAX as usize);
self.device.draw_elements_instanced(6, self.buffered_fills.len() as u32, &RenderState {
target: &RenderTarget::Framebuffer(&self.mask_framebuffer),
target: &RenderTarget::Framebuffer(&self.fill_framebuffer),
program: &self.fill_program.program,
vertex_array: &self.fill_vertex_array.vertex_array,
primitive: Primitive::Triangles,
@ -486,7 +519,7 @@ where
self.device.end_timer_query(&timer_query);
self.current_timers.stage_0.push(timer_query);
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS);
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS);
self.buffered_fills.clear();
}
@ -496,6 +529,38 @@ where
Transform4F::from_scale(scale).translate(Vector4F::new(-1.0, 1.0, 0.0, 1.0))
}
fn draw_mask_tiles(&mut self, tile_count: u32) {
let clear_color =
if self.framebuffer_flags
.contains(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS) {
None
} else {
Some(ColorF::new(1.0, 1.0, 1.0, 1.0))
};
let textures = vec![self.device.framebuffer_texture(&self.fill_framebuffer)];
let uniforms = vec![
(&self.mask_winding_tile_program.mask_texture_uniform, UniformData::TextureUnit(0)),
];
self.device.draw_elements(tile_count * 6, &RenderState {
target: &RenderTarget::Framebuffer(&self.mask_framebuffer),
program: &self.mask_winding_tile_program.program,
vertex_array: &self.mask_winding_tile_vertex_array.vertex_array,
primitive: Primitive::Triangles,
textures: &textures,
uniforms: &uniforms,
viewport: self.mask_viewport(),
options: RenderOptions {
// TODO(pcwalton): MIN blending for masks.
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
..RenderOptions::default()
},
});
self.framebuffer_flags.insert(FramebufferFlags::MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS);
}
fn draw_alpha_tiles(&mut self, tile_count: u32) {
let clear_color = self.clear_color_for_draw_operation();
@ -937,8 +1002,9 @@ impl Add<RenderTime> for RenderTime {
bitflags! {
struct FramebufferFlags: u8 {
const MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS = 0x01;
const MUST_PRESERVE_POSTPROCESS_FRAMEBUFFER_CONTENTS = 0x02;
const MUST_PRESERVE_DEST_FRAMEBUFFER_CONTENTS = 0x04;
const MUST_PRESERVE_FILL_FRAMEBUFFER_CONTENTS = 0x01;
const MUST_PRESERVE_MASK_FRAMEBUFFER_CONTENTS = 0x02;
const MUST_PRESERVE_POSTPROCESS_FRAMEBUFFER_CONTENTS = 0x04;
const MUST_PRESERVE_DEST_FRAMEBUFFER_CONTENTS = 0x08;
}
}

View File

@ -9,13 +9,15 @@
// except according to those terms.
use crate::gpu_data::FillBatchPrimitive;
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass};
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
use pathfinder_gpu::resources::ResourceLoader;
// TODO(pcwalton): Replace with `mem::size_of` calls?
const FILL_INSTANCE_SIZE: usize = 8;
const SOLID_TILE_VERTEX_SIZE: usize = 12;
const MASK_TILE_VERTEX_SIZE: usize = 16;
const ALPHA_TILE_VERTEX_SIZE: usize = 16;
const MASK_TILE_VERTEX_SIZE: usize = 12;
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
@ -118,39 +120,30 @@ where
}
}
pub struct AlphaTileVertexArray<D>
where
D: Device,
{
pub struct MaskWindingTileVertexArray<D> where D: Device {
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
}
impl<D> AlphaTileVertexArray<D>
where
D: Device,
{
pub fn new(
device: &D,
alpha_tile_program: &AlphaTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer,
) -> AlphaTileVertexArray<D> {
impl<D> MaskWindingTileVertexArray<D> where D: Device {
pub fn new(device: &D,
mask_winding_tile_program: &MaskWindingTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer)
-> MaskWindingTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
let tile_position_attr =
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"ColorTexCoord").unwrap();
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
let position_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "Position")
.unwrap();
let mask_tex_coord_attr = device.get_vertex_attr(&mask_winding_tile_program.program,
"MaskTexCoord").unwrap();
let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop")
let backdrop_attr = device.get_vertex_attr(&mask_winding_tile_program.program, "Backdrop")
.unwrap();
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 0,
divisor: 0,
@ -165,21 +158,66 @@ where
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 8,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &backdrop_attr, &VertexAttrDescriptor {
size: 1,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: MASK_TILE_VERTEX_SIZE,
offset: 12,
offset: 8,
divisor: 0,
buffer_index: 0,
});
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
MaskWindingTileVertexArray { vertex_array, vertex_buffer }
}
}
pub struct AlphaTileVertexArray<D> where D: Device {
pub vertex_array: D::VertexArray,
pub vertex_buffer: D::Buffer,
}
impl<D> AlphaTileVertexArray<D> where D: Device {
pub fn new(
device: &D,
alpha_tile_program: &AlphaTileProgram<D>,
quads_vertex_indices_buffer: &D::Buffer,
) -> AlphaTileVertexArray<D> {
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
let tile_position_attr =
device.get_vertex_attr(&alpha_tile_program.program, "TilePosition").unwrap();
let color_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"ColorTexCoord").unwrap();
let mask_tex_coord_attr = device.get_vertex_attr(&alpha_tile_program.program,
"MaskTexCoord").unwrap();
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::Int,
attr_type: VertexAttrType::I16,
stride: ALPHA_TILE_VERTEX_SIZE,
offset: 0,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &mask_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: ALPHA_TILE_VERTEX_SIZE,
offset: 4,
divisor: 0,
buffer_index: 0,
});
device.configure_vertex_attr(&vertex_array, &color_tex_coord_attr, &VertexAttrDescriptor {
size: 2,
class: VertexAttrClass::FloatNorm,
attr_type: VertexAttrType::U16,
stride: ALPHA_TILE_VERTEX_SIZE,
offset: 8,
divisor: 0,
buffer_index: 0,
});
@ -270,6 +308,19 @@ where
}
}
pub struct MaskWindingTileProgram<D> where D: Device {
pub program: D::Program,
pub mask_texture_uniform: D::Uniform,
}
impl<D> MaskWindingTileProgram<D> where D: Device {
pub fn new(device: &D, resources: &dyn ResourceLoader) -> MaskWindingTileProgram<D> {
let program = device.create_program(resources, "mask_winding");
let mask_texture_uniform = device.get_uniform(&program, "MaskTexture");
MaskWindingTileProgram { program, mask_texture_uniform }
}
}
pub struct SolidTileProgram<D> where D: Device {
pub program: D::Program,
pub transform_uniform: D::Uniform,

View File

@ -22,6 +22,7 @@ pub enum RenderCommand {
AddPaintData(PaintData),
AddFills(Vec<FillBatchPrimitive>),
FlushFills,
RenderMaskTiles(Vec<MaskTile>),
DrawAlphaTiles(Vec<AlphaTile>),
DrawSolidTiles(Vec<SolidTileVertex>),
Finish { build_time: Duration },
@ -69,6 +70,15 @@ pub struct SolidTileVertex {
pub pad: u16,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct MaskTile {
pub upper_left: MaskTileVertex,
pub upper_right: MaskTileVertex,
pub lower_left: MaskTileVertex,
pub lower_right: MaskTileVertex,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct AlphaTile {
@ -78,6 +88,17 @@ pub struct AlphaTile {
pub lower_right: AlphaTileVertex,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct MaskTileVertex {
pub tile_x: u16,
pub tile_y: u16,
pub mask_u: u16,
pub mask_v: u16,
pub backdrop: i16,
pub object_index: u16,
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct AlphaTileVertex {
@ -87,8 +108,8 @@ pub struct AlphaTileVertex {
pub mask_v: u16,
pub color_u: u16,
pub color_v: u16,
pub backdrop: i16,
pub object_index: u16,
pub pad: u16,
}
impl Debug for RenderCommand {
@ -100,6 +121,9 @@ impl Debug for RenderCommand {
}
RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()),
RenderCommand::FlushFills => write!(formatter, "FlushFills"),
RenderCommand::RenderMaskTiles(ref tiles) => {
write!(formatter, "RenderMaskTiles(x{})", tiles.len())
}
RenderCommand::DrawAlphaTiles(ref tiles) => {
write!(formatter, "DrawAlphaTiles(x{})", tiles.len())
}

View File

@ -10,7 +10,7 @@
use crate::builder::{ObjectBuilder, SceneBuilder};
use crate::gpu::renderer::MASK_TILES_ACROSS;
use crate::gpu_data::{AlphaTile, AlphaTileVertex, TileObjectPrimitive};
use crate::gpu_data::{AlphaTile, AlphaTileVertex, MaskTile, MaskTileVertex, TileObjectPrimitive};
use crate::paint::PaintMetadata;
use pathfinder_content::outline::{Contour, Outline, PointIndex};
use pathfinder_content::segment::Segment;
@ -124,30 +124,45 @@ impl<'a> Tiler<'a> {
}
}
self.object_builder.built_object.mask_tiles.push(MaskTile {
upper_left: MaskTileVertex::new(tile.alpha_tile_index as u16,
Vector2I::default(),
self.object_index,
tile.backdrop as i16),
upper_right: MaskTileVertex::new(tile.alpha_tile_index as u16,
Vector2I::new(1, 0),
self.object_index,
tile.backdrop as i16),
lower_left: MaskTileVertex::new(tile.alpha_tile_index as u16,
Vector2I::new(0, 1),
self.object_index,
tile.backdrop as i16),
lower_right: MaskTileVertex::new(tile.alpha_tile_index as u16,
Vector2I::splat(1),
self.object_index,
tile.backdrop as i16),
});
self.object_builder.built_object.alpha_tiles.push(AlphaTile {
upper_left: AlphaTileVertex::new(tile_coords,
tile.alpha_tile_index as u16,
Vector2I::default(),
self.object_index,
tile.backdrop as i16,
&self.paint_metadata),
upper_right: AlphaTileVertex::new(tile_coords,
tile.alpha_tile_index as u16,
Vector2I::new(1, 0),
Vector2I::new(1, 0),
self.object_index,
tile.backdrop as i16,
&self.paint_metadata),
lower_left: AlphaTileVertex::new(tile_coords,
tile.alpha_tile_index as u16,
Vector2I::new(0, 1),
self.object_index,
tile.backdrop as i16,
&self.paint_metadata),
lower_right: AlphaTileVertex::new(tile_coords,
tile.alpha_tile_index as u16,
Vector2I::splat(1),
self.object_index,
tile.backdrop as i16,
&self.paint_metadata),
});
}
@ -540,18 +555,33 @@ impl PartialOrd<ActiveEdge> for ActiveEdge {
}
}
impl MaskTileVertex {
#[inline]
fn new(tile_index: u16, tile_offset: Vector2I, object_index: u16, backdrop: i16)
-> MaskTileVertex {
let mask_uv = calculate_mask_uv(tile_index, tile_offset);
MaskTileVertex {
tile_x: mask_uv.x() as u16,
tile_y: mask_uv.y() as u16,
mask_u: mask_uv.x() as u16,
mask_v: mask_uv.y() as u16,
backdrop,
object_index,
}
}
}
impl AlphaTileVertex {
#[inline]
fn new(tile_origin: Vector2I,
tile_index: u16,
tile_offset: Vector2I,
object_index: u16,
backdrop: i16,
paint_metadata: &PaintMetadata)
-> AlphaTileVertex {
let tile_position = tile_origin + tile_offset;
let color_uv = paint_metadata.calculate_tex_coords(tile_position).scale(65535.0).to_i32();
let mask_uv = calculate_mask_uv(tile_index as u16, tile_offset);
let mask_uv = calculate_mask_uv(tile_index, tile_offset);
AlphaTileVertex {
tile_x: tile_position.x() as i16,
@ -561,7 +591,7 @@ impl AlphaTileVertex {
mask_u: mask_uv.x() as u16,
mask_v: mask_uv.y() as u16,
object_index,
backdrop,
pad: 0,
}
}

View File

@ -20,13 +20,12 @@ uniform vec2 uPaintTextureSize;
in vec2 vColorTexCoord;
in vec2 vMaskTexCoord;
in float vBackdrop;
in vec4 vColor;
out vec4 oFragColor;
void main(){
float coverage = abs(texture(uStencilTexture, vMaskTexCoord). r + vBackdrop);
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
vec4 color = texture(uPaintTexture, vColorTexCoord);
oFragColor = vec4(color . rgb, color . a * coverage);
}

View File

@ -21,18 +21,15 @@ uniform vec2 uStencilTextureSize;
in ivec2 aTilePosition;
in vec2 aColorTexCoord;
in vec2 aMaskTexCoord;
in int aBackdrop;
out vec2 vColorTexCoord;
out vec2 vMaskTexCoord;
out float vBackdrop;
void main(){
vec2 position = aTilePosition * uTileSize;
vMaskTexCoord = aMaskTexCoord;
vColorTexCoord = aColorTexCoord;
vBackdrop = float(aBackdrop);
gl_Position = uTransform * vec4(position, 0.0, 1.0);
}

View File

@ -21,13 +21,12 @@ struct main0_in
{
float2 vColorTexCoord [[user(locn0)]];
float2 vMaskTexCoord [[user(locn1)]];
float vBackdrop [[user(locn2)]];
};
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
{
main0_out out = {};
float coverage = abs(spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x + in.vBackdrop);
float coverage = spvDescriptorSet0.uStencilTexture.sample(spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord).x;
float4 color = spvDescriptorSet0.uPaintTexture.sample(spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord);
out.oFragColor = float4(color.xyz, color.w * coverage);
return out;

View File

@ -14,7 +14,6 @@ struct main0_out
{
float2 vColorTexCoord [[user(locn0)]];
float2 vMaskTexCoord [[user(locn1)]];
float vBackdrop [[user(locn2)]];
float4 gl_Position [[position]];
};
@ -23,7 +22,6 @@ struct main0_in
int2 aTilePosition [[attribute(0)]];
float2 aColorTexCoord [[attribute(1)]];
float2 aMaskTexCoord [[attribute(2)]];
int aBackdrop [[attribute(3)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
@ -32,7 +30,6 @@ vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
out.vMaskTexCoord = in.aMaskTexCoord;
out.vColorTexCoord = in.aColorTexCoord;
out.vBackdrop = float(in.aBackdrop);
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
return out;
}

View File

@ -11,6 +11,8 @@ SHADERS=\
demo_ground.vs.glsl \
fill.fs.glsl \
fill.vs.glsl \
mask_winding.fs.glsl \
mask_winding.vs.glsl \
post.fs.glsl \
post.vs.glsl \
reproject.fs.glsl \

View File

@ -0,0 +1,24 @@
#version 330
// pathfinder/shaders/mask_winding.fs.glsl
//
// Copyright © 2020 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.
precision highp float;
uniform sampler2D uMaskTexture;
in vec2 vMaskTexCoord;
in float vBackdrop;
out vec4 oFragColor;
void main() {
oFragColor = vec4(abs(texture(uMaskTexture, vMaskTexCoord).r + vBackdrop));
}

View File

@ -0,0 +1,26 @@
#version 330
// pathfinder/shaders/mask_winding.vs.glsl
//
// Copyright © 2020 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.
precision highp float;
in vec2 aPosition;
in vec2 aMaskTexCoord;
in int aBackdrop;
out vec2 vMaskTexCoord;
out float vBackdrop;
void main() {
vMaskTexCoord = aMaskTexCoord;
vBackdrop = float(aBackdrop);
gl_Position = vec4(mix(vec2(-1.0, -1.0), vec2(1.0, 1.0), aPosition), 0.0, 1.0);
}

View File

@ -18,13 +18,12 @@ uniform vec2 uPaintTextureSize;
in vec2 vColorTexCoord;
in vec2 vMaskTexCoord;
in float vBackdrop;
in vec4 vColor;
out vec4 oFragColor;
void main() {
float coverage = abs(texture(uStencilTexture, vMaskTexCoord).r + vBackdrop);
float coverage = texture(uStencilTexture, vMaskTexCoord).r;
vec4 color = texture(uPaintTexture, vColorTexCoord);
oFragColor = vec4(color.rgb, color.a * coverage);
}

View File

@ -19,17 +19,14 @@ uniform vec2 uStencilTextureSize;
in ivec2 aTilePosition;
in vec2 aColorTexCoord;
in vec2 aMaskTexCoord;
in int aBackdrop;
out vec2 vColorTexCoord;
out vec2 vMaskTexCoord;
out float vBackdrop;
void main() {
vec2 position = aTilePosition * uTileSize;
vMaskTexCoord = aMaskTexCoord;
vColorTexCoord = aColorTexCoord;
vBackdrop = float(aBackdrop);
gl_Position = uTransform * vec4(position, 0.0, 1.0);
}