Rename "postprocessing" to "effects" and start initial work on composite ops
This commit is contained in:
parent
d9e994e46d
commit
16a2de88df
|
@ -1658,6 +1658,7 @@ dependencies = [
|
|||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"metal 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pathfinder_color 0.1.0",
|
||||
"pathfinder_content 0.1.0",
|
||||
"pathfinder_export 0.1.0",
|
||||
"pathfinder_geometry 0.4.0",
|
||||
"pathfinder_gl 0.1.0",
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// pathfinder/content/src/effects.rs
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! Special effects that can be applied to layers.
|
||||
|
||||
use pathfinder_color::ColorF;
|
||||
|
||||
/// This intentionally does not precisely match what Core Graphics does (a
|
||||
/// Lanczos function), because we don't want any ringing artefacts.
|
||||
pub static DEFRINGING_KERNEL_CORE_GRAPHICS: DefringingKernel =
|
||||
DefringingKernel([0.033165660, 0.102074051, 0.221434336, 0.286651906]);
|
||||
pub static DEFRINGING_KERNEL_FREETYPE: DefringingKernel =
|
||||
DefringingKernel([0.0, 0.031372549, 0.301960784, 0.337254902]);
|
||||
|
||||
/// Should match macOS 10.13 High Sierra.
|
||||
pub static STEM_DARKENING_FACTORS: [f32; 2] = [0.0121, 0.0121 * 1.25];
|
||||
|
||||
/// Should match macOS 10.13 High Sierra.
|
||||
pub const MAX_STEM_DARKENING_AMOUNT: [f32; 2] = [0.3, 0.3];
|
||||
|
||||
/// This value is a subjective cutoff. Above this ppem value, no stem darkening is performed.
|
||||
pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0;
|
||||
|
||||
/// Effects that can be applied to a layer.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Effects {
|
||||
/// The shader that should be used when compositing this layer onto its destination.
|
||||
pub filter: Filter,
|
||||
}
|
||||
|
||||
/// The shader that should be used when compositing this layer onto its destination.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Filter {
|
||||
/// A compositing operation.
|
||||
Composite(CompositeOp),
|
||||
/// Performs postprocessing operations useful for monochrome text.
|
||||
Text {
|
||||
/// The foreground color of the text.
|
||||
fg_color: ColorF,
|
||||
/// The background color of the text.
|
||||
bg_color: ColorF,
|
||||
/// The kernel used for defringing, if subpixel AA is enabled.
|
||||
defringing_kernel: Option<DefringingKernel>,
|
||||
/// Whether gamma correction is used when compositing.
|
||||
///
|
||||
/// If this is enabled, stem darkening is advised.
|
||||
gamma_correction: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum CompositeOp {
|
||||
/// The default.
|
||||
SourceOver,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct DefringingKernel(pub [f32; 4]);
|
||||
|
||||
impl Default for CompositeOp {
|
||||
#[inline]
|
||||
fn default() -> CompositeOp {
|
||||
CompositeOp::SourceOver
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ extern crate log;
|
|||
|
||||
pub mod clip;
|
||||
pub mod dash;
|
||||
pub mod effects;
|
||||
pub mod fill;
|
||||
pub mod gradient;
|
||||
pub mod orientation;
|
||||
|
|
|
@ -24,6 +24,9 @@ version = "0.4"
|
|||
[dependencies.pathfinder_color]
|
||||
path = "../../color"
|
||||
|
||||
[dependencies.pathfinder_content]
|
||||
path = "../../content"
|
||||
|
||||
[dependencies.pathfinder_export]
|
||||
path = "../../export"
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ use crate::device::{GroundProgram, GroundVertexArray};
|
|||
use crate::ui::{DemoUIModel, DemoUIPresenter, ScreenshotInfo, ScreenshotType, UIAction};
|
||||
use crate::window::{Event, Keycode, SVGPath, Window, WindowSize};
|
||||
use clap::{App, Arg};
|
||||
use pathfinder_content::effects::{DEFRINGING_KERNEL_CORE_GRAPHICS, Effects};
|
||||
use pathfinder_content::effects::{Filter, STEM_DARKENING_FACTORS};
|
||||
use pathfinder_export::{Export, FileFormat};
|
||||
use pathfinder_geometry::rect::RectF;
|
||||
use pathfinder_geometry::transform2d::Transform2F;
|
||||
|
@ -31,9 +33,8 @@ use pathfinder_gpu::resources::ResourceLoader;
|
|||
use pathfinder_gpu::Device;
|
||||
use pathfinder_renderer::concurrent::scene_proxy::{RenderCommandStream, SceneProxy};
|
||||
use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererOptions};
|
||||
use pathfinder_renderer::gpu::renderer::{PostprocessOptions, RenderStats, RenderTime, Renderer};
|
||||
use pathfinder_renderer::gpu::renderer::{RenderStats, RenderTime, Renderer};
|
||||
use pathfinder_renderer::options::{BuildOptions, RenderTransform};
|
||||
use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_FACTORS};
|
||||
use pathfinder_renderer::scene::Scene;
|
||||
use pathfinder_svg::BuiltSVG;
|
||||
use pathfinder_ui::{MousePosition, UIEvent};
|
||||
|
@ -742,9 +743,7 @@ pub enum UIVisibility {
|
|||
All,
|
||||
}
|
||||
|
||||
fn load_scene(resource_loader: &dyn ResourceLoader,
|
||||
input_path: &SVGPath,
|
||||
effects: Option<PostprocessOptions>)
|
||||
fn load_scene(resource_loader: &dyn ResourceLoader, input_path: &SVGPath, effects: Option<Effects>)
|
||||
-> (BuiltSVG, Tree) {
|
||||
let mut data;
|
||||
match *input_path {
|
||||
|
@ -761,7 +760,7 @@ fn load_scene(resource_loader: &dyn ResourceLoader,
|
|||
(built_svg, tree)
|
||||
}
|
||||
|
||||
fn build_svg_tree(tree: &Tree, effects: Option<PostprocessOptions>) -> BuiltSVG {
|
||||
fn build_svg_tree(tree: &Tree, effects: Option<Effects>) -> BuiltSVG {
|
||||
let mut scene = Scene::new();
|
||||
if let Some(effects) = effects {
|
||||
scene.push_layer(effects);
|
||||
|
@ -860,12 +859,13 @@ impl SceneMetadata {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_effects(ui_model: &DemoUIModel) -> Option<PostprocessOptions> {
|
||||
fn build_effects(ui_model: &DemoUIModel) -> Option<Effects> {
|
||||
if !ui_model.gamma_correction_effect_enabled && !ui_model.subpixel_aa_effect_enabled {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(PostprocessOptions {
|
||||
Some(Effects {
|
||||
filter: Filter::Text {
|
||||
fg_color: ui_model.foreground_color().to_f32(),
|
||||
bg_color: ui_model.background_color().to_f32(),
|
||||
gamma_correction: ui_model.gamma_correction_effect_enabled,
|
||||
|
@ -874,6 +874,7 @@ fn build_effects(ui_model: &DemoUIModel) -> Option<PostprocessOptions> {
|
|||
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//! Packs data onto the GPU.
|
||||
|
||||
use crate::concurrent::executor::Executor;
|
||||
use crate::gpu::renderer::{MASK_TILES_ACROSS, PostprocessOptions};
|
||||
use crate::gpu::renderer::MASK_TILES_ACROSS;
|
||||
use crate::gpu_data::{AlphaTile, AlphaTileVertex, FillBatchPrimitive, MaskTile, MaskTileVertex};
|
||||
use crate::gpu_data::{RenderCommand, SolidTileVertex, TileObjectPrimitive};
|
||||
use crate::options::{PreparedBuildOptions, RenderCommandListener};
|
||||
|
@ -20,6 +20,7 @@ use crate::scene::{DisplayItem, Scene};
|
|||
use crate::tile_map::DenseTileMap;
|
||||
use crate::tiles::{self, TILE_HEIGHT, TILE_WIDTH, Tiler, TilingPathInfo};
|
||||
use crate::z_buffer::ZBuffer;
|
||||
use pathfinder_content::effects::Effects;
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_geometry::line_segment::{LineSegment2F, LineSegmentU4, LineSegmentU8};
|
||||
use pathfinder_geometry::vector::{Vector2F, Vector2I};
|
||||
|
@ -358,7 +359,7 @@ struct CulledTiles {
|
|||
enum CulledDisplayItem {
|
||||
DrawSolidTiles(Vec<SolidTileVertex>),
|
||||
DrawAlphaTiles(Vec<AlphaTile>),
|
||||
PushLayer { effects: PostprocessOptions },
|
||||
PushLayer { effects: Effects },
|
||||
PopLayer,
|
||||
}
|
||||
|
||||
|
|
|
@ -10,16 +10,17 @@
|
|||
|
||||
use crate::gpu::debug::DebugUIPresenter;
|
||||
use crate::gpu::options::{DestFramebuffer, RendererOptions};
|
||||
use crate::gpu::shaders::{FillProgram, AlphaTileProgram, AlphaTileVertexArray, FillVertexArray};
|
||||
use crate::gpu::shaders::{MAX_FILLS_PER_BATCH, MaskTileProgram, MaskTileVertexArray};
|
||||
use crate::gpu::shaders::{PostprocessProgram, PostprocessVertexArray, ReprojectionProgram};
|
||||
use crate::gpu::shaders::{ReprojectionVertexArray, SolidTileProgram, SolidTileVertexArray};
|
||||
use crate::gpu::shaders::{AlphaTileProgram, AlphaTileVertexArray, FillProgram, FillVertexArray};
|
||||
use crate::gpu::shaders::{FilterBasicProgram, FilterBasicVertexArray, FilterTextProgram};
|
||||
use crate::gpu::shaders::{FilterTextVertexArray, MAX_FILLS_PER_BATCH, MaskTileProgram};
|
||||
use crate::gpu::shaders::{MaskTileVertexArray, ReprojectionProgram, ReprojectionVertexArray};
|
||||
use crate::gpu::shaders::{SolidTileProgram, SolidTileVertexArray};
|
||||
use crate::gpu::shaders::{StencilProgram, StencilVertexArray};
|
||||
use crate::gpu_data::{AlphaTile, FillBatchPrimitive, MaskTile, PaintData};
|
||||
use crate::gpu_data::{RenderCommand, SolidTileVertex};
|
||||
use crate::post::DefringingKernel;
|
||||
use crate::tiles::{TILE_HEIGHT, TILE_WIDTH};
|
||||
use pathfinder_color::{self as color, ColorF};
|
||||
use pathfinder_content::effects::{CompositeOp, DefringingKernel, Effects, Filter};
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_geometry::vector::{Vector2I, Vector4F};
|
||||
use pathfinder_geometry::rect::RectI;
|
||||
|
@ -79,9 +80,11 @@ where
|
|||
paint_texture: Option<D::Texture>,
|
||||
layer_framebuffer_stack: Vec<LayerFramebufferInfo<D>>,
|
||||
|
||||
// Postprocessing shader
|
||||
postprocess_program: PostprocessProgram<D>,
|
||||
postprocess_vertex_array: PostprocessVertexArray<D>,
|
||||
// Filter shaders
|
||||
filter_basic_program: FilterBasicProgram<D>,
|
||||
filter_basic_vertex_array: FilterBasicVertexArray<D>,
|
||||
filter_text_program: FilterTextProgram<D>,
|
||||
filter_text_vertex_array: FilterTextVertexArray<D>,
|
||||
gamma_lut_texture: D::Texture,
|
||||
|
||||
// Stencil shader
|
||||
|
@ -126,7 +129,8 @@ where
|
|||
resources);
|
||||
let solid_tile_program = SolidTileProgram::new(&device, resources);
|
||||
let alpha_tile_program = AlphaTileProgram::new(&device, resources);
|
||||
let postprocess_program = PostprocessProgram::new(&device, resources);
|
||||
let filter_basic_program = FilterBasicProgram::new(&device, resources);
|
||||
let filter_text_program = FilterTextProgram::new(&device, resources);
|
||||
let stencil_program = StencilProgram::new(&device, resources);
|
||||
let reprojection_program = ReprojectionProgram::new(&device, resources);
|
||||
|
||||
|
@ -175,9 +179,15 @@ where
|
|||
&solid_tile_program,
|
||||
&quads_vertex_indices_buffer,
|
||||
);
|
||||
let postprocess_vertex_array = PostprocessVertexArray::new(
|
||||
let filter_basic_vertex_array = FilterBasicVertexArray::new(
|
||||
&device,
|
||||
&postprocess_program,
|
||||
&filter_basic_program,
|
||||
&quad_vertex_positions_buffer,
|
||||
&quad_vertex_indices_buffer,
|
||||
);
|
||||
let filter_text_vertex_array = FilterTextVertexArray::new(
|
||||
&device,
|
||||
&filter_text_program,
|
||||
&quad_vertex_positions_buffer,
|
||||
&quad_vertex_indices_buffer,
|
||||
);
|
||||
|
@ -229,8 +239,10 @@ where
|
|||
paint_texture: None,
|
||||
layer_framebuffer_stack: vec![],
|
||||
|
||||
postprocess_program,
|
||||
postprocess_vertex_array,
|
||||
filter_basic_program,
|
||||
filter_basic_vertex_array,
|
||||
filter_text_program,
|
||||
filter_text_vertex_array,
|
||||
gamma_lut_texture,
|
||||
|
||||
stencil_program,
|
||||
|
@ -757,12 +769,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn push_layer(&mut self, effects: PostprocessOptions) {
|
||||
fn push_layer(&mut self, effects: Effects) {
|
||||
let main_framebuffer_size = self.main_viewport().size();
|
||||
let framebuffer_size = if effects.defringing_kernel.is_some() {
|
||||
let framebuffer_size = match effects.filter {
|
||||
Filter::Text { defringing_kernel: Some(_), .. } => {
|
||||
main_framebuffer_size.scale_xy(Vector2I::new(3, 1))
|
||||
} else {
|
||||
main_framebuffer_size
|
||||
}
|
||||
_ => main_framebuffer_size,
|
||||
};
|
||||
|
||||
let framebuffer = self.framebuffer_cache.create_framebuffer(&mut self.device,
|
||||
|
@ -780,45 +793,106 @@ where
|
|||
.pop()
|
||||
.expect("Where's the layer?");
|
||||
|
||||
let clear_color = self.clear_color_for_draw_operation();
|
||||
match layer_framebuffer_info.effects.filter {
|
||||
Filter::Composite(composite_op) => {
|
||||
self.composite_layer(&layer_framebuffer_info, composite_op)
|
||||
}
|
||||
Filter::Text { fg_color, bg_color, defringing_kernel, gamma_correction } => {
|
||||
self.draw_text_layer(&layer_framebuffer_info,
|
||||
fg_color,
|
||||
bg_color,
|
||||
defringing_kernel,
|
||||
gamma_correction)
|
||||
}
|
||||
}
|
||||
|
||||
let postprocess_source_framebuffer = &layer_framebuffer_info.framebuffer;
|
||||
let source_texture = self
|
||||
.device
|
||||
.framebuffer_texture(postprocess_source_framebuffer);
|
||||
self.preserve_draw_framebuffer();
|
||||
|
||||
self.framebuffer_cache.release_framebuffer(layer_framebuffer_info.framebuffer);
|
||||
}
|
||||
|
||||
fn composite_layer(&self,
|
||||
layer_framebuffer_info: &LayerFramebufferInfo<D>,
|
||||
composite_op: CompositeOp) {
|
||||
let clear_color = self.clear_color_for_draw_operation();
|
||||
let source_framebuffer = &layer_framebuffer_info.framebuffer;
|
||||
let source_texture = self.device.framebuffer_texture(source_framebuffer);
|
||||
let source_texture_size = self.device.texture_size(source_texture);
|
||||
let main_viewport = self.main_viewport();
|
||||
|
||||
let uniforms = vec![
|
||||
(&self.filter_basic_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(main_viewport.size().to_f32().0)),
|
||||
(&self.filter_basic_program.source_uniform, UniformData::TextureUnit(0)),
|
||||
(&self.filter_basic_program.source_size_uniform,
|
||||
UniformData::Vec2(source_texture_size.0.to_f32x2())),
|
||||
];
|
||||
|
||||
let blend_state = match composite_op {
|
||||
CompositeOp::SourceOver => {
|
||||
BlendState {
|
||||
func: BlendFunc::RGBSrcAlphaAlphaOneMinusSrcAlpha,
|
||||
..BlendState::default()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.device.draw_elements(6, &RenderState {
|
||||
target: &self.draw_render_target(),
|
||||
program: &self.filter_basic_program.program,
|
||||
vertex_array: &self.filter_basic_vertex_array.vertex_array,
|
||||
primitive: Primitive::Triangles,
|
||||
textures: &[&source_texture],
|
||||
uniforms: &uniforms,
|
||||
viewport: main_viewport,
|
||||
options: RenderOptions {
|
||||
clear_ops: ClearOps { color: clear_color, ..ClearOps::default() },
|
||||
blend: Some(blend_state),
|
||||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
fn draw_text_layer(&self,
|
||||
layer_framebuffer_info: &LayerFramebufferInfo<D>,
|
||||
fg_color: ColorF,
|
||||
bg_color: ColorF,
|
||||
defringing_kernel: Option<DefringingKernel>,
|
||||
gamma_correction: bool) {
|
||||
let clear_color = self.clear_color_for_draw_operation();
|
||||
let source_framebuffer = &layer_framebuffer_info.framebuffer;
|
||||
let source_texture = self.device.framebuffer_texture(source_framebuffer);
|
||||
let source_texture_size = self.device.texture_size(source_texture);
|
||||
let main_viewport = self.main_viewport();
|
||||
|
||||
let mut uniforms = vec![
|
||||
(&self.postprocess_program.framebuffer_size_uniform,
|
||||
(&self.filter_text_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(main_viewport.size().to_f32().0)),
|
||||
(&self.postprocess_program.source_uniform, UniformData::TextureUnit(0)),
|
||||
(&self.postprocess_program.source_size_uniform,
|
||||
(&self.filter_text_program.source_uniform, UniformData::TextureUnit(0)),
|
||||
(&self.filter_text_program.source_size_uniform,
|
||||
UniformData::Vec2(source_texture_size.0.to_f32x2())),
|
||||
(&self.postprocess_program.gamma_lut_uniform, UniformData::TextureUnit(1)),
|
||||
(&self.postprocess_program.fg_color_uniform,
|
||||
UniformData::Vec4(layer_framebuffer_info.effects.fg_color.0)),
|
||||
(&self.postprocess_program.bg_color_uniform,
|
||||
UniformData::Vec4(layer_framebuffer_info.effects.bg_color.0)),
|
||||
(&self.postprocess_program.gamma_correction_enabled_uniform,
|
||||
UniformData::Int(layer_framebuffer_info.effects.gamma_correction as i32)),
|
||||
(&self.filter_text_program.gamma_lut_uniform, UniformData::TextureUnit(1)),
|
||||
(&self.filter_text_program.fg_color_uniform, UniformData::Vec4(fg_color.0)),
|
||||
(&self.filter_text_program.bg_color_uniform, UniformData::Vec4(bg_color.0)),
|
||||
(&self.filter_text_program.gamma_correction_enabled_uniform,
|
||||
UniformData::Int(gamma_correction as i32)),
|
||||
];
|
||||
|
||||
match layer_framebuffer_info.effects.defringing_kernel {
|
||||
match defringing_kernel {
|
||||
Some(ref kernel) => {
|
||||
uniforms.push((&self.postprocess_program.kernel_uniform,
|
||||
uniforms.push((&self.filter_text_program.kernel_uniform,
|
||||
UniformData::Vec4(F32x4::from_slice(&kernel.0))));
|
||||
}
|
||||
None => {
|
||||
uniforms.push((&self.postprocess_program.kernel_uniform,
|
||||
uniforms.push((&self.filter_text_program.kernel_uniform,
|
||||
UniformData::Vec4(F32x4::default())));
|
||||
}
|
||||
}
|
||||
|
||||
self.device.draw_elements(6, &RenderState {
|
||||
target: &self.draw_render_target(),
|
||||
program: &self.postprocess_program.program,
|
||||
vertex_array: &self.postprocess_vertex_array.vertex_array,
|
||||
program: &self.filter_text_program.program,
|
||||
vertex_array: &self.filter_text_vertex_array.vertex_array,
|
||||
primitive: Primitive::Triangles,
|
||||
textures: &[&source_texture, &self.gamma_lut_texture],
|
||||
uniforms: &uniforms,
|
||||
|
@ -828,10 +902,6 @@ where
|
|||
..RenderOptions::default()
|
||||
},
|
||||
});
|
||||
|
||||
self.preserve_draw_framebuffer();
|
||||
|
||||
self.framebuffer_cache.release_framebuffer(layer_framebuffer_info.framebuffer);
|
||||
}
|
||||
|
||||
fn stencil_state(&self) -> Option<StencilState> {
|
||||
|
@ -847,7 +917,7 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn clear_color_for_draw_operation(&mut self) -> Option<ColorF> {
|
||||
fn clear_color_for_draw_operation(&self) -> Option<ColorF> {
|
||||
let must_preserve_contents = match self.layer_framebuffer_stack.last() {
|
||||
Some(ref layer_framebuffer_info) => layer_framebuffer_info.must_preserve_contents,
|
||||
None => {
|
||||
|
@ -924,15 +994,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): Rename to `Effects` and move to `pathfinder_content`, perhaps?
|
||||
#[derive(Clone, Copy, Default, Debug)]
|
||||
pub struct PostprocessOptions {
|
||||
pub fg_color: ColorF,
|
||||
pub bg_color: ColorF,
|
||||
pub defringing_kernel: Option<DefringingKernel>,
|
||||
pub gamma_correction: bool,
|
||||
}
|
||||
|
||||
// Render stats
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
|
@ -1047,6 +1108,6 @@ impl<D> FramebufferCache<D> where D: Device {
|
|||
|
||||
struct LayerFramebufferInfo<D> where D: Device {
|
||||
framebuffer: D::Framebuffer,
|
||||
effects: PostprocessOptions,
|
||||
effects: Effects,
|
||||
must_preserve_contents: bool,
|
||||
}
|
||||
|
|
|
@ -388,69 +388,44 @@ impl<D> AlphaTileProgram<D> where D: Device {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct PostprocessProgram<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub struct FilterBasicProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub source_uniform: D::Uniform,
|
||||
pub source_size_uniform: D::Uniform,
|
||||
pub framebuffer_size_uniform: D::Uniform,
|
||||
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> PostprocessProgram<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> PostprocessProgram<D> {
|
||||
let program = device.create_program(resources, "post");
|
||||
impl<D> FilterBasicProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterBasicProgram<D> {
|
||||
let program = device.create_program_from_shader_names(resources,
|
||||
"filter_basic",
|
||||
"filter",
|
||||
"filter_basic");
|
||||
let source_uniform = device.get_uniform(&program, "Source");
|
||||
let source_size_uniform = device.get_uniform(&program, "SourceSize");
|
||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let kernel_uniform = device.get_uniform(&program, "Kernel");
|
||||
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
|
||||
let gamma_correction_enabled_uniform = device.get_uniform(&program,
|
||||
"GammaCorrectionEnabled");
|
||||
let fg_color_uniform = device.get_uniform(&program, "FGColor");
|
||||
let bg_color_uniform = device.get_uniform(&program, "BGColor");
|
||||
PostprocessProgram {
|
||||
FilterBasicProgram {
|
||||
program,
|
||||
source_uniform,
|
||||
source_size_uniform,
|
||||
framebuffer_size_uniform,
|
||||
kernel_uniform,
|
||||
gamma_lut_uniform,
|
||||
gamma_correction_enabled_uniform,
|
||||
fg_color_uniform,
|
||||
bg_color_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PostprocessVertexArray<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
pub struct FilterBasicVertexArray<D> where D: Device {
|
||||
pub vertex_array: D::VertexArray,
|
||||
}
|
||||
|
||||
impl<D> PostprocessVertexArray<D>
|
||||
where
|
||||
D: Device,
|
||||
{
|
||||
impl<D> FilterBasicVertexArray<D> where D: Device {
|
||||
pub fn new(
|
||||
device: &D,
|
||||
postprocess_program: &PostprocessProgram<D>,
|
||||
fill_basic_program: &FilterBasicProgram<D>,
|
||||
quad_vertex_positions_buffer: &D::Buffer,
|
||||
quad_vertex_indices_buffer: &D::Buffer,
|
||||
) -> PostprocessVertexArray<D> {
|
||||
) -> FilterBasicVertexArray<D> {
|
||||
let vertex_array = device.create_vertex_array();
|
||||
let position_attr = device.get_vertex_attr(&postprocess_program.program, "Position")
|
||||
let position_attr = device.get_vertex_attr(&fill_basic_program.program, "Position")
|
||||
.unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
||||
|
@ -465,7 +440,79 @@ where
|
|||
});
|
||||
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
PostprocessVertexArray { vertex_array }
|
||||
FilterBasicVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilterTextProgram<D> where D: Device {
|
||||
pub program: D::Program,
|
||||
pub source_uniform: D::Uniform,
|
||||
pub source_size_uniform: D::Uniform,
|
||||
pub framebuffer_size_uniform: D::Uniform,
|
||||
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> FilterTextProgram<D> where D: Device {
|
||||
pub fn new(device: &D, resources: &dyn ResourceLoader) -> FilterTextProgram<D> {
|
||||
let program = device.create_program_from_shader_names(resources,
|
||||
"filter_text",
|
||||
"filter",
|
||||
"filter_text");
|
||||
let source_uniform = device.get_uniform(&program, "Source");
|
||||
let source_size_uniform = device.get_uniform(&program, "SourceSize");
|
||||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let kernel_uniform = device.get_uniform(&program, "Kernel");
|
||||
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
|
||||
let gamma_correction_enabled_uniform = device.get_uniform(&program,
|
||||
"GammaCorrectionEnabled");
|
||||
let fg_color_uniform = device.get_uniform(&program, "FGColor");
|
||||
let bg_color_uniform = device.get_uniform(&program, "BGColor");
|
||||
FilterTextProgram {
|
||||
program,
|
||||
source_uniform,
|
||||
source_size_uniform,
|
||||
framebuffer_size_uniform,
|
||||
kernel_uniform,
|
||||
gamma_lut_uniform,
|
||||
gamma_correction_enabled_uniform,
|
||||
fg_color_uniform,
|
||||
bg_color_uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilterTextVertexArray<D> where D: Device {
|
||||
pub vertex_array: D::VertexArray,
|
||||
}
|
||||
|
||||
impl<D> FilterTextVertexArray<D> where D: Device {
|
||||
pub fn new(
|
||||
device: &D,
|
||||
fill_text_program: &FilterTextProgram<D>,
|
||||
quad_vertex_positions_buffer: &D::Buffer,
|
||||
quad_vertex_indices_buffer: &D::Buffer,
|
||||
) -> FilterTextVertexArray<D> {
|
||||
let vertex_array = device.create_vertex_array();
|
||||
let position_attr = device.get_vertex_attr(&fill_text_program.program, "Position")
|
||||
.unwrap();
|
||||
|
||||
device.bind_buffer(&vertex_array, quad_vertex_positions_buffer, BufferTarget::Vertex);
|
||||
device.configure_vertex_attr(&vertex_array, &position_attr, &VertexAttrDescriptor {
|
||||
size: 2,
|
||||
class: VertexAttrClass::Int,
|
||||
attr_type: VertexAttrType::I16,
|
||||
stride: 4,
|
||||
offset: 0,
|
||||
divisor: 0,
|
||||
buffer_index: 0,
|
||||
});
|
||||
device.bind_buffer(&vertex_array, quad_vertex_indices_buffer, BufferTarget::Index);
|
||||
|
||||
FilterTextVertexArray { vertex_array }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// pathfinder/renderer/src/gpu_data.rs
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
// 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
|
||||
|
@ -10,9 +10,9 @@
|
|||
|
||||
//! Packed data ready to be sent to the GPU.
|
||||
|
||||
use crate::gpu::renderer::PostprocessOptions;
|
||||
use crate::options::BoundingQuad;
|
||||
use pathfinder_color::ColorU;
|
||||
use pathfinder_content::effects::Effects;
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_geometry::line_segment::{LineSegmentU4, LineSegmentU8};
|
||||
use pathfinder_geometry::vector::Vector2I;
|
||||
|
@ -25,7 +25,7 @@ pub enum RenderCommand {
|
|||
AddFills(Vec<FillBatchPrimitive>),
|
||||
FlushFills,
|
||||
RenderMaskTiles { tiles: Vec<MaskTile>, fill_rule: FillRule },
|
||||
PushLayer { effects: PostprocessOptions },
|
||||
PushLayer { effects: Effects },
|
||||
PopLayer,
|
||||
DrawAlphaTiles(Vec<AlphaTile>),
|
||||
DrawSolidTiles(Vec<SolidTileVertex>),
|
||||
|
|
|
@ -20,7 +20,6 @@ pub mod gpu;
|
|||
pub mod gpu_data;
|
||||
pub mod options;
|
||||
pub mod paint;
|
||||
pub mod post;
|
||||
pub mod scene;
|
||||
|
||||
mod allocator;
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
// pathfinder/renderer/src/post.rs
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! Functionality related to postprocessing effects.
|
||||
//!
|
||||
//! Since these effects run on GPU as fragment shaders, this contains no
|
||||
//! implementations, just shared declarations.
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub struct DefringingKernel(pub [f32; 4]);
|
||||
|
||||
/// This intentionally does not precisely match what Core Graphics does (a
|
||||
/// Lanczos function), because we don't want any ringing artefacts.
|
||||
pub static DEFRINGING_KERNEL_CORE_GRAPHICS: DefringingKernel =
|
||||
DefringingKernel([0.033165660, 0.102074051, 0.221434336, 0.286651906]);
|
||||
pub static DEFRINGING_KERNEL_FREETYPE: DefringingKernel =
|
||||
DefringingKernel([0.0, 0.031372549, 0.301960784, 0.337254902]);
|
||||
|
||||
/// Should match macOS 10.13 High Sierra.
|
||||
pub static STEM_DARKENING_FACTORS: [f32; 2] = [0.0121, 0.0121 * 1.25];
|
||||
|
||||
/// Should match macOS 10.13 High Sierra.
|
||||
pub const MAX_STEM_DARKENING_AMOUNT: [f32; 2] = [0.3, 0.3];
|
||||
|
||||
/// This value is a subjective cutoff. Above this ppem value, no stem darkening is performed.
|
||||
pub const MAX_STEM_DARKENING_PIXELS_PER_EM: f32 = 72.0;
|
|
@ -12,10 +12,10 @@
|
|||
|
||||
use crate::builder::SceneBuilder;
|
||||
use crate::concurrent::executor::Executor;
|
||||
use crate::gpu::renderer::PostprocessOptions;
|
||||
use crate::options::{BuildOptions, PreparedBuildOptions};
|
||||
use crate::options::{PreparedRenderTransform, RenderCommandListener};
|
||||
use crate::paint::{Paint, PaintId, PaintInfo, Palette};
|
||||
use pathfinder_content::effects::Effects;
|
||||
use pathfinder_content::fill::FillRule;
|
||||
use pathfinder_geometry::vector::Vector2F;
|
||||
use pathfinder_geometry::rect::RectF;
|
||||
|
@ -70,7 +70,7 @@ impl Scene {
|
|||
clip_path_id
|
||||
}
|
||||
|
||||
pub fn push_layer(&mut self, effects: PostprocessOptions) {
|
||||
pub fn push_layer(&mut self, effects: Effects) {
|
||||
self.display_list.push(DisplayItem::PushLayer { effects });
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ pub struct ClipPathId(pub u32);
|
|||
#[derive(Clone, Debug)]
|
||||
pub enum DisplayItem {
|
||||
DrawPaths { start_index: u32, end_index: u32 },
|
||||
PushLayer { effects: PostprocessOptions },
|
||||
PushLayer { effects: Effects },
|
||||
PopLayer,
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
precision highp float;
|
||||
|
||||
in ivec2 aPosition;
|
||||
|
||||
out vec2 vTexCoord;
|
||||
|
||||
void main(){
|
||||
vec2 position = vec2(aPosition);
|
||||
vTexCoord = position;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
gl_Position = vec4(vec2(position)* 2.0 - 1.0, 0.0, 1.0);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uSource;
|
||||
uniform vec2 uSourceSize;
|
||||
|
||||
in vec2 vTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main(){
|
||||
oFragColor = texture(uSource, vTexCoord);
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
#version {{version}}
|
||||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uSource;
|
||||
uniform vec2 uSourceSize;
|
||||
uniform vec4 uFGColor;
|
||||
uniform vec4 uBGColor;
|
||||
uniform int uGammaCorrectionEnabled;
|
||||
|
||||
in vec2 vTexCoord;
|
||||
|
||||
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(uSource, vec2(vTexCoord . x + offset, vTexCoord . y)). r;
|
||||
}
|
||||
|
||||
void main(){
|
||||
|
||||
vec3 alpha;
|
||||
if(uKernel . w == 0.0){
|
||||
alpha = texture(uSource, vTexCoord). rrr;
|
||||
} else {
|
||||
vec4 alphaLeft, alphaRight;
|
||||
float alphaCenter;
|
||||
sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSourceSize . 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);
|
||||
}
|
||||
|
|
@ -24,8 +24,7 @@ fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuff
|
|||
{
|
||||
main0_out out = {};
|
||||
float2 texCoordPx = fract(in.vTexCoord) / fwidth(in.vTexCoord);
|
||||
bool4 _33 = bool4(any(texCoordPx <= float2(1.0)));
|
||||
out.oFragColor = float4(_33.x ? (*spvDescriptorSet0.uGridlineColor).x : (*spvDescriptorSet0.uGroundColor).x, _33.y ? (*spvDescriptorSet0.uGridlineColor).y : (*spvDescriptorSet0.uGroundColor).y, _33.z ? (*spvDescriptorSet0.uGridlineColor).z : (*spvDescriptorSet0.uGroundColor).z, _33.w ? (*spvDescriptorSet0.uGridlineColor).w : (*spvDescriptorSet0.uGroundColor).w);
|
||||
out.oFragColor = select((*spvDescriptorSet0.uGroundColor), (*spvDescriptorSet0.uGridlineColor), bool4(any(texCoordPx <= float2(1.0))));
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,8 @@ fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuff
|
|||
main0_out out = {};
|
||||
float2 from = in.vFrom;
|
||||
float2 to = in.vTo;
|
||||
bool2 _29 = bool2(from.x < to.x);
|
||||
float2 left = float2(_29.x ? from.x : to.x, _29.y ? from.y : to.y);
|
||||
bool2 _39 = bool2(from.x < to.x);
|
||||
float2 right = float2(_39.x ? to.x : from.x, _39.y ? to.y : from.y);
|
||||
float2 left = select(to, from, bool2(from.x < to.x));
|
||||
float2 right = select(from, to, bool2(from.x < to.x));
|
||||
float2 window = fast::clamp(float2(from.x, to.x), float2(-0.5), float2(0.5));
|
||||
float offset = mix(window.x, window.y, 0.5) - left.x;
|
||||
float t = offset / (right.x - left.x);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 vTexCoord [[user(locn0)]];
|
||||
float4 gl_Position [[position]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
int2 aPosition [[attribute(0)]];
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float2 position = float2(in.aPosition);
|
||||
out.vTexCoord = position;
|
||||
position.y = 1.0 - position.y;
|
||||
out.gl_Position = float4((float2(position) * 2.0) - float2(1.0), 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Automatically generated from files in pathfinder/shaders/. Do not edit!
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct spvDescriptorSetBuffer0
|
||||
{
|
||||
texture2d<float> uSource [[id(0)]];
|
||||
sampler uSourceSmplr [[id(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float4 oFragColor [[color(0)]];
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float2 vTexCoord [[user(locn0)]];
|
||||
};
|
||||
|
||||
fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer0& spvDescriptorSet0 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.oFragColor = spvDescriptorSet0.uSource.sample(spvDescriptorSet0.uSourceSmplr, in.vTexCoord);
|
||||
return out;
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
// 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> uSource [[id(3)]];
|
||||
sampler uSourceSmplr [[id(4)]];
|
||||
constant float2* uSourceSize [[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 vTexCoord [[user(locn0)]];
|
||||
};
|
||||
|
||||
float sample1Tap(thread const float& offset, thread texture2d<float> uSource, thread const sampler uSourceSmplr, thread float2& vTexCoord)
|
||||
{
|
||||
return uSource.sample(uSourceSmplr, float2(vTexCoord.x + offset, vTexCoord.y)).x;
|
||||
}
|
||||
|
||||
void sample9Tap(thread float4& outAlphaLeft, thread float& outAlphaCenter, thread float4& outAlphaRight, thread const float& onePixel, thread float4 uKernel, thread texture2d<float> uSource, thread const sampler uSourceSmplr, thread float2& vTexCoord)
|
||||
{
|
||||
float _89;
|
||||
if (uKernel.x > 0.0)
|
||||
{
|
||||
float param = (-4.0) * onePixel;
|
||||
_89 = sample1Tap(param, uSource, uSourceSmplr, vTexCoord);
|
||||
}
|
||||
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, uSource, uSourceSmplr, vTexCoord), sample1Tap(param_2, uSource, uSourceSmplr, vTexCoord), sample1Tap(param_3, uSource, uSourceSmplr, vTexCoord));
|
||||
float param_4 = 0.0;
|
||||
outAlphaCenter = sample1Tap(param_4, uSource, uSourceSmplr, vTexCoord);
|
||||
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, uSource, uSourceSmplr, vTexCoord);
|
||||
}
|
||||
else
|
||||
{
|
||||
_134 = 0.0;
|
||||
}
|
||||
outAlphaRight = float4(sample1Tap(param_5, uSource, uSourceSmplr, vTexCoord), sample1Tap(param_6, uSource, uSourceSmplr, vTexCoord), sample1Tap(param_7, uSource, uSourceSmplr, vTexCoord), _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.uSource.sample(spvDescriptorSet0.uSourceSmplr, in.vTexCoord).xxx;
|
||||
}
|
||||
else
|
||||
{
|
||||
float param_3 = 1.0 / (*spvDescriptorSet0.uSourceSize).x;
|
||||
float4 param;
|
||||
float param_1;
|
||||
float4 param_2;
|
||||
sample9Tap(param, param_1, param_2, param_3, (*spvDescriptorSet0.uKernel), spvDescriptorSet0.uSource, spvDescriptorSet0.uSourceSmplr, in.vTexCoord);
|
||||
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;
|
||||
}
|
||||
|
|
@ -14,8 +14,9 @@ SHADERS=\
|
|||
mask.vs.glsl \
|
||||
mask_evenodd.fs.glsl \
|
||||
mask_winding.fs.glsl \
|
||||
post.fs.glsl \
|
||||
post.vs.glsl \
|
||||
filter.vs.glsl \
|
||||
filter_basic.fs.glsl \
|
||||
filter_text.fs.glsl \
|
||||
reproject.fs.glsl \
|
||||
reproject.vs.glsl \
|
||||
stencil.fs.glsl \
|
||||
|
@ -27,8 +28,8 @@ SHADERS=\
|
|||
$(EMPTY)
|
||||
|
||||
INCLUDES=\
|
||||
post_convolve.inc.glsl \
|
||||
post_gamma_correct.inc.glsl \
|
||||
filter_text_convolve.inc.glsl \
|
||||
filter_text_gamma_correct.inc.glsl \
|
||||
$(EMPTY)
|
||||
|
||||
OUT=\
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/post.vs.glsl
|
||||
// pathfinder/shaders/filter.vs.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
// 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
|
|
@ -0,0 +1,29 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/filter_basic.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.
|
||||
|
||||
#extension GL_GOOGLE_include_directive : enable
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D uSource;
|
||||
uniform vec2 uSourceSize;
|
||||
|
||||
in vec2 vTexCoord;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
void main() {
|
||||
oFragColor = texture(uSource, vTexCoord);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#version 330
|
||||
|
||||
// pathfinder/shaders/post.fs.glsl
|
||||
// pathfinder/shaders/filter_text.fs.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
|
@ -27,8 +27,8 @@ in vec2 vTexCoord;
|
|||
|
||||
out vec4 oFragColor;
|
||||
|
||||
#include "post_gamma_correct.inc.glsl"
|
||||
#include "post_convolve.inc.glsl"
|
||||
#include "filter_text_gamma_correct.inc.glsl"
|
||||
#include "filter_text_convolve.inc.glsl"
|
||||
|
||||
// Convolve horizontally in this pass.
|
||||
float sample1Tap(float offset) {
|
|
@ -1,4 +1,4 @@
|
|||
// pathfinder/shaders/post_convolve.inc.glsl
|
||||
// pathfinder/shaders/filter_text_convolve.inc.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
|
@ -1,4 +1,4 @@
|
|||
// pathfinder/shaders/post_gamma_correct.inc.glsl
|
||||
// pathfinder/shaders/filter_text_gamma_correct.inc.glsl
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
Loading…
Reference in New Issue