Replace the individual tile shaders with an ubershader
This commit is contained in:
parent
51277a2027
commit
0c93045f50
|
@ -1131,6 +1131,9 @@ dependencies = [
|
|||
name = "instant"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
|
@ -1808,6 +1811,7 @@ dependencies = [
|
|||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"instant 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pathfinder_color 0.1.0",
|
||||
"pathfinder_content 0.1.0",
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use pathfinder_color::ColorU;
|
||||
use pathfinder_content::dash::OutlineDash;
|
||||
use pathfinder_content::effects::{BlendMode, BlurDirection, CompositeOp, Effects, Filter};
|
||||
use pathfinder_content::effects::{BlendMode, BlurDirection, Effects, Filter};
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_content::gradient::Gradient;
|
||||
use pathfinder_content::outline::{ArcDirection, Contour, Outline};
|
||||
|
@ -251,11 +251,9 @@ impl CanvasRenderingContext2D {
|
|||
let transform = self.current_state.transform;
|
||||
let clip_path = self.current_state.clip_path;
|
||||
let blend_mode = self.current_state.global_composite_operation.to_blend_mode();
|
||||
let composite_op = self.current_state.global_composite_operation.to_composite_op();
|
||||
let opacity = (self.current_state.global_alpha * 255.0) as u8;
|
||||
|
||||
if !self.current_state.shadow_paint.is_fully_transparent() {
|
||||
let composite_render_target_id = self.push_render_target_if_needed(composite_op);
|
||||
let shadow_blur_render_target_ids = self.push_shadow_blur_render_targets_if_needed();
|
||||
|
||||
let paint = self.current_state.resolve_paint(&self.current_state.shadow_paint);
|
||||
|
@ -273,10 +271,8 @@ impl CanvasRenderingContext2D {
|
|||
self.scene.push_path(path);
|
||||
|
||||
self.composite_shadow_blur_render_targets_if_needed(shadow_blur_render_target_ids);
|
||||
self.composite_render_target_if_needed(composite_op, composite_render_target_id);
|
||||
}
|
||||
|
||||
let render_target_id = self.push_render_target_if_needed(composite_op);
|
||||
outline.transform(&transform);
|
||||
|
||||
let mut path = DrawPath::new(outline, paint_id);
|
||||
|
@ -285,18 +281,6 @@ impl CanvasRenderingContext2D {
|
|||
path.set_blend_mode(blend_mode);
|
||||
path.set_opacity(opacity);
|
||||
self.scene.push_path(path);
|
||||
|
||||
self.composite_render_target_if_needed(composite_op, render_target_id);
|
||||
}
|
||||
|
||||
fn push_render_target_if_needed(&mut self, composite_op: Option<CompositeOp>)
|
||||
-> Option<RenderTargetId> {
|
||||
if composite_op.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let render_target_size = self.scene.view_box().size().ceil().to_i32();
|
||||
Some(self.scene.push_render_target(RenderTarget::new(render_target_size, String::new())))
|
||||
}
|
||||
|
||||
fn push_shadow_blur_render_targets_if_needed(&mut self) -> Option<[RenderTargetId; 2]> {
|
||||
|
@ -312,19 +296,6 @@ impl CanvasRenderingContext2D {
|
|||
Some([render_target_id_a, render_target_id_b])
|
||||
}
|
||||
|
||||
fn composite_render_target_if_needed(&mut self,
|
||||
composite_op: Option<CompositeOp>,
|
||||
render_target_id: Option<RenderTargetId>) {
|
||||
let composite_op = match composite_op {
|
||||
None => return,
|
||||
Some(composite_op) => composite_op,
|
||||
};
|
||||
|
||||
self.scene.pop_render_target();
|
||||
self.scene.draw_render_target(render_target_id.unwrap(),
|
||||
Effects::new(Filter::Composite(composite_op)));
|
||||
}
|
||||
|
||||
fn composite_shadow_blur_render_targets_if_needed(
|
||||
&mut self,
|
||||
render_target_ids: Option<[RenderTargetId; 2]>) {
|
||||
|
@ -679,6 +650,7 @@ pub enum CompositeOperation {
|
|||
impl CompositeOperation {
|
||||
fn to_blend_mode(self) -> BlendMode {
|
||||
match self {
|
||||
CompositeOperation::Copy => BlendMode::Copy,
|
||||
CompositeOperation::SourceAtop => BlendMode::SrcAtop,
|
||||
CompositeOperation::DestinationOver => BlendMode::DestOver,
|
||||
CompositeOperation::DestinationOut => BlendMode::DestOut,
|
||||
|
@ -699,43 +671,11 @@ impl CompositeOperation {
|
|||
CompositeOperation::Saturation => BlendMode::Saturation,
|
||||
CompositeOperation::Color => BlendMode::Color,
|
||||
CompositeOperation::Luminosity => BlendMode::Luminosity,
|
||||
CompositeOperation::SourceOver |
|
||||
CompositeOperation::SourceIn |
|
||||
CompositeOperation::SourceOut |
|
||||
CompositeOperation::DestinationIn |
|
||||
CompositeOperation::DestinationAtop |
|
||||
CompositeOperation::Copy => BlendMode::SrcOver,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_composite_op(self) -> Option<CompositeOp> {
|
||||
match self {
|
||||
CompositeOperation::SourceIn => Some(CompositeOp::SrcIn),
|
||||
CompositeOperation::SourceOut => Some(CompositeOp::SrcOut),
|
||||
CompositeOperation::DestinationIn => Some(CompositeOp::DestIn),
|
||||
CompositeOperation::DestinationAtop => Some(CompositeOp::DestAtop),
|
||||
CompositeOperation::Copy => Some(CompositeOp::Copy),
|
||||
CompositeOperation::SourceOver |
|
||||
CompositeOperation::SourceAtop |
|
||||
CompositeOperation::DestinationOver |
|
||||
CompositeOperation::DestinationOut |
|
||||
CompositeOperation::Xor |
|
||||
CompositeOperation::Lighter |
|
||||
CompositeOperation::Multiply |
|
||||
CompositeOperation::Screen |
|
||||
CompositeOperation::Overlay |
|
||||
CompositeOperation::Darken |
|
||||
CompositeOperation::Lighten |
|
||||
CompositeOperation::ColorDodge |
|
||||
CompositeOperation::ColorBurn |
|
||||
CompositeOperation::HardLight |
|
||||
CompositeOperation::SoftLight |
|
||||
CompositeOperation::Difference |
|
||||
CompositeOperation::Exclusion |
|
||||
CompositeOperation::Hue |
|
||||
CompositeOperation::Saturation |
|
||||
CompositeOperation::Color |
|
||||
CompositeOperation::Luminosity => None,
|
||||
CompositeOperation::SourceOver => BlendMode::SrcOver,
|
||||
CompositeOperation::SourceIn => BlendMode::SrcIn,
|
||||
CompositeOperation::SourceOut => BlendMode::SrcOut,
|
||||
CompositeOperation::DestinationIn => BlendMode::DestIn,
|
||||
CompositeOperation::DestinationAtop => BlendMode::DestAtop,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ pub const MAX_STEM_DARKENING_AMOUNT: [f32; 2] = [0.3, 0.3];
|
|||
pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0;
|
||||
|
||||
/// Effects that can be applied to a layer.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct Effects {
|
||||
/// The shader that should be used when compositing this layer onto its destination.
|
||||
pub filter: Filter,
|
||||
|
@ -38,11 +38,8 @@ pub struct Effects {
|
|||
/// The shader that should be used when compositing this layer onto its destination.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Filter {
|
||||
/// A Porter-Duff compositing operation.
|
||||
///
|
||||
/// The compositing operations here are the ones that can't be blend modes because they can
|
||||
/// clear parts of the destination not overlapped by the source, plus the regular source-over.
|
||||
Composite(CompositeOp),
|
||||
/// No special filter.
|
||||
None,
|
||||
|
||||
/// Performs postprocessing operations useful for monochrome text.
|
||||
Text {
|
||||
|
@ -68,61 +65,35 @@ pub enum Filter {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum CompositeOp {
|
||||
/// The default.
|
||||
SrcOver,
|
||||
/// No regions are enabled.
|
||||
Clear,
|
||||
/// Only the source will be present.
|
||||
Copy,
|
||||
/// The source that overlaps the destination replaces the destination.
|
||||
SrcIn,
|
||||
/// Destination which overlaps the source replaces the source.
|
||||
DestIn,
|
||||
/// Source is placed where it falls outside of the destination.
|
||||
SrcOut,
|
||||
/// Destination which overlaps the source replaces the source. Source is placed elsewhere.
|
||||
DestAtop,
|
||||
}
|
||||
|
||||
/// Blend modes that can be applied to individual paths.
|
||||
///
|
||||
/// All blend modes preserve parts of the destination that are not overlapped by the source path.
|
||||
/// Other Porter-Duff compositing operations are `CompositeOp`s.
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum BlendMode {
|
||||
// Supported by GPU blender
|
||||
// Porter-Duff, supported by GPU blender
|
||||
Clear,
|
||||
Copy,
|
||||
SrcIn,
|
||||
SrcOut,
|
||||
SrcOver,
|
||||
DestOver,
|
||||
DestOut,
|
||||
SrcAtop,
|
||||
DestIn,
|
||||
DestOut,
|
||||
DestOver,
|
||||
DestAtop,
|
||||
Xor,
|
||||
Lighter,
|
||||
Lighten,
|
||||
Darken,
|
||||
|
||||
// Overlay
|
||||
// Others, unsupported by GPU blender
|
||||
Darken,
|
||||
Lighten,
|
||||
Multiply,
|
||||
Screen,
|
||||
HardLight,
|
||||
Overlay,
|
||||
|
||||
// Dodge/burn
|
||||
ColorDodge,
|
||||
ColorBurn,
|
||||
|
||||
// Soft light
|
||||
SoftLight,
|
||||
|
||||
// Difference
|
||||
Difference,
|
||||
|
||||
// Exclusion
|
||||
Exclusion,
|
||||
|
||||
// HSL
|
||||
Hue,
|
||||
Saturation,
|
||||
Color,
|
||||
|
@ -138,13 +109,6 @@ pub enum BlurDirection {
|
|||
Y,
|
||||
}
|
||||
|
||||
impl Default for CompositeOp {
|
||||
#[inline]
|
||||
fn default() -> CompositeOp {
|
||||
CompositeOp::SrcOver
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BlendMode {
|
||||
#[inline]
|
||||
fn default() -> BlendMode {
|
||||
|
@ -152,6 +116,13 @@ impl Default for BlendMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for Filter {
|
||||
#[inline]
|
||||
fn default() -> Filter {
|
||||
Filter::None
|
||||
}
|
||||
}
|
||||
|
||||
impl Effects {
|
||||
#[inline]
|
||||
pub fn new(filter: Filter) -> Effects {
|
||||
|
@ -173,6 +144,44 @@ impl BlendMode {
|
|||
BlendMode::Lighter |
|
||||
BlendMode::Lighten |
|
||||
BlendMode::Darken |
|
||||
BlendMode::Copy |
|
||||
BlendMode::SrcIn |
|
||||
BlendMode::DestIn |
|
||||
BlendMode::SrcOut |
|
||||
BlendMode::DestAtop |
|
||||
BlendMode::Multiply |
|
||||
BlendMode::Screen |
|
||||
BlendMode::HardLight |
|
||||
BlendMode::Overlay |
|
||||
BlendMode::ColorDodge |
|
||||
BlendMode::ColorBurn |
|
||||
BlendMode::SoftLight |
|
||||
BlendMode::Difference |
|
||||
BlendMode::Exclusion |
|
||||
BlendMode::Hue |
|
||||
BlendMode::Saturation |
|
||||
BlendMode::Color |
|
||||
BlendMode::Luminosity => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// True if this blend mode does not preserve destination areas outside the source.
|
||||
pub fn is_destructive(self) -> bool {
|
||||
match self {
|
||||
BlendMode::Clear |
|
||||
BlendMode::Copy |
|
||||
BlendMode::SrcIn |
|
||||
BlendMode::DestIn |
|
||||
BlendMode::SrcOut |
|
||||
BlendMode::DestAtop => true,
|
||||
BlendMode::SrcOver |
|
||||
BlendMode::DestOver |
|
||||
BlendMode::DestOut |
|
||||
BlendMode::SrcAtop |
|
||||
BlendMode::Xor |
|
||||
BlendMode::Lighter |
|
||||
BlendMode::Lighten |
|
||||
BlendMode::Darken |
|
||||
BlendMode::Multiply |
|
||||
BlendMode::Screen |
|
||||
BlendMode::HardLight |
|
||||
|
|
|
@ -169,11 +169,24 @@ impl GLDevice {
|
|||
}
|
||||
}
|
||||
|
||||
// Workaround for a macOS driver bug, it seems.
|
||||
fn unset_uniform(&self, uniform: &GLUniform, data: &UniformData) {
|
||||
unsafe {
|
||||
match *data {
|
||||
UniformData::TextureUnit(_) => {
|
||||
gl::Uniform1i(uniform.location, 0); ck();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_render_state(&self, render_state: &RenderState<GLDevice>) {
|
||||
self.reset_render_options(&render_state.options);
|
||||
for texture_unit in 0..(render_state.textures.len() as u32) {
|
||||
self.unbind_texture(texture_unit);
|
||||
}
|
||||
render_state.uniforms.iter().for_each(|(uniform, data)| self.unset_uniform(uniform, data));
|
||||
self.unuse_program();
|
||||
self.unbind_vertex_array();
|
||||
}
|
||||
|
|
|
@ -11,21 +11,22 @@
|
|||
//! Packs data onto the GPU.
|
||||
|
||||
use crate::concurrent::executor::Executor;
|
||||
use crate::gpu::renderer::{BlendModeProgram, MASK_TILES_ACROSS};
|
||||
use crate::gpu_data::{AlphaTile, AlphaTileBatch, AlphaTileVertex, FillBatchPrimitive, MaskTile};
|
||||
use crate::gpu_data::{MaskTileVertex, RenderCommand, SolidTile, SolidTileBatch};
|
||||
use crate::gpu_data::{TexturePageId, TileObjectPrimitive};
|
||||
use crate::gpu::renderer::{BlendModeExt, MASK_TILES_ACROSS, MASK_TILES_DOWN};
|
||||
use crate::gpu_data::{FillBatchPrimitive, RenderCommand, TexturePageId, Tile, TileBatch};
|
||||
use crate::gpu_data::{TileBatchTexture, TileObjectPrimitive, TileVertex};
|
||||
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
||||
use crate::paint::{PaintInfo, PaintMetadata, RenderTargetMetadata};
|
||||
use crate::scene::{DisplayItem, Scene};
|
||||
use crate::tile_map::DenseTileMap;
|
||||
use crate::tiles::{self, DrawTilingPathInfo, TILE_HEIGHT, TILE_WIDTH, Tiler, TilingPathInfo};
|
||||
use crate::tiles::{self, DrawTilingPathInfo, PackedTile, TILE_HEIGHT, TILE_WIDTH};
|
||||
use crate::tiles::{Tiler, TilingPathInfo};
|
||||
use crate::z_buffer::{DepthMetadata, ZBuffer};
|
||||
use pathfinder_content::effects::BlendMode;
|
||||
use pathfinder_content::effects::{BlendMode, Effects, Filter};
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_content::render_target::RenderTargetId;
|
||||
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
|
||||
use pathfinder_geometry::rect::{RectF, RectI};
|
||||
use pathfinder_geometry::transform2d::Transform2F;
|
||||
use pathfinder_geometry::util;
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||
use pathfinder_gpu::TextureSamplingFlags;
|
||||
|
@ -39,7 +40,6 @@ pub(crate) struct SceneBuilder<'a> {
|
|||
built_options: &'a PreparedBuildOptions,
|
||||
|
||||
next_alpha_tile_index: AtomicUsize,
|
||||
next_mask_tile_index: AtomicUsize,
|
||||
|
||||
pub(crate) listener: Box<dyn RenderCommandListener>,
|
||||
}
|
||||
|
@ -55,21 +55,32 @@ pub(crate) struct ObjectBuilder {
|
|||
struct BuiltDrawPath {
|
||||
path: BuiltPath,
|
||||
blend_mode: BlendMode,
|
||||
sampling_flags: TextureSamplingFlags,
|
||||
color_texture_page: TexturePageId,
|
||||
color_texture_page_0: TexturePageId,
|
||||
color_texture_page_1: TexturePageId,
|
||||
sampling_flags_0: TextureSamplingFlags,
|
||||
sampling_flags_1: TextureSamplingFlags,
|
||||
mask_0_fill_rule: FillRule,
|
||||
mask_1_fill_rule: Option<FillRule>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct BuiltPath {
|
||||
pub mask_tiles: Vec<MaskTile>,
|
||||
pub alpha_tiles: Vec<AlphaTile>,
|
||||
pub solid_tiles: Vec<SolidTileInfo>,
|
||||
pub solid_tiles: SolidTiles,
|
||||
pub empty_tiles: Vec<Tile>,
|
||||
pub single_mask_tiles: Vec<Tile>,
|
||||
pub dual_mask_tiles: Vec<Tile>,
|
||||
pub tiles: DenseTileMap<TileObjectPrimitive>,
|
||||
pub fill_rule: FillRule,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum SolidTiles {
|
||||
Occluders(Vec<Occluder>),
|
||||
Regular(Vec<Tile>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(crate) struct SolidTileInfo {
|
||||
pub(crate) struct Occluder {
|
||||
pub(crate) coords: Vector2I,
|
||||
}
|
||||
|
||||
|
@ -82,10 +93,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
SceneBuilder {
|
||||
scene,
|
||||
built_options,
|
||||
|
||||
next_alpha_tile_index: AtomicUsize::new(0),
|
||||
next_mask_tile_index: AtomicUsize::new(0),
|
||||
|
||||
listener,
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +121,8 @@ impl<'a> SceneBuilder<'a> {
|
|||
render_commands,
|
||||
paint_metadata,
|
||||
render_target_metadata,
|
||||
opacity_tile_page,
|
||||
opacity_tile_transform,
|
||||
} = self.scene.build_paint_info();
|
||||
for render_command in render_commands {
|
||||
self.listener.send(render_command);
|
||||
|
@ -121,34 +131,37 @@ impl<'a> SceneBuilder<'a> {
|
|||
let effective_view_box = self.scene.effective_view_box(self.built_options);
|
||||
|
||||
let built_clip_paths = executor.build_vector(clip_path_count, |path_index| {
|
||||
self.build_clip_path(path_index, effective_view_box, &self.built_options, &self.scene)
|
||||
self.build_clip_path(PathBuildParams {
|
||||
path_index,
|
||||
view_box: effective_view_box,
|
||||
built_options: &self.built_options,
|
||||
scene: &self.scene,
|
||||
})
|
||||
});
|
||||
|
||||
let built_draw_paths = executor.build_vector(draw_path_count, |path_index| {
|
||||
self.build_draw_path(path_index,
|
||||
effective_view_box,
|
||||
&self.built_options,
|
||||
&self.scene,
|
||||
&paint_metadata,
|
||||
&built_clip_paths)
|
||||
self.build_draw_path(DrawPathBuildParams {
|
||||
path_build_params: PathBuildParams {
|
||||
path_index,
|
||||
view_box: effective_view_box,
|
||||
built_options: &self.built_options,
|
||||
scene: &self.scene,
|
||||
},
|
||||
paint_metadata: &paint_metadata,
|
||||
opacity_tile_page,
|
||||
opacity_tile_transform,
|
||||
built_clip_paths: &built_clip_paths,
|
||||
})
|
||||
});
|
||||
|
||||
self.finish_building(&paint_metadata,
|
||||
&render_target_metadata,
|
||||
built_clip_paths,
|
||||
built_draw_paths);
|
||||
self.finish_building(&paint_metadata, &render_target_metadata, built_draw_paths);
|
||||
|
||||
let build_time = Instant::now() - start_time;
|
||||
self.listener.send(RenderCommand::Finish { build_time });
|
||||
}
|
||||
|
||||
fn build_clip_path(
|
||||
&self,
|
||||
path_index: usize,
|
||||
view_box: RectF,
|
||||
built_options: &PreparedBuildOptions,
|
||||
scene: &Scene,
|
||||
) -> BuiltPath {
|
||||
fn build_clip_path(&self, params: PathBuildParams) -> BuiltPath {
|
||||
let PathBuildParams { path_index, view_box, built_options, scene } = params;
|
||||
let path_object = &scene.clip_paths[path_index];
|
||||
let outline = scene.apply_render_options(path_object.outline(), built_options);
|
||||
|
||||
|
@ -156,7 +169,6 @@ impl<'a> SceneBuilder<'a> {
|
|||
&outline,
|
||||
path_object.fill_rule(),
|
||||
view_box,
|
||||
path_index as u16,
|
||||
TilingPathInfo::Clip);
|
||||
|
||||
tiler.generate_tiles();
|
||||
|
@ -165,15 +177,15 @@ impl<'a> SceneBuilder<'a> {
|
|||
tiler.object_builder.built_path
|
||||
}
|
||||
|
||||
fn build_draw_path(
|
||||
&self,
|
||||
path_index: usize,
|
||||
view_box: RectF,
|
||||
built_options: &PreparedBuildOptions,
|
||||
scene: &Scene,
|
||||
paint_metadata: &[PaintMetadata],
|
||||
built_clip_paths: &[BuiltPath],
|
||||
) -> BuiltDrawPath {
|
||||
fn build_draw_path(&self, params: DrawPathBuildParams) -> BuiltDrawPath {
|
||||
let DrawPathBuildParams {
|
||||
path_build_params: PathBuildParams { path_index, view_box, built_options, scene },
|
||||
paint_metadata,
|
||||
opacity_tile_page,
|
||||
opacity_tile_transform,
|
||||
built_clip_paths,
|
||||
} = params;
|
||||
|
||||
let path_object = &scene.paths[path_index];
|
||||
let outline = scene.apply_render_options(path_object.outline(), built_options);
|
||||
|
||||
|
@ -186,9 +198,9 @@ impl<'a> SceneBuilder<'a> {
|
|||
&outline,
|
||||
path_object.fill_rule(),
|
||||
view_box,
|
||||
path_index as u16,
|
||||
TilingPathInfo::Draw(DrawTilingPathInfo {
|
||||
paint_metadata,
|
||||
opacity_tile_transform,
|
||||
blend_mode: path_object.blend_mode(),
|
||||
opacity: path_object.opacity(),
|
||||
built_clip_path,
|
||||
|
@ -201,26 +213,21 @@ impl<'a> SceneBuilder<'a> {
|
|||
BuiltDrawPath {
|
||||
path: tiler.object_builder.built_path,
|
||||
blend_mode: path_object.blend_mode(),
|
||||
color_texture_page: paint_metadata.location.page,
|
||||
sampling_flags: paint_metadata.sampling_flags,
|
||||
color_texture_page_0: paint_metadata.location.page,
|
||||
sampling_flags_0: paint_metadata.sampling_flags,
|
||||
color_texture_page_1: opacity_tile_page,
|
||||
sampling_flags_1: TextureSamplingFlags::empty(),
|
||||
mask_0_fill_rule: path_object.fill_rule(),
|
||||
mask_1_fill_rule: built_clip_path.map(|_| FillRule::Winding),
|
||||
}
|
||||
}
|
||||
|
||||
fn cull_tiles(&self,
|
||||
paint_metadata: &[PaintMetadata],
|
||||
render_target_metadata: &[RenderTargetMetadata],
|
||||
built_clip_paths: Vec<BuiltPath>,
|
||||
built_draw_paths: Vec<BuiltDrawPath>)
|
||||
-> CulledTiles {
|
||||
let mut culled_tiles = CulledTiles {
|
||||
mask_winding_tiles: vec![],
|
||||
mask_evenodd_tiles: vec![],
|
||||
display_list: vec![],
|
||||
};
|
||||
|
||||
for built_clip_path in built_clip_paths {
|
||||
culled_tiles.push_mask_tiles(&built_clip_path);
|
||||
}
|
||||
let mut culled_tiles = CulledTiles { display_list: vec![] };
|
||||
|
||||
let mut remaining_layer_z_buffers = self.build_solid_tiles(&built_draw_paths);
|
||||
remaining_layer_z_buffers.reverse();
|
||||
|
@ -229,7 +236,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
let first_z_buffer = remaining_layer_z_buffers.pop().unwrap();
|
||||
let first_solid_tiles = first_z_buffer.build_solid_tiles(paint_metadata);
|
||||
for batch in first_solid_tiles.batches {
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawTiles(batch));
|
||||
}
|
||||
|
||||
let mut layer_z_buffers_stack = vec![first_z_buffer];
|
||||
|
@ -244,7 +251,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
let z_buffer = remaining_layer_z_buffers.pop().unwrap();
|
||||
let solid_tiles = z_buffer.build_solid_tiles(paint_metadata);
|
||||
for batch in solid_tiles.batches {
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawTiles(batch));
|
||||
}
|
||||
layer_z_buffers_stack.push(z_buffer);
|
||||
}
|
||||
|
@ -271,16 +278,22 @@ impl<'a> SceneBuilder<'a> {
|
|||
let uv_rect =
|
||||
RectI::new(tile_coords, Vector2I::splat(1)).to_f32()
|
||||
.scale_xy(uv_scale);
|
||||
tiles.push(SolidTile::from_texture_rect(tile_coords, uv_rect));
|
||||
tiles.push(Tile::new_solid_from_texture_rect(tile_coords, uv_rect));
|
||||
}
|
||||
}
|
||||
let batch = SolidTileBatch {
|
||||
let batch = TileBatch {
|
||||
tiles,
|
||||
color_texture_page: metadata.location.page,
|
||||
color_texture_0: Some(TileBatchTexture {
|
||||
page: metadata.location.page,
|
||||
sampling_flags: TextureSamplingFlags::empty(),
|
||||
}),
|
||||
color_texture_1: None,
|
||||
effects,
|
||||
blend_mode: BlendMode::SrcOver,
|
||||
mask_0_fill_rule: None,
|
||||
mask_1_fill_rule: None,
|
||||
};
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawSolidTiles(batch));
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawTiles(batch));
|
||||
current_depth += 1;
|
||||
}
|
||||
|
||||
|
@ -290,55 +303,63 @@ impl<'a> SceneBuilder<'a> {
|
|||
} => {
|
||||
for draw_path_index in start_draw_path_index..end_draw_path_index {
|
||||
let built_draw_path = &built_draw_paths[draw_path_index as usize];
|
||||
culled_tiles.push_mask_tiles(&built_draw_path.path);
|
||||
|
||||
// Create a new `DrawAlphaTiles` display item if we don't have one or if we
|
||||
// have to break a batch due to blend mode or paint page. Note that every
|
||||
// path with a blend mode that requires a readable framebuffer needs its
|
||||
// own batch.
|
||||
//
|
||||
// TODO(pcwalton): If we really wanted to, we could use tile maps to avoid
|
||||
// batch breaks in some cases…
|
||||
match culled_tiles.display_list.last() {
|
||||
Some(&CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
||||
tiles: _,
|
||||
color_texture_page,
|
||||
blend_mode,
|
||||
sampling_flags
|
||||
})) if color_texture_page == built_draw_path.color_texture_page &&
|
||||
blend_mode == built_draw_path.blend_mode &&
|
||||
sampling_flags == built_draw_path.sampling_flags &&
|
||||
!BlendModeProgram::from_blend_mode(
|
||||
blend_mode).needs_readable_framebuffer() => {}
|
||||
_ => {
|
||||
let batch = AlphaTileBatch {
|
||||
tiles: vec![],
|
||||
color_texture_page: built_draw_path.color_texture_page,
|
||||
blend_mode: built_draw_path.blend_mode,
|
||||
sampling_flags: built_draw_path.sampling_flags,
|
||||
};
|
||||
culled_tiles.display_list
|
||||
.push(CulledDisplayItem::DrawAlphaTiles(batch))
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the destination alpha tiles buffer.
|
||||
let culled_alpha_tiles = match *culled_tiles.display_list
|
||||
.last_mut()
|
||||
.unwrap() {
|
||||
CulledDisplayItem::DrawAlphaTiles(AlphaTileBatch {
|
||||
tiles: ref mut culled_alpha_tiles,
|
||||
..
|
||||
}) => culled_alpha_tiles,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let layer_z_buffer = layer_z_buffers_stack.last().unwrap();
|
||||
for alpha_tile in &built_draw_path.path.alpha_tiles {
|
||||
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
||||
if layer_z_buffer.test(alpha_tile_coords, current_depth) {
|
||||
culled_alpha_tiles.push(*alpha_tile);
|
||||
let color_texture_0 = Some(TileBatchTexture {
|
||||
page: built_draw_path.color_texture_page_0,
|
||||
sampling_flags: built_draw_path.sampling_flags_0,
|
||||
});
|
||||
let color_texture_1 = Some(TileBatchTexture {
|
||||
page: built_draw_path.color_texture_page_1,
|
||||
sampling_flags: built_draw_path.sampling_flags_1,
|
||||
});
|
||||
|
||||
debug_assert!(built_draw_path.path.empty_tiles.is_empty() ||
|
||||
built_draw_path.blend_mode.is_destructive());
|
||||
self.add_alpha_tiles(&mut culled_tiles,
|
||||
layer_z_buffer,
|
||||
&built_draw_path.path.empty_tiles,
|
||||
current_depth,
|
||||
None,
|
||||
None,
|
||||
built_draw_path.blend_mode,
|
||||
None,
|
||||
None);
|
||||
|
||||
self.add_alpha_tiles(&mut culled_tiles,
|
||||
layer_z_buffer,
|
||||
&built_draw_path.path.single_mask_tiles,
|
||||
current_depth,
|
||||
color_texture_0,
|
||||
color_texture_1,
|
||||
built_draw_path.blend_mode,
|
||||
Some(built_draw_path.mask_0_fill_rule),
|
||||
None);
|
||||
|
||||
if let Some(mask_1_fill_rule) = built_draw_path.mask_1_fill_rule {
|
||||
self.add_alpha_tiles(&mut culled_tiles,
|
||||
layer_z_buffer,
|
||||
&built_draw_path.path.dual_mask_tiles,
|
||||
current_depth,
|
||||
color_texture_0,
|
||||
color_texture_1,
|
||||
built_draw_path.blend_mode,
|
||||
Some(built_draw_path.mask_0_fill_rule),
|
||||
Some(mask_1_fill_rule));
|
||||
}
|
||||
|
||||
match built_draw_path.path.solid_tiles {
|
||||
SolidTiles::Regular(ref tiles) => {
|
||||
self.add_alpha_tiles(&mut culled_tiles,
|
||||
layer_z_buffer,
|
||||
tiles,
|
||||
current_depth,
|
||||
color_texture_0,
|
||||
color_texture_1,
|
||||
built_draw_path.blend_mode,
|
||||
None,
|
||||
built_draw_path.mask_1_fill_rule);
|
||||
}
|
||||
SolidTiles::Occluders(_) => {}
|
||||
}
|
||||
|
||||
current_depth += 1;
|
||||
|
@ -354,7 +375,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
let effective_view_box = self.scene.effective_view_box(self.built_options);
|
||||
let mut z_buffers = vec![ZBuffer::new(effective_view_box)];
|
||||
let mut z_buffer_index_stack = vec![0];
|
||||
let mut current_depth = 0;
|
||||
let mut current_depth = 1;
|
||||
|
||||
// Create Z-buffers.
|
||||
for display_item in &self.scene.display_list {
|
||||
|
@ -371,11 +392,17 @@ impl<'a> SceneBuilder<'a> {
|
|||
let z_buffer = &mut z_buffers[*z_buffer_index_stack.last().unwrap()];
|
||||
for (path_subindex, built_draw_path) in
|
||||
built_draw_paths[start_index..end_index].iter().enumerate() {
|
||||
let solid_tiles = &built_draw_path.path.solid_tiles;
|
||||
let path_index = (path_subindex + start_index) as u32;
|
||||
let path = &self.scene.paths[path_index as usize];
|
||||
let metadata = DepthMetadata { paint_id: path.paint() };
|
||||
z_buffer.update(solid_tiles, current_depth, metadata);
|
||||
match built_draw_path.path.solid_tiles {
|
||||
SolidTiles::Regular(_) => {
|
||||
z_buffer.update(&[], current_depth, metadata);
|
||||
}
|
||||
SolidTiles::Occluders(ref occluders) => {
|
||||
z_buffer.update(occluders, current_depth, metadata);
|
||||
}
|
||||
}
|
||||
current_depth += 1;
|
||||
}
|
||||
}
|
||||
|
@ -390,27 +417,76 @@ impl<'a> SceneBuilder<'a> {
|
|||
z_buffers
|
||||
}
|
||||
|
||||
fn pack_tiles(&mut self, culled_tiles: CulledTiles) {
|
||||
if !culled_tiles.mask_winding_tiles.is_empty() {
|
||||
self.listener.send(RenderCommand::RenderMaskTiles {
|
||||
tiles: culled_tiles.mask_winding_tiles,
|
||||
fill_rule: FillRule::Winding,
|
||||
});
|
||||
}
|
||||
if !culled_tiles.mask_evenodd_tiles.is_empty() {
|
||||
self.listener.send(RenderCommand::RenderMaskTiles {
|
||||
tiles: culled_tiles.mask_evenodd_tiles,
|
||||
fill_rule: FillRule::EvenOdd,
|
||||
});
|
||||
fn add_alpha_tiles(&self,
|
||||
culled_tiles: &mut CulledTiles,
|
||||
layer_z_buffer: &ZBuffer,
|
||||
alpha_tiles: &[Tile],
|
||||
current_depth: u32,
|
||||
color_texture_0: Option<TileBatchTexture>,
|
||||
color_texture_1: Option<TileBatchTexture>,
|
||||
blend_mode: BlendMode,
|
||||
mask_0_fill_rule: Option<FillRule>,
|
||||
mask_1_fill_rule: Option<FillRule>) {
|
||||
if alpha_tiles.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new `DrawTiles` display item if we don't have one or if we have to break a
|
||||
// batch due to blend mode or paint page. Note that every path with a blend mode that
|
||||
// requires a readable framebuffer needs its own batch.
|
||||
//
|
||||
// TODO(pcwalton): If we really wanted to, we could use tile maps to avoid
|
||||
// batch breaks in some cases…
|
||||
match culled_tiles.display_list.last() {
|
||||
Some(&CulledDisplayItem::DrawTiles(TileBatch {
|
||||
tiles: _,
|
||||
color_texture_0: ref batch_color_texture_0,
|
||||
color_texture_1: ref batch_color_texture_1,
|
||||
blend_mode: batch_blend_mode,
|
||||
effects: Effects { filter: Filter::None },
|
||||
mask_0_fill_rule: batch_mask_0_fill_rule,
|
||||
mask_1_fill_rule: batch_mask_1_fill_rule,
|
||||
})) if *batch_color_texture_0 == color_texture_0 &&
|
||||
*batch_color_texture_1 == color_texture_1 &&
|
||||
batch_blend_mode == blend_mode &&
|
||||
batch_mask_0_fill_rule == mask_0_fill_rule &&
|
||||
batch_mask_1_fill_rule == mask_1_fill_rule &&
|
||||
!batch_blend_mode.needs_readable_framebuffer() => {}
|
||||
_ => {
|
||||
let batch = TileBatch {
|
||||
tiles: vec![],
|
||||
color_texture_0,
|
||||
color_texture_1,
|
||||
blend_mode,
|
||||
effects: Effects::default(),
|
||||
mask_0_fill_rule,
|
||||
mask_1_fill_rule,
|
||||
};
|
||||
culled_tiles.display_list.push(CulledDisplayItem::DrawTiles(batch))
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch the destination alpha tiles buffer.
|
||||
let culled_alpha_tiles = match *culled_tiles.display_list.last_mut().unwrap() {
|
||||
CulledDisplayItem::DrawTiles(TileBatch { tiles: ref mut culled_alpha_tiles, .. }) => {
|
||||
culled_alpha_tiles
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
for alpha_tile in alpha_tiles {
|
||||
let alpha_tile_coords = alpha_tile.upper_left.tile_position();
|
||||
if layer_z_buffer.test(alpha_tile_coords, current_depth) {
|
||||
culled_alpha_tiles.push(*alpha_tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pack_tiles(&mut self, culled_tiles: CulledTiles) {
|
||||
for display_item in culled_tiles.display_list {
|
||||
match display_item {
|
||||
CulledDisplayItem::DrawSolidTiles(batch) => {
|
||||
self.listener.send(RenderCommand::DrawSolidTiles(batch))
|
||||
}
|
||||
CulledDisplayItem::DrawAlphaTiles(batch) => {
|
||||
self.listener.send(RenderCommand::DrawAlphaTiles(batch))
|
||||
CulledDisplayItem::DrawTiles(batch) => {
|
||||
self.listener.send(RenderCommand::DrawTiles(batch))
|
||||
}
|
||||
CulledDisplayItem::PushRenderTarget(render_target_id) => {
|
||||
self.listener.send(RenderCommand::PushRenderTarget(render_target_id))
|
||||
|
@ -425,21 +501,14 @@ impl<'a> SceneBuilder<'a> {
|
|||
fn finish_building(&mut self,
|
||||
paint_metadata: &[PaintMetadata],
|
||||
render_target_metadata: &[RenderTargetMetadata],
|
||||
built_clip_paths: Vec<BuiltPath>,
|
||||
built_draw_paths: Vec<BuiltDrawPath>) {
|
||||
self.listener.send(RenderCommand::FlushFills);
|
||||
let culled_tiles = self.cull_tiles(paint_metadata,
|
||||
render_target_metadata,
|
||||
built_clip_paths,
|
||||
built_draw_paths);
|
||||
self.pack_tiles(culled_tiles);
|
||||
}
|
||||
|
||||
pub(crate) fn allocate_mask_tile_index(&self) -> u16 {
|
||||
// FIXME(pcwalton): Check for overflow!
|
||||
self.next_mask_tile_index.fetch_add(1, Ordering::Relaxed) as u16
|
||||
}
|
||||
|
||||
fn needs_readable_framebuffer(&self) -> bool {
|
||||
let mut framebuffer_nesting = 0;
|
||||
for display_item in &self.scene.display_list {
|
||||
|
@ -453,8 +522,7 @@ impl<'a> SceneBuilder<'a> {
|
|||
}
|
||||
for path_index in start_index..end_index {
|
||||
let blend_mode = self.scene.paths[path_index as usize].blend_mode();
|
||||
let blend_mode_program = BlendModeProgram::from_blend_mode(blend_mode);
|
||||
if blend_mode_program.needs_readable_framebuffer() {
|
||||
if blend_mode.needs_readable_framebuffer() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -465,34 +533,70 @@ impl<'a> SceneBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
struct PathBuildParams<'a> {
|
||||
path_index: usize,
|
||||
view_box: RectF,
|
||||
built_options: &'a PreparedBuildOptions,
|
||||
scene: &'a Scene,
|
||||
}
|
||||
|
||||
struct DrawPathBuildParams<'a> {
|
||||
path_build_params: PathBuildParams<'a>,
|
||||
paint_metadata: &'a [PaintMetadata],
|
||||
opacity_tile_page: TexturePageId,
|
||||
opacity_tile_transform: Transform2F,
|
||||
built_clip_paths: &'a [BuiltPath],
|
||||
}
|
||||
|
||||
impl BuiltPath {
|
||||
fn new(bounds: RectF, fill_rule: FillRule) -> BuiltPath {
|
||||
fn new(path_bounds: RectF,
|
||||
view_box_bounds: RectF,
|
||||
fill_rule: FillRule,
|
||||
tiling_path_info: &TilingPathInfo)
|
||||
-> BuiltPath {
|
||||
let occludes = match *tiling_path_info {
|
||||
TilingPathInfo::Draw(ref draw_tiling_path_info) => {
|
||||
draw_tiling_path_info.paint_metadata.is_opaque &&
|
||||
draw_tiling_path_info.blend_mode.occludes_backdrop() &&
|
||||
draw_tiling_path_info.opacity == !0
|
||||
}
|
||||
TilingPathInfo::Clip => true,
|
||||
};
|
||||
|
||||
let tile_map_bounds = if tiling_path_info.has_destructive_blend_mode() {
|
||||
view_box_bounds
|
||||
} else {
|
||||
path_bounds
|
||||
};
|
||||
|
||||
BuiltPath {
|
||||
mask_tiles: vec![],
|
||||
alpha_tiles: vec![],
|
||||
solid_tiles: vec![],
|
||||
tiles: DenseTileMap::new(tiles::round_rect_out_to_tile_bounds(bounds)),
|
||||
single_mask_tiles: vec![],
|
||||
dual_mask_tiles: vec![],
|
||||
empty_tiles: vec![],
|
||||
solid_tiles: if occludes {
|
||||
SolidTiles::Occluders(vec![])
|
||||
} else {
|
||||
SolidTiles::Regular(vec![])
|
||||
},
|
||||
tiles: DenseTileMap::new(tiles::round_rect_out_to_tile_bounds(tile_map_bounds)),
|
||||
fill_rule,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SolidTileInfo {
|
||||
impl Occluder {
|
||||
#[inline]
|
||||
pub(crate) fn new(coords: Vector2I) -> SolidTileInfo {
|
||||
SolidTileInfo { coords }
|
||||
pub(crate) fn new(coords: Vector2I) -> Occluder {
|
||||
Occluder { coords }
|
||||
}
|
||||
}
|
||||
|
||||
struct CulledTiles {
|
||||
mask_winding_tiles: Vec<MaskTile>,
|
||||
mask_evenodd_tiles: Vec<MaskTile>,
|
||||
display_list: Vec<CulledDisplayItem>,
|
||||
}
|
||||
|
||||
enum CulledDisplayItem {
|
||||
DrawSolidTiles(SolidTileBatch),
|
||||
DrawAlphaTiles(AlphaTileBatch),
|
||||
DrawTiles(TileBatch),
|
||||
PushRenderTarget(RenderTargetId),
|
||||
PopRenderTarget,
|
||||
}
|
||||
|
@ -506,8 +610,16 @@ pub struct TileStats {
|
|||
// Utilities for built objects
|
||||
|
||||
impl ObjectBuilder {
|
||||
pub(crate) fn new(bounds: RectF, fill_rule: FillRule) -> ObjectBuilder {
|
||||
ObjectBuilder { built_path: BuiltPath::new(bounds, fill_rule), bounds, fills: vec![] }
|
||||
pub(crate) fn new(path_bounds: RectF,
|
||||
view_box_bounds: RectF,
|
||||
fill_rule: FillRule,
|
||||
tiling_path_info: &TilingPathInfo)
|
||||
-> ObjectBuilder {
|
||||
ObjectBuilder {
|
||||
built_path: BuiltPath::new(path_bounds, view_box_bounds, fill_rule, tiling_path_info),
|
||||
bounds: path_bounds,
|
||||
fills: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -685,107 +797,81 @@ impl ObjectBuilder {
|
|||
pub(crate) fn local_tile_index_to_coords(&self, tile_index: u32) -> Vector2I {
|
||||
self.built_path.tiles.index_to_coords(tile_index as usize)
|
||||
}
|
||||
|
||||
pub(crate) fn push_mask_tile(mask_tiles: &mut Vec<MaskTile>,
|
||||
fill_tile: &TileObjectPrimitive,
|
||||
mask_tile_index: u16,
|
||||
object_index: u16) {
|
||||
mask_tiles.push(MaskTile {
|
||||
upper_left: MaskTileVertex::new(mask_tile_index,
|
||||
fill_tile.alpha_tile_index as u16,
|
||||
Vector2I::default(),
|
||||
object_index,
|
||||
fill_tile.backdrop as i16),
|
||||
upper_right: MaskTileVertex::new(mask_tile_index,
|
||||
fill_tile.alpha_tile_index as u16,
|
||||
Vector2I::new(1, 0),
|
||||
object_index,
|
||||
fill_tile.backdrop as i16),
|
||||
lower_left: MaskTileVertex::new(mask_tile_index,
|
||||
fill_tile.alpha_tile_index as u16,
|
||||
Vector2I::new(0, 1),
|
||||
object_index,
|
||||
fill_tile.backdrop as i16),
|
||||
lower_right: MaskTileVertex::new(mask_tile_index,
|
||||
fill_tile.alpha_tile_index as u16,
|
||||
Vector2I::splat(1),
|
||||
object_index,
|
||||
fill_tile.backdrop as i16),
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn push_alpha_tile(alpha_tiles: &mut Vec<AlphaTile>,
|
||||
mask_tile_index: u16,
|
||||
tile_coords: Vector2I,
|
||||
object_index: u16,
|
||||
impl<'a> PackedTile<'a> {
|
||||
pub(crate) fn add_to(&self,
|
||||
tiles: &mut Vec<Tile>,
|
||||
draw_tiling_path_info: &DrawTilingPathInfo) {
|
||||
alpha_tiles.push(AlphaTile {
|
||||
upper_left: AlphaTileVertex::new(tile_coords,
|
||||
mask_tile_index,
|
||||
let fill_tile_index = self.draw_tile.alpha_tile_index as u16;
|
||||
let fill_tile_backdrop = self.draw_tile.backdrop as i16;
|
||||
let (clip_tile_index, clip_tile_backdrop) = match self.clip_tile {
|
||||
None => (0, 0),
|
||||
Some(clip_tile) => (clip_tile.alpha_tile_index as u16, clip_tile.backdrop as i16),
|
||||
};
|
||||
|
||||
tiles.push(Tile {
|
||||
upper_left: TileVertex::new_alpha(self.tile_coords,
|
||||
fill_tile_index,
|
||||
fill_tile_backdrop,
|
||||
clip_tile_index,
|
||||
clip_tile_backdrop,
|
||||
Vector2I::default(),
|
||||
object_index,
|
||||
draw_tiling_path_info),
|
||||
upper_right: AlphaTileVertex::new(tile_coords,
|
||||
mask_tile_index,
|
||||
upper_right: TileVertex::new_alpha(self.tile_coords,
|
||||
fill_tile_index,
|
||||
fill_tile_backdrop,
|
||||
clip_tile_index,
|
||||
clip_tile_backdrop,
|
||||
Vector2I::new(1, 0),
|
||||
object_index,
|
||||
draw_tiling_path_info),
|
||||
lower_left: AlphaTileVertex::new(tile_coords,
|
||||
mask_tile_index,
|
||||
lower_left: TileVertex::new_alpha(self.tile_coords,
|
||||
fill_tile_index,
|
||||
fill_tile_backdrop,
|
||||
clip_tile_index,
|
||||
clip_tile_backdrop,
|
||||
Vector2I::new(0, 1),
|
||||
object_index,
|
||||
draw_tiling_path_info),
|
||||
lower_right: AlphaTileVertex::new(tile_coords,
|
||||
mask_tile_index,
|
||||
lower_right: TileVertex::new_alpha(self.tile_coords,
|
||||
fill_tile_index,
|
||||
fill_tile_backdrop,
|
||||
clip_tile_index,
|
||||
clip_tile_backdrop,
|
||||
Vector2I::splat(1),
|
||||
object_index,
|
||||
draw_tiling_path_info),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl MaskTileVertex {
|
||||
impl TileVertex {
|
||||
#[inline]
|
||||
fn new(mask_index: u16,
|
||||
fill_index: u16,
|
||||
fn new_alpha(tile_origin: Vector2I,
|
||||
draw_tile_index: u16,
|
||||
draw_tile_backdrop: i16,
|
||||
clip_tile_index: u16,
|
||||
clip_tile_backdrop: i16,
|
||||
tile_offset: Vector2I,
|
||||
object_index: u16,
|
||||
backdrop: i16)
|
||||
-> MaskTileVertex {
|
||||
let mask_uv = calculate_mask_uv(mask_index, tile_offset);
|
||||
let fill_uv = calculate_mask_uv(fill_index, tile_offset);
|
||||
MaskTileVertex {
|
||||
mask_u: mask_uv.x() as u16,
|
||||
mask_v: mask_uv.y() as u16,
|
||||
fill_u: fill_uv.x() as u16,
|
||||
fill_v: fill_uv.y() as u16,
|
||||
backdrop,
|
||||
object_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AlphaTileVertex {
|
||||
#[inline]
|
||||
fn new(tile_origin: Vector2I,
|
||||
tile_index: u16,
|
||||
tile_offset: Vector2I,
|
||||
object_index: u16,
|
||||
draw_tiling_path_info: &DrawTilingPathInfo)
|
||||
-> AlphaTileVertex {
|
||||
-> TileVertex {
|
||||
// TODO(pcwalton): Opacity.
|
||||
let tile_position = tile_origin + tile_offset;
|
||||
let color_uv = draw_tiling_path_info.paint_metadata.calculate_tex_coords(tile_position);
|
||||
let mask_uv = calculate_mask_uv(tile_index, tile_offset);
|
||||
AlphaTileVertex {
|
||||
let color_0_uv = draw_tiling_path_info.paint_metadata.calculate_tex_coords(tile_position);
|
||||
let color_1_uv = calculate_opacity_uv(draw_tiling_path_info);
|
||||
let mask_0_uv = calculate_mask_uv(draw_tile_index, tile_offset);
|
||||
let mask_1_uv = calculate_mask_uv(clip_tile_index, tile_offset);
|
||||
TileVertex {
|
||||
tile_x: tile_position.x() as i16,
|
||||
tile_y: tile_position.y() as i16,
|
||||
color_u: color_uv.x(),
|
||||
color_v: color_uv.y(),
|
||||
mask_u: mask_uv.x() as u16,
|
||||
mask_v: mask_uv.y() as u16,
|
||||
object_index,
|
||||
opacity: draw_tiling_path_info.opacity,
|
||||
pad: 0,
|
||||
color_0_u: color_0_uv.x(),
|
||||
color_0_v: color_0_uv.y(),
|
||||
color_1_u: color_1_uv.x(),
|
||||
color_1_v: color_1_uv.y(),
|
||||
mask_0_u: mask_0_uv.x(),
|
||||
mask_0_v: mask_0_uv.y(),
|
||||
mask_1_u: mask_1_uv.x(),
|
||||
mask_1_v: mask_1_uv.y(),
|
||||
mask_0_backdrop: draw_tile_backdrop,
|
||||
mask_1_backdrop: clip_tile_backdrop,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -795,19 +881,16 @@ impl AlphaTileVertex {
|
|||
}
|
||||
}
|
||||
|
||||
fn calculate_mask_uv(tile_index: u16, tile_offset: Vector2I) -> Vector2I {
|
||||
fn calculate_mask_uv(tile_index: u16, tile_offset: Vector2I) -> Vector2F {
|
||||
let mask_u = tile_index as i32 % MASK_TILES_ACROSS as i32;
|
||||
let mask_v = tile_index as i32 / MASK_TILES_ACROSS as i32;
|
||||
let mask_scale = 65535.0 / MASK_TILES_ACROSS as f32;
|
||||
let mask_uv = Vector2I::new(mask_u, mask_v) + tile_offset;
|
||||
mask_uv.to_f32().scale(mask_scale).to_i32()
|
||||
let scale = Vector2F::new(1.0 / MASK_TILES_ACROSS as f32, 1.0 / MASK_TILES_DOWN as f32);
|
||||
(Vector2I::new(mask_u, mask_v) + tile_offset).to_f32().scale_xy(scale)
|
||||
}
|
||||
|
||||
impl CulledTiles {
|
||||
fn push_mask_tiles(&mut self, built_path: &BuiltPath) {
|
||||
match built_path.fill_rule {
|
||||
FillRule::Winding => self.mask_winding_tiles.extend_from_slice(&built_path.mask_tiles),
|
||||
FillRule::EvenOdd => self.mask_evenodd_tiles.extend_from_slice(&built_path.mask_tiles),
|
||||
}
|
||||
}
|
||||
fn calculate_opacity_uv(draw_tiling_path_info: &DrawTilingPathInfo) -> Vector2F {
|
||||
let DrawTilingPathInfo { opacity_tile_transform, opacity, .. } = *draw_tiling_path_info;
|
||||
let texel_coord = (Vector2I::new((opacity % 16) as i32, (opacity / 16) as i32).to_f32() +
|
||||
Vector2F::splat(0.5)).scale(1.0 / 16.0);
|
||||
opacity_tile_transform * texel_coord
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -9,16 +9,13 @@
|
|||
// except according to those terms.
|
||||
|
||||
use crate::gpu_data::FillBatchPrimitive;
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_gpu::{BufferData, BufferTarget, BufferUploadMode, Device, VertexAttrClass};
|
||||
use pathfinder_gpu::{VertexAttrDescriptor, VertexAttrType};
|
||||
use pathfinder_resources::ResourceLoader;
|
||||
|
||||
// TODO(pcwalton): Replace with `mem::size_of` calls?
|
||||
const FILL_INSTANCE_SIZE: usize = 8;
|
||||
const SOLID_TILE_VERTEX_SIZE: usize = 12;
|
||||
const ALPHA_TILE_VERTEX_SIZE: usize = 20;
|
||||
const MASK_TILE_VERTEX_SIZE: usize = 12;
|
||||
const TILE_VERTEX_SIZE: usize = 40;
|
||||
|
||||
pub const MAX_FILLS_PER_BATCH: usize = 0x4000;
|
||||
|
||||
|
@ -150,173 +147,93 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MaskTileVertexArray<D> where D: Device {
|
||||
pub struct TileVertexArray<D> where D: Device {
|
||||
pub vertex_array: D::VertexArray,
|
||||
pub vertex_buffer: D::Buffer,
|
||||
}
|
||||
|
||||
impl<D> MaskTileVertexArray<D> where D: Device {
|
||||
impl<D> TileVertexArray<D> where D: Device {
|
||||
pub fn new(device: &D,
|
||||
mask_tile_program: &MaskTileProgram<D>,
|
||||
tile_program: &TileProgram<D>,
|
||||
tile_vertex_buffer: &D::Buffer,
|
||||
quads_vertex_indices_buffer: &D::Buffer)
|
||||
-> MaskTileVertexArray<D> {
|
||||
let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer());
|
||||
|
||||
let position_attr = device.get_vertex_attr(&mask_tile_program.program, "Position")
|
||||
.unwrap();
|
||||
let fill_tex_coord_attr = device.get_vertex_attr(&mask_tile_program.program,
|
||||
"FillTexCoord").unwrap();
|
||||
let backdrop_attr = device.get_vertex_attr(&mask_tile_program.program, "Backdrop")
|
||||
.unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, &vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &fill_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U16,
|
||||
stride: MASK_TILE_VERTEX_SIZE,
|
||||
offset: 4,
|
||||
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: 8,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
MaskTileVertexArray { vertex_array, vertex_buffer }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileVertexArray<D> where D: Device {
|
||||
pub vertex_array: D::VertexArray,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileVertexArray<D> where D: Device {
|
||||
pub fn new(
|
||||
device: &D,
|
||||
alpha_tile_program: &AlphaTileProgram<D>,
|
||||
alpha_tile_vertex_buffer: &D::Buffer,
|
||||
quads_vertex_indices_buffer: &D::Buffer,
|
||||
) -> AlphaTileVertexArray<D> {
|
||||
-> TileVertexArray<D> {
|
||||
let vertex_array = device.create_vertex_array();
|
||||
|
||||
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();
|
||||
let opacity_attr = device.get_vertex_attr(&alpha_tile_program.program, "Opacity").unwrap();
|
||||
device.get_vertex_attr(&tile_program.program, "TilePosition").unwrap();
|
||||
let color_0_tex_coord_attr =
|
||||
device.get_vertex_attr(&tile_program.program, "ColorTexCoord0").unwrap();
|
||||
let color_1_tex_coord_attr =
|
||||
device.get_vertex_attr(&tile_program.program, "ColorTexCoord1").unwrap();
|
||||
let mask_0_tex_coord_attr =
|
||||
device.get_vertex_attr(&tile_program.program, "MaskTexCoord0").unwrap();
|
||||
let mask_1_tex_coord_attr =
|
||||
device.get_vertex_attr(&tile_program.program, "MaskTexCoord1").unwrap();
|
||||
let mask_backdrop_attr =
|
||||
device.get_vertex_attr(&tile_program.program, "MaskBackdrop").unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, alpha_tile_vertex_buffer, BufferTarget::Vertex);
|
||||
device.bind_buffer(&vertex_array, tile_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::Float,
|
||||
attr_type: VertexAttrType::F32,
|
||||
stride: ALPHA_TILE_VERTEX_SIZE,
|
||||
offset: 8,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &opacity_attr, &VertexAttrDescriptor {
|
||||
size: 1,
|
||||
class: VertexAttrClass::FloatNorm,
|
||||
attr_type: VertexAttrType::U8,
|
||||
stride: ALPHA_TILE_VERTEX_SIZE,
|
||||
offset: 18,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
AlphaTileVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SolidTileVertexArray<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub vertex_array: D::VertexArray,
|
||||
}
|
||||
|
||||
impl<D> SolidTileVertexArray<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub fn new(
|
||||
device: &D,
|
||||
solid_tile_program: &SolidTileProgram<D>,
|
||||
solid_tile_vertex_buffer: &D::Buffer,
|
||||
quads_vertex_indices_buffer: &D::Buffer,
|
||||
) -> SolidTileVertexArray<D> {
|
||||
let vertex_array = device.create_vertex_array();
|
||||
|
||||
let tile_position_attr =
|
||||
device.get_vertex_attr(&solid_tile_program.program, "TilePosition").unwrap();
|
||||
let color_tex_coord_attr =
|
||||
device.get_vertex_attr(&solid_tile_program.program, "ColorTexCoord").unwrap();
|
||||
|
||||
// NB: The tile origin must be of type short, not unsigned short, to work around a macOS
|
||||
// Radeon driver bug.
|
||||
device.bind_buffer(&vertex_array, solid_tile_vertex_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &tile_position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: SOLID_TILE_VERTEX_SIZE,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array,
|
||||
&color_tex_coord_attr,
|
||||
&color_0_tex_coord_attr,
|
||||
&VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Float,
|
||||
attr_type: VertexAttrType::F32,
|
||||
stride: SOLID_TILE_VERTEX_SIZE,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 4,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array,
|
||||
&color_1_tex_coord_attr,
|
||||
&VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Float,
|
||||
attr_type: VertexAttrType::F32,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 12,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &mask_0_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Float,
|
||||
attr_type: VertexAttrType::F32,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 20,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &mask_1_tex_coord_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Float,
|
||||
attr_type: VertexAttrType::F32,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 28,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.configure_vertex_attr(&vertex_array, &mask_backdrop_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 36,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.bind_buffer(&vertex_array, quads_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
SolidTileVertexArray { vertex_array }
|
||||
TileVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,7 +258,7 @@ impl<D> CopyTileVertexArray<D> where D: Device {
|
|||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: ALPHA_TILE_VERTEX_SIZE,
|
||||
stride: TILE_VERTEX_SIZE,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
|
@ -393,90 +310,57 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MaskTileProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub fill_texture_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> MaskTileProgram<D> where D: Device {
|
||||
pub fn new(fill_rule: FillRule, device: &D, resources: &dyn ResourceLoader)
|
||||
-> MaskTileProgram<D> {
|
||||
let program_name = match fill_rule {
|
||||
FillRule::Winding => "mask_winding",
|
||||
FillRule::EvenOdd => "mask_evenodd",
|
||||
};
|
||||
|
||||
let program = device.create_program_from_shader_names(resources,
|
||||
program_name,
|
||||
"mask",
|
||||
program_name);
|
||||
|
||||
let fill_texture_uniform = device.get_uniform(&program, "FillTexture");
|
||||
MaskTileProgram { program, fill_texture_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SolidTileProgram<D> where D: Device {
|
||||
pub struct TileProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub transform_uniform: D::Uniform,
|
||||
pub tile_size_uniform: D::Uniform,
|
||||
pub color_texture_uniform: D::Uniform,
|
||||
pub dest_texture_uniform: D::Uniform,
|
||||
pub color_texture_0_uniform: D::Uniform,
|
||||
pub color_texture_1_uniform: D::Uniform,
|
||||
pub mask_texture_0_uniform: D::Uniform,
|
||||
pub mask_texture_1_uniform: D::Uniform,
|
||||
pub gamma_lut_uniform: D::Uniform,
|
||||
pub color_texture_0_size_uniform: D::Uniform,
|
||||
pub filter_params_0_uniform: D::Uniform,
|
||||
pub filter_params_1_uniform: D::Uniform,
|
||||
pub filter_params_2_uniform: D::Uniform,
|
||||
pub dest_texture_size_uniform: D::Uniform,
|
||||
pub ctrl_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> SolidTileProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader, program_name: &str)
|
||||
-> SolidTileProgram<D> {
|
||||
let program = device.create_program_from_shader_names(resources,
|
||||
program_name,
|
||||
"tile_solid",
|
||||
program_name);
|
||||
impl<D> TileProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> TileProgram<D> {
|
||||
let program = device.create_program(resources, "tile");
|
||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||
let color_texture_uniform = device.get_uniform(&program, "ColorTexture");
|
||||
SolidTileProgram {
|
||||
let dest_texture_uniform = device.get_uniform(&program, "DestTexture");
|
||||
let color_texture_0_uniform = device.get_uniform(&program, "ColorTexture0");
|
||||
let color_texture_1_uniform = device.get_uniform(&program, "ColorTexture1");
|
||||
let mask_texture_0_uniform = device.get_uniform(&program, "MaskTexture0");
|
||||
let mask_texture_1_uniform = device.get_uniform(&program, "MaskTexture1");
|
||||
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
|
||||
let color_texture_0_size_uniform = device.get_uniform(&program, "ColorTexture0Size");
|
||||
let filter_params_0_uniform = device.get_uniform(&program, "FilterParams0");
|
||||
let filter_params_1_uniform = device.get_uniform(&program, "FilterParams1");
|
||||
let filter_params_2_uniform = device.get_uniform(&program, "FilterParams2");
|
||||
let dest_texture_size_uniform = device.get_uniform(&program, "DestTextureSize");
|
||||
let ctrl_uniform = device.get_uniform(&program, "Ctrl");
|
||||
TileProgram {
|
||||
program,
|
||||
transform_uniform,
|
||||
tile_size_uniform,
|
||||
color_texture_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub transform_uniform: D::Uniform,
|
||||
pub tile_size_uniform: D::Uniform,
|
||||
pub framebuffer_size_uniform: D::Uniform,
|
||||
pub stencil_texture_uniform: D::Uniform,
|
||||
pub paint_texture_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileProgram<D> where D: Device {
|
||||
#[inline]
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileProgram<D> {
|
||||
AlphaTileProgram::from_fragment_shader_name(device, resources, "tile_alpha")
|
||||
}
|
||||
|
||||
fn from_fragment_shader_name(device: &D,
|
||||
resources: &dyn ResourceLoader,
|
||||
fragment_shader_name: &str)
|
||||
-> AlphaTileProgram<D> {
|
||||
let program = device.create_program_from_shader_names(resources,
|
||||
fragment_shader_name,
|
||||
"tile_alpha",
|
||||
fragment_shader_name);
|
||||
let transform_uniform = device.get_uniform(&program, "Transform");
|
||||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let stencil_texture_uniform = device.get_uniform(&program, "StencilTexture");
|
||||
let paint_texture_uniform = device.get_uniform(&program, "PaintTexture");
|
||||
AlphaTileProgram {
|
||||
program,
|
||||
transform_uniform,
|
||||
tile_size_uniform,
|
||||
framebuffer_size_uniform,
|
||||
stencil_texture_uniform,
|
||||
paint_texture_uniform,
|
||||
dest_texture_uniform,
|
||||
color_texture_0_uniform,
|
||||
color_texture_1_uniform,
|
||||
mask_texture_0_uniform,
|
||||
mask_texture_1_uniform,
|
||||
gamma_lut_uniform,
|
||||
color_texture_0_size_uniform,
|
||||
filter_params_0_uniform,
|
||||
filter_params_1_uniform,
|
||||
filter_params_2_uniform,
|
||||
dest_texture_size_uniform,
|
||||
ctrl_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -506,126 +390,6 @@ impl<D> CopyTileProgram<D> where D: Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileBlendModeProgram<D> where D: Device {
|
||||
pub alpha_tile_program: AlphaTileProgram<D>,
|
||||
pub dest_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileBlendModeProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader, name: &str)
|
||||
-> AlphaTileBlendModeProgram<D> {
|
||||
let alpha_tile_program =
|
||||
AlphaTileProgram::from_fragment_shader_name(device, resources, name);
|
||||
let dest_uniform = device.get_uniform(&alpha_tile_program.program, "Dest");
|
||||
AlphaTileBlendModeProgram { alpha_tile_program, dest_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileHSLProgram<D> where D: Device {
|
||||
pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram<D>,
|
||||
pub blend_hsl_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileHSLProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileHSLProgram<D> {
|
||||
let alpha_tile_blend_mode_program =
|
||||
AlphaTileBlendModeProgram::new(device, resources, "tile_alpha_hsl");
|
||||
let blend_hsl_uniform =
|
||||
device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program,
|
||||
"BlendHSL");
|
||||
AlphaTileHSLProgram { alpha_tile_blend_mode_program, blend_hsl_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileOverlayProgram<D> where D: Device {
|
||||
pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram<D>,
|
||||
pub blend_mode_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileOverlayProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileOverlayProgram<D> {
|
||||
let alpha_tile_blend_mode_program = AlphaTileBlendModeProgram::new(device,
|
||||
resources,
|
||||
"tile_alpha_overlay");
|
||||
let blend_mode_uniform =
|
||||
device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program,
|
||||
"BlendMode");
|
||||
AlphaTileOverlayProgram { alpha_tile_blend_mode_program, blend_mode_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AlphaTileDodgeBurnProgram<D> where D: Device {
|
||||
pub alpha_tile_blend_mode_program: AlphaTileBlendModeProgram<D>,
|
||||
pub burn_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> AlphaTileDodgeBurnProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileDodgeBurnProgram<D> {
|
||||
let alpha_tile_blend_mode_program =
|
||||
AlphaTileBlendModeProgram::new(device, resources, "tile_alpha_dodgeburn");
|
||||
let burn_uniform =
|
||||
device.get_uniform(&alpha_tile_blend_mode_program.alpha_tile_program.program, "Burn");
|
||||
AlphaTileDodgeBurnProgram { alpha_tile_blend_mode_program, burn_uniform }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SolidTileBlurFilterProgram<D> where D: Device {
|
||||
pub solid_tile_program: SolidTileProgram<D>,
|
||||
pub src_offset_scale_uniform: D::Uniform,
|
||||
pub initial_gauss_coeff_uniform: D::Uniform,
|
||||
pub support_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> SolidTileBlurFilterProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileBlurFilterProgram<D> {
|
||||
let solid_tile_program = SolidTileProgram::new(device,
|
||||
resources,
|
||||
"tile_solid_filter_blur");
|
||||
let src_offset_scale_uniform = device.get_uniform(&solid_tile_program.program,
|
||||
"SrcOffsetScale");
|
||||
let initial_gauss_coeff_uniform = device.get_uniform(&solid_tile_program.program,
|
||||
"InitialGaussCoeff");
|
||||
let support_uniform = device.get_uniform(&solid_tile_program.program, "Support");
|
||||
SolidTileBlurFilterProgram {
|
||||
solid_tile_program,
|
||||
src_offset_scale_uniform,
|
||||
initial_gauss_coeff_uniform,
|
||||
support_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SolidTileTextFilterProgram<D> where D: Device {
|
||||
pub solid_tile_program: SolidTileProgram<D>,
|
||||
pub kernel_uniform: D::Uniform,
|
||||
pub gamma_lut_uniform: D::Uniform,
|
||||
pub gamma_correction_enabled_uniform: D::Uniform,
|
||||
pub fg_color_uniform: D::Uniform,
|
||||
pub bg_color_uniform: D::Uniform,
|
||||
}
|
||||
|
||||
impl<D> SolidTileTextFilterProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileTextFilterProgram<D> {
|
||||
let solid_tile_program = SolidTileProgram::new(device,
|
||||
resources,
|
||||
"tile_solid_filter_text");
|
||||
let kernel_uniform = device.get_uniform(&solid_tile_program.program, "Kernel");
|
||||
let gamma_lut_uniform = device.get_uniform(&solid_tile_program.program, "GammaLUT");
|
||||
let gamma_correction_enabled_uniform = device.get_uniform(&solid_tile_program.program,
|
||||
"GammaCorrectionEnabled");
|
||||
let fg_color_uniform = device.get_uniform(&solid_tile_program.program, "FGColor");
|
||||
let bg_color_uniform = device.get_uniform(&solid_tile_program.program, "BGColor");
|
||||
SolidTileTextFilterProgram {
|
||||
solid_tile_program,
|
||||
kernel_uniform,
|
||||
gamma_lut_uniform,
|
||||
gamma_correction_enabled_uniform,
|
||||
fg_color_uniform,
|
||||
bg_color_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StencilProgram<D>
|
||||
where
|
||||
D: Device,
|
||||
|
|
|
@ -55,9 +55,6 @@ pub enum RenderCommand {
|
|||
// Flushes the queue of fills.
|
||||
FlushFills,
|
||||
|
||||
// Render fills to a set of mask tiles.
|
||||
RenderMaskTiles { tiles: Vec<MaskTile>, fill_rule: FillRule },
|
||||
|
||||
// Pushes a render target onto the stack. Draw commands go to the render target on top of the
|
||||
// stack.
|
||||
PushRenderTarget(RenderTargetId),
|
||||
|
@ -65,11 +62,8 @@ pub enum RenderCommand {
|
|||
// Pops a render target from the stack.
|
||||
PopRenderTarget,
|
||||
|
||||
// Draws a batch of alpha tiles to the render target on top of the stack.
|
||||
DrawAlphaTiles(AlphaTileBatch),
|
||||
|
||||
// Draws a batch of solid tiles to the render target on top of the stack.
|
||||
DrawSolidTiles(SolidTileBatch),
|
||||
// Draws a batch of tiles to the render target on top of the stack.
|
||||
DrawTiles(TileBatch),
|
||||
|
||||
// Presents a rendered frame.
|
||||
Finish { build_time: Duration },
|
||||
|
@ -90,19 +84,20 @@ pub struct TextureLocation {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AlphaTileBatch {
|
||||
pub tiles: Vec<AlphaTile>,
|
||||
pub color_texture_page: TexturePageId,
|
||||
pub struct TileBatch {
|
||||
pub tiles: Vec<Tile>,
|
||||
pub color_texture_0: Option<TileBatchTexture>,
|
||||
pub color_texture_1: Option<TileBatchTexture>,
|
||||
pub mask_0_fill_rule: Option<FillRule>,
|
||||
pub mask_1_fill_rule: Option<FillRule>,
|
||||
pub blend_mode: BlendMode,
|
||||
pub sampling_flags: TextureSamplingFlags,
|
||||
pub effects: Effects,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SolidTileBatch {
|
||||
pub tiles: Vec<SolidTile>,
|
||||
pub color_texture_page: TexturePageId,
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct TileBatchTexture {
|
||||
pub page: TexturePageId,
|
||||
pub sampling_flags: TextureSamplingFlags,
|
||||
pub effects: Effects,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -132,63 +127,28 @@ pub struct FillBatchPrimitive {
|
|||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct SolidTileVertex {
|
||||
pub struct Tile {
|
||||
pub upper_left: TileVertex,
|
||||
pub upper_right: TileVertex,
|
||||
pub lower_left: TileVertex,
|
||||
pub lower_right: TileVertex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct TileVertex {
|
||||
pub tile_x: i16,
|
||||
pub tile_y: i16,
|
||||
pub color_u: f32,
|
||||
pub color_v: f32,
|
||||
}
|
||||
|
||||
#[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 {
|
||||
pub upper_left: AlphaTileVertex,
|
||||
pub upper_right: AlphaTileVertex,
|
||||
pub lower_left: AlphaTileVertex,
|
||||
pub lower_right: AlphaTileVertex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct SolidTile {
|
||||
pub upper_left: SolidTileVertex,
|
||||
pub upper_right: SolidTileVertex,
|
||||
pub lower_left: SolidTileVertex,
|
||||
pub lower_right: SolidTileVertex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct MaskTileVertex {
|
||||
pub mask_u: u16,
|
||||
pub mask_v: u16,
|
||||
pub fill_u: u16,
|
||||
pub fill_v: u16,
|
||||
pub backdrop: i16,
|
||||
pub object_index: u16,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[repr(C)]
|
||||
pub struct AlphaTileVertex {
|
||||
pub tile_x: i16,
|
||||
pub tile_y: i16,
|
||||
pub mask_u: u16,
|
||||
pub mask_v: u16,
|
||||
pub color_u: f32,
|
||||
pub color_v: f32,
|
||||
pub object_index: u16,
|
||||
pub opacity: u8,
|
||||
pub pad: u8,
|
||||
pub color_0_u: f32,
|
||||
pub color_0_v: f32,
|
||||
pub color_1_u: f32,
|
||||
pub color_1_v: f32,
|
||||
pub mask_0_u: f32,
|
||||
pub mask_0_v: f32,
|
||||
pub mask_1_u: f32,
|
||||
pub mask_1_v: f32,
|
||||
pub mask_0_backdrop: i16,
|
||||
pub mask_1_backdrop: i16,
|
||||
}
|
||||
|
||||
impl Debug for RenderCommand {
|
||||
|
@ -199,34 +159,25 @@ impl Debug for RenderCommand {
|
|||
write!(formatter, "AllocateTexturePages(x{})", pages.len())
|
||||
}
|
||||
RenderCommand::UploadTexelData { ref texels, location } => {
|
||||
write!(formatter, "UploadTexelData({:?}, {:?})", texels, location)
|
||||
write!(formatter, "UploadTexelData(x{:?}, {:?})", texels.len(), location)
|
||||
}
|
||||
RenderCommand::DeclareRenderTarget { id, location } => {
|
||||
write!(formatter, "DeclareRenderTarget({:?}, {:?})", id, location)
|
||||
}
|
||||
RenderCommand::AddFills(ref fills) => write!(formatter, "AddFills(x{})", fills.len()),
|
||||
RenderCommand::FlushFills => write!(formatter, "FlushFills"),
|
||||
RenderCommand::RenderMaskTiles { ref tiles, fill_rule } => {
|
||||
write!(formatter, "RenderMaskTiles(x{}, {:?})", tiles.len(), fill_rule)
|
||||
}
|
||||
RenderCommand::PushRenderTarget(render_target_id) => {
|
||||
write!(formatter, "PushRenderTarget({:?})", render_target_id)
|
||||
}
|
||||
RenderCommand::PopRenderTarget => write!(formatter, "PopRenderTarget"),
|
||||
RenderCommand::DrawAlphaTiles(ref batch) => {
|
||||
RenderCommand::DrawTiles(ref batch) => {
|
||||
write!(formatter,
|
||||
"DrawAlphaTiles(x{}, {:?}, {:?}, {:?})",
|
||||
"DrawTiles(x{}, C0 {:?}, C1 {:?}, M0 {:?}, {:?})",
|
||||
batch.tiles.len(),
|
||||
batch.color_texture_page,
|
||||
batch.blend_mode,
|
||||
batch.sampling_flags)
|
||||
}
|
||||
RenderCommand::DrawSolidTiles(ref batch) => {
|
||||
write!(formatter,
|
||||
"DrawSolidTiles(x{}, {:?}, {:?})",
|
||||
batch.tiles.len(),
|
||||
batch.color_texture_page,
|
||||
batch.sampling_flags)
|
||||
batch.color_texture_0,
|
||||
batch.color_texture_1,
|
||||
batch.mask_0_fill_rule,
|
||||
batch.blend_mode)
|
||||
}
|
||||
RenderCommand::Finish { .. } => write!(formatter, "Finish"),
|
||||
}
|
||||
|
|
|
@ -161,6 +161,10 @@ pub struct PaintInfo {
|
|||
///
|
||||
/// The indices of this vector are render target IDs.
|
||||
pub render_target_metadata: Vec<RenderTargetMetadata>,
|
||||
/// The page containing the opacity tile.
|
||||
pub opacity_tile_page: TexturePageId,
|
||||
/// The transform for the opacity tile.
|
||||
pub opacity_tile_transform: Transform2F,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -212,6 +216,7 @@ impl Palette {
|
|||
}
|
||||
|
||||
// Assign paint locations.
|
||||
let opacity_tile_builder = OpacityTileBuilder::new(&mut allocator);
|
||||
let mut solid_color_tile_builder = SolidColorTileBuilder::new();
|
||||
let mut gradient_tile_builder = GradientTileBuilder::new();
|
||||
for paint in &self.paints {
|
||||
|
@ -344,6 +349,7 @@ impl Palette {
|
|||
// Draw to texels.
|
||||
//
|
||||
// TODO(pcwalton): Do more of this on GPU.
|
||||
opacity_tile_builder.render(&mut page_texels);
|
||||
for (paint, metadata) in self.paints.iter().zip(paint_metadata.iter()) {
|
||||
let texture_page = metadata.location.page;
|
||||
let texels = &mut page_texels[texture_page.0 as usize];
|
||||
|
@ -392,7 +398,13 @@ impl Palette {
|
|||
}
|
||||
}
|
||||
|
||||
PaintInfo { render_commands, paint_metadata, render_target_metadata }
|
||||
PaintInfo {
|
||||
render_commands,
|
||||
paint_metadata,
|
||||
render_target_metadata,
|
||||
opacity_tile_page: opacity_tile_builder.tile_location.page,
|
||||
opacity_tile_transform: opacity_tile_builder.tile_transform(&allocator),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(pcwalton): This is slow. Do on GPU instead.
|
||||
|
@ -599,6 +611,38 @@ fn rect_to_inset_uv(rect: RectI, texture_scale: Vector2F) -> RectF {
|
|||
rect_to_uv(rect, texture_scale).contract(texture_scale.scale(0.5))
|
||||
}
|
||||
|
||||
// Opacity allocation
|
||||
|
||||
struct OpacityTileBuilder {
|
||||
tile_location: TextureLocation,
|
||||
}
|
||||
|
||||
impl OpacityTileBuilder {
|
||||
fn new(allocator: &mut TextureAllocator) -> OpacityTileBuilder {
|
||||
OpacityTileBuilder {
|
||||
tile_location: allocator.allocate(Vector2I::splat(16), AllocationMode::Atlas),
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&self, page_texels: &mut [Texels]) {
|
||||
let texels = &mut page_texels[self.tile_location.page.0 as usize];
|
||||
for y in 0..16 {
|
||||
for x in 0..16 {
|
||||
let color = ColorU::new(0xff, 0xff, 0xff, y * 16 + x);
|
||||
let coords = self.tile_location.rect.origin() + Vector2I::new(x as i32, y as i32);
|
||||
texels.put_texel(coords, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tile_transform(&self, allocator: &TextureAllocator) -> Transform2F {
|
||||
let texture_scale = allocator.page_scale(self.tile_location.page);
|
||||
let matrix = Matrix2x2F::from_scale(texture_scale.scale(16.0));
|
||||
let vector = rect_to_uv(self.tile_location.rect, texture_scale).origin();
|
||||
Transform2F { matrix, vector }
|
||||
}
|
||||
}
|
||||
|
||||
// Solid color allocation
|
||||
|
||||
struct SolidColorTileBuilder(Option<SolidColorTileBuilderData>);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use crate::builder::{BuiltPath, ObjectBuilder, SceneBuilder, SolidTileInfo};
|
||||
use crate::builder::{BuiltPath, ObjectBuilder, Occluder, SceneBuilder, SolidTiles};
|
||||
use crate::gpu_data::TileObjectPrimitive;
|
||||
use crate::paint::PaintMetadata;
|
||||
use pathfinder_content::effects::BlendMode;
|
||||
|
@ -18,6 +18,7 @@ use pathfinder_content::segment::Segment;
|
|||
use pathfinder_content::sorted_vector::SortedVector;
|
||||
use pathfinder_geometry::line_segment::LineSegment2F;
|
||||
use pathfinder_geometry::rect::{RectF, RectI};
|
||||
use pathfinder_geometry::transform2d::Transform2F;
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||
use std::cmp::Ordering;
|
||||
use std::mem;
|
||||
|
@ -33,7 +34,6 @@ pub(crate) struct Tiler<'a> {
|
|||
pub(crate) object_builder: ObjectBuilder,
|
||||
outline: &'a Outline,
|
||||
path_info: TilingPathInfo<'a>,
|
||||
object_index: u16,
|
||||
|
||||
point_queue: SortedVector<QueuedEndpoint>,
|
||||
active_edges: SortedVector<ActiveEdge>,
|
||||
|
@ -49,6 +49,7 @@ pub(crate) enum TilingPathInfo<'a> {
|
|||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct DrawTilingPathInfo<'a> {
|
||||
pub(crate) paint_metadata: &'a PaintMetadata,
|
||||
pub(crate) opacity_tile_transform: Transform2F,
|
||||
pub(crate) blend_mode: BlendMode,
|
||||
pub(crate) opacity: u8,
|
||||
pub(crate) built_clip_path: Option<&'a BuiltPath>,
|
||||
|
@ -61,20 +62,18 @@ impl<'a> Tiler<'a> {
|
|||
outline: &'a Outline,
|
||||
fill_rule: FillRule,
|
||||
view_box: RectF,
|
||||
object_index: u16,
|
||||
path_info: TilingPathInfo<'a>,
|
||||
) -> Tiler<'a> {
|
||||
let bounds = outline
|
||||
.bounds()
|
||||
.intersection(view_box)
|
||||
.unwrap_or(RectF::default());
|
||||
let object_builder = ObjectBuilder::new(bounds, fill_rule);
|
||||
let object_builder = ObjectBuilder::new(bounds, view_box, fill_rule, &path_info);
|
||||
|
||||
Tiler {
|
||||
scene_builder,
|
||||
object_builder,
|
||||
outline,
|
||||
object_index,
|
||||
path_info,
|
||||
|
||||
point_queue: SortedVector::new(),
|
||||
|
@ -124,105 +123,52 @@ impl<'a> Tiler<'a> {
|
|||
}
|
||||
|
||||
fn pack_and_cull(&mut self) {
|
||||
match self.path_info {
|
||||
TilingPathInfo::Clip => self.pack_and_cull_clip_path(),
|
||||
TilingPathInfo::Draw { .. } => self.pack_and_cull_draw_path(),
|
||||
}
|
||||
}
|
||||
|
||||
fn pack_and_cull_draw_path(&mut self) {
|
||||
let draw_tiling_path_info = match self.path_info {
|
||||
TilingPathInfo::Clip => unreachable!(),
|
||||
TilingPathInfo::Clip => return,
|
||||
TilingPathInfo::Draw(draw_tiling_path_info) => draw_tiling_path_info,
|
||||
};
|
||||
|
||||
let blend_mode_is_destructive = draw_tiling_path_info.blend_mode.is_destructive();
|
||||
|
||||
for (draw_tile_index, draw_tile) in self.object_builder
|
||||
.built_path
|
||||
.tiles
|
||||
.data
|
||||
.iter()
|
||||
.enumerate() {
|
||||
let tile_coords = self.object_builder
|
||||
.local_tile_index_to_coords(draw_tile_index as u32);
|
||||
|
||||
// Figure out what clip tile we need, if any.
|
||||
let clip_tile = match draw_tiling_path_info.built_clip_path {
|
||||
None => None,
|
||||
Some(built_clip_path) => {
|
||||
match built_clip_path.tiles.get(tile_coords) {
|
||||
None => {
|
||||
// This tile is outside of the bounds of the clip path entirely. We can
|
||||
// cull it.
|
||||
continue;
|
||||
}
|
||||
Some(clip_tile) if clip_tile.is_solid() => {
|
||||
if clip_tile.backdrop != 0 {
|
||||
// The clip tile is fully opaque, so this tile isn't clipped at
|
||||
// all.
|
||||
None
|
||||
} else {
|
||||
// This tile is completely clipped out. Cull it.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(clip_tile) => Some(clip_tile),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if clip_tile.is_none() && draw_tile.is_solid() {
|
||||
// This is the simple case of a solid tile with no clip, so there are optimization
|
||||
// opportunities. First, tiles that must be blank per the fill rule are always
|
||||
// skipped.
|
||||
match (self.object_builder.built_path.fill_rule, draw_tile.backdrop) {
|
||||
(FillRule::Winding, 0) => continue,
|
||||
(FillRule::Winding, _) => {}
|
||||
(FillRule::EvenOdd, backdrop) if backdrop % 2 == 0 => continue,
|
||||
(FillRule::EvenOdd, _) => {}
|
||||
}
|
||||
|
||||
// Next, if this is a solid tile that completely occludes the background, record
|
||||
// that fact and stop here.
|
||||
if draw_tiling_path_info.paint_metadata.is_opaque &&
|
||||
draw_tiling_path_info.blend_mode.occludes_backdrop() &&
|
||||
draw_tiling_path_info.opacity == !0 {
|
||||
self.object_builder
|
||||
.built_path
|
||||
.solid_tiles
|
||||
.push(SolidTileInfo::new(tile_coords));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate a mask tile.
|
||||
let mask_tile_index = self.scene_builder.allocate_mask_tile_index();
|
||||
|
||||
// Add the clip primitive to the mask framebuffer, if necessary.
|
||||
if let Some(clip_tile) = clip_tile {
|
||||
ObjectBuilder::push_mask_tile(&mut self.object_builder.built_path.mask_tiles,
|
||||
clip_tile,
|
||||
mask_tile_index,
|
||||
self.object_index);
|
||||
}
|
||||
|
||||
// Add the primitive to the mask framebuffer.
|
||||
ObjectBuilder::push_mask_tile(&mut self.object_builder.built_path.mask_tiles,
|
||||
let packed_tile = PackedTile::new(draw_tile_index as u32,
|
||||
draw_tile,
|
||||
mask_tile_index,
|
||||
self.object_index);
|
||||
&draw_tiling_path_info,
|
||||
&self.object_builder);
|
||||
|
||||
// Add the primitive to draw the mask.
|
||||
ObjectBuilder::push_alpha_tile(&mut self.object_builder.built_path.alpha_tiles,
|
||||
mask_tile_index,
|
||||
tile_coords,
|
||||
self.object_index,
|
||||
match packed_tile.tile_type {
|
||||
TileType::Solid => {
|
||||
match self.object_builder.built_path.solid_tiles {
|
||||
SolidTiles::Occluders(ref mut occluders) => {
|
||||
occluders.push(Occluder::new(packed_tile.tile_coords));
|
||||
}
|
||||
SolidTiles::Regular(ref mut solid_tiles) => {
|
||||
packed_tile.add_to(solid_tiles, &draw_tiling_path_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
TileType::SingleMask => {
|
||||
packed_tile.add_to(&mut self.object_builder.built_path.single_mask_tiles,
|
||||
&draw_tiling_path_info);
|
||||
|
||||
}
|
||||
TileType::DualMask => {
|
||||
packed_tile.add_to(&mut self.object_builder.built_path.dual_mask_tiles,
|
||||
&draw_tiling_path_info);
|
||||
}
|
||||
TileType::Empty if blend_mode_is_destructive => {
|
||||
packed_tile.add_to(&mut self.object_builder.built_path.empty_tiles,
|
||||
&draw_tiling_path_info);
|
||||
}
|
||||
TileType::Empty => {
|
||||
// Just cull.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pack_and_cull_clip_path(&mut self) {
|
||||
// TODO(pcwalton)
|
||||
}
|
||||
|
||||
fn process_old_active_edges(&mut self, tile_y: i32) {
|
||||
|
@ -435,6 +381,123 @@ impl<'a> Tiler<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> TilingPathInfo<'a> {
|
||||
pub(crate) fn has_destructive_blend_mode(&self) -> bool {
|
||||
match *self {
|
||||
TilingPathInfo::Draw(ref draw_tiling_path_info) => {
|
||||
draw_tiling_path_info.blend_mode.is_destructive()
|
||||
}
|
||||
TilingPathInfo::Clip => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PackedTile<'a> {
|
||||
pub(crate) tile_type: TileType,
|
||||
pub(crate) tile_coords: Vector2I,
|
||||
pub(crate) draw_tile: &'a TileObjectPrimitive,
|
||||
pub(crate) clip_tile: Option<&'a TileObjectPrimitive>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub(crate) enum TileType {
|
||||
Solid,
|
||||
Empty,
|
||||
SingleMask,
|
||||
DualMask,
|
||||
}
|
||||
|
||||
impl<'a> PackedTile<'a> {
|
||||
fn new(draw_tile_index: u32,
|
||||
draw_tile: &'a TileObjectPrimitive,
|
||||
draw_tiling_path_info: &DrawTilingPathInfo<'a>,
|
||||
object_builder: &ObjectBuilder)
|
||||
-> PackedTile<'a> {
|
||||
let tile_coords = object_builder.local_tile_index_to_coords(draw_tile_index as u32);
|
||||
|
||||
// Figure out what clip tile we need, if any.
|
||||
let clip_tile = match draw_tiling_path_info.built_clip_path {
|
||||
None => None,
|
||||
Some(built_clip_path) => {
|
||||
match built_clip_path.tiles.get(tile_coords) {
|
||||
None => {
|
||||
// This tile is outside of the bounds of the clip path entirely. We can
|
||||
// cull it.
|
||||
return PackedTile {
|
||||
tile_type: TileType::Empty,
|
||||
tile_coords,
|
||||
draw_tile,
|
||||
clip_tile: None,
|
||||
};
|
||||
}
|
||||
Some(clip_tile) if clip_tile.is_solid() => {
|
||||
if clip_tile.backdrop != 0 {
|
||||
// The clip tile is fully opaque, so this tile isn't clipped at
|
||||
// all.
|
||||
None
|
||||
} else {
|
||||
// This tile is completely clipped out. Cull it.
|
||||
return PackedTile {
|
||||
tile_type: TileType::Empty,
|
||||
tile_coords,
|
||||
draw_tile,
|
||||
clip_tile: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
Some(clip_tile) => Some(clip_tile),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if clip_tile.is_none() {
|
||||
if draw_tile.is_solid() {
|
||||
// This is the simple case of a solid tile with no clip, so there are optimization
|
||||
// opportunities. First, tiles that must be blank per the fill rule are always
|
||||
// skipped.
|
||||
match (object_builder.built_path.fill_rule, draw_tile.backdrop) {
|
||||
(FillRule::Winding, 0) => {
|
||||
return PackedTile {
|
||||
tile_type: TileType::Empty,
|
||||
tile_coords,
|
||||
draw_tile,
|
||||
clip_tile,
|
||||
};
|
||||
}
|
||||
(FillRule::Winding, _) => {}
|
||||
(FillRule::EvenOdd, backdrop) if backdrop % 2 == 0 => {
|
||||
return PackedTile {
|
||||
tile_type: TileType::Empty,
|
||||
tile_coords,
|
||||
draw_tile,
|
||||
clip_tile,
|
||||
};
|
||||
}
|
||||
(FillRule::EvenOdd, _) => {}
|
||||
}
|
||||
|
||||
// Next, if this is a solid tile that completely occludes the background, record
|
||||
// that fact. Otherwise, add a regular solid tile.
|
||||
return PackedTile {
|
||||
tile_type: TileType::Solid,
|
||||
tile_coords,
|
||||
draw_tile,
|
||||
clip_tile,
|
||||
};
|
||||
}
|
||||
|
||||
return PackedTile {
|
||||
tile_type: TileType::SingleMask,
|
||||
tile_coords,
|
||||
draw_tile,
|
||||
clip_tile,
|
||||
};
|
||||
}
|
||||
|
||||
PackedTile { tile_type: TileType::DualMask, tile_coords, draw_tile, clip_tile }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn round_rect_out_to_tile_bounds(rect: RectF) -> RectI {
|
||||
rect.scale_xy(Vector2F::new(
|
||||
1.0 / TILE_WIDTH as f32,
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
|
||||
//! Software occlusion culling.
|
||||
|
||||
use crate::builder::SolidTileInfo;
|
||||
use crate::gpu_data::{SolidTile, SolidTileBatch, SolidTileVertex};
|
||||
use crate::builder::Occluder;
|
||||
use crate::gpu_data::{Tile, TileBatch, TileBatchTexture, TileVertex};
|
||||
use crate::paint::{PaintId, PaintMetadata};
|
||||
use crate::tile_map::DenseTileMap;
|
||||
use crate::tiles;
|
||||
use pathfinder_content::effects::{CompositeOp, Effects, Filter};
|
||||
use pathfinder_content::effects::{BlendMode, Effects};
|
||||
use pathfinder_geometry::rect::RectF;
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||
use vec_map::VecMap;
|
||||
|
@ -26,7 +26,7 @@ pub(crate) struct ZBuffer {
|
|||
}
|
||||
|
||||
pub(crate) struct SolidTiles {
|
||||
pub(crate) batches: Vec<SolidTileBatch>,
|
||||
pub(crate) batches: Vec<TileBatch>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -48,7 +48,7 @@ impl ZBuffer {
|
|||
}
|
||||
|
||||
pub(crate) fn update(&mut self,
|
||||
solid_tiles: &[SolidTileInfo],
|
||||
solid_tiles: &[Occluder],
|
||||
depth: u32,
|
||||
metadata: DepthMetadata) {
|
||||
self.depth_metadata.insert(depth as usize, metadata);
|
||||
|
@ -77,76 +77,92 @@ impl ZBuffer {
|
|||
|
||||
// Create a batch if necessary.
|
||||
match solid_tiles.batches.last() {
|
||||
Some(ref batch) if batch.color_texture_page == paint_metadata.location.page &&
|
||||
batch.sampling_flags == paint_metadata.sampling_flags => {}
|
||||
Some(TileBatch {
|
||||
color_texture_0: Some(TileBatchTexture { page, sampling_flags }),
|
||||
..
|
||||
}) if *page == paint_metadata.location.page &&
|
||||
*sampling_flags == paint_metadata.sampling_flags => {}
|
||||
_ => {
|
||||
// Batch break.
|
||||
//
|
||||
// TODO(pcwalton): We could be more aggressive with batching here, since we
|
||||
// know there are no overlaps.
|
||||
solid_tiles.batches.push(SolidTileBatch {
|
||||
color_texture_page: paint_metadata.location.page,
|
||||
solid_tiles.batches.push(TileBatch {
|
||||
color_texture_0: Some(TileBatchTexture {
|
||||
page: paint_metadata.location.page,
|
||||
sampling_flags: paint_metadata.sampling_flags,
|
||||
}),
|
||||
color_texture_1: None,
|
||||
tiles: vec![],
|
||||
effects: Effects::new(Filter::Composite(CompositeOp::SrcOver)),
|
||||
effects: Effects::default(),
|
||||
blend_mode: BlendMode::default(),
|
||||
mask_0_fill_rule: None,
|
||||
mask_1_fill_rule: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let batch = solid_tiles.batches.last_mut().unwrap();
|
||||
batch.tiles.push(SolidTile::from_paint_metadata(tile_position, paint_metadata));
|
||||
batch.tiles.push(Tile::new_solid_with_paint_metadata(tile_position, paint_metadata));
|
||||
}
|
||||
|
||||
solid_tiles
|
||||
}
|
||||
}
|
||||
|
||||
impl SolidTile {
|
||||
pub(crate) fn from_paint_metadata(tile_position: Vector2I, paint_metadata: &PaintMetadata)
|
||||
-> SolidTile {
|
||||
SolidTile {
|
||||
upper_left: SolidTileVertex::from_paint_metadata(tile_position, paint_metadata),
|
||||
upper_right: SolidTileVertex::from_paint_metadata(tile_position + Vector2I::new(1, 0),
|
||||
impl Tile {
|
||||
pub(crate) fn new_solid_with_paint_metadata(tile_position: Vector2I,
|
||||
paint_metadata: &PaintMetadata)
|
||||
-> Tile {
|
||||
Tile {
|
||||
upper_left: TileVertex::new_solid_from_paint_metadata(tile_position, paint_metadata),
|
||||
upper_right: TileVertex::new_solid_from_paint_metadata(tile_position +
|
||||
Vector2I::new(1, 0),
|
||||
paint_metadata),
|
||||
lower_left: SolidTileVertex::from_paint_metadata(tile_position + Vector2I::new(0, 1),
|
||||
lower_left: TileVertex::new_solid_from_paint_metadata(tile_position +
|
||||
Vector2I::new(0, 1),
|
||||
paint_metadata),
|
||||
lower_right: SolidTileVertex::from_paint_metadata(tile_position + Vector2I::new(1, 1),
|
||||
lower_right: TileVertex::new_solid_from_paint_metadata(tile_position +
|
||||
Vector2I::new(1, 1),
|
||||
paint_metadata),
|
||||
}
|
||||
}
|
||||
|
||||
// The texture rect is in normalized coordinates.
|
||||
pub(crate) fn from_texture_rect(tile_position: Vector2I, texture_rect: RectF) -> SolidTile {
|
||||
SolidTile {
|
||||
upper_left: SolidTileVertex::new(tile_position, texture_rect.origin()),
|
||||
upper_right: SolidTileVertex::new(tile_position + Vector2I::new(1, 0),
|
||||
pub(crate) fn new_solid_from_texture_rect(tile_position: Vector2I, texture_rect: RectF)
|
||||
-> Tile {
|
||||
Tile {
|
||||
upper_left: TileVertex::new_solid_from_uv(tile_position, texture_rect.origin()),
|
||||
upper_right: TileVertex::new_solid_from_uv(tile_position + Vector2I::new(1, 0),
|
||||
texture_rect.upper_right()),
|
||||
lower_left: SolidTileVertex::new(tile_position + Vector2I::new(0, 1),
|
||||
lower_left: TileVertex::new_solid_from_uv(tile_position + Vector2I::new(0, 1),
|
||||
texture_rect.lower_left()),
|
||||
lower_right: SolidTileVertex::new(tile_position + Vector2I::new(1, 1),
|
||||
lower_right: TileVertex::new_solid_from_uv(tile_position + Vector2I::new(1, 1),
|
||||
texture_rect.lower_right()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SolidTileVertex {
|
||||
fn new(tile_position: Vector2I, color_tex_coords: Vector2F) -> SolidTileVertex {
|
||||
SolidTileVertex {
|
||||
impl TileVertex {
|
||||
fn new_solid_from_uv(tile_position: Vector2I, color_0_uv: Vector2F) -> TileVertex {
|
||||
TileVertex {
|
||||
tile_x: tile_position.x() as i16,
|
||||
tile_y: tile_position.y() as i16,
|
||||
color_u: color_tex_coords.x(),
|
||||
color_v: color_tex_coords.y(),
|
||||
color_0_u: color_0_uv.x(),
|
||||
color_0_v: color_0_uv.y(),
|
||||
color_1_u: 0.0,
|
||||
color_1_v: 0.0,
|
||||
mask_0_u: 0.0,
|
||||
mask_0_v: 0.0,
|
||||
mask_1_u: 0.0,
|
||||
mask_1_v: 0.0,
|
||||
mask_0_backdrop: 0,
|
||||
mask_1_backdrop: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_paint_metadata(tile_position: Vector2I, paint_metadata: &PaintMetadata)
|
||||
-> SolidTileVertex {
|
||||
fn new_solid_from_paint_metadata(tile_position: Vector2I, paint_metadata: &PaintMetadata)
|
||||
-> TileVertex {
|
||||
let color_uv = paint_metadata.calculate_tex_coords(tile_position);
|
||||
SolidTileVertex {
|
||||
tile_x: tile_position.x() as i16,
|
||||
tile_y: tile_position.y() as i16,
|
||||
color_u: color_uv.x(),
|
||||
color_v: color_uv.y(),
|
||||
}
|
||||
TileVertex::new_solid_from_uv(tile_position, color_uv)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,27 +13,14 @@ shaders/gl3/demo_ground.fs.glsl
|
|||
shaders/gl3/demo_ground.vs.glsl
|
||||
shaders/gl3/fill.fs.glsl
|
||||
shaders/gl3/fill.vs.glsl
|
||||
shaders/gl3/mask.vs.glsl
|
||||
shaders/gl3/mask_evenodd.fs.glsl
|
||||
shaders/gl3/mask_winding.fs.glsl
|
||||
shaders/gl3/reproject.fs.glsl
|
||||
shaders/gl3/reproject.vs.glsl
|
||||
shaders/gl3/stencil.fs.glsl
|
||||
shaders/gl3/stencil.vs.glsl
|
||||
shaders/gl3/tile_alpha.fs.glsl
|
||||
shaders/gl3/tile_alpha.vs.glsl
|
||||
shaders/gl3/tile_alpha_difference.fs.glsl
|
||||
shaders/gl3/tile_alpha_dodgeburn.fs.glsl
|
||||
shaders/gl3/tile_alpha_exclusion.fs.glsl
|
||||
shaders/gl3/tile_alpha_hsl.fs.glsl
|
||||
shaders/gl3/tile_alpha_overlay.fs.glsl
|
||||
shaders/gl3/tile_alpha_softlight.fs.glsl
|
||||
shaders/gl3/tile.fs.glsl
|
||||
shaders/gl3/tile.vs.glsl
|
||||
shaders/gl3/tile_copy.fs.glsl
|
||||
shaders/gl3/tile_copy.vs.glsl
|
||||
shaders/gl3/tile_solid.fs.glsl
|
||||
shaders/gl3/tile_solid.vs.glsl
|
||||
shaders/gl3/tile_solid_filter_blur.fs.glsl
|
||||
shaders/gl3/tile_solid_filter_text.fs.glsl
|
||||
shaders/metal/blit.fs.metal
|
||||
shaders/metal/blit.vs.metal
|
||||
shaders/metal/debug_solid.fs.metal
|
||||
|
@ -44,27 +31,14 @@ shaders/metal/demo_ground.fs.metal
|
|||
shaders/metal/demo_ground.vs.metal
|
||||
shaders/metal/fill.fs.metal
|
||||
shaders/metal/fill.vs.metal
|
||||
shaders/metal/mask.vs.metal
|
||||
shaders/metal/mask_evenodd.fs.metal
|
||||
shaders/metal/mask_winding.fs.metal
|
||||
shaders/metal/reproject.fs.metal
|
||||
shaders/metal/reproject.vs.metal
|
||||
shaders/metal/stencil.fs.metal
|
||||
shaders/metal/stencil.vs.metal
|
||||
shaders/metal/tile_alpha.fs.metal
|
||||
shaders/metal/tile_alpha.vs.metal
|
||||
shaders/metal/tile_alpha_difference.fs.metal
|
||||
shaders/metal/tile_alpha_dodgeburn.fs.metal
|
||||
shaders/metal/tile_alpha_exclusion.fs.metal
|
||||
shaders/metal/tile_alpha_hsl.fs.metal
|
||||
shaders/metal/tile_alpha_overlay.fs.metal
|
||||
shaders/metal/tile_alpha_softlight.fs.metal
|
||||
shaders/metal/tile.fs.metal
|
||||
shaders/metal/tile.vs.metal
|
||||
shaders/metal/tile_copy.fs.metal
|
||||
shaders/metal/tile_copy.vs.metal
|
||||
shaders/metal/tile_solid.fs.metal
|
||||
shaders/metal/tile_solid.vs.metal
|
||||
shaders/metal/tile_solid_filter_blur.fs.metal
|
||||
shaders/metal/tile_solid_filter_text.fs.metal
|
||||
textures/area-lut.png
|
||||
textures/debug-corner-fill.png
|
||||
textures/debug-corner-outline.png
|
||||
|
|
|
@ -14,12 +14,16 @@
|
|||
|
||||
precision highp float;
|
||||
|
||||
in vec2 aPosition;
|
||||
in ivec2 aPosition;
|
||||
|
||||
out vec2 vTexCoord;
|
||||
|
||||
void main(){
|
||||
vTexCoord = aPosition;
|
||||
gl_Position = vec4(mix(aPosition, vec2(- 1.0), vec2(1.0)), 0.0, 1.0);
|
||||
vec2 texCoord = vec2(aPosition);
|
||||
|
||||
|
||||
|
||||
vTexCoord = texCoord;
|
||||
gl_Position = vec4(mix(vec2(- 1.0), vec2(1.0), vec2(aPosition)), 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
in vec2 aPosition;
|
||||
in vec2 aFillTexCoord;
|
||||
in int aBackdrop;
|
||||
|
||||
out vec2 vFillTexCoord;
|
||||
out float vBackdrop;
|
||||
|
||||
void main(){
|
||||
vec2 position = mix(vec2(- 1.0), vec2(1.0), aPosition);
|
||||
|
||||
|
||||
|
||||
|
||||
vFillTexCoord = aFillTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uFillTexture;
|
||||
|
||||
in vec2 vFillTexCoord;
|
||||
in float vBackdrop;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main(){
|
||||
float alpha = texture(uFillTexture, vFillTexCoord). r + vBackdrop;
|
||||
oFragColor = vec4(1.0 - abs(1.0 - mod(alpha, 2.0)));
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uFillTexture;
|
||||
|
||||
in vec2 vFillTexCoord;
|
||||
in float vBackdrop;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main(){
|
||||
oFragColor = vec4(abs(texture(uFillTexture, vFillTexCoord). r + vBackdrop));
|
||||
}
|
||||
|
|
@ -0,0 +1,463 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uColorTexture0;
|
||||
uniform sampler2D uColorTexture1;
|
||||
uniform sampler2D uMaskTexture0;
|
||||
uniform sampler2D uMaskTexture1;
|
||||
uniform sampler2D uDestTexture;
|
||||
uniform sampler2D uGammaLUT;
|
||||
uniform vec4 uFilterParams0;
|
||||
uniform vec4 uFilterParams1;
|
||||
uniform vec4 uFilterParams2;
|
||||
uniform vec2 uDestTextureSize;
|
||||
uniform vec2 uColorTexture0Size;
|
||||
uniform int uCtrl;
|
||||
|
||||
in vec3 vMaskTexCoord0;
|
||||
in vec3 vMaskTexCoord1;
|
||||
in vec2 vColorTexCoord0;
|
||||
in vec2 vColorTexCoord1;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
vec4 sampleColor(sampler2D colorTexture, vec2 colorTexCoord){
|
||||
return texture(colorTexture, colorTexCoord);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float filterTextSample1Tap(float offset, sampler2D colorTexture, vec2 colorTexCoord){
|
||||
return texture(colorTexture, colorTexCoord + vec2(offset, 0.0)). r;
|
||||
}
|
||||
|
||||
|
||||
void filterTextSample9Tap(out vec4 outAlphaLeft,
|
||||
out float outAlphaCenter,
|
||||
out vec4 outAlphaRight,
|
||||
sampler2D colorTexture,
|
||||
vec2 colorTexCoord,
|
||||
vec4 kernel,
|
||||
float onePixel){
|
||||
bool wide = kernel . x > 0.0;
|
||||
outAlphaLeft =
|
||||
vec4(wide ? filterTextSample1Tap(- 4.0 * onePixel, colorTexture, colorTexCoord): 0.0,
|
||||
filterTextSample1Tap(- 3.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(- 2.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(- 1.0 * onePixel, colorTexture, colorTexCoord));
|
||||
outAlphaCenter = filterTextSample1Tap(0.0, colorTexture, colorTexCoord);
|
||||
outAlphaRight =
|
||||
vec4(filterTextSample1Tap(1.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(2.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(3.0 * onePixel, colorTexture, colorTexCoord),
|
||||
wide ? filterTextSample1Tap(4.0 * onePixel, colorTexture, colorTexCoord): 0.0);
|
||||
}
|
||||
|
||||
float filterTextConvolve7Tap(vec4 alpha0, vec3 alpha1, vec4 kernel){
|
||||
return dot(alpha0, kernel)+ dot(alpha1, kernel . zyx);
|
||||
}
|
||||
|
||||
float filterTextGammaCorrectChannel(float bgColor, float fgColor, sampler2D gammaLUT){
|
||||
return texture(gammaLUT, vec2(fgColor, 1.0 - bgColor)). r;
|
||||
}
|
||||
|
||||
|
||||
vec3 filterTextGammaCorrect(vec3 bgColor, vec3 fgColor, sampler2D gammaLUT){
|
||||
return vec3(filterTextGammaCorrectChannel(bgColor . r, fgColor . r, gammaLUT),
|
||||
filterTextGammaCorrectChannel(bgColor . g, fgColor . g, gammaLUT),
|
||||
filterTextGammaCorrectChannel(bgColor . b, fgColor . b, gammaLUT));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vec4 filterText(vec2 colorTexCoord,
|
||||
sampler2D colorTexture,
|
||||
sampler2D gammaLUT,
|
||||
vec2 colorTextureSize,
|
||||
vec4 filterParams0,
|
||||
vec4 filterParams1,
|
||||
vec4 filterParams2){
|
||||
|
||||
vec4 kernel = filterParams0;
|
||||
vec3 bgColor = filterParams1 . rgb;
|
||||
vec3 fgColor = filterParams2 . rgb;
|
||||
bool gammaCorrectionEnabled = filterParams2 . a != 0.0;
|
||||
|
||||
|
||||
vec3 alpha;
|
||||
if(kernel . w == 0.0){
|
||||
alpha = texture(colorTexture, colorTexCoord). rrr;
|
||||
} else {
|
||||
vec4 alphaLeft, alphaRight;
|
||||
float alphaCenter;
|
||||
filterTextSample9Tap(alphaLeft,
|
||||
alphaCenter,
|
||||
alphaRight,
|
||||
colorTexture,
|
||||
colorTexCoord,
|
||||
kernel,
|
||||
1.0 / colorTextureSize . x);
|
||||
|
||||
float r = filterTextConvolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight . xy), kernel);
|
||||
float g = filterTextConvolve7Tap(vec4(alphaLeft . yzw, alphaCenter), alphaRight . xyz, kernel);
|
||||
float b = filterTextConvolve7Tap(vec4(alphaLeft . zw, alphaCenter, alphaRight . x),
|
||||
alphaRight . yzw,
|
||||
kernel);
|
||||
|
||||
alpha = vec3(r, g, b);
|
||||
}
|
||||
|
||||
|
||||
if(gammaCorrectionEnabled)
|
||||
alpha = filterTextGammaCorrect(bgColor, alpha, gammaLUT);
|
||||
|
||||
|
||||
return vec4(mix(bgColor, fgColor, alpha), 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vec4 filterBlur(vec2 colorTexCoord,
|
||||
sampler2D colorTexture,
|
||||
vec2 colorTextureSize,
|
||||
vec4 filterParams0,
|
||||
vec4 filterParams1){
|
||||
|
||||
vec2 srcOffsetScale = filterParams0 . xy / colorTextureSize;
|
||||
int support = int(filterParams0 . z);
|
||||
vec3 gaussCoeff = filterParams1 . xyz;
|
||||
|
||||
|
||||
float gaussSum = gaussCoeff . x;
|
||||
vec4 color = texture(colorTexture, colorTexCoord)* gaussCoeff . x;
|
||||
gaussCoeff . xy *= gaussCoeff . yz;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for(int i = 1;i <= support;i += 2){
|
||||
float gaussPartialSum = gaussCoeff . x;
|
||||
gaussCoeff . xy *= gaussCoeff . yz;
|
||||
gaussPartialSum += gaussCoeff . x;
|
||||
|
||||
vec2 srcOffset = srcOffsetScale *(float(i)+ gaussCoeff . x / gaussPartialSum);
|
||||
color +=(texture(colorTexture, colorTexCoord - srcOffset)+
|
||||
texture(colorTexture, colorTexCoord + srcOffset))* gaussPartialSum;
|
||||
|
||||
gaussSum += 2.0 * gaussPartialSum;
|
||||
gaussCoeff . xy *= gaussCoeff . yz;
|
||||
}
|
||||
|
||||
|
||||
return color / gaussSum;
|
||||
}
|
||||
|
||||
vec4 filterNone(vec2 colorTexCoord, sampler2D colorTexture){
|
||||
return sampleColor(colorTexture, colorTexCoord);
|
||||
}
|
||||
|
||||
vec4 filterColor(vec2 colorTexCoord,
|
||||
sampler2D colorTexture,
|
||||
sampler2D gammaLUT,
|
||||
vec2 colorTextureSize,
|
||||
vec4 filterParams0,
|
||||
vec4 filterParams1,
|
||||
vec4 filterParams2,
|
||||
int colorFilter){
|
||||
switch(colorFilter){
|
||||
case 0x3 :
|
||||
return filterBlur(colorTexCoord,
|
||||
colorTexture,
|
||||
colorTextureSize,
|
||||
filterParams0,
|
||||
filterParams1);
|
||||
case 0x2 :
|
||||
return filterText(colorTexCoord,
|
||||
colorTexture,
|
||||
gammaLUT,
|
||||
colorTextureSize,
|
||||
filterParams0,
|
||||
filterParams1,
|
||||
filterParams2);
|
||||
}
|
||||
return filterNone(colorTexCoord, colorTexture);
|
||||
}
|
||||
|
||||
|
||||
|
||||
vec3 compositeSelect(bvec3 cond, vec3 ifTrue, vec3 ifFalse){
|
||||
return vec3(cond . x ? ifTrue . x : ifFalse . x,
|
||||
cond . y ? ifTrue . y : ifFalse . y,
|
||||
cond . z ? ifTrue . z : ifFalse . z);
|
||||
}
|
||||
|
||||
float compositeDivide(float num, float denom){
|
||||
return denom != 0.0 ? num / denom : 0.0;
|
||||
}
|
||||
|
||||
vec3 compositeColorDodge(vec3 destColor, vec3 srcColor){
|
||||
bvec3 destZero = equal(destColor, vec3(0.0)), srcOne = equal(srcColor, vec3(1.0));
|
||||
return compositeSelect(destZero,
|
||||
vec3(0.0),
|
||||
compositeSelect(srcOne, vec3(1.0), destColor /(vec3(1.0)- srcColor)));
|
||||
}
|
||||
|
||||
|
||||
vec3 compositeHSLToRGB(vec3 hsl){
|
||||
float a = hsl . y * min(hsl . z, 1.0 - hsl . z);
|
||||
vec3 ks = mod(vec3(0.0, 8.0, 4.0)+ vec3(hsl . x * 1.9098593171027443), 12.0);
|
||||
return hsl . zzz - clamp(min(ks - vec3(3.0), vec3(9.0)- ks), - 1.0, 1.0)* a;
|
||||
}
|
||||
|
||||
|
||||
vec3 compositeRGBToHSL(vec3 rgb){
|
||||
float v = max(max(rgb . r, rgb . g), rgb . b), xMin = min(min(rgb . r, rgb . g), rgb . b);
|
||||
float c = v - xMin, l = mix(xMin, v, 0.5);
|
||||
vec3 terms = rgb . r == v ? vec3(0.0, rgb . gb):
|
||||
rgb . g == v ? vec3(2.0, rgb . br):
|
||||
vec3(4.0, rgb . rg);
|
||||
float h = 1.0471975511965976 * compositeDivide(terms . x * c + terms . y - terms . z, c);
|
||||
float s = compositeDivide(c, v);
|
||||
return vec3(h, s, l);
|
||||
}
|
||||
|
||||
vec3 compositeScreen(vec3 destColor, vec3 srcColor){
|
||||
return destColor + srcColor - destColor * srcColor;
|
||||
}
|
||||
|
||||
vec3 compositeHardLight(vec3 destColor, vec3 srcColor){
|
||||
return compositeSelect(lessThanEqual(srcColor, vec3(0.5)),
|
||||
destColor * vec3(2.0)* srcColor,
|
||||
compositeScreen(destColor, vec3(2.0)* srcColor - vec3(1.0)));
|
||||
}
|
||||
|
||||
vec3 compositeSoftLight(vec3 destColor, vec3 srcColor){
|
||||
vec3 darkenedDestColor =
|
||||
compositeSelect(lessThanEqual(destColor, vec3(0.25)),
|
||||
((vec3(16.0)* destColor - 12.0)* destColor + 4.0)* destColor,
|
||||
sqrt(destColor));
|
||||
vec3 factor = compositeSelect(lessThanEqual(srcColor, vec3(0.5)),
|
||||
destColor *(vec3(1.0)- destColor),
|
||||
darkenedDestColor - destColor);
|
||||
return destColor +(srcColor * 2.0 - 1.0)* factor;
|
||||
}
|
||||
|
||||
vec3 compositeHSL(vec3 destColor, vec3 srcColor, int op){
|
||||
switch(op){
|
||||
case 0xc :
|
||||
return vec3(srcColor . x, destColor . y, destColor . z);
|
||||
case 0xd :
|
||||
return vec3(destColor . x, srcColor . y, destColor . z);
|
||||
case 0xe :
|
||||
return vec3(srcColor . x, srcColor . y, destColor . z);
|
||||
default :
|
||||
return vec3(destColor . x, destColor . y, srcColor . z);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 compositeRGB(vec3 destColor, vec3 srcColor, int op){
|
||||
switch(op){
|
||||
case 0x1 :
|
||||
return destColor * srcColor;
|
||||
case 0x2 :
|
||||
return compositeScreen(destColor, srcColor);
|
||||
case 0x3 :
|
||||
return compositeHardLight(srcColor, destColor);
|
||||
case 0x4 :
|
||||
return min(destColor, srcColor);
|
||||
case 0x5 :
|
||||
return max(destColor, srcColor);
|
||||
case 0x6 :
|
||||
return compositeColorDodge(destColor, srcColor);
|
||||
case 0x7 :
|
||||
return vec3(1.0)- compositeColorDodge(vec3(1.0)- destColor, vec3(1.0)- srcColor);
|
||||
case 0x8 :
|
||||
return compositeHardLight(destColor, srcColor);
|
||||
case 0x9 :
|
||||
return compositeSoftLight(destColor, srcColor);
|
||||
case 0xa :
|
||||
return abs(destColor - srcColor);
|
||||
case 0xb :
|
||||
return destColor + srcColor - vec3(2.0)* destColor * srcColor;
|
||||
case 0xc :
|
||||
case 0xd :
|
||||
case 0xe :
|
||||
case 0xf :
|
||||
return compositeHSLToRGB(compositeHSL(compositeRGBToHSL(destColor),
|
||||
compositeRGBToHSL(srcColor),
|
||||
op));
|
||||
}
|
||||
return srcColor;
|
||||
}
|
||||
|
||||
vec4 composite(vec4 srcColor,
|
||||
sampler2D destTexture,
|
||||
vec2 destTextureSize,
|
||||
vec2 fragCoord,
|
||||
int op){
|
||||
if(op == 0x0)
|
||||
return srcColor;
|
||||
|
||||
|
||||
vec2 destTexCoord = fragCoord / destTextureSize;
|
||||
vec4 destColor = texture(destTexture, destTexCoord);
|
||||
vec3 blendedRGB = compositeRGB(destColor . rgb, srcColor . rgb, op);
|
||||
return vec4(srcColor . a *(1.0 - destColor . a)* srcColor . rgb +
|
||||
srcColor . a * destColor . a * blendedRGB +
|
||||
(1.0 - srcColor . a)* destColor . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float sampleMask(float maskAlpha,
|
||||
sampler2D maskTexture,
|
||||
vec3 maskTexCoord,
|
||||
int maskCtrl){
|
||||
if(maskCtrl == 0)
|
||||
return maskAlpha;
|
||||
float coverage = texture(maskTexture, maskTexCoord . xy). r + maskTexCoord . z;
|
||||
if((maskCtrl & 0x1)!= 0)
|
||||
coverage = abs(coverage);
|
||||
else
|
||||
coverage = 1.0 - abs(1.0 - mod(coverage, 2.0));
|
||||
return min(maskAlpha, coverage);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void calculateColor(int ctrl){
|
||||
|
||||
int maskCtrl0 =(ctrl >> 0)& 0x3;
|
||||
int maskCtrl1 =(ctrl >> 2)& 0x3;
|
||||
float maskAlpha = 1.0;
|
||||
maskAlpha = sampleMask(maskAlpha, uMaskTexture0, vMaskTexCoord0, maskCtrl0);
|
||||
maskAlpha = sampleMask(maskAlpha, uMaskTexture1, vMaskTexCoord1, maskCtrl1);
|
||||
|
||||
|
||||
vec4 color = vec4(0.0);
|
||||
if(((ctrl >> 6)& 0x1)!= 0){
|
||||
int color0Filter =(ctrl >> 4)&
|
||||
0x3;
|
||||
color += filterColor(vColorTexCoord0,
|
||||
uColorTexture0,
|
||||
uGammaLUT,
|
||||
uColorTexture0Size,
|
||||
uFilterParams0,
|
||||
uFilterParams1,
|
||||
uFilterParams2,
|
||||
color0Filter);
|
||||
}
|
||||
if(((ctrl >> 7)& 0x1)!= 0)
|
||||
color *= sampleColor(uColorTexture1, vColorTexCoord1);
|
||||
|
||||
|
||||
color . a *= maskAlpha;
|
||||
|
||||
|
||||
int compositeOp =(ctrl >> 8)& 0xf;
|
||||
color = composite(color, uDestTexture, uDestTextureSize, gl_FragCoord . xy, compositeOp);
|
||||
|
||||
|
||||
color . rgb *= color . a;
|
||||
oFragColor = color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void main(){
|
||||
calculateColor(uCtrl);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec2 uTileSize;
|
||||
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord0;
|
||||
in vec2 aColorTexCoord1;
|
||||
in vec2 aMaskTexCoord0;
|
||||
in vec2 aMaskTexCoord1;
|
||||
in ivec2 aMaskBackdrop;
|
||||
|
||||
out vec3 vMaskTexCoord0;
|
||||
out vec3 vMaskTexCoord1;
|
||||
out vec2 vColorTexCoord0;
|
||||
out vec2 vColorTexCoord1;
|
||||
|
||||
void main(){
|
||||
vec2 position = vec2(aTilePosition)* uTileSize;
|
||||
vColorTexCoord0 = aColorTexCoord0;
|
||||
vColorTexCoord1 = aColorTexCoord1;
|
||||
vMaskTexCoord0 = vec3(aMaskTexCoord0, float(aMaskBackdrop . x));
|
||||
vMaskTexCoord1 = vec3(aMaskTexCoord1, float(aMaskBackdrop . y));
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
oFragColor = vec4(srcRGBA . rgb * srcRGBA . a, srcRGBA . a);
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec2 uTileSize;
|
||||
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
in vec2 aMaskTexCoord;
|
||||
in float aOpacity;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
out float vOpacity;
|
||||
|
||||
void main(){
|
||||
vec2 position = vec2(aTilePosition)* uTileSize;
|
||||
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vOpacity = aOpacity;
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 blended = abs(destRGBA . rgb - srcRGBA . rgb);
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform int uBurn;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 dest = uBurn == 0 ? destRGBA . rgb : vec3(1.0)- destRGBA . rgb;
|
||||
vec3 src = uBurn == 0 ? vec3(1.0)- srcRGBA . rgb : srcRGBA . rgb;
|
||||
|
||||
bvec3 srcNonzero = notEqual(src, vec3(0.0));
|
||||
vec3 blended = min(vec3(srcNonzero . x ? dest . x / src . x : 1.0,
|
||||
srcNonzero . y ? dest . y / src . y : 1.0,
|
||||
srcNonzero . z ? dest . z / src . z : 1.0),
|
||||
vec3(1.0));
|
||||
if(uBurn != 0)
|
||||
blended = vec3(1.0)- blended;
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 dest = destRGBA . rgb, src = srcRGBA . rgb;
|
||||
vec3 blended = dest + src - dest * src * 2.0;
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform ivec3 uBlendHSL;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
vec3 convertHSLToRGB(vec3 hsl){
|
||||
float a = hsl . y * min(hsl . z, 1.0 - hsl . z);
|
||||
vec3 ks = mod(vec3(0.0, 8.0, 4.0)+ vec3(hsl . x * 1.9098593171027443), 12.0);
|
||||
return hsl . zzz - clamp(min(ks - vec3(3.0), vec3(9.0)- ks), - 1.0, 1.0)* a;
|
||||
}
|
||||
|
||||
|
||||
vec3 convertRGBToHSL(vec3 rgb){
|
||||
float v = max((rgb . x, rgb . y), rgb . z);
|
||||
float c = v - min((rgb . x, rgb . y), rgb . z);
|
||||
float l = v - 0.5 * c;
|
||||
|
||||
vec3 tmp = vec3(0.0);
|
||||
bvec3 is_v = equal(rgb, vec3(v));
|
||||
if(is_v . r)
|
||||
tmp = vec3(0.0, rgb . gb);
|
||||
else if(is_v . g)
|
||||
tmp = vec3(2.0, rgb . br);
|
||||
else if(is_v . b)
|
||||
tmp = vec3(4.0, rgb . rg);
|
||||
float h = 1.0471975511965976 *(tmp . x +(tmp . y - tmp . z)/ c);
|
||||
|
||||
float s = 0.0;
|
||||
if(l > 0.0 && l < 1.0)
|
||||
s =(v - l)/ min(l, 1.0 - l);
|
||||
|
||||
return vec3(h, s, l);
|
||||
}
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 destHSL = convertRGBToHSL(destRGBA . rgb);
|
||||
vec3 srcHSL = convertRGBToHSL(srcRGBA . rgb);
|
||||
vec3 blendedHSL = select3(equal(uBlendHSL, ivec3(0)), destHSL, srcHSL);
|
||||
vec3 blendedRGB = convertHSLToRGB(blendedHSL);
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blendedRGB);
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform int uBlendMode;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
bool reversed = uBlendMode == 3;
|
||||
vec3 src = reversed ? srcRGBA . rgb : destRGBA . rgb;
|
||||
vec3 dest = reversed ? destRGBA . rgb : srcRGBA . rgb;
|
||||
|
||||
vec3 multiply = src * dest;
|
||||
vec3 blended;
|
||||
if(uBlendMode == 0){
|
||||
blended = multiply;
|
||||
} else {
|
||||
vec3 screen = dest + src - multiply;
|
||||
if(uBlendMode == 1)
|
||||
blended = screen;
|
||||
else
|
||||
blended = select3(lessThanEqual(src, vec3(0.5)), multiply, screen * 2.0 - 1.0);
|
||||
}
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
|
||||
vec4 sampleSrcColor(){
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord). r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA . rgb, srcRGBA . a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor(){
|
||||
vec2 destTexCoord = gl_FragCoord . xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB){
|
||||
return vec4(srcRGBA . a *(1.0 - destRGBA . a)* srcRGBA . rgb +
|
||||
srcRGBA . a * destRGBA . a * blendedRGB +
|
||||
(1.0 - srcRGBA . a)* destRGBA . a * destRGBA . rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b){
|
||||
return vec3(cond . x ? a . x : b . x, cond . y ? a . y : b . y, cond . z ? a . z : b . z);
|
||||
}
|
||||
|
||||
|
||||
void main(){
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
|
||||
|
||||
|
||||
vec3 dest = destRGBA . rgb, src = srcRGBA . rgb;
|
||||
bvec3 destDark = lessThanEqual(dest, vec3(0.25)), srcDark = lessThanEqual(src, vec3(0.5));
|
||||
vec3 d = select3(destDark,(dest * 16.0 - 12.0)* dest + 4.0, inversesqrt(dest));
|
||||
vec3 x = select3(srcDark, vec3(1.0)- dest, d - 1.0);
|
||||
vec3 blended = dest *((src * 2.0 - 1.0)* x + 1.0);
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uColorTexture;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main(){
|
||||
vec4 color = texture(uColorTexture, vColorTexCoord);
|
||||
oFragColor = vec4(color . rgb * color . a, color . a);
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec2 uTileSize;
|
||||
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
|
||||
void main(){
|
||||
vec2 position = vec2(aTilePosition)* uTileSize;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uColorTexture;
|
||||
uniform vec2 uSrcOffsetScale;
|
||||
uniform vec3 uInitialGaussCoeff;
|
||||
uniform int uSupport;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main(){
|
||||
|
||||
vec3 gaussCoeff = uInitialGaussCoeff;
|
||||
float gaussSum = gaussCoeff . x;
|
||||
vec4 color = texture(uColorTexture, vColorTexCoord)* gaussCoeff . x;
|
||||
gaussCoeff . xy *= gaussCoeff . yz;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for(int i = 1;i <= uSupport;i += 2){
|
||||
float gaussPartialSum = gaussCoeff . x;
|
||||
gaussCoeff . xy *= gaussCoeff . yz;
|
||||
gaussPartialSum += gaussCoeff . x;
|
||||
|
||||
vec2 srcOffset = uSrcOffsetScale *(float(i)+ gaussCoeff . x / gaussPartialSum);
|
||||
color +=(texture(uColorTexture, vColorTexCoord - srcOffset)+
|
||||
texture(uColorTexture, vColorTexCoord + srcOffset))* gaussPartialSum;
|
||||
|
||||
gaussSum += 2.0 * gaussPartialSum;
|
||||
gaussCoeff . xy *= gaussCoeff . yz;
|
||||
}
|
||||
|
||||
|
||||
color /= gaussSum;
|
||||
color . rgb *= color . a;
|
||||
oFragColor = color;
|
||||
}
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uColorTexture;
|
||||
uniform vec2 uSrcSize;
|
||||
uniform vec4 uFGColor;
|
||||
uniform vec4 uBGColor;
|
||||
uniform int uGammaCorrectionEnabled;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform sampler2D uGammaLUT;
|
||||
|
||||
float gammaCorrectChannel(float bgColor, float fgColor){
|
||||
return texture(uGammaLUT, vec2(fgColor, 1.0 - bgColor)). r;
|
||||
}
|
||||
|
||||
|
||||
vec3 gammaCorrect(vec3 bgColor, vec3 fgColor){
|
||||
return vec3(gammaCorrectChannel(bgColor . r, fgColor . r),
|
||||
gammaCorrectChannel(bgColor . g, fgColor . g),
|
||||
gammaCorrectChannel(bgColor . b, fgColor . b));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uniform vec4 uKernel;
|
||||
|
||||
|
||||
|
||||
float sample1Tap(float offset);
|
||||
|
||||
|
||||
void sample9Tap(out vec4 outAlphaLeft,
|
||||
out float outAlphaCenter,
|
||||
out vec4 outAlphaRight,
|
||||
float onePixel){
|
||||
outAlphaLeft = vec4(uKernel . x > 0.0 ? sample1Tap(- 4.0 * onePixel): 0.0,
|
||||
sample1Tap(- 3.0 * onePixel),
|
||||
sample1Tap(- 2.0 * onePixel),
|
||||
sample1Tap(- 1.0 * onePixel));
|
||||
outAlphaCenter = sample1Tap(0.0);
|
||||
outAlphaRight = vec4(sample1Tap(1.0 * onePixel),
|
||||
sample1Tap(2.0 * onePixel),
|
||||
sample1Tap(3.0 * onePixel),
|
||||
uKernel . x > 0.0 ? sample1Tap(4.0 * onePixel): 0.0);
|
||||
}
|
||||
|
||||
|
||||
float convolve7Tap(vec4 alpha0, vec3 alpha1){
|
||||
return dot(alpha0, uKernel)+ dot(alpha1, uKernel . zyx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
float sample1Tap(float offset){
|
||||
return texture(uColorTexture, vec2(vColorTexCoord . x + offset, vColorTexCoord . y)). r;
|
||||
}
|
||||
|
||||
void main(){
|
||||
|
||||
vec3 alpha;
|
||||
if(uKernel . w == 0.0){
|
||||
alpha = texture(uColorTexture, vColorTexCoord). rrr;
|
||||
} else {
|
||||
vec4 alphaLeft, alphaRight;
|
||||
float alphaCenter;
|
||||
sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSrcSize . x);
|
||||
|
||||
float r = convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight . xy));
|
||||
float g = convolve7Tap(vec4(alphaLeft . yzw, alphaCenter), alphaRight . xyz);
|
||||
float b = convolve7Tap(vec4(alphaLeft . zw, alphaCenter, alphaRight . x), alphaRight . yzw);
|
||||
|
||||
alpha = vec3(r, g, b);
|
||||
}
|
||||
|
||||
|
||||
if(uGammaCorrectionEnabled != 0)
|
||||
alpha = gammaCorrect(uBGColor . rgb, alpha);
|
||||
|
||||
|
||||
oFragColor = vec4(mix(uBGColor . rgb, uFGColor . rgb, alpha), 1.0);
|
||||
}
|
||||
|
|
@ -12,14 +12,16 @@ struct main0_out
|
|||
|
||||
struct main0_in
|
||||
{
|
||||
float2 aPosition [[attribute(0)]];
|
||||
int2 aPosition [[attribute(0)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.vTexCoord = in.aPosition;
|
||||
out.gl_Position = float4(mix(in.aPosition, float2(-1.0), float2(1.0)), 0.0, 1.0);
|
||||
float2 texCoord = float2(in.aPosition);
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
out.vTexCoord = texCoord;
|
||||
out.gl_Position = float4(mix(float2(-1.0), float2(1.0), float2(in.aPosition)), 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 vFillTexCoord [[user(locn0)]];
|
||||
float vBackdrop [[user(locn1)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 aPosition [[attribute(0)]];
|
||||
float2 aFillTexCoord [[attribute(1)]];
|
||||
int aBackdrop [[attribute(2)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float2 position = mix(float2(-1.0), float2(1.0), in.aPosition);
|
||||
position.y = -position.y;
|
||||
out.vFillTexCoord = in.aFillTexCoord;
|
||||
out.vBackdrop = float(in.aBackdrop);
|
||||
out.gl_Position = float4(position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uFillTexture [[id(0)]];
|
||||
sampler uFillTextureSmplr [[id(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vFillTexCoord [[user(locn0)]];
|
||||
float vBackdrop [[user(locn1)]];
|
||||
};
|
||||
|
||||
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
|
||||
template<typename Tx, typename Ty>
|
||||
Tx mod(Tx x, Ty y)
|
||||
{
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float alpha = spvDescriptorSet0.uFillTexture.sample(spvDescriptorSet0.uFillTextureSmplr, in.vFillTexCoord).x + in.vBackdrop;
|
||||
out.oFragColor = float4(1.0 - abs(1.0 - mod(alpha, 2.0)));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uFillTexture [[id(0)]];
|
||||
sampler uFillTextureSmplr [[id(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vFillTexCoord [[user(locn0)]];
|
||||
float vBackdrop [[user(locn1)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.oFragColor = float4(abs(spvDescriptorSet0.uFillTexture.sample(spvDescriptorSet0.uFillTextureSmplr, in.vFillTexCoord).x + in.vBackdrop));
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,540 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uMaskTexture0 [[id(0)]];
|
||||
sampler uMaskTexture0Smplr [[id(1)]];
|
||||
texture2d<float> uMaskTexture1 [[id(2)]];
|
||||
sampler uMaskTexture1Smplr [[id(3)]];
|
||||
texture2d<float> uColorTexture0 [[id(4)]];
|
||||
sampler uColorTexture0Smplr [[id(5)]];
|
||||
texture2d<float> uGammaLUT [[id(6)]];
|
||||
sampler uGammaLUTSmplr [[id(7)]];
|
||||
constant float2* uColorTexture0Size [[id(8)]];
|
||||
constant float4* uFilterParams0 [[id(9)]];
|
||||
constant float4* uFilterParams1 [[id(10)]];
|
||||
constant float4* uFilterParams2 [[id(11)]];
|
||||
texture2d<float> uColorTexture1 [[id(12)]];
|
||||
sampler uColorTexture1Smplr [[id(13)]];
|
||||
texture2d<float> uDestTexture [[id(14)]];
|
||||
sampler uDestTextureSmplr [[id(15)]];
|
||||
constant float2* uDestTextureSize [[id(16)]];
|
||||
constant int* uCtrl [[id(17)]];
|
||||
};
|
||||
|
||||
constant float3 _862 = {};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float3 vMaskTexCoord0 [[user(locn0)]];
|
||||
float3 vMaskTexCoord1 [[user(locn1)]];
|
||||
float2 vColorTexCoord0 [[user(locn2)]];
|
||||
float2 vColorTexCoord1 [[user(locn3)]];
|
||||
};
|
||||
|
||||
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
|
||||
template<typename Tx, typename Ty>
|
||||
Tx mod(Tx x, Ty y)
|
||||
{
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
float sampleMask(thread const float& maskAlpha, thread const texture2d<float> maskTexture, thread const sampler maskTextureSmplr, thread const float3& maskTexCoord, thread const int& maskCtrl)
|
||||
{
|
||||
if (maskCtrl == 0)
|
||||
{
|
||||
return maskAlpha;
|
||||
}
|
||||
float coverage = maskTexture.sample(maskTextureSmplr, maskTexCoord.xy).x + maskTexCoord.z;
|
||||
if ((maskCtrl & 1) != 0)
|
||||
{
|
||||
coverage = abs(coverage);
|
||||
}
|
||||
else
|
||||
{
|
||||
coverage = 1.0 - abs(1.0 - mod(coverage, 2.0));
|
||||
}
|
||||
return fast::min(maskAlpha, coverage);
|
||||
}
|
||||
|
||||
float4 filterBlur(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTextureSize, thread const float4& filterParams0, thread const float4& filterParams1)
|
||||
{
|
||||
float2 srcOffsetScale = filterParams0.xy / colorTextureSize;
|
||||
int support = int(filterParams0.z);
|
||||
float3 gaussCoeff = filterParams1.xyz;
|
||||
float gaussSum = gaussCoeff.x;
|
||||
float4 color = colorTexture.sample(colorTextureSmplr, colorTexCoord) * gaussCoeff.x;
|
||||
float2 _435 = gaussCoeff.xy * gaussCoeff.yz;
|
||||
gaussCoeff = float3(_435.x, _435.y, gaussCoeff.z);
|
||||
for (int i = 1; i <= support; i += 2)
|
||||
{
|
||||
float gaussPartialSum = gaussCoeff.x;
|
||||
float2 _455 = gaussCoeff.xy * gaussCoeff.yz;
|
||||
gaussCoeff = float3(_455.x, _455.y, gaussCoeff.z);
|
||||
gaussPartialSum += gaussCoeff.x;
|
||||
float2 srcOffset = srcOffsetScale * (float(i) + (gaussCoeff.x / gaussPartialSum));
|
||||
color += ((colorTexture.sample(colorTextureSmplr, (colorTexCoord - srcOffset)) + colorTexture.sample(colorTextureSmplr, (colorTexCoord + srcOffset))) * gaussPartialSum);
|
||||
gaussSum += (2.0 * gaussPartialSum);
|
||||
float2 _495 = gaussCoeff.xy * gaussCoeff.yz;
|
||||
gaussCoeff = float3(_495.x, _495.y, gaussCoeff.z);
|
||||
}
|
||||
return color / float4(gaussSum);
|
||||
}
|
||||
|
||||
float filterTextSample1Tap(thread const float& offset, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTexCoord)
|
||||
{
|
||||
return colorTexture.sample(colorTextureSmplr, (colorTexCoord + float2(offset, 0.0))).x;
|
||||
}
|
||||
|
||||
void filterTextSample9Tap(thread float4& outAlphaLeft, thread float& outAlphaCenter, thread float4& outAlphaRight, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTexCoord, thread const float4& kernel0, thread const float& onePixel)
|
||||
{
|
||||
bool wide = kernel0.x > 0.0;
|
||||
float _183;
|
||||
if (wide)
|
||||
{
|
||||
float param = (-4.0) * onePixel;
|
||||
float2 param_1 = colorTexCoord;
|
||||
_183 = filterTextSample1Tap(param, colorTexture, colorTextureSmplr, param_1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_183 = 0.0;
|
||||
}
|
||||
float param_2 = (-3.0) * onePixel;
|
||||
float2 param_3 = colorTexCoord;
|
||||
float param_4 = (-2.0) * onePixel;
|
||||
float2 param_5 = colorTexCoord;
|
||||
float param_6 = (-1.0) * onePixel;
|
||||
float2 param_7 = colorTexCoord;
|
||||
outAlphaLeft = float4(_183, filterTextSample1Tap(param_2, colorTexture, colorTextureSmplr, param_3), filterTextSample1Tap(param_4, colorTexture, colorTextureSmplr, param_5), filterTextSample1Tap(param_6, colorTexture, colorTextureSmplr, param_7));
|
||||
float param_8 = 0.0;
|
||||
float2 param_9 = colorTexCoord;
|
||||
outAlphaCenter = filterTextSample1Tap(param_8, colorTexture, colorTextureSmplr, param_9);
|
||||
float param_10 = 1.0 * onePixel;
|
||||
float2 param_11 = colorTexCoord;
|
||||
float param_12 = 2.0 * onePixel;
|
||||
float2 param_13 = colorTexCoord;
|
||||
float param_14 = 3.0 * onePixel;
|
||||
float2 param_15 = colorTexCoord;
|
||||
float _243;
|
||||
if (wide)
|
||||
{
|
||||
float param_16 = 4.0 * onePixel;
|
||||
float2 param_17 = colorTexCoord;
|
||||
_243 = filterTextSample1Tap(param_16, colorTexture, colorTextureSmplr, param_17);
|
||||
}
|
||||
else
|
||||
{
|
||||
_243 = 0.0;
|
||||
}
|
||||
outAlphaRight = float4(filterTextSample1Tap(param_10, colorTexture, colorTextureSmplr, param_11), filterTextSample1Tap(param_12, colorTexture, colorTextureSmplr, param_13), filterTextSample1Tap(param_14, colorTexture, colorTextureSmplr, param_15), _243);
|
||||
}
|
||||
|
||||
float filterTextConvolve7Tap(thread const float4& alpha0, thread const float3& alpha1, thread const float4& kernel0)
|
||||
{
|
||||
return dot(alpha0, kernel0) + dot(alpha1, kernel0.zyx);
|
||||
}
|
||||
|
||||
float filterTextGammaCorrectChannel(thread const float& bgColor, thread const float& fgColor, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr)
|
||||
{
|
||||
return gammaLUT.sample(gammaLUTSmplr, float2(fgColor, 1.0 - bgColor)).x;
|
||||
}
|
||||
|
||||
float3 filterTextGammaCorrect(thread const float3& bgColor, thread const float3& fgColor, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr)
|
||||
{
|
||||
float param = bgColor.x;
|
||||
float param_1 = fgColor.x;
|
||||
float param_2 = bgColor.y;
|
||||
float param_3 = fgColor.y;
|
||||
float param_4 = bgColor.z;
|
||||
float param_5 = fgColor.z;
|
||||
return float3(filterTextGammaCorrectChannel(param, param_1, gammaLUT, gammaLUTSmplr), filterTextGammaCorrectChannel(param_2, param_3, gammaLUT, gammaLUTSmplr), filterTextGammaCorrectChannel(param_4, param_5, gammaLUT, gammaLUTSmplr));
|
||||
}
|
||||
|
||||
float4 filterText(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr, thread const float2& colorTextureSize, thread const float4& filterParams0, thread const float4& filterParams1, thread const float4& filterParams2)
|
||||
{
|
||||
float4 kernel0 = filterParams0;
|
||||
float3 bgColor = filterParams1.xyz;
|
||||
float3 fgColor = filterParams2.xyz;
|
||||
bool gammaCorrectionEnabled = filterParams2.w != 0.0;
|
||||
float3 alpha;
|
||||
if (kernel0.w == 0.0)
|
||||
{
|
||||
alpha = colorTexture.sample(colorTextureSmplr, colorTexCoord).xxx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float2 param_3 = colorTexCoord;
|
||||
float4 param_4 = kernel0;
|
||||
float param_5 = 1.0 / colorTextureSize.x;
|
||||
float4 param;
|
||||
float param_1;
|
||||
float4 param_2;
|
||||
filterTextSample9Tap(param, param_1, param_2, colorTexture, colorTextureSmplr, param_3, param_4, param_5);
|
||||
float4 alphaLeft = param;
|
||||
float alphaCenter = param_1;
|
||||
float4 alphaRight = param_2;
|
||||
float4 param_6 = alphaLeft;
|
||||
float3 param_7 = float3(alphaCenter, alphaRight.xy);
|
||||
float4 param_8 = kernel0;
|
||||
float r = filterTextConvolve7Tap(param_6, param_7, param_8);
|
||||
float4 param_9 = float4(alphaLeft.yzw, alphaCenter);
|
||||
float3 param_10 = alphaRight.xyz;
|
||||
float4 param_11 = kernel0;
|
||||
float g = filterTextConvolve7Tap(param_9, param_10, param_11);
|
||||
float4 param_12 = float4(alphaLeft.zw, alphaCenter, alphaRight.x);
|
||||
float3 param_13 = alphaRight.yzw;
|
||||
float4 param_14 = kernel0;
|
||||
float b = filterTextConvolve7Tap(param_12, param_13, param_14);
|
||||
alpha = float3(r, g, b);
|
||||
}
|
||||
if (gammaCorrectionEnabled)
|
||||
{
|
||||
float3 param_15 = bgColor;
|
||||
float3 param_16 = alpha;
|
||||
alpha = filterTextGammaCorrect(param_15, param_16, gammaLUT, gammaLUTSmplr);
|
||||
}
|
||||
return float4(mix(bgColor, fgColor, alpha), 1.0);
|
||||
}
|
||||
|
||||
float4 sampleColor(thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const float2& colorTexCoord)
|
||||
{
|
||||
return colorTexture.sample(colorTextureSmplr, colorTexCoord);
|
||||
}
|
||||
|
||||
float4 filterNone(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr)
|
||||
{
|
||||
float2 param = colorTexCoord;
|
||||
return sampleColor(colorTexture, colorTextureSmplr, param);
|
||||
}
|
||||
|
||||
float4 filterColor(thread const float2& colorTexCoord, thread const texture2d<float> colorTexture, thread const sampler colorTextureSmplr, thread const texture2d<float> gammaLUT, thread const sampler gammaLUTSmplr, thread const float2& colorTextureSize, thread const float4& filterParams0, thread const float4& filterParams1, thread const float4& filterParams2, thread const int& colorFilter)
|
||||
{
|
||||
switch (colorFilter)
|
||||
{
|
||||
case 3:
|
||||
{
|
||||
float2 param = colorTexCoord;
|
||||
float2 param_1 = colorTextureSize;
|
||||
float4 param_2 = filterParams0;
|
||||
float4 param_3 = filterParams1;
|
||||
return filterBlur(param, colorTexture, colorTextureSmplr, param_1, param_2, param_3);
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
float2 param_4 = colorTexCoord;
|
||||
float2 param_5 = colorTextureSize;
|
||||
float4 param_6 = filterParams0;
|
||||
float4 param_7 = filterParams1;
|
||||
float4 param_8 = filterParams2;
|
||||
return filterText(param_4, colorTexture, colorTextureSmplr, gammaLUT, gammaLUTSmplr, param_5, param_6, param_7, param_8);
|
||||
}
|
||||
}
|
||||
float2 param_9 = colorTexCoord;
|
||||
return filterNone(param_9, colorTexture, colorTextureSmplr);
|
||||
}
|
||||
|
||||
float3 compositeScreen(thread const float3& destColor, thread const float3& srcColor)
|
||||
{
|
||||
return (destColor + srcColor) - (destColor * srcColor);
|
||||
}
|
||||
|
||||
float3 compositeSelect(thread const bool3& cond, thread const float3& ifTrue, thread const float3& ifFalse)
|
||||
{
|
||||
float _546;
|
||||
if (cond.x)
|
||||
{
|
||||
_546 = ifTrue.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
_546 = ifFalse.x;
|
||||
}
|
||||
float _557;
|
||||
if (cond.y)
|
||||
{
|
||||
_557 = ifTrue.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
_557 = ifFalse.y;
|
||||
}
|
||||
float _568;
|
||||
if (cond.z)
|
||||
{
|
||||
_568 = ifTrue.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
_568 = ifFalse.z;
|
||||
}
|
||||
return float3(_546, _557, _568);
|
||||
}
|
||||
|
||||
float3 compositeHardLight(thread const float3& destColor, thread const float3& srcColor)
|
||||
{
|
||||
float3 param = destColor;
|
||||
float3 param_1 = (float3(2.0) * srcColor) - float3(1.0);
|
||||
bool3 param_2 = srcColor <= float3(0.5);
|
||||
float3 param_3 = (destColor * float3(2.0)) * srcColor;
|
||||
float3 param_4 = compositeScreen(param, param_1);
|
||||
return compositeSelect(param_2, param_3, param_4);
|
||||
}
|
||||
|
||||
float3 compositeColorDodge(thread const float3& destColor, thread const float3& srcColor)
|
||||
{
|
||||
bool3 destZero = destColor == float3(0.0);
|
||||
bool3 srcOne = srcColor == float3(1.0);
|
||||
bool3 param = srcOne;
|
||||
float3 param_1 = float3(1.0);
|
||||
float3 param_2 = destColor / (float3(1.0) - srcColor);
|
||||
bool3 param_3 = destZero;
|
||||
float3 param_4 = float3(0.0);
|
||||
float3 param_5 = compositeSelect(param, param_1, param_2);
|
||||
return compositeSelect(param_3, param_4, param_5);
|
||||
}
|
||||
|
||||
float3 compositeSoftLight(thread const float3& destColor, thread const float3& srcColor)
|
||||
{
|
||||
bool3 param = destColor <= float3(0.25);
|
||||
float3 param_1 = ((((float3(16.0) * destColor) - float3(12.0)) * destColor) + float3(4.0)) * destColor;
|
||||
float3 param_2 = sqrt(destColor);
|
||||
float3 darkenedDestColor = compositeSelect(param, param_1, param_2);
|
||||
bool3 param_3 = srcColor <= float3(0.5);
|
||||
float3 param_4 = destColor * (float3(1.0) - destColor);
|
||||
float3 param_5 = darkenedDestColor - destColor;
|
||||
float3 factor = compositeSelect(param_3, param_4, param_5);
|
||||
return destColor + (((srcColor * 2.0) - float3(1.0)) * factor);
|
||||
}
|
||||
|
||||
float compositeDivide(thread const float& num, thread const float& denom)
|
||||
{
|
||||
float _582;
|
||||
if (denom != 0.0)
|
||||
{
|
||||
_582 = num / denom;
|
||||
}
|
||||
else
|
||||
{
|
||||
_582 = 0.0;
|
||||
}
|
||||
return _582;
|
||||
}
|
||||
|
||||
float3 compositeRGBToHSL(thread const float3& rgb)
|
||||
{
|
||||
float v = fast::max(fast::max(rgb.x, rgb.y), rgb.z);
|
||||
float xMin = fast::min(fast::min(rgb.x, rgb.y), rgb.z);
|
||||
float c = v - xMin;
|
||||
float l = mix(xMin, v, 0.5);
|
||||
float3 _688;
|
||||
if (rgb.x == v)
|
||||
{
|
||||
_688 = float3(0.0, rgb.yz);
|
||||
}
|
||||
else
|
||||
{
|
||||
float3 _701;
|
||||
if (rgb.y == v)
|
||||
{
|
||||
_701 = float3(2.0, rgb.zx);
|
||||
}
|
||||
else
|
||||
{
|
||||
_701 = float3(4.0, rgb.xy);
|
||||
}
|
||||
_688 = _701;
|
||||
}
|
||||
float3 terms = _688;
|
||||
float param = ((terms.x * c) + terms.y) - terms.z;
|
||||
float param_1 = c;
|
||||
float h = 1.0471975803375244140625 * compositeDivide(param, param_1);
|
||||
float param_2 = c;
|
||||
float param_3 = v;
|
||||
float s = compositeDivide(param_2, param_3);
|
||||
return float3(h, s, l);
|
||||
}
|
||||
|
||||
float3 compositeHSL(thread const float3& destColor, thread const float3& srcColor, thread const int& op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case 12:
|
||||
{
|
||||
return float3(srcColor.x, destColor.y, destColor.z);
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
return float3(destColor.x, srcColor.y, destColor.z);
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
return float3(srcColor.x, srcColor.y, destColor.z);
|
||||
}
|
||||
default:
|
||||
{
|
||||
return float3(destColor.x, destColor.y, srcColor.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float3 compositeHSLToRGB(thread const float3& hsl)
|
||||
{
|
||||
float a = hsl.y * fast::min(hsl.z, 1.0 - hsl.z);
|
||||
float3 ks = mod(float3(0.0, 8.0, 4.0) + float3(hsl.x * 1.90985929965972900390625), float3(12.0));
|
||||
return hsl.zzz - (fast::clamp(fast::min(ks - float3(3.0), float3(9.0) - ks), float3(-1.0), float3(1.0)) * a);
|
||||
}
|
||||
|
||||
float3 compositeRGB(thread const float3& destColor, thread const float3& srcColor, thread const int& op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
return destColor * srcColor;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
float3 param = destColor;
|
||||
float3 param_1 = srcColor;
|
||||
return compositeScreen(param, param_1);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
float3 param_2 = srcColor;
|
||||
float3 param_3 = destColor;
|
||||
return compositeHardLight(param_2, param_3);
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
return fast::min(destColor, srcColor);
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
return fast::max(destColor, srcColor);
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
float3 param_4 = destColor;
|
||||
float3 param_5 = srcColor;
|
||||
return compositeColorDodge(param_4, param_5);
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
float3 param_6 = float3(1.0) - destColor;
|
||||
float3 param_7 = float3(1.0) - srcColor;
|
||||
return float3(1.0) - compositeColorDodge(param_6, param_7);
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
float3 param_8 = destColor;
|
||||
float3 param_9 = srcColor;
|
||||
return compositeHardLight(param_8, param_9);
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
float3 param_10 = destColor;
|
||||
float3 param_11 = srcColor;
|
||||
return compositeSoftLight(param_10, param_11);
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
return abs(destColor - srcColor);
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
return (destColor + srcColor) - ((float3(2.0) * destColor) * srcColor);
|
||||
}
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
{
|
||||
float3 param_12 = destColor;
|
||||
float3 param_13 = srcColor;
|
||||
float3 param_14 = compositeRGBToHSL(param_12);
|
||||
float3 param_15 = compositeRGBToHSL(param_13);
|
||||
int param_16 = op;
|
||||
float3 param_17 = compositeHSL(param_14, param_15, param_16);
|
||||
return compositeHSLToRGB(param_17);
|
||||
}
|
||||
}
|
||||
return srcColor;
|
||||
}
|
||||
|
||||
float4 composite(thread const float4& srcColor, thread const texture2d<float> destTexture, thread const sampler destTextureSmplr, thread const float2& destTextureSize, thread const float2& fragCoord, thread const int& op)
|
||||
{
|
||||
if (op == 0)
|
||||
{
|
||||
return srcColor;
|
||||
}
|
||||
float2 destTexCoord = fragCoord / destTextureSize;
|
||||
float4 destColor = destTexture.sample(destTextureSmplr, destTexCoord);
|
||||
float3 param = destColor.xyz;
|
||||
float3 param_1 = srcColor.xyz;
|
||||
int param_2 = op;
|
||||
float3 blendedRGB = compositeRGB(param, param_1, param_2);
|
||||
return float4(((srcColor.xyz * (srcColor.w * (1.0 - destColor.w))) + (blendedRGB * (srcColor.w * destColor.w))) + (destColor.xyz * (1.0 - srcColor.w)), 1.0);
|
||||
}
|
||||
|
||||
void calculateColor(thread const int& ctrl, thread texture2d<float> uMaskTexture0, thread const sampler uMaskTexture0Smplr, thread float3& vMaskTexCoord0, thread texture2d<float> uMaskTexture1, thread const sampler uMaskTexture1Smplr, thread float3& vMaskTexCoord1, thread float2& vColorTexCoord0, thread texture2d<float> uColorTexture0, thread const sampler uColorTexture0Smplr, thread texture2d<float> uGammaLUT, thread const sampler uGammaLUTSmplr, thread float2 uColorTexture0Size, thread float4 uFilterParams0, thread float4 uFilterParams1, thread float4 uFilterParams2, thread texture2d<float> uColorTexture1, thread const sampler uColorTexture1Smplr, thread float2& vColorTexCoord1, thread texture2d<float> uDestTexture, thread const sampler uDestTextureSmplr, thread float2 uDestTextureSize, thread float4& gl_FragCoord, thread float4& oFragColor)
|
||||
{
|
||||
int maskCtrl0 = (ctrl >> 0) & 3;
|
||||
int maskCtrl1 = (ctrl >> 2) & 3;
|
||||
float maskAlpha = 1.0;
|
||||
float param = maskAlpha;
|
||||
float3 param_1 = vMaskTexCoord0;
|
||||
int param_2 = maskCtrl0;
|
||||
maskAlpha = sampleMask(param, uMaskTexture0, uMaskTexture0Smplr, param_1, param_2);
|
||||
float param_3 = maskAlpha;
|
||||
float3 param_4 = vMaskTexCoord1;
|
||||
int param_5 = maskCtrl1;
|
||||
maskAlpha = sampleMask(param_3, uMaskTexture1, uMaskTexture1Smplr, param_4, param_5);
|
||||
float4 color = float4(0.0);
|
||||
if (((ctrl >> 6) & 1) != 0)
|
||||
{
|
||||
int color0Filter = (ctrl >> 4) & 3;
|
||||
float2 param_6 = vColorTexCoord0;
|
||||
float2 param_7 = uColorTexture0Size;
|
||||
float4 param_8 = uFilterParams0;
|
||||
float4 param_9 = uFilterParams1;
|
||||
float4 param_10 = uFilterParams2;
|
||||
int param_11 = color0Filter;
|
||||
color += filterColor(param_6, uColorTexture0, uColorTexture0Smplr, uGammaLUT, uGammaLUTSmplr, param_7, param_8, param_9, param_10, param_11);
|
||||
}
|
||||
if (((ctrl >> 7) & 1) != 0)
|
||||
{
|
||||
float2 param_12 = vColorTexCoord1;
|
||||
color *= sampleColor(uColorTexture1, uColorTexture1Smplr, param_12);
|
||||
}
|
||||
color.w *= maskAlpha;
|
||||
int compositeOp = (ctrl >> 8) & 15;
|
||||
float4 param_13 = color;
|
||||
float2 param_14 = uDestTextureSize;
|
||||
float2 param_15 = gl_FragCoord.xy;
|
||||
int param_16 = compositeOp;
|
||||
color = composite(param_13, uDestTexture, uDestTextureSmplr, param_14, param_15, param_16);
|
||||
float3 _1159 = color.xyz * color.w;
|
||||
color = float4(_1159.x, _1159.y, _1159.z, color.w);
|
||||
oFragColor = color;
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
int param = (*spvDescriptorSet0.uCtrl);
|
||||
calculateColor(param, spvDescriptorSet0.uMaskTexture0, spvDescriptorSet0.uMaskTexture0Smplr, in.vMaskTexCoord0, spvDescriptorSet0.uMaskTexture1, spvDescriptorSet0.uMaskTexture1Smplr, in.vMaskTexCoord1, in.vColorTexCoord0, spvDescriptorSet0.uColorTexture0, spvDescriptorSet0.uColorTexture0Smplr, spvDescriptorSet0.uGammaLUT, spvDescriptorSet0.uGammaLUTSmplr, (*spvDescriptorSet0.uColorTexture0Size), (*spvDescriptorSet0.uFilterParams0), (*spvDescriptorSet0.uFilterParams1), (*spvDescriptorSet0.uFilterParams2), spvDescriptorSet0.uColorTexture1, spvDescriptorSet0.uColorTexture1Smplr, in.vColorTexCoord1, spvDescriptorSet0.uDestTexture, spvDescriptorSet0.uDestTextureSmplr, (*spvDescriptorSet0.uDestTextureSize), gl_FragCoord, out.oFragColor);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -12,21 +12,31 @@ struct spvDescriptorSetBuffer0
|
|||
|
||||
struct main0_out
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float3 vMaskTexCoord0 [[user(locn0)]];
|
||||
float3 vMaskTexCoord1 [[user(locn1)]];
|
||||
float2 vColorTexCoord0 [[user(locn2)]];
|
||||
float2 vColorTexCoord1 [[user(locn3)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int2 aTilePosition [[attribute(0)]];
|
||||
float2 aColorTexCoord [[attribute(1)]];
|
||||
float2 aColorTexCoord0 [[attribute(1)]];
|
||||
float2 aColorTexCoord1 [[attribute(2)]];
|
||||
float2 aMaskTexCoord0 [[attribute(3)]];
|
||||
float2 aMaskTexCoord1 [[attribute(4)]];
|
||||
int2 aMaskBackdrop [[attribute(5)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||
out.vColorTexCoord = in.aColorTexCoord;
|
||||
out.vColorTexCoord0 = in.aColorTexCoord0;
|
||||
out.vColorTexCoord1 = in.aColorTexCoord1;
|
||||
out.vMaskTexCoord0 = float3(in.aMaskTexCoord0, float(in.aMaskBackdrop.x));
|
||||
out.vMaskTexCoord1 = float3(in.aMaskTexCoord1, float(in.aMaskBackdrop.y));
|
||||
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
out.oFragColor = float4(srcRGBA.xyz * srcRGBA.w, srcRGBA.w);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
constant float2* uTileSize [[id(0)]];
|
||||
constant float4x4* uTransform [[id(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int2 aTilePosition [[attribute(0)]];
|
||||
float2 aColorTexCoord [[attribute(1)]];
|
||||
float2 aMaskTexCoord [[attribute(2)]];
|
||||
float aOpacity [[attribute(3)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float2 position = float2(in.aTilePosition) * (*spvDescriptorSet0.uTileSize);
|
||||
out.vMaskTexCoord = in.aMaskTexCoord;
|
||||
out.vColorTexCoord = in.aColorTexCoord;
|
||||
out.vOpacity = in.aOpacity;
|
||||
out.gl_Position = (*spvDescriptorSet0.uTransform) * float4(position, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d<float> uDest, thread const sampler uDestSmplr)
|
||||
{
|
||||
float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return uDest.sample(uDestSmplr, destTexCoord);
|
||||
}
|
||||
|
||||
float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB)
|
||||
{
|
||||
return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr);
|
||||
float3 blended = abs(destRGBA.xyz - srcRGBA.xyz);
|
||||
float4 param = destRGBA;
|
||||
float4 param_1 = srcRGBA;
|
||||
float3 param_2 = blended;
|
||||
out.oFragColor = blendColors(param, param_1, param_2);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
constant int* uBurn [[id(7)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d<float> uDest, thread const sampler uDestSmplr)
|
||||
{
|
||||
float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return uDest.sample(uDestSmplr, destTexCoord);
|
||||
}
|
||||
|
||||
float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB)
|
||||
{
|
||||
return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr);
|
||||
float3 _122;
|
||||
if ((*spvDescriptorSet0.uBurn) == 0)
|
||||
{
|
||||
_122 = destRGBA.xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
_122 = float3(1.0) - destRGBA.xyz;
|
||||
}
|
||||
float3 dest = _122;
|
||||
float3 _136;
|
||||
if ((*spvDescriptorSet0.uBurn) == 0)
|
||||
{
|
||||
_136 = float3(1.0) - srcRGBA.xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
_136 = srcRGBA.xyz;
|
||||
}
|
||||
float3 src = _136;
|
||||
bool3 srcNonzero = src != float3(0.0);
|
||||
float _157;
|
||||
if (srcNonzero.x)
|
||||
{
|
||||
_157 = dest.x / src.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
_157 = 1.0;
|
||||
}
|
||||
float _170;
|
||||
if (srcNonzero.y)
|
||||
{
|
||||
_170 = dest.y / src.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
_170 = 1.0;
|
||||
}
|
||||
float _183;
|
||||
if (srcNonzero.z)
|
||||
{
|
||||
_183 = dest.z / src.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
_183 = 1.0;
|
||||
}
|
||||
float3 blended = fast::min(float3(_157, _170, _183), float3(1.0));
|
||||
if ((*spvDescriptorSet0.uBurn) != 0)
|
||||
{
|
||||
blended = float3(1.0) - blended;
|
||||
}
|
||||
float4 param = destRGBA;
|
||||
float4 param_1 = srcRGBA;
|
||||
float3 param_2 = blended;
|
||||
out.oFragColor = blendColors(param, param_1, param_2);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d<float> uDest, thread const sampler uDestSmplr)
|
||||
{
|
||||
float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return uDest.sample(uDestSmplr, destTexCoord);
|
||||
}
|
||||
|
||||
float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB)
|
||||
{
|
||||
return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr);
|
||||
float3 dest = destRGBA.xyz;
|
||||
float3 src = srcRGBA.xyz;
|
||||
float3 blended = (dest + src) - ((dest * src) * 2.0);
|
||||
float4 param = destRGBA;
|
||||
float4 param_1 = srcRGBA;
|
||||
float3 param_2 = blended;
|
||||
out.oFragColor = blendColors(param, param_1, param_2);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
constant int3* uBlendHSL [[id(7)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
// Implementation of the GLSL mod() function, which is slightly different than Metal fmod()
|
||||
template<typename Tx, typename Ty>
|
||||
Tx mod(Tx x, Ty y)
|
||||
{
|
||||
return x - y * floor(x / y);
|
||||
}
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d<float> uDest, thread const sampler uDestSmplr)
|
||||
{
|
||||
float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return uDest.sample(uDestSmplr, destTexCoord);
|
||||
}
|
||||
|
||||
float3 convertRGBToHSL(thread const float3& rgb)
|
||||
{
|
||||
float v = fast::max(rgb.y, rgb.z);
|
||||
float c = v - fast::min(rgb.y, rgb.z);
|
||||
float l = v - (0.5 * c);
|
||||
float3 tmp = float3(0.0);
|
||||
bool3 is_v = rgb == float3(v);
|
||||
if (is_v.x)
|
||||
{
|
||||
tmp = float3(0.0, rgb.yz);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_v.y)
|
||||
{
|
||||
tmp = float3(2.0, rgb.zx);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_v.z)
|
||||
{
|
||||
tmp = float3(4.0, rgb.xy);
|
||||
}
|
||||
}
|
||||
}
|
||||
float h = 1.0471975803375244140625 * (tmp.x + ((tmp.y - tmp.z) / c));
|
||||
float s = 0.0;
|
||||
if ((l > 0.0) && (l < 1.0))
|
||||
{
|
||||
s = (v - l) / fast::min(l, 1.0 - l);
|
||||
}
|
||||
return float3(h, s, l);
|
||||
}
|
||||
|
||||
float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b)
|
||||
{
|
||||
float _129;
|
||||
if (cond.x)
|
||||
{
|
||||
_129 = a.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
_129 = b.x;
|
||||
}
|
||||
float _141;
|
||||
if (cond.y)
|
||||
{
|
||||
_141 = a.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
_141 = b.y;
|
||||
}
|
||||
float _153;
|
||||
if (cond.z)
|
||||
{
|
||||
_153 = a.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
_153 = b.z;
|
||||
}
|
||||
return float3(_129, _141, _153);
|
||||
}
|
||||
|
||||
float3 convertHSLToRGB(thread const float3& hsl)
|
||||
{
|
||||
float a = hsl.y * fast::min(hsl.z, 1.0 - hsl.z);
|
||||
float3 ks = mod(float3(0.0, 8.0, 4.0) + float3(hsl.x * 1.90985929965972900390625), float3(12.0));
|
||||
return hsl.zzz - (fast::clamp(fast::min(ks - float3(3.0), float3(9.0) - ks), float3(-1.0), float3(1.0)) * a);
|
||||
}
|
||||
|
||||
float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB)
|
||||
{
|
||||
return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr);
|
||||
float3 param = destRGBA.xyz;
|
||||
float3 destHSL = convertRGBToHSL(param);
|
||||
float3 param_1 = srcRGBA.xyz;
|
||||
float3 srcHSL = convertRGBToHSL(param_1);
|
||||
bool3 param_2 = (*spvDescriptorSet0.uBlendHSL) == int3(0);
|
||||
float3 param_3 = destHSL;
|
||||
float3 param_4 = srcHSL;
|
||||
float3 blendedHSL = select3(param_2, param_3, param_4);
|
||||
float3 param_5 = blendedHSL;
|
||||
float3 blendedRGB = convertHSLToRGB(param_5);
|
||||
float4 param_6 = destRGBA;
|
||||
float4 param_7 = srcRGBA;
|
||||
float3 param_8 = blendedRGB;
|
||||
out.oFragColor = blendColors(param_6, param_7, param_8);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
constant int* uBlendMode [[id(7)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d<float> uDest, thread const sampler uDestSmplr)
|
||||
{
|
||||
float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return uDest.sample(uDestSmplr, destTexCoord);
|
||||
}
|
||||
|
||||
float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b)
|
||||
{
|
||||
float _122;
|
||||
if (cond.x)
|
||||
{
|
||||
_122 = a.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
_122 = b.x;
|
||||
}
|
||||
float _134;
|
||||
if (cond.y)
|
||||
{
|
||||
_134 = a.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
_134 = b.y;
|
||||
}
|
||||
float _146;
|
||||
if (cond.z)
|
||||
{
|
||||
_146 = a.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
_146 = b.z;
|
||||
}
|
||||
return float3(_122, _134, _146);
|
||||
}
|
||||
|
||||
float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB)
|
||||
{
|
||||
return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr);
|
||||
bool reversed = (*spvDescriptorSet0.uBlendMode) == 3;
|
||||
float3 _171;
|
||||
if (reversed)
|
||||
{
|
||||
_171 = srcRGBA.xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
_171 = destRGBA.xyz;
|
||||
}
|
||||
float3 src = _171;
|
||||
float3 _182;
|
||||
if (reversed)
|
||||
{
|
||||
_182 = destRGBA.xyz;
|
||||
}
|
||||
else
|
||||
{
|
||||
_182 = srcRGBA.xyz;
|
||||
}
|
||||
float3 dest = _182;
|
||||
float3 multiply = src * dest;
|
||||
float3 blended;
|
||||
if ((*spvDescriptorSet0.uBlendMode) == 0)
|
||||
{
|
||||
blended = multiply;
|
||||
}
|
||||
else
|
||||
{
|
||||
float3 screen = (dest + src) - multiply;
|
||||
if ((*spvDescriptorSet0.uBlendMode) == 1)
|
||||
{
|
||||
blended = screen;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool3 param = src <= float3(0.5);
|
||||
float3 param_1 = multiply;
|
||||
float3 param_2 = (screen * 2.0) - float3(1.0);
|
||||
blended = select3(param, param_1, param_2);
|
||||
}
|
||||
}
|
||||
float4 param_3 = destRGBA;
|
||||
float4 param_4 = srcRGBA;
|
||||
float3 param_5 = blended;
|
||||
out.oFragColor = blendColors(param_3, param_4, param_5);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uStencilTexture [[id(0)]];
|
||||
sampler uStencilTextureSmplr [[id(1)]];
|
||||
texture2d<float> uPaintTexture [[id(2)]];
|
||||
sampler uPaintTextureSmplr [[id(3)]];
|
||||
constant float2* uFramebufferSize [[id(4)]];
|
||||
texture2d<float> uDest [[id(5)]];
|
||||
sampler uDestSmplr [[id(6)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
float2 vMaskTexCoord [[user(locn1)]];
|
||||
float vOpacity [[user(locn2)]];
|
||||
};
|
||||
|
||||
float4 sampleSrcColor(thread texture2d<float> uStencilTexture, thread const sampler uStencilTextureSmplr, thread float2& vMaskTexCoord, thread texture2d<float> uPaintTexture, thread const sampler uPaintTextureSmplr, thread float2& vColorTexCoord, thread float& vOpacity)
|
||||
{
|
||||
float coverage = uStencilTexture.sample(uStencilTextureSmplr, vMaskTexCoord).x;
|
||||
float4 srcRGBA = uPaintTexture.sample(uPaintTextureSmplr, vColorTexCoord);
|
||||
return float4(srcRGBA.xyz, (srcRGBA.w * coverage) * vOpacity);
|
||||
}
|
||||
|
||||
float4 sampleDestColor(thread float4& gl_FragCoord, thread float2 uFramebufferSize, thread texture2d<float> uDest, thread const sampler uDestSmplr)
|
||||
{
|
||||
float2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return uDest.sample(uDestSmplr, destTexCoord);
|
||||
}
|
||||
|
||||
float3 select3(thread const bool3& cond, thread const float3& a, thread const float3& b)
|
||||
{
|
||||
float _122;
|
||||
if (cond.x)
|
||||
{
|
||||
_122 = a.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
_122 = b.x;
|
||||
}
|
||||
float _134;
|
||||
if (cond.y)
|
||||
{
|
||||
_134 = a.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
_134 = b.y;
|
||||
}
|
||||
float _146;
|
||||
if (cond.z)
|
||||
{
|
||||
_146 = a.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
_146 = b.z;
|
||||
}
|
||||
return float3(_122, _134, _146);
|
||||
}
|
||||
|
||||
float4 blendColors(thread const float4& destRGBA, thread const float4& srcRGBA, thread const float3& blendedRGB)
|
||||
{
|
||||
return float4(((srcRGBA.xyz * (srcRGBA.w * (1.0 - destRGBA.w))) + (blendedRGB * (srcRGBA.w * destRGBA.w))) + (destRGBA.xyz * ((1.0 - srcRGBA.w) * destRGBA.w)), 1.0);
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]], float4 gl_FragCoord [[position]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 srcRGBA = sampleSrcColor(spvDescriptorSet0.uStencilTexture, spvDescriptorSet0.uStencilTextureSmplr, in.vMaskTexCoord, spvDescriptorSet0.uPaintTexture, spvDescriptorSet0.uPaintTextureSmplr, in.vColorTexCoord, in.vOpacity);
|
||||
float4 destRGBA = sampleDestColor(gl_FragCoord, (*spvDescriptorSet0.uFramebufferSize), spvDescriptorSet0.uDest, spvDescriptorSet0.uDestSmplr);
|
||||
float3 dest = destRGBA.xyz;
|
||||
float3 src = srcRGBA.xyz;
|
||||
bool3 destDark = dest <= float3(0.25);
|
||||
bool3 srcDark = src <= float3(0.5);
|
||||
bool3 param = destDark;
|
||||
float3 param_1 = (((dest * 16.0) - float3(12.0)) * dest) + float3(4.0);
|
||||
float3 param_2 = rsqrt(dest);
|
||||
float3 d = select3(param, param_1, param_2);
|
||||
bool3 param_3 = srcDark;
|
||||
float3 param_4 = float3(1.0) - dest;
|
||||
float3 param_5 = d - float3(1.0);
|
||||
float3 x = select3(param_3, param_4, param_5);
|
||||
float3 blended = dest * ((((src * 2.0) - float3(1.0)) * x) + float3(1.0));
|
||||
float4 param_6 = destRGBA;
|
||||
float4 param_7 = srcRGBA;
|
||||
float3 param_8 = blended;
|
||||
out.oFragColor = blendColors(param_6, param_7, param_8);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uColorTexture [[id(0)]];
|
||||
sampler uColorTextureSmplr [[id(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 color = spvDescriptorSet0.uColorTexture.sample(spvDescriptorSet0.uColorTextureSmplr, in.vColorTexCoord);
|
||||
out.oFragColor = float4(color.xyz * color.w, color.w);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
constant float3* uInitialGaussCoeff [[id(0)]];
|
||||
texture2d<float> uColorTexture [[id(1)]];
|
||||
sampler uColorTextureSmplr [[id(2)]];
|
||||
constant int* uSupport [[id(3)]];
|
||||
constant float2* uSrcOffsetScale [[id(4)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float3 gaussCoeff = (*spvDescriptorSet0.uInitialGaussCoeff);
|
||||
float gaussSum = gaussCoeff.x;
|
||||
float4 color = spvDescriptorSet0.uColorTexture.sample(spvDescriptorSet0.uColorTextureSmplr, in.vColorTexCoord) * gaussCoeff.x;
|
||||
float2 _39 = gaussCoeff.xy * gaussCoeff.yz;
|
||||
gaussCoeff = float3(_39.x, _39.y, gaussCoeff.z);
|
||||
for (int i = 1; i <= (*spvDescriptorSet0.uSupport); i += 2)
|
||||
{
|
||||
float gaussPartialSum = gaussCoeff.x;
|
||||
float2 _64 = gaussCoeff.xy * gaussCoeff.yz;
|
||||
gaussCoeff = float3(_64.x, _64.y, gaussCoeff.z);
|
||||
gaussPartialSum += gaussCoeff.x;
|
||||
float2 srcOffset = (*spvDescriptorSet0.uSrcOffsetScale) * (float(i) + (gaussCoeff.x / gaussPartialSum));
|
||||
color += ((spvDescriptorSet0.uColorTexture.sample(spvDescriptorSet0.uColorTextureSmplr, (in.vColorTexCoord - srcOffset)) + spvDescriptorSet0.uColorTexture.sample(spvDescriptorSet0.uColorTextureSmplr, (in.vColorTexCoord + srcOffset))) * gaussPartialSum);
|
||||
gaussSum += (2.0 * gaussPartialSum);
|
||||
float2 _108 = gaussCoeff.xy * gaussCoeff.yz;
|
||||
gaussCoeff = float3(_108.x, _108.y, gaussCoeff.z);
|
||||
}
|
||||
color /= float4(gaussSum);
|
||||
float3 _123 = color.xyz * color.w;
|
||||
color = float4(_123.x, _123.y, _123.z, color.w);
|
||||
out.oFragColor = color;
|
||||
return out;
|
||||
}
|
||||
|
|
@ -1,130 +0,0 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uGammaLUT [[id(0)]];
|
||||
sampler uGammaLUTSmplr [[id(1)]];
|
||||
constant float4* uKernel [[id(2)]];
|
||||
texture2d<float> uColorTexture [[id(3)]];
|
||||
sampler uColorTextureSmplr [[id(4)]];
|
||||
constant float2* uSrcSize [[id(5)]];
|
||||
constant int* uGammaCorrectionEnabled [[id(6)]];
|
||||
constant float4* uBGColor [[id(7)]];
|
||||
constant float4* uFGColor [[id(8)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vColorTexCoord [[user(locn0)]];
|
||||
};
|
||||
|
||||
float sample1Tap(thread const float& offset, thread texture2d<float> uColorTexture, thread const sampler uColorTextureSmplr, thread float2& vColorTexCoord)
|
||||
{
|
||||
return uColorTexture.sample(uColorTextureSmplr, float2(vColorTexCoord.x + offset, vColorTexCoord.y)).x;
|
||||
}
|
||||
|
||||
void sample9Tap(thread float4& outAlphaLeft, thread float& outAlphaCenter, thread float4& outAlphaRight, thread const float& onePixel, thread float4 uKernel, thread texture2d<float> uColorTexture, thread const sampler uColorTextureSmplr, thread float2& vColorTexCoord)
|
||||
{
|
||||
float _89;
|
||||
if (uKernel.x > 0.0)
|
||||
{
|
||||
float param = (-4.0) * onePixel;
|
||||
_89 = sample1Tap(param, uColorTexture, uColorTextureSmplr, vColorTexCoord);
|
||||
}
|
||||
else
|
||||
{
|
||||
_89 = 0.0;
|
||||
}
|
||||
float param_1 = (-3.0) * onePixel;
|
||||
float param_2 = (-2.0) * onePixel;
|
||||
float param_3 = (-1.0) * onePixel;
|
||||
outAlphaLeft = float4(_89, sample1Tap(param_1, uColorTexture, uColorTextureSmplr, vColorTexCoord), sample1Tap(param_2, uColorTexture, uColorTextureSmplr, vColorTexCoord), sample1Tap(param_3, uColorTexture, uColorTextureSmplr, vColorTexCoord));
|
||||
float param_4 = 0.0;
|
||||
outAlphaCenter = sample1Tap(param_4, uColorTexture, uColorTextureSmplr, vColorTexCoord);
|
||||
float param_5 = 1.0 * onePixel;
|
||||
float param_6 = 2.0 * onePixel;
|
||||
float param_7 = 3.0 * onePixel;
|
||||
float _134;
|
||||
if (uKernel.x > 0.0)
|
||||
{
|
||||
float param_8 = 4.0 * onePixel;
|
||||
_134 = sample1Tap(param_8, uColorTexture, uColorTextureSmplr, vColorTexCoord);
|
||||
}
|
||||
else
|
||||
{
|
||||
_134 = 0.0;
|
||||
}
|
||||
outAlphaRight = float4(sample1Tap(param_5, uColorTexture, uColorTextureSmplr, vColorTexCoord), sample1Tap(param_6, uColorTexture, uColorTextureSmplr, vColorTexCoord), sample1Tap(param_7, uColorTexture, uColorTextureSmplr, vColorTexCoord), _134);
|
||||
}
|
||||
|
||||
float convolve7Tap(thread const float4& alpha0, thread const float3& alpha1, thread float4 uKernel)
|
||||
{
|
||||
return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx);
|
||||
}
|
||||
|
||||
float gammaCorrectChannel(thread const float& bgColor, thread const float& fgColor, thread texture2d<float> uGammaLUT, thread const sampler uGammaLUTSmplr)
|
||||
{
|
||||
return uGammaLUT.sample(uGammaLUTSmplr, float2(fgColor, 1.0 - bgColor)).x;
|
||||
}
|
||||
|
||||
float3 gammaCorrect(thread const float3& bgColor, thread const float3& fgColor, thread texture2d<float> uGammaLUT, thread const sampler uGammaLUTSmplr)
|
||||
{
|
||||
float param = bgColor.x;
|
||||
float param_1 = fgColor.x;
|
||||
float param_2 = bgColor.y;
|
||||
float param_3 = fgColor.y;
|
||||
float param_4 = bgColor.z;
|
||||
float param_5 = fgColor.z;
|
||||
return float3(gammaCorrectChannel(param, param_1, uGammaLUT, uGammaLUTSmplr), gammaCorrectChannel(param_2, param_3, uGammaLUT, uGammaLUTSmplr), gammaCorrectChannel(param_4, param_5, uGammaLUT, uGammaLUTSmplr));
|
||||
}
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float3 alpha;
|
||||
if ((*spvDescriptorSet0.uKernel).w == 0.0)
|
||||
{
|
||||
alpha = spvDescriptorSet0.uColorTexture.sample(spvDescriptorSet0.uColorTextureSmplr, in.vColorTexCoord).xxx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float param_3 = 1.0 / (*spvDescriptorSet0.uSrcSize).x;
|
||||
float4 param;
|
||||
float param_1;
|
||||
float4 param_2;
|
||||
sample9Tap(param, param_1, param_2, param_3, (*spvDescriptorSet0.uKernel), spvDescriptorSet0.uColorTexture, spvDescriptorSet0.uColorTextureSmplr, in.vColorTexCoord);
|
||||
float4 alphaLeft = param;
|
||||
float alphaCenter = param_1;
|
||||
float4 alphaRight = param_2;
|
||||
float4 param_4 = alphaLeft;
|
||||
float3 param_5 = float3(alphaCenter, alphaRight.xy);
|
||||
float r = convolve7Tap(param_4, param_5, (*spvDescriptorSet0.uKernel));
|
||||
float4 param_6 = float4(alphaLeft.yzw, alphaCenter);
|
||||
float3 param_7 = alphaRight.xyz;
|
||||
float g = convolve7Tap(param_6, param_7, (*spvDescriptorSet0.uKernel));
|
||||
float4 param_8 = float4(alphaLeft.zw, alphaCenter, alphaRight.x);
|
||||
float3 param_9 = alphaRight.yzw;
|
||||
float b = convolve7Tap(param_8, param_9, (*spvDescriptorSet0.uKernel));
|
||||
alpha = float3(r, g, b);
|
||||
}
|
||||
if ((*spvDescriptorSet0.uGammaCorrectionEnabled) != 0)
|
||||
{
|
||||
float3 param_10 = (*spvDescriptorSet0.uBGColor).xyz;
|
||||
float3 param_11 = alpha;
|
||||
alpha = gammaCorrect(param_10, param_11, spvDescriptorSet0.uGammaLUT, spvDescriptorSet0.uGammaLUTSmplr);
|
||||
}
|
||||
out.oFragColor = float4(mix((*spvDescriptorSet0.uBGColor).xyz, (*spvDescriptorSet0.uFGColor).xyz, alpha), 1.0);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -13,33 +13,17 @@ SHADERS=\
|
|||
demo_ground.vs.glsl \
|
||||
fill.fs.glsl \
|
||||
fill.vs.glsl \
|
||||
mask.vs.glsl \
|
||||
mask_evenodd.fs.glsl \
|
||||
mask_winding.fs.glsl \
|
||||
reproject.fs.glsl \
|
||||
reproject.vs.glsl \
|
||||
stencil.fs.glsl \
|
||||
stencil.vs.glsl \
|
||||
tile_alpha.fs.glsl \
|
||||
tile_alpha.vs.glsl \
|
||||
tile_alpha_difference.fs.glsl \
|
||||
tile_alpha_dodgeburn.fs.glsl \
|
||||
tile_alpha_exclusion.fs.glsl \
|
||||
tile_alpha_hsl.fs.glsl \
|
||||
tile_alpha_overlay.fs.glsl \
|
||||
tile_alpha_softlight.fs.glsl \
|
||||
tile.fs.glsl \
|
||||
tile.vs.glsl \
|
||||
tile_copy.fs.glsl \
|
||||
tile_copy.vs.glsl \
|
||||
tile_solid.fs.glsl \
|
||||
tile_solid.vs.glsl \
|
||||
tile_solid_filter_blur.fs.glsl \
|
||||
tile_solid_filter_text.fs.glsl \
|
||||
$(EMPTY)
|
||||
|
||||
INCLUDES=\
|
||||
tile_alpha_sample.inc.glsl \
|
||||
tile_solid_filter_text_convolve.inc.glsl \
|
||||
tile_solid_filter_text_gamma_correct.inc.glsl \
|
||||
$(EMPTY)
|
||||
|
||||
OUT=\
|
||||
|
|
|
@ -12,11 +12,15 @@
|
|||
|
||||
precision highp float;
|
||||
|
||||
in vec2 aPosition;
|
||||
in ivec2 aPosition;
|
||||
|
||||
out vec2 vTexCoord;
|
||||
|
||||
void main() {
|
||||
vTexCoord = aPosition;
|
||||
gl_Position = vec4(mix(aPosition, vec2(-1.0), vec2(1.0)), 0.0, 1.0);
|
||||
vec2 texCoord = vec2(aPosition);
|
||||
#ifdef PF_ORIGIN_UPPER_LEFT
|
||||
texCoord.y = 1.0 - texCoord.y;
|
||||
#endif
|
||||
vTexCoord = texCoord;
|
||||
gl_Position = vec4(mix(vec2(-1.0), vec2(1.0), vec2(aPosition)), 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
#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 aFillTexCoord;
|
||||
in int aBackdrop;
|
||||
|
||||
out vec2 vFillTexCoord;
|
||||
out float vBackdrop;
|
||||
|
||||
void main() {
|
||||
vec2 position = mix(vec2(-1.0), vec2(1.0), aPosition);
|
||||
#ifdef PF_ORIGIN_UPPER_LEFT
|
||||
position.y = -position.y;
|
||||
#endif
|
||||
|
||||
vFillTexCoord = aFillTexCoord;
|
||||
vBackdrop = float(aBackdrop);
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/mask_evenodd.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 uFillTexture;
|
||||
|
||||
in vec2 vFillTexCoord;
|
||||
in float vBackdrop;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
float alpha = texture(uFillTexture, vFillTexCoord).r + vBackdrop;
|
||||
oFragColor = vec4(1.0 - abs(1.0 - mod(alpha, 2.0)));
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#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 uFillTexture;
|
||||
|
||||
in vec2 vFillTexCoord;
|
||||
in float vBackdrop;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
oFragColor = vec4(abs(texture(uFillTexture, vFillTexCoord).r + vBackdrop));
|
||||
}
|
|
@ -0,0 +1,460 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile.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.
|
||||
|
||||
// Mask UV 0 Mask UV 1
|
||||
// + +
|
||||
// | |
|
||||
// +-----v-----+ +-----v-----+
|
||||
// | | MIN | |
|
||||
// | Mask 0 +-----> Mask 1 +------+
|
||||
// | | | | |
|
||||
// +-----------+ +-----------+ v +-------------+
|
||||
// Apply | | GPU
|
||||
// Mask +----> Composite +---->Blender
|
||||
// ^ | |
|
||||
// +-----------+ +-----------+ | +-------------+
|
||||
// | | | | |
|
||||
// | Color 0 +-----> Color 1 +------+
|
||||
// | Filter | × | |
|
||||
// | | | |
|
||||
// +-----^-----+ +-----^-----+
|
||||
// | |
|
||||
// + +
|
||||
// Color UV 0 Color UV 1
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
#define FRAC_6_PI 1.9098593171027443
|
||||
#define FRAC_PI_3 1.0471975511965976
|
||||
|
||||
#define COMBINER_CTRL_MASK_MASK 0x3
|
||||
#define COMBINER_CTRL_MASK_WINDING 0x1
|
||||
#define COMBINER_CTRL_MASK_EVEN_ODD 0x2
|
||||
|
||||
#define COMBINER_CTRL_COLOR_ENABLE_MASK 0x1
|
||||
|
||||
#define COMBINER_CTRL_FILTER_MASK 0x3
|
||||
#define COMBINER_CTRL_FILTER_RADIAL_GRADIENT 0x1
|
||||
#define COMBINER_CTRL_FILTER_TEXT 0x2
|
||||
#define COMBINER_CTRL_FILTER_BLUR 0x3
|
||||
|
||||
#define COMBINER_CTRL_COMPOSITE_MASK 0xf
|
||||
#define COMBINER_CTRL_COMPOSITE_NORMAL 0x0
|
||||
#define COMBINER_CTRL_COMPOSITE_MULTIPLY 0x1
|
||||
#define COMBINER_CTRL_COMPOSITE_SCREEN 0x2
|
||||
#define COMBINER_CTRL_COMPOSITE_OVERLAY 0x3
|
||||
#define COMBINER_CTRL_COMPOSITE_DARKEN 0x4
|
||||
#define COMBINER_CTRL_COMPOSITE_LIGHTEN 0x5
|
||||
#define COMBINER_CTRL_COMPOSITE_COLOR_DODGE 0x6
|
||||
#define COMBINER_CTRL_COMPOSITE_COLOR_BURN 0x7
|
||||
#define COMBINER_CTRL_COMPOSITE_HARD_LIGHT 0x8
|
||||
#define COMBINER_CTRL_COMPOSITE_SOFT_LIGHT 0x9
|
||||
#define COMBINER_CTRL_COMPOSITE_DIFFERENCE 0xa
|
||||
#define COMBINER_CTRL_COMPOSITE_EXCLUSION 0xb
|
||||
#define COMBINER_CTRL_COMPOSITE_HUE 0xc
|
||||
#define COMBINER_CTRL_COMPOSITE_SATURATION 0xd
|
||||
#define COMBINER_CTRL_COMPOSITE_COLOR 0xe
|
||||
#define COMBINER_CTRL_COMPOSITE_LUMINOSITY 0xf
|
||||
|
||||
#define COMBINER_CTRL_MASK_0_SHIFT 0
|
||||
#define COMBINER_CTRL_MASK_1_SHIFT 2
|
||||
#define COMBINER_CTRL_COLOR_0_FILTER_SHIFT 4
|
||||
#define COMBINER_CTRL_COLOR_0_ENABLE_SHIFT 6
|
||||
#define COMBINER_CTRL_COLOR_1_ENABLE_SHIFT 7
|
||||
#define COMBINER_CTRL_COMPOSITE_SHIFT 8
|
||||
|
||||
uniform sampler2D uColorTexture0;
|
||||
uniform sampler2D uColorTexture1;
|
||||
uniform sampler2D uMaskTexture0;
|
||||
uniform sampler2D uMaskTexture1;
|
||||
uniform sampler2D uDestTexture;
|
||||
uniform sampler2D uGammaLUT;
|
||||
uniform vec4 uFilterParams0;
|
||||
uniform vec4 uFilterParams1;
|
||||
uniform vec4 uFilterParams2;
|
||||
uniform vec2 uDestTextureSize;
|
||||
uniform vec2 uColorTexture0Size;
|
||||
uniform int uCtrl;
|
||||
|
||||
in vec3 vMaskTexCoord0;
|
||||
in vec3 vMaskTexCoord1;
|
||||
in vec2 vColorTexCoord0;
|
||||
in vec2 vColorTexCoord1;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
// Color sampling
|
||||
|
||||
vec4 sampleColor(sampler2D colorTexture, vec2 colorTexCoord) {
|
||||
return texture(colorTexture, colorTexCoord);
|
||||
}
|
||||
|
||||
// Text filter
|
||||
|
||||
float filterTextSample1Tap(float offset, sampler2D colorTexture, vec2 colorTexCoord) {
|
||||
return texture(colorTexture, colorTexCoord + vec2(offset, 0.0)).r;
|
||||
}
|
||||
|
||||
// Samples 9 taps around the current pixel.
|
||||
void filterTextSample9Tap(out vec4 outAlphaLeft,
|
||||
out float outAlphaCenter,
|
||||
out vec4 outAlphaRight,
|
||||
sampler2D colorTexture,
|
||||
vec2 colorTexCoord,
|
||||
vec4 kernel,
|
||||
float onePixel) {
|
||||
bool wide = kernel.x > 0.0;
|
||||
outAlphaLeft =
|
||||
vec4(wide ? filterTextSample1Tap(-4.0 * onePixel, colorTexture, colorTexCoord) : 0.0,
|
||||
filterTextSample1Tap(-3.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(-2.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(-1.0 * onePixel, colorTexture, colorTexCoord));
|
||||
outAlphaCenter = filterTextSample1Tap(0.0, colorTexture, colorTexCoord);
|
||||
outAlphaRight =
|
||||
vec4(filterTextSample1Tap(1.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(2.0 * onePixel, colorTexture, colorTexCoord),
|
||||
filterTextSample1Tap(3.0 * onePixel, colorTexture, colorTexCoord),
|
||||
wide ? filterTextSample1Tap(4.0 * onePixel, colorTexture, colorTexCoord) : 0.0);
|
||||
}
|
||||
|
||||
float filterTextConvolve7Tap(vec4 alpha0, vec3 alpha1, vec4 kernel) {
|
||||
return dot(alpha0, kernel) + dot(alpha1, kernel.zyx);
|
||||
}
|
||||
|
||||
float filterTextGammaCorrectChannel(float bgColor, float fgColor, sampler2D gammaLUT) {
|
||||
return texture(gammaLUT, vec2(fgColor, 1.0 - bgColor)).r;
|
||||
}
|
||||
|
||||
// `fgColor` is in linear space.
|
||||
vec3 filterTextGammaCorrect(vec3 bgColor, vec3 fgColor, sampler2D gammaLUT) {
|
||||
return vec3(filterTextGammaCorrectChannel(bgColor.r, fgColor.r, gammaLUT),
|
||||
filterTextGammaCorrectChannel(bgColor.g, fgColor.g, gammaLUT),
|
||||
filterTextGammaCorrectChannel(bgColor.b, fgColor.b, gammaLUT));
|
||||
}
|
||||
|
||||
// | x y z w
|
||||
// --------------+--------------------------------------------------------
|
||||
// filterParams0 | kernel[0] kernel[1] kernel[2] kernel[3]
|
||||
// filterParams1 | bgColor.r bgColor.g bgColor.b -
|
||||
// filterParams2 | fgColor.r fgColor.g fgColor.b gammaCorrectionEnabled
|
||||
vec4 filterText(vec2 colorTexCoord,
|
||||
sampler2D colorTexture,
|
||||
sampler2D gammaLUT,
|
||||
vec2 colorTextureSize,
|
||||
vec4 filterParams0,
|
||||
vec4 filterParams1,
|
||||
vec4 filterParams2) {
|
||||
// Unpack.
|
||||
vec4 kernel = filterParams0;
|
||||
vec3 bgColor = filterParams1.rgb;
|
||||
vec3 fgColor = filterParams2.rgb;
|
||||
bool gammaCorrectionEnabled = filterParams2.a != 0.0;
|
||||
|
||||
// Apply defringing if necessary.
|
||||
vec3 alpha;
|
||||
if (kernel.w == 0.0) {
|
||||
alpha = texture(colorTexture, colorTexCoord).rrr;
|
||||
} else {
|
||||
vec4 alphaLeft, alphaRight;
|
||||
float alphaCenter;
|
||||
filterTextSample9Tap(alphaLeft,
|
||||
alphaCenter,
|
||||
alphaRight,
|
||||
colorTexture,
|
||||
colorTexCoord,
|
||||
kernel,
|
||||
1.0 / colorTextureSize.x);
|
||||
|
||||
float r = filterTextConvolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight.xy), kernel);
|
||||
float g = filterTextConvolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz, kernel);
|
||||
float b = filterTextConvolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x),
|
||||
alphaRight.yzw,
|
||||
kernel);
|
||||
|
||||
alpha = vec3(r, g, b);
|
||||
}
|
||||
|
||||
// Apply gamma correction if necessary.
|
||||
if (gammaCorrectionEnabled)
|
||||
alpha = filterTextGammaCorrect(bgColor, alpha, gammaLUT);
|
||||
|
||||
// Finish.
|
||||
return vec4(mix(bgColor, fgColor, alpha), 1.0);
|
||||
}
|
||||
|
||||
// Filters
|
||||
|
||||
// | x y z w
|
||||
// --------------+----------------------------------------------------
|
||||
// filterParams0 | srcOffset.x srcOffset.y support -
|
||||
// filterParams1 | gaussCoeff.x gaussCoeff.y gaussCoeff.z -
|
||||
// filterParams2 | - - - -
|
||||
vec4 filterBlur(vec2 colorTexCoord,
|
||||
sampler2D colorTexture,
|
||||
vec2 colorTextureSize,
|
||||
vec4 filterParams0,
|
||||
vec4 filterParams1) {
|
||||
// Unpack.
|
||||
vec2 srcOffsetScale = filterParams0.xy / colorTextureSize;
|
||||
int support = int(filterParams0.z);
|
||||
vec3 gaussCoeff = filterParams1.xyz;
|
||||
|
||||
// Set up our incremental calculation.
|
||||
float gaussSum = gaussCoeff.x;
|
||||
vec4 color = texture(colorTexture, colorTexCoord) * gaussCoeff.x;
|
||||
gaussCoeff.xy *= gaussCoeff.yz;
|
||||
|
||||
// This is a common trick that lets us use the texture filtering hardware to evaluate two
|
||||
// texels at a time. The basic principle is that, if c0 and c1 are colors of adjacent texels
|
||||
// and k0 and k1 are arbitrary factors, the formula `k0 * c0 + k1 * c1` is equivalent to
|
||||
// `(k0 + k1) * lerp(c0, c1, k1 / (k0 + k1))`. Linear interpolation, as performed by the
|
||||
// texturing hardware when sampling adjacent pixels in one direction, evaluates
|
||||
// `lerp(c0, c1, t)` where t is the offset from the texel with color `c0`. To evaluate the
|
||||
// formula `k0 * c0 + k1 * c1`, therefore, we can use the texture hardware to perform linear
|
||||
// interpolation with `t = k1 / (k0 + k1)`.
|
||||
for (int i = 1; i <= support; i += 2) {
|
||||
float gaussPartialSum = gaussCoeff.x;
|
||||
gaussCoeff.xy *= gaussCoeff.yz;
|
||||
gaussPartialSum += gaussCoeff.x;
|
||||
|
||||
vec2 srcOffset = srcOffsetScale * (float(i) + gaussCoeff.x / gaussPartialSum);
|
||||
color += (texture(colorTexture, colorTexCoord - srcOffset) +
|
||||
texture(colorTexture, colorTexCoord + srcOffset)) * gaussPartialSum;
|
||||
|
||||
gaussSum += 2.0 * gaussPartialSum;
|
||||
gaussCoeff.xy *= gaussCoeff.yz;
|
||||
}
|
||||
|
||||
// Finish.
|
||||
return color / gaussSum;
|
||||
}
|
||||
|
||||
vec4 filterNone(vec2 colorTexCoord, sampler2D colorTexture) {
|
||||
return sampleColor(colorTexture, colorTexCoord);
|
||||
}
|
||||
|
||||
vec4 filterColor(vec2 colorTexCoord,
|
||||
sampler2D colorTexture,
|
||||
sampler2D gammaLUT,
|
||||
vec2 colorTextureSize,
|
||||
vec4 filterParams0,
|
||||
vec4 filterParams1,
|
||||
vec4 filterParams2,
|
||||
int colorFilter) {
|
||||
switch (colorFilter) {
|
||||
case COMBINER_CTRL_FILTER_BLUR:
|
||||
return filterBlur(colorTexCoord,
|
||||
colorTexture,
|
||||
colorTextureSize,
|
||||
filterParams0,
|
||||
filterParams1);
|
||||
case COMBINER_CTRL_FILTER_TEXT:
|
||||
return filterText(colorTexCoord,
|
||||
colorTexture,
|
||||
gammaLUT,
|
||||
colorTextureSize,
|
||||
filterParams0,
|
||||
filterParams1,
|
||||
filterParams2);
|
||||
}
|
||||
return filterNone(colorTexCoord, colorTexture);
|
||||
}
|
||||
|
||||
// Compositing
|
||||
|
||||
vec3 compositeSelect(bvec3 cond, vec3 ifTrue, vec3 ifFalse) {
|
||||
return vec3(cond.x ? ifTrue.x : ifFalse.x,
|
||||
cond.y ? ifTrue.y : ifFalse.y,
|
||||
cond.z ? ifTrue.z : ifFalse.z);
|
||||
}
|
||||
|
||||
float compositeDivide(float num, float denom) {
|
||||
return denom != 0.0 ? num / denom : 0.0;
|
||||
}
|
||||
|
||||
vec3 compositeColorDodge(vec3 destColor, vec3 srcColor) {
|
||||
bvec3 destZero = equal(destColor, vec3(0.0)), srcOne = equal(srcColor, vec3(1.0));
|
||||
return compositeSelect(destZero,
|
||||
vec3(0.0),
|
||||
compositeSelect(srcOne, vec3(1.0), destColor / (vec3(1.0) - srcColor)));
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
|
||||
vec3 compositeHSLToRGB(vec3 hsl) {
|
||||
float a = hsl.y * min(hsl.z, 1.0 - hsl.z);
|
||||
vec3 ks = mod(vec3(0.0, 8.0, 4.0) + vec3(hsl.x * FRAC_6_PI), 12.0);
|
||||
return hsl.zzz - clamp(min(ks - vec3(3.0), vec3(9.0) - ks), -1.0, 1.0) * a;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
|
||||
vec3 compositeRGBToHSL(vec3 rgb) {
|
||||
float v = max(max(rgb.r, rgb.g), rgb.b), xMin = min(min(rgb.r, rgb.g), rgb.b);
|
||||
float c = v - xMin, l = mix(xMin, v, 0.5);
|
||||
vec3 terms = rgb.r == v ? vec3(0.0, rgb.gb) :
|
||||
rgb.g == v ? vec3(2.0, rgb.br) :
|
||||
vec3(4.0, rgb.rg);
|
||||
float h = FRAC_PI_3 * compositeDivide(terms.x * c + terms.y - terms.z, c);
|
||||
float s = compositeDivide(c, v);
|
||||
return vec3(h, s, l);
|
||||
}
|
||||
|
||||
vec3 compositeScreen(vec3 destColor, vec3 srcColor) {
|
||||
return destColor + srcColor - destColor * srcColor;
|
||||
}
|
||||
|
||||
vec3 compositeHardLight(vec3 destColor, vec3 srcColor) {
|
||||
return compositeSelect(lessThanEqual(srcColor, vec3(0.5)),
|
||||
destColor * vec3(2.0) * srcColor,
|
||||
compositeScreen(destColor, vec3(2.0) * srcColor - vec3(1.0)));
|
||||
}
|
||||
|
||||
vec3 compositeSoftLight(vec3 destColor, vec3 srcColor) {
|
||||
vec3 darkenedDestColor =
|
||||
compositeSelect(lessThanEqual(destColor, vec3(0.25)),
|
||||
((vec3(16.0) * destColor - 12.0) * destColor + 4.0) * destColor,
|
||||
sqrt(destColor));
|
||||
vec3 factor = compositeSelect(lessThanEqual(srcColor, vec3(0.5)),
|
||||
destColor * (vec3(1.0) - destColor),
|
||||
darkenedDestColor - destColor);
|
||||
return destColor + (srcColor * 2.0 - 1.0) * factor;
|
||||
}
|
||||
|
||||
vec3 compositeHSL(vec3 destColor, vec3 srcColor, int op) {
|
||||
switch (op) {
|
||||
case COMBINER_CTRL_COMPOSITE_HUE:
|
||||
return vec3(srcColor.x, destColor.y, destColor.z);
|
||||
case COMBINER_CTRL_COMPOSITE_SATURATION:
|
||||
return vec3(destColor.x, srcColor.y, destColor.z);
|
||||
case COMBINER_CTRL_COMPOSITE_COLOR:
|
||||
return vec3(srcColor.x, srcColor.y, destColor.z);
|
||||
default:
|
||||
return vec3(destColor.x, destColor.y, srcColor.z);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 compositeRGB(vec3 destColor, vec3 srcColor, int op) {
|
||||
switch (op) {
|
||||
case COMBINER_CTRL_COMPOSITE_MULTIPLY:
|
||||
return destColor * srcColor;
|
||||
case COMBINER_CTRL_COMPOSITE_SCREEN:
|
||||
return compositeScreen(destColor, srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_OVERLAY:
|
||||
return compositeHardLight(srcColor, destColor);
|
||||
case COMBINER_CTRL_COMPOSITE_DARKEN:
|
||||
return min(destColor, srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_LIGHTEN:
|
||||
return max(destColor, srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_COLOR_DODGE:
|
||||
return compositeColorDodge(destColor, srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_COLOR_BURN:
|
||||
return vec3(1.0) - compositeColorDodge(vec3(1.0) - destColor, vec3(1.0) - srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_HARD_LIGHT:
|
||||
return compositeHardLight(destColor, srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_SOFT_LIGHT:
|
||||
return compositeSoftLight(destColor, srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_DIFFERENCE:
|
||||
return abs(destColor - srcColor);
|
||||
case COMBINER_CTRL_COMPOSITE_EXCLUSION:
|
||||
return destColor + srcColor - vec3(2.0) * destColor * srcColor;
|
||||
case COMBINER_CTRL_COMPOSITE_HUE:
|
||||
case COMBINER_CTRL_COMPOSITE_SATURATION:
|
||||
case COMBINER_CTRL_COMPOSITE_COLOR:
|
||||
case COMBINER_CTRL_COMPOSITE_LUMINOSITY:
|
||||
return compositeHSLToRGB(compositeHSL(compositeRGBToHSL(destColor),
|
||||
compositeRGBToHSL(srcColor),
|
||||
op));
|
||||
}
|
||||
return srcColor;
|
||||
}
|
||||
|
||||
vec4 composite(vec4 srcColor,
|
||||
sampler2D destTexture,
|
||||
vec2 destTextureSize,
|
||||
vec2 fragCoord,
|
||||
int op) {
|
||||
if (op == COMBINER_CTRL_COMPOSITE_NORMAL)
|
||||
return srcColor;
|
||||
|
||||
// FIXME(pcwalton): What should the output alpha be here?
|
||||
vec2 destTexCoord = fragCoord / destTextureSize;
|
||||
vec4 destColor = texture(destTexture, destTexCoord);
|
||||
vec3 blendedRGB = compositeRGB(destColor.rgb, srcColor.rgb, op);
|
||||
return vec4(srcColor.a * (1.0 - destColor.a) * srcColor.rgb +
|
||||
srcColor.a * destColor.a * blendedRGB +
|
||||
(1.0 - srcColor.a) * destColor.rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
// Masks
|
||||
|
||||
float sampleMask(float maskAlpha,
|
||||
sampler2D maskTexture,
|
||||
vec3 maskTexCoord,
|
||||
int maskCtrl) {
|
||||
if (maskCtrl == 0)
|
||||
return maskAlpha;
|
||||
float coverage = texture(maskTexture, maskTexCoord.xy).r + maskTexCoord.z;
|
||||
if ((maskCtrl & COMBINER_CTRL_MASK_WINDING) != 0)
|
||||
coverage = abs(coverage);
|
||||
else
|
||||
coverage = 1.0 - abs(1.0 - mod(coverage, 2.0));
|
||||
return min(maskAlpha, coverage);
|
||||
}
|
||||
|
||||
// Main function
|
||||
|
||||
void calculateColor(int ctrl) {
|
||||
// Sample mask.
|
||||
int maskCtrl0 = (ctrl >> COMBINER_CTRL_MASK_0_SHIFT) & COMBINER_CTRL_MASK_MASK;
|
||||
int maskCtrl1 = (ctrl >> COMBINER_CTRL_MASK_1_SHIFT) & COMBINER_CTRL_MASK_MASK;
|
||||
float maskAlpha = 1.0;
|
||||
maskAlpha = sampleMask(maskAlpha, uMaskTexture0, vMaskTexCoord0, maskCtrl0);
|
||||
maskAlpha = sampleMask(maskAlpha, uMaskTexture1, vMaskTexCoord1, maskCtrl1);
|
||||
|
||||
// Sample color.
|
||||
vec4 color = vec4(0.0);
|
||||
if (((ctrl >> COMBINER_CTRL_COLOR_0_ENABLE_SHIFT) & COMBINER_CTRL_COLOR_ENABLE_MASK) != 0) {
|
||||
int color0Filter = (ctrl >> COMBINER_CTRL_COLOR_0_FILTER_SHIFT) &
|
||||
COMBINER_CTRL_FILTER_MASK;
|
||||
color += filterColor(vColorTexCoord0,
|
||||
uColorTexture0,
|
||||
uGammaLUT,
|
||||
uColorTexture0Size,
|
||||
uFilterParams0,
|
||||
uFilterParams1,
|
||||
uFilterParams2,
|
||||
color0Filter);
|
||||
}
|
||||
if (((ctrl >> COMBINER_CTRL_COLOR_1_ENABLE_SHIFT) & COMBINER_CTRL_COLOR_ENABLE_MASK) != 0)
|
||||
color *= sampleColor(uColorTexture1, vColorTexCoord1);
|
||||
|
||||
// Apply mask.
|
||||
color.a *= maskAlpha;
|
||||
|
||||
// Apply composite.
|
||||
int compositeOp = (ctrl >> COMBINER_CTRL_COMPOSITE_SHIFT) & COMBINER_CTRL_COMPOSITE_MASK;
|
||||
color = composite(color, uDestTexture, uDestTextureSize, gl_FragCoord.xy, compositeOp);
|
||||
|
||||
// Premultiply alpha.
|
||||
color.rgb *= color.a;
|
||||
oFragColor = color;
|
||||
}
|
||||
|
||||
// Entry point
|
||||
//
|
||||
// TODO(pcwalton): Generate this dynamically.
|
||||
|
||||
void main() {
|
||||
calculateColor(uCtrl);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha.vs.glsl
|
||||
// pathfinder/shaders/tile.vs.glsl
|
||||
//
|
||||
// Copyright © 2020 The Pathfinder Project Developers.
|
||||
//
|
||||
|
@ -16,19 +16,22 @@ uniform mat4 uTransform;
|
|||
uniform vec2 uTileSize;
|
||||
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
in vec2 aMaskTexCoord;
|
||||
in float aOpacity;
|
||||
in vec2 aColorTexCoord0;
|
||||
in vec2 aColorTexCoord1;
|
||||
in vec2 aMaskTexCoord0;
|
||||
in vec2 aMaskTexCoord1;
|
||||
in ivec2 aMaskBackdrop;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
out float vOpacity;
|
||||
out vec3 vMaskTexCoord0;
|
||||
out vec3 vMaskTexCoord1;
|
||||
out vec2 vColorTexCoord0;
|
||||
out vec2 vColorTexCoord1;
|
||||
|
||||
void main() {
|
||||
vec2 position = vec2(aTilePosition) * uTileSize;
|
||||
|
||||
vMaskTexCoord = aMaskTexCoord;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
vOpacity = aOpacity;
|
||||
vColorTexCoord0 = aColorTexCoord0;
|
||||
vColorTexCoord1 = aColorTexCoord1;
|
||||
vMaskTexCoord0 = vec3(aMaskTexCoord0, float(aMaskBackdrop.x));
|
||||
vMaskTexCoord1 = vec3(aMaskTexCoord1, float(aMaskBackdrop.y));
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha.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.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
oFragColor = vec4(srcRGBA.rgb * srcRGBA.a, srcRGBA.a);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_difference.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.
|
||||
|
||||
// The difference blend mode.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 blended = abs(destRGBA.rgb - srcRGBA.rgb);
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_dodgeburn.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.
|
||||
|
||||
// Color dodge and color burn blend modes.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform int uBurn;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 dest = uBurn == 0 ? destRGBA.rgb : vec3(1.0) - destRGBA.rgb;
|
||||
vec3 src = uBurn == 0 ? vec3(1.0) - srcRGBA.rgb : srcRGBA.rgb;
|
||||
|
||||
bvec3 srcNonzero = notEqual(src, vec3(0.0));
|
||||
vec3 blended = min(vec3(srcNonzero.x ? dest.x / src.x : 1.0,
|
||||
srcNonzero.y ? dest.y / src.y : 1.0,
|
||||
srcNonzero.z ? dest.z / src.z : 1.0),
|
||||
vec3(1.0));
|
||||
if (uBurn != 0)
|
||||
blended = vec3(1.0) - blended;
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_exclusion.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.
|
||||
|
||||
// The exclusion blend mode.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 dest = destRGBA.rgb, src = srcRGBA.rgb;
|
||||
vec3 blended = dest + src - dest * src * 2.0;
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_hsl.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.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform ivec3 uBlendHSL;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
#define PI_2 6.283185307179586
|
||||
#define DEG_30_INV 1.9098593171027443
|
||||
#define DEG_60 1.0471975511965976
|
||||
|
||||
#define BLEND_TERM_DEST 0
|
||||
#define BLEND_TERM_SRC 1
|
||||
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative
|
||||
vec3 convertHSLToRGB(vec3 hsl) {
|
||||
float a = hsl.y * min(hsl.z, 1.0 - hsl.z);
|
||||
vec3 ks = mod(vec3(0.0, 8.0, 4.0) + vec3(hsl.x * DEG_30_INV), 12.0);
|
||||
return hsl.zzz - clamp(min(ks - vec3(3.0), vec3(9.0) - ks), -1.0, 1.0) * a;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
|
||||
vec3 convertRGBToHSL(vec3 rgb) {
|
||||
float v = max((rgb.x, rgb.y), rgb.z);
|
||||
float c = v - min((rgb.x, rgb.y), rgb.z);
|
||||
float l = v - 0.5 * c;
|
||||
|
||||
vec3 tmp = vec3(0.0);
|
||||
bvec3 is_v = equal(rgb, vec3(v));
|
||||
if (is_v.r)
|
||||
tmp = vec3(0.0, rgb.gb);
|
||||
else if (is_v.g)
|
||||
tmp = vec3(2.0, rgb.br);
|
||||
else if (is_v.b)
|
||||
tmp = vec3(4.0, rgb.rg);
|
||||
float h = DEG_60 * (tmp.x + (tmp.y - tmp.z) / c);
|
||||
|
||||
float s = 0.0;
|
||||
if (l > 0.0 && l < 1.0)
|
||||
s = (v - l) / min(l, 1.0 - l);
|
||||
|
||||
return vec3(h, s, l);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
vec3 destHSL = convertRGBToHSL(destRGBA.rgb);
|
||||
vec3 srcHSL = convertRGBToHSL(srcRGBA.rgb);
|
||||
vec3 blendedHSL = select3(equal(uBlendHSL, ivec3(BLEND_TERM_DEST)), destHSL, srcHSL);
|
||||
vec3 blendedRGB = convertHSLToRGB(blendedHSL);
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blendedRGB);
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_overlay.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.
|
||||
|
||||
// Multiply, screen, overlay, and hard light filters.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
#define OVERLAY_BLEND_MODE_MULTIPLY 0
|
||||
#define OVERLAY_BLEND_MODE_SCREEN 1
|
||||
#define OVERLAY_BLEND_MODE_HARD_LIGHT 2
|
||||
#define OVERLAY_BLEND_MODE_OVERLAY 3
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform int uBlendMode;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
bool reversed = uBlendMode == OVERLAY_BLEND_MODE_OVERLAY;
|
||||
vec3 src = reversed ? srcRGBA.rgb : destRGBA.rgb;
|
||||
vec3 dest = reversed ? destRGBA.rgb : srcRGBA.rgb;
|
||||
|
||||
vec3 multiply = src * dest;
|
||||
vec3 blended;
|
||||
if (uBlendMode == OVERLAY_BLEND_MODE_MULTIPLY) {
|
||||
blended = multiply;
|
||||
} else {
|
||||
vec3 screen = dest + src - multiply;
|
||||
if (uBlendMode == OVERLAY_BLEND_MODE_SCREEN)
|
||||
blended = screen;
|
||||
else
|
||||
blended = select3(lessThanEqual(src, vec3(0.5)), multiply, screen * 2.0 - 1.0);
|
||||
}
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
// pathfinder/shaders/tile_alpha_sample.inc.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.
|
||||
|
||||
uniform sampler2D uStencilTexture;
|
||||
uniform sampler2D uPaintTexture;
|
||||
uniform sampler2D uDest;
|
||||
uniform vec2 uFramebufferSize;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in float vOpacity;
|
||||
|
||||
// NB: This does not premultiply.
|
||||
vec4 sampleSrcColor() {
|
||||
float coverage = texture(uStencilTexture, vMaskTexCoord).r;
|
||||
vec4 srcRGBA = texture(uPaintTexture, vColorTexCoord);
|
||||
return vec4(srcRGBA.rgb, srcRGBA.a * coverage * vOpacity);
|
||||
}
|
||||
|
||||
vec4 sampleDestColor() {
|
||||
vec2 destTexCoord = gl_FragCoord.xy / uFramebufferSize;
|
||||
return texture(uDest, destTexCoord);
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): What should the output alpha be here?
|
||||
vec4 blendColors(vec4 destRGBA, vec4 srcRGBA, vec3 blendedRGB) {
|
||||
return vec4(srcRGBA.a * (1.0 - destRGBA.a) * srcRGBA.rgb +
|
||||
srcRGBA.a * destRGBA.a * blendedRGB +
|
||||
(1.0 - srcRGBA.a) * destRGBA.a * destRGBA.rgb,
|
||||
1.0);
|
||||
}
|
||||
|
||||
vec3 select3(bvec3 cond, vec3 a, vec3 b) {
|
||||
return vec3(cond.x ? a.x : b.x, cond.y ? a.y : b.y, cond.z ? a.z : b.z);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_alpha_softlight.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.
|
||||
|
||||
// The soft light blend mode.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_alpha_sample.inc.glsl"
|
||||
|
||||
void main() {
|
||||
vec4 srcRGBA = sampleSrcColor();
|
||||
vec4 destRGBA = sampleDestColor();
|
||||
|
||||
// B(Cb, Cs) = Cb*(1 + (2*Cs - 1)*X)
|
||||
// where X = if Cs <= 0.5 then 1 - Cb else D - 1
|
||||
// and D = if Cb <= 0.25 then (16*Cb - 12)*Cb + 4 else 1/sqrt(Cb)
|
||||
vec3 dest = destRGBA.rgb, src = srcRGBA.rgb;
|
||||
bvec3 destDark = lessThanEqual(dest, vec3(0.25)), srcDark = lessThanEqual(src, vec3(0.5));
|
||||
vec3 d = select3(destDark, (dest * 16.0 - 12.0) * dest + 4.0, inversesqrt(dest));
|
||||
vec3 x = select3(srcDark, vec3(1.0) - dest, d - 1.0);
|
||||
vec3 blended = dest * ((src * 2.0 - 1.0) * x + 1.0);
|
||||
|
||||
oFragColor = blendColors(destRGBA, srcRGBA, blended);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_solid.fs.glsl
|
||||
//
|
||||
// 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.
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uColorTexture;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
vec4 color = texture(uColorTexture, vColorTexCoord);
|
||||
oFragColor = vec4(color.rgb * color.a, color.a);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_solid.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;
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec2 uTileSize;
|
||||
|
||||
in ivec2 aTilePosition;
|
||||
in vec2 aColorTexCoord;
|
||||
|
||||
out vec2 vColorTexCoord;
|
||||
|
||||
void main() {
|
||||
vec2 position = vec2(aTilePosition) * uTileSize;
|
||||
vColorTexCoord = aColorTexCoord;
|
||||
gl_Position = uTransform * vec4(position, 0.0, 1.0);
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_solid_filter_blur.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.
|
||||
|
||||
// TODO(pcwalton): This could be significantly optimized by operating on a
|
||||
// sparse per-tile basis.
|
||||
|
||||
// The technique here is "Incremental Computation of the Gaussian", GPU Gems 3, chapter 40:
|
||||
// https://developer.nvidia.com/gpugems/gpugems3/part-vi-gpu-computing/chapter-40-incremental-computation-gaussian
|
||||
//
|
||||
// It's the same technique WebRender uses.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uColorTexture;
|
||||
uniform vec2 uSrcOffsetScale;
|
||||
uniform vec3 uInitialGaussCoeff;
|
||||
uniform int uSupport;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
// Set up our incremental calculation.
|
||||
vec3 gaussCoeff = uInitialGaussCoeff;
|
||||
float gaussSum = gaussCoeff.x;
|
||||
vec4 color = texture(uColorTexture, vColorTexCoord) * gaussCoeff.x;
|
||||
gaussCoeff.xy *= gaussCoeff.yz;
|
||||
|
||||
// This is a common trick that lets us use the texture filtering hardware to evaluate two
|
||||
// texels at a time. The basic principle is that, if c0 and c1 are colors of adjacent texels
|
||||
// and k0 and k1 are arbitrary factors, the formula `k0 * c0 + k1 * c1` is equivalent to
|
||||
// `(k0 + k1) * lerp(c0, c1, k1 / (k0 + k1))`. Linear interpolation, as performed by the
|
||||
// texturing hardware when sampling adjacent pixels in one direction, evaluates
|
||||
// `lerp(c0, c1, t)` where t is the offset from the texel with color `c0`. To evaluate the
|
||||
// formula `k0 * c0 + k1 * c1`, therefore, we can use the texture hardware to perform linear
|
||||
// interpolation with `t = k1 / (k0 + k1)`.
|
||||
for (int i = 1; i <= uSupport; i += 2) {
|
||||
float gaussPartialSum = gaussCoeff.x;
|
||||
gaussCoeff.xy *= gaussCoeff.yz;
|
||||
gaussPartialSum += gaussCoeff.x;
|
||||
|
||||
vec2 srcOffset = uSrcOffsetScale * (float(i) + gaussCoeff.x / gaussPartialSum);
|
||||
color += (texture(uColorTexture, vColorTexCoord - srcOffset) +
|
||||
texture(uColorTexture, vColorTexCoord + srcOffset)) * gaussPartialSum;
|
||||
|
||||
gaussSum += 2.0 * gaussPartialSum;
|
||||
gaussCoeff.xy *= gaussCoeff.yz;
|
||||
}
|
||||
|
||||
// Finish.
|
||||
color /= gaussSum;
|
||||
color.rgb *= color.a;
|
||||
oFragColor = color;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/tile_solid_filter_text.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.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uColorTexture;
|
||||
uniform vec2 uSrcSize;
|
||||
uniform vec4 uFGColor;
|
||||
uniform vec4 uBGColor;
|
||||
uniform int uGammaCorrectionEnabled;
|
||||
|
||||
in vec2 vColorTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "tile_solid_filter_text_gamma_correct.inc.glsl"
|
||||
#include "tile_solid_filter_text_convolve.inc.glsl"
|
||||
|
||||
// Convolve horizontally in this pass.
|
||||
float sample1Tap(float offset) {
|
||||
return texture(uColorTexture, vec2(vColorTexCoord.x + offset, vColorTexCoord.y)).r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// Apply defringing if necessary.
|
||||
vec3 alpha;
|
||||
if (uKernel.w == 0.0) {
|
||||
alpha = texture(uColorTexture, vColorTexCoord).rrr;
|
||||
} else {
|
||||
vec4 alphaLeft, alphaRight;
|
||||
float alphaCenter;
|
||||
sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSrcSize.x);
|
||||
|
||||
float r = convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight.xy));
|
||||
float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz);
|
||||
float b = convolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x), alphaRight.yzw);
|
||||
|
||||
alpha = vec3(r, g, b);
|
||||
}
|
||||
|
||||
// Apply gamma correction if necessary.
|
||||
if (uGammaCorrectionEnabled != 0)
|
||||
alpha = gammaCorrect(uBGColor.rgb, alpha);
|
||||
|
||||
// Finish.
|
||||
oFragColor = vec4(mix(uBGColor.rgb, uFGColor.rgb, alpha), 1.0);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// pathfinder/shaders/tile_solid_filter_text_convolve.inc.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.
|
||||
|
||||
// Zero if no convolution is to be performed.
|
||||
uniform vec4 uKernel;
|
||||
|
||||
// This function is expected to return the alpha value of the pixel at the
|
||||
// given offset in pixels. Offset 0.0 represents the current pixel.
|
||||
float sample1Tap(float offset);
|
||||
|
||||
// Samples 9 taps around the current pixel.
|
||||
void sample9Tap(out vec4 outAlphaLeft,
|
||||
out float outAlphaCenter,
|
||||
out vec4 outAlphaRight,
|
||||
float onePixel) {
|
||||
outAlphaLeft = vec4(uKernel.x > 0.0 ? sample1Tap(-4.0 * onePixel) : 0.0,
|
||||
sample1Tap(-3.0 * onePixel),
|
||||
sample1Tap(-2.0 * onePixel),
|
||||
sample1Tap(-1.0 * onePixel));
|
||||
outAlphaCenter = sample1Tap(0.0);
|
||||
outAlphaRight = vec4(sample1Tap(1.0 * onePixel),
|
||||
sample1Tap(2.0 * onePixel),
|
||||
sample1Tap(3.0 * onePixel),
|
||||
uKernel.x > 0.0 ? sample1Tap(4.0 * onePixel) : 0.0);
|
||||
}
|
||||
|
||||
// Convolves 7 values with the kernel.
|
||||
float convolve7Tap(vec4 alpha0, vec3 alpha1) {
|
||||
return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx);
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
// pathfinder/shaders/tile_solid_filter_text_gamma_correct.inc.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.
|
||||
|
||||
// The lookup table for gamma correction, in the same format WebRender
|
||||
// expects.
|
||||
uniform sampler2D uGammaLUT;
|
||||
|
||||
float gammaCorrectChannel(float bgColor, float fgColor) {
|
||||
return texture(uGammaLUT, vec2(fgColor, 1.0 - bgColor)).r;
|
||||
}
|
||||
|
||||
// `fgColor` is in linear space.
|
||||
vec3 gammaCorrect(vec3 bgColor, vec3 fgColor) {
|
||||
return vec3(gammaCorrectChannel(bgColor.r, fgColor.r),
|
||||
gammaCorrectChannel(bgColor.g, fgColor.g),
|
||||
gammaCorrectChannel(bgColor.b, fgColor.b));
|
||||
}
|
Loading…
Reference in New Issue