From 224c8e85b9886920d578deefd5ee4933c35ae383 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 22 Mar 2019 14:28:18 -0700 Subject: [PATCH] Create separate shaders for monochrome and multicolor tiles. This is preparation for fixing subpixel AA. --- demo/common/src/lib.rs | 64 +-- geometry/src/basic/point.rs | 5 + gl/src/lib.rs | 5 + gpu/src/lib.rs | 36 +- renderer/src/builder.rs | 30 +- renderer/src/gpu/debug.rs | 6 +- renderer/src/gpu/renderer.rs | 388 +++++++++++++----- renderer/src/gpu_data.rs | 19 +- renderer/src/scene.rs | 9 +- resources/shaders/post.fs.glsl | 23 +- .../{mask_tile.fs.glsl => tile_alpha.fs.glsl} | 0 .../shaders/tile_alpha_monochrome.vs.glsl | 20 + .../shaders/tile_alpha_multicolor.vs.glsl | 20 + ...ile.vs.glsl => tile_alpha_vertex.inc.glsl} | 23 +- resources/shaders/tile_monochrome.inc.glsl | 15 + resources/shaders/tile_multicolor.inc.glsl | 22 + ...{solid_tile.fs.glsl => tile_solid.fs.glsl} | 0 .../shaders/tile_solid_monochrome.vs.glsl | 20 + .../shaders/tile_solid_multicolor.vs.glsl | 20 + ...ile.vs.glsl => tile_solid_vertex.inc.glsl} | 18 +- 20 files changed, 537 insertions(+), 206 deletions(-) rename resources/shaders/{mask_tile.fs.glsl => tile_alpha.fs.glsl} (100%) create mode 100644 resources/shaders/tile_alpha_monochrome.vs.glsl create mode 100644 resources/shaders/tile_alpha_multicolor.vs.glsl rename resources/shaders/{mask_tile.vs.glsl => tile_alpha_vertex.inc.glsl} (68%) create mode 100644 resources/shaders/tile_monochrome.inc.glsl create mode 100644 resources/shaders/tile_multicolor.inc.glsl rename resources/shaders/{solid_tile.fs.glsl => tile_solid.fs.glsl} (100%) create mode 100644 resources/shaders/tile_solid_monochrome.vs.glsl create mode 100644 resources/shaders/tile_solid_multicolor.vs.glsl rename resources/shaders/{solid_tile.vs.glsl => tile_solid_vertex.inc.glsl} (58%) diff --git a/demo/common/src/lib.rs b/demo/common/src/lib.rs index 1ea24add..c4bd6117 100644 --- a/demo/common/src/lib.rs +++ b/demo/common/src/lib.rs @@ -27,7 +27,7 @@ use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{DepthFunc, DepthState, Device, Primitive, RenderState, StencilFunc}; use pathfinder_gpu::{StencilState, UniformData}; use pathfinder_renderer::builder::{RenderOptions, RenderTransform, SceneBuilder}; -use pathfinder_renderer::gpu::renderer::Renderer; +use pathfinder_renderer::gpu::renderer::{RenderMode, Renderer}; use pathfinder_renderer::gpu_data::{BuiltScene, Stats}; use pathfinder_renderer::post::{DEFRINGING_KERNEL_CORE_GRAPHICS, STEM_DARKENING_FACTORS}; use pathfinder_renderer::scene::Scene; @@ -86,7 +86,7 @@ pub struct DemoApp where W: Window { window_size: WindowSize, scene_view_box: RectF32, - scene_is_monochrome: bool, + monochrome_scene_color: Option, camera: Camera, frame_counter: u32, @@ -116,12 +116,12 @@ impl DemoApp where W: Window { let resources = window.resource_loader(); let options = Options::get(); - let view_box_size = view_box_size(options.mode, &window_size); + let view_box_size = view_box_size(options.mode, &window_size, false); let built_svg = load_scene(resources, &options.input_path); let message = get_svg_building_message(&built_svg); let scene_view_box = built_svg.scene.view_box; - let scene_is_monochrome = built_svg.scene.is_monochrome(); + let monochrome_scene_color = built_svg.scene.monochrome_color(); let renderer = Renderer::new(device, resources, @@ -155,7 +155,7 @@ impl DemoApp where W: Window { window_size, scene_view_box, - scene_is_monochrome, + monochrome_scene_color, camera, frame_counter: 0, @@ -199,7 +199,9 @@ impl DemoApp where W: Window { } fn build_scene(&mut self) { - let view_box_size = view_box_size(self.ui.mode, &self.window_size); + let view_box_size = view_box_size(self.ui.mode, + &self.window_size, + self.ui.subpixel_aa_effect_enabled); let render_transform = match self.camera { Camera::ThreeD { ref mut transform, ref mut velocity } => { @@ -252,7 +254,9 @@ impl DemoApp where W: Window { } Event::WindowResized(new_size) => { self.window_size = new_size; - let view_box_size = view_box_size(self.ui.mode, &self.window_size); + let view_box_size = view_box_size(self.ui.mode, + &self.window_size, + self.ui.subpixel_aa_effect_enabled); self.scene_thread_proxy.set_drawable_size(view_box_size); self.renderer.set_main_framebuffer_size(self.window_size.device_size()); self.dirty = true; @@ -339,9 +343,11 @@ impl DemoApp where W: Window { let built_svg = load_scene(self.window.resource_loader(), svg_path); self.ui.message = get_svg_building_message(&built_svg); - let view_box_size = view_box_size(self.ui.mode, &self.window_size); + let view_box_size = view_box_size(self.ui.mode, + &self.window_size, + self.ui.subpixel_aa_effect_enabled); self.scene_view_box = built_svg.scene.view_box; - self.scene_is_monochrome = built_svg.scene.is_monochrome(); + self.monochrome_scene_color = built_svg.scene.monochrome_color(); self.camera = if self.ui.mode == Mode::TwoD { Camera::new_2d(self.scene_view_box, view_box_size) @@ -415,7 +421,7 @@ impl DemoApp where W: Window { self.renderer.debug_ui.ui.mouse_position = get_mouse_position(&self.window, self.window_size.backing_scale_factor); - self.ui.show_text_effects = self.scene_is_monochrome; + self.ui.show_text_effects = self.monochrome_scene_color.is_some(); let mut ui_action = UIAction::None; self.ui.update(&self.renderer.device, @@ -533,21 +539,30 @@ impl DemoApp where W: Window { let render_msg = &self.current_frame.as_ref().unwrap().render_msg; let built_scene = &render_msg.render_scenes[viewport_index as usize].built_scene; - let view_box_size = view_box_size(self.ui.mode, &self.window_size); + let view_box_size = view_box_size(self.ui.mode, + &self.window_size, + self.ui.subpixel_aa_effect_enabled); let viewport_origin_x = viewport_index as i32 * view_box_size.x(); let viewport = RectI32::new(Point2DI32::new(viewport_origin_x, 0), view_box_size); self.renderer.set_viewport(viewport); - if self.ui.gamma_correction_effect_enabled { - self.renderer.enable_gamma_correction(self.background_color()); - } else { - self.renderer.disable_gamma_correction(); - } - - if self.ui.subpixel_aa_effect_enabled { - self.renderer.enable_subpixel_aa(&DEFRINGING_KERNEL_CORE_GRAPHICS); - } else { - self.renderer.disable_subpixel_aa(); + match self.monochrome_scene_color { + None => self.renderer.set_render_mode(RenderMode::Multicolor), + Some(fill_color) => { + self.renderer.set_render_mode(RenderMode::Monochrome { + fill_color: fill_color.to_f32(), + gamma_correction_bg_color: if self.ui.gamma_correction_effect_enabled { + Some(self.background_color()) + } else { + None + }, + defringing_kernel: if self.ui.subpixel_aa_effect_enabled { + Some(DEFRINGING_KERNEL_CORE_GRAPHICS) + } else { + None + } + }) + } } if self.ui.mode == Mode::TwoD { @@ -951,12 +966,13 @@ fn emit_message(ui: &mut DemoUI, }); } -fn view_box_size(mode: Mode, window_size: &WindowSize) -> Point2DI32 { +fn view_box_size(mode: Mode, window_size: &WindowSize, use_subpixel_aa: bool) -> Point2DI32 { let window_drawable_size = window_size.device_size(); - match mode { + let initial_size = match mode { Mode::TwoD | Mode::ThreeD => window_drawable_size, Mode::VR => Point2DI32::new(window_drawable_size.x() / 2, window_drawable_size.y()), - } + }; + if use_subpixel_aa { initial_size.scale_xy(Point2DI32::new(3, 1)) } else { initial_size } } struct Frame { diff --git a/geometry/src/basic/point.rs b/geometry/src/basic/point.rs index 8b421070..ec56ebba 100644 --- a/geometry/src/basic/point.rs +++ b/geometry/src/basic/point.rs @@ -220,6 +220,11 @@ impl Point2DI32 { Point2DI32(self.0 * I32x4::splat(factor)) } + #[inline] + pub fn scale_xy(&self, factors: Point2DI32) -> Point2DI32 { + Point2DI32(self.0 * factors.0) + } + #[inline] pub fn to_f32(&self) -> Point2DF32 { Point2DF32(self.0.to_f32x4()) diff --git a/gl/src/lib.rs b/gl/src/lib.rs index 030224be..61a6195f 100644 --- a/gl/src/lib.rs +++ b/gl/src/lib.rs @@ -156,6 +156,11 @@ impl Device for GLDevice { fn create_texture(&self, format: TextureFormat, size: Point2DI32) -> GLTexture { let (gl_internal_format, gl_format, gl_type); match format { + TextureFormat::R8 => { + gl_internal_format = gl::R8 as GLint; + gl_format = gl::RED; + gl_type = gl::UNSIGNED_BYTE; + } TextureFormat::R16F => { gl_internal_format = gl::R16F as GLint; gl_format = gl::RED; diff --git a/gpu/src/lib.rs b/gpu/src/lib.rs index f8b3c91b..a31aa4bb 100644 --- a/gpu/src/lib.rs +++ b/gpu/src/lib.rs @@ -110,11 +110,27 @@ pub trait Device { let suffix = match kind { ShaderKind::Vertex => 'v', ShaderKind::Fragment => 'f' }; let source = resources.slurp(&format!("shaders/{}.{}s.glsl", name, suffix)).unwrap(); + let mut load_include_tile_alpha_vertex = + |_| load_shader_include(resources, "tile_alpha_vertex"); + let mut load_include_tile_monochrome = + |_| load_shader_include(resources, "tile_monochrome"); + let mut load_include_tile_multicolor = + |_| load_shader_include(resources, "tile_multicolor"); + let mut load_include_tile_solid_vertex = + |_| load_shader_include(resources, "tile_solid_vertex"); let mut load_include_post_convolve = |_| load_shader_include(resources, "post_convolve"); let mut load_include_post_gamma_correct = |_| load_shader_include(resources, "post_gamma_correct"); let template_input = - HashBuilder::new().insert_lambda("include_post_convolve", + HashBuilder::new().insert_lambda("include_tile_alpha_vertex", + &mut load_include_tile_alpha_vertex) + .insert_lambda("include_tile_monochrome", + &mut load_include_tile_monochrome) + .insert_lambda("include_tile_multicolor", + &mut load_include_tile_multicolor) + .insert_lambda("include_tile_solid_vertex", + &mut load_include_tile_solid_vertex) + .insert_lambda("include_post_convolve", &mut load_include_post_convolve) .insert_lambda("include_post_gamma_correct", &mut load_include_post_gamma_correct); @@ -122,15 +138,27 @@ pub trait Device { self.create_shader_from_source(name, &source, kind, template_input) } + fn create_program_from_shader_names(&self, + resources: &dyn ResourceLoader, + program_name: &str, + vertex_shader_name: &str, + fragment_shader_name: &str) + -> Self::Program { + let vertex_shader = self.create_shader(resources, vertex_shader_name, ShaderKind::Vertex); + let fragment_shader = self.create_shader(resources, + fragment_shader_name, + ShaderKind::Fragment); + self.create_program_from_shaders(program_name, vertex_shader, fragment_shader) + } + fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program { - let vertex_shader = self.create_shader(resources, name, ShaderKind::Vertex); - let fragment_shader = self.create_shader(resources, name, ShaderKind::Fragment); - self.create_program_from_shaders(name, vertex_shader, fragment_shader) + self.create_program_from_shader_names(resources, name, name, name) } } #[derive(Clone, Copy, Debug)] pub enum TextureFormat { + R8, R16F, RGBA8, } diff --git a/renderer/src/builder.rs b/renderer/src/builder.rs index 1165195f..d5fbd1dc 100644 --- a/renderer/src/builder.rs +++ b/renderer/src/builder.rs @@ -11,7 +11,7 @@ //! Packs data onto the GPU. use crate::gpu_data::{Batch, BuiltObject, FillBatchPrimitive}; -use crate::gpu_data::{MaskTileBatchPrimitive, SolidTileScenePrimitive}; +use crate::gpu_data::{AlphaTileBatchPrimitive, SolidTileScenePrimitive}; use crate::scene; use crate::tiles; use crate::z_buffer::ZBuffer; @@ -25,7 +25,7 @@ use std::iter; use std::u16; const MAX_FILLS_PER_BATCH: usize = 0x0002_0000; -const MAX_MASKS_PER_BATCH: u16 = 0xffff; +const MAX_ALPHA_TILES_PER_BATCH: u16 = 0xffff; pub struct SceneBuilder { objects: Vec, @@ -53,7 +53,7 @@ impl SceneBuilder { pub fn build_batch(&mut self) -> Option { let mut batch = Batch::new(); - let mut object_tile_index_to_batch_mask_tile_index = vec![]; + let mut object_tile_index_to_batch_alpha_tile_index = vec![]; while self.current_object_index < self.objects.len() { let object = &self.objects[self.current_object_index]; @@ -61,11 +61,11 @@ impl SceneBuilder { break; } - object_tile_index_to_batch_mask_tile_index.clear(); - object_tile_index_to_batch_mask_tile_index + object_tile_index_to_batch_alpha_tile_index.clear(); + object_tile_index_to_batch_alpha_tile_index .extend(iter::repeat(u16::MAX).take(object.tiles.len())); - // Copy mask tiles. + // Copy alpha tiles. for (tile_index, tile) in object.tiles.iter().enumerate() { // Skip solid tiles, since we handled them above already. if object.solid_tiles[tile_index] { @@ -83,15 +83,15 @@ impl SceneBuilder { continue; } - // Visible mask tile. - let batch_mask_tile_index = batch.mask_tiles.len() as u16; - if batch_mask_tile_index == MAX_MASKS_PER_BATCH { + // Visible alpha tile. + let batch_alpha_tile_index = batch.alpha_tiles.len() as u16; + if batch_alpha_tile_index == MAX_ALPHA_TILES_PER_BATCH { break; } - object_tile_index_to_batch_mask_tile_index[tile_index] = batch_mask_tile_index; + object_tile_index_to_batch_alpha_tile_index[tile_index] = batch_alpha_tile_index; - batch.mask_tiles.push(MaskTileBatchPrimitive { + batch.alpha_tiles.push(AlphaTileBatchPrimitive { tile: *tile, shader: object.shader, }); @@ -101,13 +101,13 @@ impl SceneBuilder { for fill in &object.fills { let object_tile_index = object.tile_coords_to_index(fill.tile_x as i32, fill.tile_y as i32).unwrap(); - let mask_tile_index = - object_tile_index_to_batch_mask_tile_index[object_tile_index as usize]; - if mask_tile_index < u16::MAX { + let alpha_tile_index = + object_tile_index_to_batch_alpha_tile_index[object_tile_index as usize]; + if alpha_tile_index < u16::MAX { batch.fills.push(FillBatchPrimitive { px: fill.px, subpx: fill.subpx, - mask_tile_index, + alpha_tile_index, }); } } diff --git a/renderer/src/gpu/debug.rs b/renderer/src/gpu/debug.rs index 4e3b274a..0d6bd58a 100644 --- a/renderer/src/gpu/debug.rs +++ b/renderer/src/gpu/debug.rs @@ -75,7 +75,7 @@ impl DebugUI where D: Device { origin + Point2DI32::new(0, LINE_HEIGHT * 1), false); self.ui.draw_text(device, - &format!("Mask Tiles: {}", mean_cpu_sample.stats.mask_tile_count), + &format!("Alpha Tiles: {}", mean_cpu_sample.stats.alpha_tile_count), origin + Point2DI32::new(0, LINE_HEIGHT * 2), false); self.ui.draw_text(device, @@ -140,7 +140,7 @@ impl Add for CPUSample { stats: Stats { object_count: self.stats.object_count + other.stats.object_count, solid_tile_count: self.stats.solid_tile_count + other.stats.solid_tile_count, - mask_tile_count: self.stats.mask_tile_count + other.stats.mask_tile_count, + alpha_tile_count: self.stats.alpha_tile_count + other.stats.alpha_tile_count, fill_count: self.stats.fill_count + other.stats.fill_count, }, } @@ -155,7 +155,7 @@ impl Div for CPUSample { stats: Stats { object_count: self.stats.object_count / divisor, solid_tile_count: self.stats.solid_tile_count / divisor, - mask_tile_count: self.stats.mask_tile_count / divisor, + alpha_tile_count: self.stats.alpha_tile_count / divisor, fill_count: self.stats.fill_count / divisor, }, } diff --git a/renderer/src/gpu/renderer.rs b/renderer/src/gpu/renderer.rs index 6a54e184..ec0a9bef 100644 --- a/renderer/src/gpu/renderer.rs +++ b/renderer/src/gpu/renderer.rs @@ -15,7 +15,7 @@ use crate::scene::ObjectShader; use crate::tiles::{TILE_HEIGHT, TILE_WIDTH}; use pathfinder_geometry::basic::point::{Point2DI32, Point3DF32}; use pathfinder_geometry::basic::rect::RectI32; -use pathfinder_geometry::color::ColorU; +use pathfinder_geometry::color::{ColorF, ColorU}; use pathfinder_gpu::resources::ResourceLoader; use pathfinder_gpu::{BlendState, BufferTarget, BufferUploadMode, DepthFunc, DepthState, Device}; use pathfinder_gpu::{Primitive, RenderState, StencilFunc, StencilState, TextureFormat}; @@ -43,13 +43,17 @@ pub struct Renderer where D: Device { // Core data fill_program: FillProgram, - solid_tile_program: SolidTileProgram, - mask_tile_program: MaskTileProgram, + solid_multicolor_tile_program: SolidTileMulticolorProgram, + alpha_multicolor_tile_program: AlphaTileMulticolorProgram, + solid_monochrome_tile_program: SolidTileMonochromeProgram, + alpha_monochrome_tile_program: AlphaTileMonochromeProgram, + solid_multicolor_tile_vertex_array: SolidTileVertexArray, + alpha_multicolor_tile_vertex_array: AlphaTileVertexArray, + solid_monochrome_tile_vertex_array: SolidTileVertexArray, + alpha_monochrome_tile_vertex_array: AlphaTileVertexArray, area_lut_texture: D::Texture, quad_vertex_positions_buffer: D::Buffer, fill_vertex_array: FillVertexArray, - mask_tile_vertex_array: MaskTileVertexArray, - solid_tile_vertex_array: SolidTileVertexArray, mask_framebuffer: D::Framebuffer, fill_colors_texture: D::Texture, @@ -70,7 +74,7 @@ pub struct Renderer where D: Device { // Extra info viewport: RectI32, - postprocess_options: PostprocessOptions, + render_mode: RenderMode, use_depth: bool, } @@ -81,8 +85,11 @@ impl Renderer where D: Device { main_framebuffer_size: Point2DI32) -> Renderer { let fill_program = FillProgram::new(&device, resources); - let solid_tile_program = SolidTileProgram::new(&device, resources); - let mask_tile_program = MaskTileProgram::new(&device, resources); + + let solid_multicolor_tile_program = SolidTileMulticolorProgram::new(&device, resources); + let alpha_multicolor_tile_program = AlphaTileMulticolorProgram::new(&device, resources); + let solid_monochrome_tile_program = SolidTileMonochromeProgram::new(&device, resources); + let alpha_monochrome_tile_program = AlphaTileMonochromeProgram::new(&device, resources); let postprocess_program = PostprocessProgram::new(&device, resources); let stencil_program = StencilProgram::new(&device, resources); @@ -99,12 +106,22 @@ impl Renderer where D: Device { let fill_vertex_array = FillVertexArray::new(&device, &fill_program, &quad_vertex_positions_buffer); - let mask_tile_vertex_array = MaskTileVertexArray::new(&device, - &mask_tile_program, - &quad_vertex_positions_buffer); - let solid_tile_vertex_array = SolidTileVertexArray::new(&device, - &solid_tile_program, - &quad_vertex_positions_buffer); + let alpha_multicolor_tile_vertex_array = + AlphaTileVertexArray::new(&device, + &alpha_multicolor_tile_program.alpha_tile_program, + &quad_vertex_positions_buffer); + let solid_multicolor_tile_vertex_array = + SolidTileVertexArray::new(&device, + &solid_multicolor_tile_program.solid_tile_program, + &quad_vertex_positions_buffer); + let alpha_monochrome_tile_vertex_array = + AlphaTileVertexArray::new(&device, + &alpha_monochrome_tile_program.alpha_tile_program, + &quad_vertex_positions_buffer); + let solid_monochrome_tile_vertex_array = + SolidTileVertexArray::new(&device, + &solid_monochrome_tile_program.solid_tile_program, + &quad_vertex_positions_buffer); let postprocess_vertex_array = PostprocessVertexArray::new(&device, &postprocess_program, &quad_vertex_positions_buffer); @@ -125,13 +142,17 @@ impl Renderer where D: Device { Renderer { device, fill_program, - solid_tile_program, - mask_tile_program, + solid_monochrome_tile_program, + alpha_monochrome_tile_program, + solid_multicolor_tile_program, + alpha_multicolor_tile_program, + solid_monochrome_tile_vertex_array, + alpha_monochrome_tile_vertex_array, + solid_multicolor_tile_vertex_array, + alpha_multicolor_tile_vertex_array, area_lut_texture, quad_vertex_positions_buffer, fill_vertex_array, - mask_tile_vertex_array, - solid_tile_vertex_array, mask_framebuffer, fill_colors_texture, @@ -149,7 +170,7 @@ impl Renderer where D: Device { debug_ui, viewport, - postprocess_options: PostprocessOptions::default(), + render_mode: RenderMode::default(), use_depth: false, } } @@ -174,7 +195,7 @@ impl Renderer where D: Device { for batch in &built_scene.batches { self.upload_batch(batch); self.draw_batch_fills(batch); - self.draw_batch_mask_tiles(batch); + self.draw_batch_alpha_tiles(batch); } if self.postprocessing_needed() { @@ -212,23 +233,8 @@ impl Renderer where D: Device { } #[inline] - pub fn disable_subpixel_aa(&mut self) { - self.postprocess_options.defringing_kernel = None; - } - - #[inline] - pub fn enable_subpixel_aa(&mut self, defringing_kernel: &DefringingKernel) { - self.postprocess_options.defringing_kernel = Some(*defringing_kernel); - } - - #[inline] - pub fn disable_gamma_correction(&mut self) { - self.postprocess_options.gamma_correction_bg_color = None; - } - - #[inline] - pub fn enable_gamma_correction(&mut self, bg_color: ColorU) { - self.postprocess_options.gamma_correction_bg_color = Some(bg_color); + pub fn set_render_mode(&mut self, mode: RenderMode) { + self.render_mode = mode; } #[inline] @@ -259,7 +265,7 @@ impl Renderer where D: Device { } fn upload_solid_tiles(&mut self, solid_tiles: &[SolidTileScenePrimitive]) { - self.device.upload_to_buffer(&self.solid_tile_vertex_array.vertex_buffer, + self.device.upload_to_buffer(&self.solid_tile_vertex_array().vertex_buffer, solid_tiles, BufferTarget::Vertex, BufferUploadMode::Dynamic); @@ -270,8 +276,8 @@ impl Renderer where D: Device { &batch.fills, BufferTarget::Vertex, BufferUploadMode::Dynamic); - self.device.upload_to_buffer(&self.mask_tile_vertex_array.vertex_buffer, - &batch.mask_tiles, + self.device.upload_to_buffer(&self.alpha_tile_vertex_array().vertex_buffer, + &batch.alpha_tiles, BufferTarget::Vertex, BufferUploadMode::Dynamic); } @@ -306,36 +312,51 @@ impl Renderer where D: Device { &render_state); } - fn draw_batch_mask_tiles(&mut self, batch: &Batch) { + fn draw_batch_alpha_tiles(&mut self, batch: &Batch) { self.bind_draw_framebuffer(); - self.device.bind_vertex_array(&self.mask_tile_vertex_array.vertex_array); - self.device.use_program(&self.mask_tile_program.program); - self.device.set_uniform(&self.mask_tile_program.framebuffer_size_uniform, + let alpha_tile_vertex_array = self.alpha_tile_vertex_array(); + let alpha_tile_program = self.alpha_tile_program(); + + self.device.bind_vertex_array(&alpha_tile_vertex_array.vertex_array); + self.device.use_program(&alpha_tile_program.program); + self.device.set_uniform(&alpha_tile_program.framebuffer_size_uniform, UniformData::Vec2(self.viewport.size().to_f32().0)); - self.device.set_uniform(&self.mask_tile_program.tile_size_uniform, + self.device.set_uniform(&alpha_tile_program.tile_size_uniform, UniformData::Vec2(I32x4::new(TILE_WIDTH as i32, TILE_HEIGHT as i32, 0, 0).to_f32x4())); self.device.bind_texture(self.device.framebuffer_texture(&self.mask_framebuffer), 0); - self.device.set_uniform(&self.mask_tile_program.stencil_texture_uniform, + self.device.set_uniform(&alpha_tile_program.stencil_texture_uniform, UniformData::TextureUnit(0)); - self.device.set_uniform(&self.mask_tile_program.stencil_texture_size_uniform, + self.device.set_uniform(&alpha_tile_program.stencil_texture_size_uniform, UniformData::Vec2(I32x4::new(MASK_FRAMEBUFFER_WIDTH, MASK_FRAMEBUFFER_HEIGHT, 0, 0).to_f32x4())); - self.device.bind_texture(&self.fill_colors_texture, 1); - self.device.set_uniform(&self.mask_tile_program.fill_colors_texture_uniform, - UniformData::TextureUnit(1)); - self.device.set_uniform(&self.mask_tile_program.fill_colors_texture_size_uniform, - UniformData::Vec2(I32x4::new(FILL_COLORS_TEXTURE_WIDTH, - FILL_COLORS_TEXTURE_HEIGHT, - 0, - 0).to_f32x4())); + + match self.render_mode { + RenderMode::Multicolor => { + self.device.bind_texture(&self.fill_colors_texture, 1); + self.device.set_uniform(&self.alpha_multicolor_tile_program + .fill_colors_texture_uniform, + UniformData::TextureUnit(1)); + self.device.set_uniform(&self.alpha_multicolor_tile_program + .fill_colors_texture_size_uniform, + UniformData::Vec2(I32x4::new(FILL_COLORS_TEXTURE_WIDTH, + FILL_COLORS_TEXTURE_HEIGHT, + 0, + 0).to_f32x4())); + } + RenderMode::Monochrome { fill_color, .. } => { + self.device.set_uniform(&self.alpha_monochrome_tile_program.fill_color_uniform, + UniformData::Vec4(fill_color.0)); + } + } + // FIXME(pcwalton): Fill this in properly! - self.device.set_uniform(&self.mask_tile_program.view_box_origin_uniform, + self.device.set_uniform(&alpha_tile_program.view_box_origin_uniform, UniformData::Vec2(F32x4::default())); let render_state = RenderState { blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha, @@ -344,30 +365,45 @@ impl Renderer where D: Device { }; self.device.draw_arrays_instanced(Primitive::TriangleFan, 4, - batch.mask_tiles.len() as u32, + batch.alpha_tiles.len() as u32, &render_state); } fn draw_solid_tiles(&mut self, built_scene: &BuiltScene) { - self.device.bind_vertex_array(&self.solid_tile_vertex_array.vertex_array); - self.device.use_program(&self.solid_tile_program.program); - self.device.set_uniform(&self.solid_tile_program.framebuffer_size_uniform, + let solid_tile_vertex_array = self.solid_tile_vertex_array(); + let solid_tile_program = self.solid_tile_program(); + + self.device.bind_vertex_array(&solid_tile_vertex_array.vertex_array); + self.device.use_program(&solid_tile_program.program); + self.device.set_uniform(&solid_tile_program.framebuffer_size_uniform, UniformData::Vec2(self.viewport.size().0.to_f32x4())); - self.device.set_uniform(&self.solid_tile_program.tile_size_uniform, + self.device.set_uniform(&solid_tile_program.tile_size_uniform, UniformData::Vec2(I32x4::new(TILE_WIDTH as i32, TILE_HEIGHT as i32, 0, 0).to_f32x4())); - self.device.bind_texture(&self.fill_colors_texture, 0); - self.device.set_uniform(&self.solid_tile_program.fill_colors_texture_uniform, - UniformData::TextureUnit(0)); - self.device.set_uniform(&self.solid_tile_program.fill_colors_texture_size_uniform, - UniformData::Vec2(I32x4::new(FILL_COLORS_TEXTURE_WIDTH, - FILL_COLORS_TEXTURE_HEIGHT, - 0, - 0).to_f32x4())); + + match self.render_mode { + RenderMode::Multicolor => { + self.device.bind_texture(&self.fill_colors_texture, 0); + self.device.set_uniform(&self.solid_multicolor_tile_program + .fill_colors_texture_uniform, + UniformData::TextureUnit(0)); + self.device.set_uniform(&self.solid_multicolor_tile_program + .fill_colors_texture_size_uniform, + UniformData::Vec2(I32x4::new(FILL_COLORS_TEXTURE_WIDTH, + FILL_COLORS_TEXTURE_HEIGHT, + 0, + 0).to_f32x4())); + } + RenderMode::Monochrome { fill_color, .. } => { + self.device.set_uniform(&self.solid_monochrome_tile_program.fill_color_uniform, + UniformData::Vec4(fill_color.0)); + } + } + // FIXME(pcwalton): Fill this in properly! - self.device.set_uniform(&self.solid_tile_program.view_box_origin_uniform, + self.device.set_uniform(&solid_tile_program.view_box_origin_uniform, UniformData::Vec2(F32x4::default())); let render_state = RenderState { stencil: self.stencil_state(), @@ -378,13 +414,27 @@ impl Renderer where D: Device { } fn postprocess(&mut self) { + let (fill_color, defringing_kernel, gamma_correction_bg_color); + match self.render_mode { + RenderMode::Multicolor => return, + RenderMode::Monochrome { + fill_color: fc, + defringing_kernel: dk, + gamma_correction_bg_color: gcbc, + } => { + fill_color = fc; + defringing_kernel = dk; + gamma_correction_bg_color = gcbc; + } + } + self.device.bind_default_framebuffer(self.viewport); self.device.bind_vertex_array(&self.postprocess_vertex_array.vertex_array); self.device.use_program(&self.postprocess_program.program); self.device.set_uniform(&self.postprocess_program.framebuffer_size_uniform, UniformData::Vec2(self.viewport.size().to_f32().0)); - match self.postprocess_options.defringing_kernel { + match defringing_kernel { Some(ref kernel) => { self.device.set_uniform(&self.postprocess_program.kernel_uniform, UniformData::Vec4(F32x4::from_slice(&kernel.0))); @@ -394,17 +444,21 @@ impl Renderer where D: Device { UniformData::Vec4(F32x4::default())); } } - let source_texture = - self.device.framebuffer_texture(self.postprocess_source_framebuffer.as_ref().unwrap()); + + let postprocess_source_framebuffer = self.postprocess_source_framebuffer.as_ref().unwrap(); + let source_texture = self.device.framebuffer_texture(postprocess_source_framebuffer); + let source_texture_size = self.device.texture_size(source_texture); self.device.bind_texture(&source_texture, 0); self.device.set_uniform(&self.postprocess_program.source_uniform, UniformData::TextureUnit(0)); + self.device.set_uniform(&self.postprocess_program.source_size_uniform, + UniformData::Vec2(source_texture_size.0.to_f32x4())); self.device.bind_texture(&self.gamma_lut_texture, 1); self.device.set_uniform(&self.postprocess_program.gamma_lut_uniform, UniformData::TextureUnit(1)); let gamma_correction_bg_color_uniform = &self.postprocess_program .gamma_correction_bg_color_uniform; - match self.postprocess_options.gamma_correction_bg_color { + match gamma_correction_bg_color { None => { self.device.set_uniform(gamma_correction_bg_color_uniform, UniformData::Vec4(F32x4::default())); @@ -415,11 +469,43 @@ impl Renderer where D: Device { } } self.device.draw_arrays(Primitive::TriangleFan, 4, &RenderState { - blend: BlendState::RGBSrcAlphaAlphaOneMinusSrcAlpha, + blend: BlendState::RGBOneAlphaOne, ..RenderState::default() }); } + fn solid_tile_program(&self) -> &SolidTileProgram { + match self.render_mode { + RenderMode::Monochrome { .. } => { + &self.solid_monochrome_tile_program.solid_tile_program + } + RenderMode::Multicolor => &self.solid_multicolor_tile_program.solid_tile_program, + } + } + + fn alpha_tile_program(&self) -> &AlphaTileProgram { + match self.render_mode { + RenderMode::Monochrome { .. } => { + &self.alpha_monochrome_tile_program.alpha_tile_program + } + RenderMode::Multicolor => &self.alpha_multicolor_tile_program.alpha_tile_program, + } + } + + fn solid_tile_vertex_array(&self) -> &SolidTileVertexArray { + match self.render_mode { + RenderMode::Monochrome { .. } => &self.solid_monochrome_tile_vertex_array, + RenderMode::Multicolor => &self.solid_multicolor_tile_vertex_array, + } + } + + fn alpha_tile_vertex_array(&self) -> &AlphaTileVertexArray { + match self.render_mode { + RenderMode::Monochrome { .. } => &self.alpha_monochrome_tile_vertex_array, + RenderMode::Multicolor => &self.alpha_multicolor_tile_vertex_array, + } + } + fn draw_stencil(&self, quad_positions: &[Point3DF32]) { self.device.upload_to_buffer(&self.stencil_vertex_array.vertex_buffer, quad_positions, @@ -462,8 +548,7 @@ impl Renderer where D: Device { self.device.texture_size(self.device.framebuffer_texture(framebuffer)) == self.viewport.size() => {} _ => { - let texture = self.device.create_texture(TextureFormat::RGBA8, - self.viewport.size()); + let texture = self.device.create_texture(TextureFormat::R8, self.viewport.size()); self.postprocess_source_framebuffer = Some(self.device.create_framebuffer(texture)) } }; @@ -473,8 +558,12 @@ impl Renderer where D: Device { } fn postprocessing_needed(&self) -> bool { - self.postprocess_options.defringing_kernel.is_some() || - self.postprocess_options.gamma_correction_bg_color.is_some() + match self.render_mode { + RenderMode::Monochrome { ref defringing_kernel, gamma_correction_bg_color, .. } => { + defringing_kernel.is_some() || gamma_correction_bg_color.is_some() + } + _ => false, + } } fn stencil_state(&self) -> Option { @@ -486,12 +575,6 @@ impl Renderer where D: Device { } } -#[derive(Clone, Copy, Default)] -struct PostprocessOptions { - defringing_kernel: Option, - gamma_correction_bg_color: Option, -} - struct FillVertexArray where D: Device { vertex_array: D::VertexArray, vertex_buffer: D::Buffer, @@ -558,27 +641,27 @@ impl FillVertexArray where D: Device { } } -struct MaskTileVertexArray where D: Device { +struct AlphaTileVertexArray where D: Device { vertex_array: D::VertexArray, vertex_buffer: D::Buffer, } -impl MaskTileVertexArray where D: Device { +impl AlphaTileVertexArray where D: Device { fn new(device: &D, - mask_tile_program: &MaskTileProgram, + alpha_tile_program: &AlphaTileProgram, quad_vertex_positions_buffer: &D::Buffer) - -> MaskTileVertexArray { + -> AlphaTileVertexArray { let (vertex_array, vertex_buffer) = (device.create_vertex_array(), device.create_buffer()); - let tess_coord_attr = device.get_vertex_attr(&mask_tile_program.program, "TessCoord"); - let tile_origin_attr = device.get_vertex_attr(&mask_tile_program.program, "TileOrigin"); - let backdrop_attr = device.get_vertex_attr(&mask_tile_program.program, "Backdrop"); - let object_attr = device.get_vertex_attr(&mask_tile_program.program, "Object"); + let tess_coord_attr = device.get_vertex_attr(&alpha_tile_program.program, "TessCoord"); + let tile_origin_attr = device.get_vertex_attr(&alpha_tile_program.program, "TileOrigin"); + let backdrop_attr = device.get_vertex_attr(&alpha_tile_program.program, "Backdrop"); + let object_attr = device.get_vertex_attr(&alpha_tile_program.program, "Object"); // NB: The object must be of type `I16`, not `U16`, to work around a macOS Radeon // driver bug. device.bind_vertex_array(&vertex_array); - device.use_program(&mask_tile_program.program); + device.use_program(&alpha_tile_program.program); device.bind_buffer(quad_vertex_positions_buffer, BufferTarget::Vertex); device.configure_float_vertex_attr(&tess_coord_attr, 2, @@ -608,7 +691,7 @@ impl MaskTileVertexArray where D: Device { 6, 1); - MaskTileVertexArray { vertex_array, vertex_buffer } + AlphaTileVertexArray { vertex_array, vertex_buffer } } } @@ -680,32 +763,62 @@ struct SolidTileProgram where D: Device { program: D::Program, framebuffer_size_uniform: D::Uniform, tile_size_uniform: D::Uniform, - fill_colors_texture_uniform: D::Uniform, - fill_colors_texture_size_uniform: D::Uniform, view_box_origin_uniform: D::Uniform, } impl SolidTileProgram where D: Device { - fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileProgram { - let program = device.create_program(resources, "solid_tile"); + fn new(device: &D, program_name: &str, resources: &dyn ResourceLoader) -> SolidTileProgram { + let program = device.create_program_from_shader_names(resources, + program_name, + program_name, + "tile_solid"); let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); let tile_size_uniform = device.get_uniform(&program, "TileSize"); - let fill_colors_texture_uniform = device.get_uniform(&program, "FillColorsTexture"); - let fill_colors_texture_size_uniform = device.get_uniform(&program, - "FillColorsTextureSize"); let view_box_origin_uniform = device.get_uniform(&program, "ViewBoxOrigin"); SolidTileProgram { program, framebuffer_size_uniform, tile_size_uniform, - fill_colors_texture_uniform, - fill_colors_texture_size_uniform, view_box_origin_uniform, } } } -struct MaskTileProgram where D: Device { +struct SolidTileMulticolorProgram where D: Device { + solid_tile_program: SolidTileProgram, + fill_colors_texture_uniform: D::Uniform, + fill_colors_texture_size_uniform: D::Uniform, +} + +impl SolidTileMulticolorProgram where D: Device { + fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileMulticolorProgram { + let solid_tile_program = SolidTileProgram::new(device, "tile_solid_multicolor", resources); + let fill_colors_texture_uniform = device.get_uniform(&solid_tile_program.program, + "FillColorsTexture"); + let fill_colors_texture_size_uniform = device.get_uniform(&solid_tile_program.program, + "FillColorsTextureSize"); + SolidTileMulticolorProgram { + solid_tile_program, + fill_colors_texture_uniform, + fill_colors_texture_size_uniform, + } + } +} + +struct SolidTileMonochromeProgram where D: Device { + solid_tile_program: SolidTileProgram, + fill_color_uniform: D::Uniform, +} + +impl SolidTileMonochromeProgram where D: Device { + fn new(device: &D, resources: &dyn ResourceLoader) -> SolidTileMonochromeProgram { + let solid_tile_program = SolidTileProgram::new(device, "tile_solid_monochrome", resources); + let fill_color_uniform = device.get_uniform(&solid_tile_program.program, "FillColor"); + SolidTileMonochromeProgram { solid_tile_program, fill_color_uniform } + } +} + +struct AlphaTileProgram where D: Device { program: D::Program, framebuffer_size_uniform: D::Uniform, tile_size_uniform: D::Uniform, @@ -716,9 +829,12 @@ struct MaskTileProgram where D: Device { view_box_origin_uniform: D::Uniform, } -impl MaskTileProgram where D: Device { - fn new(device: &D, resources: &dyn ResourceLoader) -> MaskTileProgram { - let program = device.create_program(resources, "mask_tile"); +impl AlphaTileProgram where D: Device { + fn new(device: &D, program_name: &str, resources: &dyn ResourceLoader) -> AlphaTileProgram { + let program = device.create_program_from_shader_names(resources, + program_name, + program_name, + "tile_alpha"); let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize"); let tile_size_uniform = device.get_uniform(&program, "TileSize"); let stencil_texture_uniform = device.get_uniform(&program, "StencilTexture"); @@ -727,7 +843,7 @@ impl MaskTileProgram where D: Device { let fill_colors_texture_size_uniform = device.get_uniform(&program, "FillColorsTextureSize"); let view_box_origin_uniform = device.get_uniform(&program, "ViewBoxOrigin"); - MaskTileProgram { + AlphaTileProgram { program, framebuffer_size_uniform, tile_size_uniform, @@ -740,9 +856,44 @@ impl MaskTileProgram where D: Device { } } +struct AlphaTileMulticolorProgram where D: Device { + alpha_tile_program: AlphaTileProgram, + fill_colors_texture_uniform: D::Uniform, + fill_colors_texture_size_uniform: D::Uniform, +} + +impl AlphaTileMulticolorProgram where D: Device { + fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileMulticolorProgram { + let alpha_tile_program = AlphaTileProgram::new(device, "tile_alpha_multicolor", resources); + let fill_colors_texture_uniform = device.get_uniform(&alpha_tile_program.program, + "FillColorsTexture"); + let fill_colors_texture_size_uniform = device.get_uniform(&alpha_tile_program.program, + "FillColorsTextureSize"); + AlphaTileMulticolorProgram { + alpha_tile_program, + fill_colors_texture_uniform, + fill_colors_texture_size_uniform, + } + } +} + +struct AlphaTileMonochromeProgram where D: Device { + alpha_tile_program: AlphaTileProgram, + fill_color_uniform: D::Uniform, +} + +impl AlphaTileMonochromeProgram where D: Device { + fn new(device: &D, resources: &dyn ResourceLoader) -> AlphaTileMonochromeProgram { + let alpha_tile_program = AlphaTileProgram::new(device, "tile_alpha_monochrome", resources); + let fill_color_uniform = device.get_uniform(&alpha_tile_program.program, "FillColor"); + AlphaTileMonochromeProgram { alpha_tile_program, fill_color_uniform } + } +} + struct PostprocessProgram where D: Device { program: D::Program, source_uniform: D::Uniform, + source_size_uniform: D::Uniform, framebuffer_size_uniform: D::Uniform, kernel_uniform: D::Uniform, gamma_lut_uniform: D::Uniform, @@ -753,6 +904,7 @@ impl PostprocessProgram where D: Device { fn new(device: &D, resources: &dyn ResourceLoader) -> PostprocessProgram { let program = device.create_program(resources, "post"); 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"); @@ -761,6 +913,7 @@ impl PostprocessProgram where D: Device { PostprocessProgram { program, source_uniform, + source_size_uniform, framebuffer_size_uniform, kernel_uniform, gamma_lut_uniform, @@ -832,3 +985,20 @@ impl StencilVertexArray where D: Device { StencilVertexArray { vertex_array, vertex_buffer } } } + +#[derive(Clone, Copy)] +pub enum RenderMode { + Multicolor, + Monochrome { + fill_color: ColorF, + defringing_kernel: Option, + gamma_correction_bg_color: Option, + }, +} + +impl Default for RenderMode { + #[inline] + fn default() -> RenderMode { + RenderMode::Multicolor + } +} diff --git a/renderer/src/gpu_data.rs b/renderer/src/gpu_data.rs index 430ac670..114729c3 100644 --- a/renderer/src/gpu_data.rs +++ b/renderer/src/gpu_data.rs @@ -43,7 +43,7 @@ pub struct BuiltScene { #[derive(Debug)] pub struct Batch { pub fills: Vec, - pub mask_tiles: Vec, + pub alpha_tiles: Vec, } #[derive(Clone, Copy, Debug)] @@ -68,7 +68,7 @@ pub struct TileObjectPrimitive { pub struct FillBatchPrimitive { pub px: LineSegmentU4, pub subpx: LineSegmentU8, - pub mask_tile_index: u16, + pub alpha_tile_index: u16, } #[derive(Clone, Copy, Debug)] @@ -81,7 +81,7 @@ pub struct SolidTileScenePrimitive { #[derive(Clone, Copy, Debug)] #[repr(C)] -pub struct MaskTileBatchPrimitive { +pub struct AlphaTileBatchPrimitive { pub tile: TileObjectPrimitive, pub shader: ShaderId, } @@ -90,7 +90,7 @@ pub struct MaskTileBatchPrimitive { pub struct Stats { pub object_count: u32, pub solid_tile_count: u32, - pub mask_tile_count: u32, + pub alpha_tile_count: u32, pub fill_count: u32, } @@ -276,7 +276,10 @@ impl BuiltScene { Stats { object_count: self.object_count, solid_tile_count: self.solid_tiles.len() as u32, - mask_tile_count: self.batches.iter().map(|batch| batch.mask_tiles.len() as u32).sum(), + alpha_tile_count: self.batches + .iter() + .map(|batch| batch.alpha_tiles.len() as u32) + .sum(), fill_count: self.batches.iter().map(|batch| batch.fills.len() as u32).sum(), } } @@ -287,13 +290,13 @@ impl Batch { pub fn new() -> Batch { Batch { fills: vec![], - mask_tiles: vec![], + alpha_tiles: vec![], } } #[inline] pub fn is_empty(&self) -> bool { - self.mask_tiles.is_empty() + self.alpha_tiles.is_empty() } } @@ -314,7 +317,7 @@ impl Add for Stats { Stats { object_count: other.object_count, solid_tile_count: other.solid_tile_count, - mask_tile_count: other.mask_tile_count, + alpha_tile_count: other.alpha_tile_count, fill_count: other.fill_count, } } diff --git a/renderer/src/scene.rs b/renderer/src/scene.rs index 24225e40..be5422a9 100644 --- a/renderer/src/scene.rs +++ b/renderer/src/scene.rs @@ -145,12 +145,15 @@ impl Scene { outline } - pub fn is_monochrome(&self) -> bool { + pub fn monochrome_color(&self) -> Option { if self.objects.is_empty() { - return true; + return None; } let first_paint_id = self.objects[0].paint; - self.objects.iter().skip(1).all(|object| object.paint == first_paint_id) + if self.objects.iter().skip(1).any(|object| object.paint != first_paint_id) { + return None; + } + Some(self.paints[first_paint_id.0 as usize].color) } } diff --git a/resources/shaders/post.fs.glsl b/resources/shaders/post.fs.glsl index 9915b403..364b6f2c 100644 --- a/resources/shaders/post.fs.glsl +++ b/resources/shaders/post.fs.glsl @@ -16,7 +16,7 @@ precision highp float; uniform sampler2D uSource; -uniform vec2 uFramebufferSize; +uniform vec2 uSourceSize; in vec2 vTexCoord; @@ -32,21 +32,24 @@ float sample1Tap(float offset) { void main() { // Apply defringing if necessary. - vec4 fgColor = texture(uSource, vTexCoord); - if (uKernel.w != 0.0) { + vec4 fgColor; + if (uKernel.w == 0.0) { + fgColor = texture(uSource, vTexCoord); + } else { vec4 alphaLeft, alphaRight; float alphaCenter; - sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uFramebufferSize.x); + sample9Tap(alphaLeft, alphaCenter, alphaRight, 1.0 / uSourceSize.x); - fgColor.rgb = - vec3(convolve7Tap(alphaLeft, vec3(alphaCenter, alphaRight.xy)), - convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz), - convolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x), alphaRight.yzw)); + 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); + + fgColor = vec4(r); } // Apply gamma correction if necessary. - if (uGammaCorrectionBGColor.a > 0.0) - fgColor.rgb = gammaCorrect(fgColor.rgb); + /*if (uGammaCorrectionBGColor.a > 0.0) + fgColor.rgb = gammaCorrect(fgColor.rgb);*/ // Finish. oFragColor = fgColor; diff --git a/resources/shaders/mask_tile.fs.glsl b/resources/shaders/tile_alpha.fs.glsl similarity index 100% rename from resources/shaders/mask_tile.fs.glsl rename to resources/shaders/tile_alpha.fs.glsl diff --git a/resources/shaders/tile_alpha_monochrome.vs.glsl b/resources/shaders/tile_alpha_monochrome.vs.glsl new file mode 100644 index 00000000..dbe6be03 --- /dev/null +++ b/resources/shaders/tile_alpha_monochrome.vs.glsl @@ -0,0 +1,20 @@ +#version {{version}} + +// pathfinder/resources/shaders/tile_alpha_monochrome.vs.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +{{{include_tile_alpha_vertex}}} +{{{include_tile_monochrome}}} + +void main() { + computeVaryings(); +} diff --git a/resources/shaders/tile_alpha_multicolor.vs.glsl b/resources/shaders/tile_alpha_multicolor.vs.glsl new file mode 100644 index 00000000..43e9d3c7 --- /dev/null +++ b/resources/shaders/tile_alpha_multicolor.vs.glsl @@ -0,0 +1,20 @@ +#version {{version}} + +// pathfinder/resources/shaders/tile_alpha_multicolor.vs.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +{{{include_tile_alpha_vertex}}} +{{{include_tile_multicolor}}} + +void main() { + computeVaryings(); +} diff --git a/resources/shaders/mask_tile.vs.glsl b/resources/shaders/tile_alpha_vertex.inc.glsl similarity index 68% rename from resources/shaders/mask_tile.vs.glsl rename to resources/shaders/tile_alpha_vertex.inc.glsl index c0486f1f..a07231fa 100644 --- a/resources/shaders/mask_tile.vs.glsl +++ b/resources/shaders/tile_alpha_vertex.inc.glsl @@ -1,8 +1,6 @@ -#version {{version}} - -// pathfinder/demo/shaders/mask_tile.vs.glsl +// pathfinder/resources/shaders/tile_alpha_vertex.inc.glsl // -// Copyright © 2018 The Pathfinder Project Developers. +// Copyright © 2019 The Pathfinder Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -10,13 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -precision highp float; - uniform vec2 uFramebufferSize; uniform vec2 uTileSize; uniform vec2 uStencilTextureSize; -uniform sampler2D uFillColorsTexture; -uniform vec2 uFillColorsTextureSize; uniform vec2 uViewBoxOrigin; in vec2 aTessCoord; @@ -28,26 +22,23 @@ out vec2 vTexCoord; out float vBackdrop; out vec4 vColor; +vec4 getFillColor(uint object); + vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow); return vec2(tileOffset) * uTileSize; } -vec2 computeFillColorTexCoord(uint object, vec2 textureSize) { - uint width = uint(textureSize.x); - return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize; -} - -void main() { +void computeVaryings() { uint tileIndex = uint(gl_InstanceID); vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); vec2 texCoord = computeTileOffset(tileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize; - vec2 colorTexCoord = computeFillColorTexCoord(aObject, uFillColorsTextureSize); vTexCoord = texCoord / uStencilTextureSize; vBackdrop = float(aBackdrop); - vColor = texture(uFillColorsTexture, colorTexCoord); + vColor = getFillColor(aObject); gl_Position = vec4(position, 0.0, 1.0); } + diff --git a/resources/shaders/tile_monochrome.inc.glsl b/resources/shaders/tile_monochrome.inc.glsl new file mode 100644 index 00000000..b8d255fc --- /dev/null +++ b/resources/shaders/tile_monochrome.inc.glsl @@ -0,0 +1,15 @@ +// pathfinder/resources/shaders/tile_monochrome.inc.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uniform vec4 uFillColor; + +vec4 getFillColor(uint object) { + return uFillColor; +} diff --git a/resources/shaders/tile_multicolor.inc.glsl b/resources/shaders/tile_multicolor.inc.glsl new file mode 100644 index 00000000..a66a3f56 --- /dev/null +++ b/resources/shaders/tile_multicolor.inc.glsl @@ -0,0 +1,22 @@ +// pathfinder/resources/shaders/tile_multicolor.inc.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +uniform sampler2D uFillColorsTexture; +uniform vec2 uFillColorsTextureSize; + +vec2 computeFillColorTexCoord(uint object, vec2 textureSize) { + uint width = uint(textureSize.x); + return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize; +} + +vec4 getFillColor(uint object) { + vec2 colorTexCoord = computeFillColorTexCoord(object, uFillColorsTextureSize); + return texture(uFillColorsTexture, colorTexCoord); +} diff --git a/resources/shaders/solid_tile.fs.glsl b/resources/shaders/tile_solid.fs.glsl similarity index 100% rename from resources/shaders/solid_tile.fs.glsl rename to resources/shaders/tile_solid.fs.glsl diff --git a/resources/shaders/tile_solid_monochrome.vs.glsl b/resources/shaders/tile_solid_monochrome.vs.glsl new file mode 100644 index 00000000..d682f3c0 --- /dev/null +++ b/resources/shaders/tile_solid_monochrome.vs.glsl @@ -0,0 +1,20 @@ +#version {{version}} + +// pathfinder/resources/shaders/tile_solid_monochrome.vs.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +{{{include_tile_solid_vertex}}} +{{{include_tile_monochrome}}} + +void main() { + computeVaryings(); +} diff --git a/resources/shaders/tile_solid_multicolor.vs.glsl b/resources/shaders/tile_solid_multicolor.vs.glsl new file mode 100644 index 00000000..868d2655 --- /dev/null +++ b/resources/shaders/tile_solid_multicolor.vs.glsl @@ -0,0 +1,20 @@ +#version {{version}} + +// pathfinder/resources/shaders/tile_solid_multicolor.vs.glsl +// +// Copyright © 2019 The Pathfinder Project Developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +precision highp float; + +{{{include_tile_solid_vertex}}} +{{{include_tile_multicolor}}} + +void main() { + computeVaryings(); +} diff --git a/resources/shaders/solid_tile.vs.glsl b/resources/shaders/tile_solid_vertex.inc.glsl similarity index 58% rename from resources/shaders/solid_tile.vs.glsl rename to resources/shaders/tile_solid_vertex.inc.glsl index e9105322..3c56f2d5 100644 --- a/resources/shaders/solid_tile.vs.glsl +++ b/resources/shaders/tile_solid_vertex.inc.glsl @@ -1,6 +1,4 @@ -#version {{version}} - -// pathfinder/demo/resources/shaders/solid_tile.vs.glsl +// pathfinder/resources/shaders/tile_solid_vertex.inc.glsl // // Copyright © 2019 The Pathfinder Project Developers. // @@ -10,12 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -precision highp float; - uniform vec2 uFramebufferSize; uniform vec2 uTileSize; -uniform sampler2D uFillColorsTexture; -uniform vec2 uFillColorsTextureSize; uniform vec2 uViewBoxOrigin; in vec2 aTessCoord; @@ -24,16 +18,12 @@ in uint aObject; out vec4 vColor; -vec2 computeFillColorTexCoord(uint object, vec2 textureSize) { - uint width = uint(textureSize.x); - return (vec2(float(object % width), float(object / width)) + vec2(0.5)) / textureSize; -} +vec4 getFillColor(uint object); -void main() { +void computeVaryings() { vec2 pixelPosition = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; vec2 position = (pixelPosition / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0); - vec2 colorTexCoord = computeFillColorTexCoord(aObject, uFillColorsTextureSize); - vColor = texture(uFillColorsTexture, colorTexCoord); + vColor = getFillColor(aObject); gl_Position = vec4(position, 0.0, 1.0); }