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