Get subpixel AA and gamma correction working in 2D
This commit is contained in:
parent
29cedb96ef
commit
db3851d754
|
@ -116,7 +116,7 @@ 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, false);
|
let view_box_size = view_box_size(options.mode, &window_size);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -199,9 +199,7 @@ 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,
|
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||||
&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 } => {
|
||||||
|
@ -232,6 +230,7 @@ impl<W> DemoApp<W> where W: Window {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
subpixel_aa_enabled: self.ui.subpixel_aa_effect_enabled,
|
||||||
barrel_distortion,
|
barrel_distortion,
|
||||||
})).unwrap();
|
})).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -254,9 +253,7 @@ 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,
|
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||||
&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;
|
||||||
|
@ -343,9 +340,7 @@ 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,
|
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||||
&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.monochrome_scene_color = built_svg.scene.monochrome_color();
|
self.monochrome_scene_color = built_svg.scene.monochrome_color();
|
||||||
|
|
||||||
|
@ -539,24 +534,20 @@ 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,
|
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||||
&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);
|
||||||
|
|
||||||
match self.monochrome_scene_color {
|
match self.monochrome_scene_color {
|
||||||
None => self.renderer.set_render_mode(RenderMode::Multicolor),
|
None => self.renderer.set_render_mode(RenderMode::Multicolor),
|
||||||
Some(fill_color) => {
|
Some(fg_color) => {
|
||||||
self.renderer.set_render_mode(RenderMode::Monochrome {
|
self.renderer.set_render_mode(RenderMode::Monochrome {
|
||||||
fill_color: fill_color.to_f32(),
|
fg_color: fg_color.to_f32(),
|
||||||
gamma_correction_bg_color: if self.ui.gamma_correction_effect_enabled {
|
bg_color: self.background_color().to_f32(),
|
||||||
Some(self.background_color())
|
gamma_correction: self.ui.gamma_correction_effect_enabled,
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
defringing_kernel: if self.ui.subpixel_aa_effect_enabled {
|
defringing_kernel: if self.ui.subpixel_aa_effect_enabled {
|
||||||
|
// TODO(pcwalton): Select FreeType defringing kernel as necessary.
|
||||||
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -709,6 +700,7 @@ struct BuildOptions {
|
||||||
render_transforms: Vec<RenderTransform>,
|
render_transforms: Vec<RenderTransform>,
|
||||||
stem_darkening_font_size: Option<f32>,
|
stem_darkening_font_size: Option<f32>,
|
||||||
barrel_distortion: Option<BarrelDistortionCoefficients>,
|
barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||||
|
subpixel_aa_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SceneToMainMsg {
|
struct SceneToMainMsg {
|
||||||
|
@ -810,8 +802,6 @@ fn build_scene(scene: &Scene,
|
||||||
render_transform: RenderTransform,
|
render_transform: RenderTransform,
|
||||||
jobs: Option<usize>)
|
jobs: Option<usize>)
|
||||||
-> BuiltScene {
|
-> BuiltScene {
|
||||||
let z_buffer = ZBuffer::new(scene.view_box);
|
|
||||||
|
|
||||||
let render_options = RenderOptions {
|
let render_options = RenderOptions {
|
||||||
transform: render_transform,
|
transform: render_transform,
|
||||||
dilation: match build_options.stem_darkening_font_size {
|
dilation: match build_options.stem_darkening_font_size {
|
||||||
|
@ -822,9 +812,13 @@ fn build_scene(scene: &Scene,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
barrel_distortion: build_options.barrel_distortion,
|
barrel_distortion: build_options.barrel_distortion,
|
||||||
|
subpixel_aa_enabled: build_options.subpixel_aa_enabled,
|
||||||
};
|
};
|
||||||
|
|
||||||
let built_options = render_options.prepare(scene.bounds);
|
let built_options = render_options.prepare(scene.bounds);
|
||||||
|
let effective_view_box = scene.effective_view_box(&built_options);
|
||||||
|
let z_buffer = ZBuffer::new(effective_view_box);
|
||||||
|
|
||||||
let quad = built_options.quad();
|
let quad = built_options.quad();
|
||||||
|
|
||||||
let built_objects = panic::catch_unwind(|| {
|
let built_objects = panic::catch_unwind(|| {
|
||||||
|
@ -846,7 +840,7 @@ fn build_scene(scene: &Scene,
|
||||||
let mut built_scene = BuiltScene::new(scene.view_box, &quad, scene.objects.len() as u32);
|
let mut built_scene = BuiltScene::new(scene.view_box, &quad, scene.objects.len() as u32);
|
||||||
built_scene.shaders = scene.build_shaders();
|
built_scene.shaders = scene.build_shaders();
|
||||||
|
|
||||||
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, scene.view_box);
|
let mut scene_builder = SceneBuilder::new(built_objects, z_buffer, effective_view_box);
|
||||||
built_scene.solid_tiles = scene_builder.build_solid_tiles();
|
built_scene.solid_tiles = scene_builder.build_solid_tiles();
|
||||||
while let Some(batch) = scene_builder.build_batch() {
|
while let Some(batch) = scene_builder.build_batch() {
|
||||||
built_scene.batches.push(batch);
|
built_scene.batches.push(batch);
|
||||||
|
@ -966,13 +960,12 @@ fn emit_message<W>(ui: &mut DemoUI<GLDevice>,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_box_size(mode: Mode, window_size: &WindowSize, use_subpixel_aa: bool) -> Point2DI32 {
|
fn view_box_size(mode: Mode, window_size: &WindowSize) -> Point2DI32 {
|
||||||
let window_drawable_size = window_size.device_size();
|
let window_drawable_size = window_size.device_size();
|
||||||
let initial_size = match mode {
|
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 {
|
||||||
|
|
|
@ -364,6 +364,9 @@ impl Device for GLDevice {
|
||||||
fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData) {
|
fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData) {
|
||||||
unsafe {
|
unsafe {
|
||||||
match data {
|
match data {
|
||||||
|
UniformData::Int(value) => {
|
||||||
|
gl::Uniform1i(uniform.location, value); ck();
|
||||||
|
}
|
||||||
UniformData::Mat4(data) => {
|
UniformData::Mat4(data) => {
|
||||||
assert_eq!(mem::size_of::<[F32x4; 4]>(), 4 * 4 * 4);
|
assert_eq!(mem::size_of::<[F32x4; 4]>(), 4 * 4 * 4);
|
||||||
let data_ptr: *const F32x4 = data.as_ptr();
|
let data_ptr: *const F32x4 = data.as_ptr();
|
||||||
|
|
|
@ -191,6 +191,7 @@ pub enum ShaderKind {
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum UniformData {
|
pub enum UniformData {
|
||||||
|
Int(i32),
|
||||||
Mat4([F32x4; 4]),
|
Mat4([F32x4; 4]),
|
||||||
Vec2(F32x4),
|
Vec2(F32x4),
|
||||||
Vec4(F32x4),
|
Vec4(F32x4),
|
||||||
|
|
|
@ -128,6 +128,7 @@ pub struct RenderOptions {
|
||||||
pub transform: RenderTransform,
|
pub transform: RenderTransform,
|
||||||
pub dilation: Point2DF32,
|
pub dilation: Point2DF32,
|
||||||
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||||
|
pub subpixel_aa_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOptions {
|
impl RenderOptions {
|
||||||
|
@ -136,6 +137,7 @@ impl RenderOptions {
|
||||||
transform: self.transform.prepare(bounds),
|
transform: self.transform.prepare(bounds),
|
||||||
dilation: self.dilation,
|
dilation: self.dilation,
|
||||||
barrel_distortion: self.barrel_distortion,
|
barrel_distortion: self.barrel_distortion,
|
||||||
|
subpixel_aa_enabled: self.subpixel_aa_enabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,6 +207,7 @@ pub struct PreparedRenderOptions {
|
||||||
pub transform: PreparedRenderTransform,
|
pub transform: PreparedRenderTransform,
|
||||||
pub dilation: Point2DF32,
|
pub dilation: Point2DF32,
|
||||||
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||||
|
pub subpixel_aa_enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreparedRenderOptions {
|
impl PreparedRenderOptions {
|
||||||
|
@ -222,3 +225,13 @@ pub enum PreparedRenderTransform {
|
||||||
Transform2D(Transform2DF32),
|
Transform2D(Transform2DF32),
|
||||||
Perspective { perspective: Perspective, clip_polygon: Vec<Point2DF32>, quad: [Point3DF32; 4] }
|
Perspective { perspective: Perspective, clip_polygon: Vec<Point2DF32>, quad: [Point3DF32; 4] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PreparedRenderTransform {
|
||||||
|
#[inline]
|
||||||
|
pub fn is_2d(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
PreparedRenderTransform::Transform2D(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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::{ColorF, ColorU};
|
use pathfinder_geometry::color::ColorF;
|
||||||
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};
|
||||||
|
@ -321,7 +321,7 @@ impl<D> Renderer<D> where D: Device {
|
||||||
self.device.bind_vertex_array(&alpha_tile_vertex_array.vertex_array);
|
self.device.bind_vertex_array(&alpha_tile_vertex_array.vertex_array);
|
||||||
self.device.use_program(&alpha_tile_program.program);
|
self.device.use_program(&alpha_tile_program.program);
|
||||||
self.device.set_uniform(&alpha_tile_program.framebuffer_size_uniform,
|
self.device.set_uniform(&alpha_tile_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(self.viewport.size().to_f32().0));
|
UniformData::Vec2(self.draw_viewport().size().to_f32().0));
|
||||||
self.device.set_uniform(&alpha_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,
|
||||||
|
@ -349,9 +349,13 @@ impl<D> Renderer<D> where D: Device {
|
||||||
0,
|
0,
|
||||||
0).to_f32x4()));
|
0).to_f32x4()));
|
||||||
}
|
}
|
||||||
RenderMode::Monochrome { fill_color, .. } => {
|
RenderMode::Monochrome { .. } if self.postprocessing_needed() => {
|
||||||
self.device.set_uniform(&self.alpha_monochrome_tile_program.fill_color_uniform,
|
self.device.set_uniform(&self.alpha_monochrome_tile_program.fill_color_uniform,
|
||||||
UniformData::Vec4(fill_color.0));
|
UniformData::Vec4(F32x4::splat(1.0)));
|
||||||
|
}
|
||||||
|
RenderMode::Monochrome { fg_color, .. } => {
|
||||||
|
self.device.set_uniform(&self.alpha_monochrome_tile_program.fill_color_uniform,
|
||||||
|
UniformData::Vec4(fg_color.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,13 +374,15 @@ impl<D> Renderer<D> where D: Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_solid_tiles(&mut self, built_scene: &BuiltScene) {
|
fn draw_solid_tiles(&mut self, built_scene: &BuiltScene) {
|
||||||
|
self.bind_draw_framebuffer();
|
||||||
|
|
||||||
let solid_tile_vertex_array = self.solid_tile_vertex_array();
|
let solid_tile_vertex_array = self.solid_tile_vertex_array();
|
||||||
let solid_tile_program = self.solid_tile_program();
|
let solid_tile_program = self.solid_tile_program();
|
||||||
|
|
||||||
self.device.bind_vertex_array(&solid_tile_vertex_array.vertex_array);
|
self.device.bind_vertex_array(&solid_tile_vertex_array.vertex_array);
|
||||||
self.device.use_program(&solid_tile_program.program);
|
self.device.use_program(&solid_tile_program.program);
|
||||||
self.device.set_uniform(&solid_tile_program.framebuffer_size_uniform,
|
self.device.set_uniform(&solid_tile_program.framebuffer_size_uniform,
|
||||||
UniformData::Vec2(self.viewport.size().0.to_f32x4()));
|
UniformData::Vec2(self.draw_viewport().size().0.to_f32x4()));
|
||||||
self.device.set_uniform(&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,
|
||||||
|
@ -396,9 +402,13 @@ impl<D> Renderer<D> where D: Device {
|
||||||
0,
|
0,
|
||||||
0).to_f32x4()));
|
0).to_f32x4()));
|
||||||
}
|
}
|
||||||
RenderMode::Monochrome { fill_color, .. } => {
|
RenderMode::Monochrome { .. } if self.postprocessing_needed() => {
|
||||||
self.device.set_uniform(&self.solid_monochrome_tile_program.fill_color_uniform,
|
self.device.set_uniform(&self.solid_monochrome_tile_program.fill_color_uniform,
|
||||||
UniformData::Vec4(fill_color.0));
|
UniformData::Vec4(F32x4::splat(1.0)));
|
||||||
|
}
|
||||||
|
RenderMode::Monochrome { fg_color, .. } => {
|
||||||
|
self.device.set_uniform(&self.solid_monochrome_tile_program.fill_color_uniform,
|
||||||
|
UniformData::Vec4(fg_color.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,17 +424,19 @@ impl<D> Renderer<D> where D: Device {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn postprocess(&mut self) {
|
fn postprocess(&mut self) {
|
||||||
let (fill_color, defringing_kernel, gamma_correction_bg_color);
|
let (fg_color, bg_color, defringing_kernel, gamma_correction_enabled);
|
||||||
match self.render_mode {
|
match self.render_mode {
|
||||||
RenderMode::Multicolor => return,
|
RenderMode::Multicolor => return,
|
||||||
RenderMode::Monochrome {
|
RenderMode::Monochrome {
|
||||||
fill_color: fc,
|
fg_color: fg,
|
||||||
defringing_kernel: dk,
|
bg_color: bg,
|
||||||
gamma_correction_bg_color: gcbc,
|
defringing_kernel: kernel,
|
||||||
|
gamma_correction,
|
||||||
} => {
|
} => {
|
||||||
fill_color = fc;
|
fg_color = fg;
|
||||||
defringing_kernel = dk;
|
bg_color = bg;
|
||||||
gamma_correction_bg_color = gcbc;
|
defringing_kernel = kernel;
|
||||||
|
gamma_correction_enabled = gamma_correction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,22 +468,13 @@ impl<D> Renderer<D> where D: Device {
|
||||||
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
|
self.device.set_uniform(&self.postprocess_program.fg_color_uniform,
|
||||||
.gamma_correction_bg_color_uniform;
|
UniformData::Vec4(fg_color.0));
|
||||||
match gamma_correction_bg_color {
|
self.device.set_uniform(&self.postprocess_program.bg_color_uniform,
|
||||||
None => {
|
UniformData::Vec4(bg_color.0));
|
||||||
self.device.set_uniform(gamma_correction_bg_color_uniform,
|
self.device.set_uniform(&self.postprocess_program.gamma_correction_enabled_uniform,
|
||||||
UniformData::Vec4(F32x4::default()));
|
UniformData::Int(gamma_correction_enabled as i32));
|
||||||
}
|
self.device.draw_arrays(Primitive::TriangleFan, 4, &RenderState::default());
|
||||||
Some(color) => {
|
|
||||||
self.device.set_uniform(gamma_correction_bg_color_uniform,
|
|
||||||
UniformData::Vec4(color.to_f32().0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.device.draw_arrays(Primitive::TriangleFan, 4, &RenderState {
|
|
||||||
blend: BlendState::RGBOneAlphaOne,
|
|
||||||
..RenderState::default()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solid_tile_program(&self) -> &SolidTileProgram<D> {
|
fn solid_tile_program(&self) -> &SolidTileProgram<D> {
|
||||||
|
@ -543,12 +546,14 @@ impl<D> Renderer<D> where D: Device {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let source_framebuffer_size = self.draw_viewport().size();
|
||||||
match self.postprocess_source_framebuffer {
|
match self.postprocess_source_framebuffer {
|
||||||
Some(ref framebuffer) if
|
Some(ref framebuffer) if
|
||||||
self.device.texture_size(self.device.framebuffer_texture(framebuffer)) ==
|
self.device.texture_size(self.device.framebuffer_texture(framebuffer)) ==
|
||||||
self.viewport.size() => {}
|
source_framebuffer_size => {}
|
||||||
_ => {
|
_ => {
|
||||||
let texture = self.device.create_texture(TextureFormat::R8, self.viewport.size());
|
let texture = self.device.create_texture(TextureFormat::R8,
|
||||||
|
source_framebuffer_size);
|
||||||
self.postprocess_source_framebuffer = Some(self.device.create_framebuffer(texture))
|
self.postprocess_source_framebuffer = Some(self.device.create_framebuffer(texture))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -559,8 +564,8 @@ impl<D> Renderer<D> where D: Device {
|
||||||
|
|
||||||
fn postprocessing_needed(&self) -> bool {
|
fn postprocessing_needed(&self) -> bool {
|
||||||
match self.render_mode {
|
match self.render_mode {
|
||||||
RenderMode::Monochrome { ref defringing_kernel, gamma_correction_bg_color, .. } => {
|
RenderMode::Monochrome { ref defringing_kernel, gamma_correction, .. } => {
|
||||||
defringing_kernel.is_some() || gamma_correction_bg_color.is_some()
|
defringing_kernel.is_some() || gamma_correction
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -573,6 +578,16 @@ impl<D> Renderer<D> where D: Device {
|
||||||
|
|
||||||
Some(StencilState { func: StencilFunc::Equal, reference: 1, mask: 1, write: false })
|
Some(StencilState { func: StencilFunc::Equal, reference: 1, mask: 1, write: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_viewport(&self) -> RectI32 {
|
||||||
|
match self.render_mode {
|
||||||
|
RenderMode::Monochrome { defringing_kernel: Some(..), .. } => {
|
||||||
|
RectI32::new(Point2DI32::default(),
|
||||||
|
self.viewport.size().scale_xy(Point2DI32::new(3, 1)))
|
||||||
|
}
|
||||||
|
_ => self.viewport
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FillVertexArray<D> where D: Device {
|
struct FillVertexArray<D> where D: Device {
|
||||||
|
@ -824,8 +839,6 @@ struct AlphaTileProgram<D> where D: Device {
|
||||||
tile_size_uniform: D::Uniform,
|
tile_size_uniform: D::Uniform,
|
||||||
stencil_texture_uniform: D::Uniform,
|
stencil_texture_uniform: D::Uniform,
|
||||||
stencil_texture_size_uniform: D::Uniform,
|
stencil_texture_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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -839,9 +852,6 @@ impl<D> AlphaTileProgram<D> where D: Device {
|
||||||
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");
|
||||||
let stencil_texture_size_uniform = device.get_uniform(&program, "StencilTextureSize");
|
let stencil_texture_size_uniform = device.get_uniform(&program, "StencilTextureSize");
|
||||||
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");
|
||||||
AlphaTileProgram {
|
AlphaTileProgram {
|
||||||
program,
|
program,
|
||||||
|
@ -849,8 +859,6 @@ impl<D> AlphaTileProgram<D> where D: Device {
|
||||||
tile_size_uniform,
|
tile_size_uniform,
|
||||||
stencil_texture_uniform,
|
stencil_texture_uniform,
|
||||||
stencil_texture_size_uniform,
|
stencil_texture_size_uniform,
|
||||||
fill_colors_texture_uniform,
|
|
||||||
fill_colors_texture_size_uniform,
|
|
||||||
view_box_origin_uniform,
|
view_box_origin_uniform,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -897,7 +905,9 @@ struct PostprocessProgram<D> where D: Device {
|
||||||
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,
|
||||||
gamma_correction_bg_color_uniform: D::Uniform,
|
gamma_correction_enabled_uniform: D::Uniform,
|
||||||
|
fg_color_uniform: D::Uniform,
|
||||||
|
bg_color_uniform: D::Uniform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> PostprocessProgram<D> where D: Device {
|
impl<D> PostprocessProgram<D> where D: Device {
|
||||||
|
@ -908,8 +918,10 @@ impl<D> PostprocessProgram<D> where D: Device {
|
||||||
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");
|
||||||
let gamma_correction_bg_color_uniform = device.get_uniform(&program,
|
let gamma_correction_enabled_uniform = device.get_uniform(&program,
|
||||||
"GammaCorrectionBGColor");
|
"GammaCorrectionEnabled");
|
||||||
|
let fg_color_uniform = device.get_uniform(&program, "FGColor");
|
||||||
|
let bg_color_uniform = device.get_uniform(&program, "BGColor");
|
||||||
PostprocessProgram {
|
PostprocessProgram {
|
||||||
program,
|
program,
|
||||||
source_uniform,
|
source_uniform,
|
||||||
|
@ -917,7 +929,9 @@ impl<D> PostprocessProgram<D> where D: Device {
|
||||||
framebuffer_size_uniform,
|
framebuffer_size_uniform,
|
||||||
kernel_uniform,
|
kernel_uniform,
|
||||||
gamma_lut_uniform,
|
gamma_lut_uniform,
|
||||||
gamma_correction_bg_color_uniform,
|
gamma_correction_enabled_uniform,
|
||||||
|
fg_color_uniform,
|
||||||
|
bg_color_uniform,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -990,9 +1004,10 @@ impl<D> StencilVertexArray<D> where D: Device {
|
||||||
pub enum RenderMode {
|
pub enum RenderMode {
|
||||||
Multicolor,
|
Multicolor,
|
||||||
Monochrome {
|
Monochrome {
|
||||||
fill_color: ColorF,
|
fg_color: ColorF,
|
||||||
|
bg_color: ColorF,
|
||||||
defringing_kernel: Option<DefringingKernel>,
|
defringing_kernel: Option<DefringingKernel>,
|
||||||
gamma_correction_bg_color: Option<ColorU>,
|
gamma_correction: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,9 @@ use crate::gpu_data::BuiltObject;
|
||||||
use crate::tiles::Tiler;
|
use crate::tiles::Tiler;
|
||||||
use crate::z_buffer::ZBuffer;
|
use crate::z_buffer::ZBuffer;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use pathfinder_geometry::basic::point::Point2DF32;
|
||||||
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
||||||
|
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
||||||
use pathfinder_geometry::color::ColorU;
|
use pathfinder_geometry::color::ColorU;
|
||||||
use pathfinder_geometry::outline::Outline;
|
use pathfinder_geometry::outline::Outline;
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
|
@ -74,7 +76,7 @@ impl Scene {
|
||||||
let outline = self.apply_render_options(&object.outline, &built_options);
|
let outline = self.apply_render_options(&object.outline, &built_options);
|
||||||
let mut tiler = Tiler::new(
|
let mut tiler = Tiler::new(
|
||||||
&outline,
|
&outline,
|
||||||
self.view_box,
|
self.effective_view_box(&built_options),
|
||||||
object_index as u16,
|
object_index as u16,
|
||||||
ShaderId(object.paint.0),
|
ShaderId(object.paint.0),
|
||||||
z_buffer,
|
z_buffer,
|
||||||
|
@ -94,7 +96,7 @@ impl Scene {
|
||||||
let outline = self.apply_render_options(&object.outline, &built_options);
|
let outline = self.apply_render_options(&object.outline, &built_options);
|
||||||
let mut tiler = Tiler::new(
|
let mut tiler = Tiler::new(
|
||||||
&outline,
|
&outline,
|
||||||
self.view_box,
|
self.effective_view_box(&built_options),
|
||||||
object_index as u16,
|
object_index as u16,
|
||||||
ShaderId(object.paint.0),
|
ShaderId(object.paint.0),
|
||||||
z_buffer,
|
z_buffer,
|
||||||
|
@ -107,6 +109,8 @@ impl Scene {
|
||||||
|
|
||||||
fn apply_render_options(&self, original_outline: &Outline, options: &PreparedRenderOptions)
|
fn apply_render_options(&self, original_outline: &Outline, options: &PreparedRenderOptions)
|
||||||
-> Outline {
|
-> Outline {
|
||||||
|
let effective_view_box = self.effective_view_box(options);
|
||||||
|
|
||||||
let mut outline;
|
let mut outline;
|
||||||
match options.transform {
|
match options.transform {
|
||||||
PreparedRenderTransform::Perspective { ref perspective, ref clip_polygon, .. } => {
|
PreparedRenderTransform::Perspective { ref perspective, ref clip_polygon, .. } => {
|
||||||
|
@ -121,17 +125,26 @@ impl Scene {
|
||||||
if let Some(barrel_distortion) = options.barrel_distortion {
|
if let Some(barrel_distortion) = options.barrel_distortion {
|
||||||
outline.barrel_distort(barrel_distortion, perspective.window_size);
|
outline.barrel_distort(barrel_distortion, perspective.window_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(pcwalton): Support subpixel AA in 3D.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PreparedRenderTransform::Transform2D(ref transform) => {
|
_ => {
|
||||||
// TODO(pcwalton): Short circuit.
|
// TODO(pcwalton): Short circuit.
|
||||||
outline = (*original_outline).clone();
|
outline = (*original_outline).clone();
|
||||||
outline.transform(transform);
|
if options.transform.is_2d() || options.subpixel_aa_enabled {
|
||||||
outline.clip_against_rect(self.view_box);
|
let mut transform = match options.transform {
|
||||||
|
PreparedRenderTransform::Transform2D(transform) => transform,
|
||||||
|
PreparedRenderTransform::None => Transform2DF32::default(),
|
||||||
|
PreparedRenderTransform::Perspective { .. } => unreachable!(),
|
||||||
|
};
|
||||||
|
if options.subpixel_aa_enabled {
|
||||||
|
transform = transform.post_mul(&Transform2DF32::from_scale(
|
||||||
|
&Point2DF32::new(3.0, 1.0)))
|
||||||
}
|
}
|
||||||
PreparedRenderTransform::None => {
|
outline.transform(&transform);
|
||||||
outline = (*original_outline).clone();
|
}
|
||||||
outline.clip_against_rect(self.view_box);
|
outline.clip_against_rect(effective_view_box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +154,7 @@ impl Scene {
|
||||||
|
|
||||||
// TODO(pcwalton): Fold this into previous passes to avoid unnecessary clones during
|
// TODO(pcwalton): Fold this into previous passes to avoid unnecessary clones during
|
||||||
// monotonic conversion.
|
// monotonic conversion.
|
||||||
outline.prepare_for_tiling(self.view_box);
|
outline.prepare_for_tiling(self.effective_view_box(options));
|
||||||
outline
|
outline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +168,15 @@ impl Scene {
|
||||||
}
|
}
|
||||||
Some(self.paints[first_paint_id.0 as usize].color)
|
Some(self.paints[first_paint_id.0 as usize].color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn effective_view_box(&self, render_options: &PreparedRenderOptions) -> RectF32 {
|
||||||
|
if render_options.subpixel_aa_enabled {
|
||||||
|
self.view_box.scale_xy(Point2DF32::new(3.0, 1.0))
|
||||||
|
} else {
|
||||||
|
self.view_box
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for Scene {
|
impl Debug for Scene {
|
||||||
|
|
|
@ -17,6 +17,9 @@ precision highp float;
|
||||||
|
|
||||||
uniform sampler2D uSource;
|
uniform sampler2D uSource;
|
||||||
uniform vec2 uSourceSize;
|
uniform vec2 uSourceSize;
|
||||||
|
uniform vec4 uFGColor;
|
||||||
|
uniform vec4 uBGColor;
|
||||||
|
uniform int uGammaCorrectionEnabled;
|
||||||
|
|
||||||
in vec2 vTexCoord;
|
in vec2 vTexCoord;
|
||||||
|
|
||||||
|
@ -32,9 +35,9 @@ float sample1Tap(float offset) {
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// Apply defringing if necessary.
|
// Apply defringing if necessary.
|
||||||
vec4 fgColor;
|
vec3 alpha;
|
||||||
if (uKernel.w == 0.0) {
|
if (uKernel.w == 0.0) {
|
||||||
fgColor = texture(uSource, vTexCoord);
|
alpha = texture(uSource, vTexCoord).rrr;
|
||||||
} else {
|
} else {
|
||||||
vec4 alphaLeft, alphaRight;
|
vec4 alphaLeft, alphaRight;
|
||||||
float alphaCenter;
|
float alphaCenter;
|
||||||
|
@ -44,13 +47,13 @@ void main() {
|
||||||
float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz);
|
float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz);
|
||||||
float b = convolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x), alphaRight.yzw);
|
float b = convolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x), alphaRight.yzw);
|
||||||
|
|
||||||
fgColor = vec4(r);
|
alpha = vec3(r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply gamma correction if necessary.
|
// Apply gamma correction if necessary.
|
||||||
/*if (uGammaCorrectionBGColor.a > 0.0)
|
if (uGammaCorrectionEnabled != 0)
|
||||||
fgColor.rgb = gammaCorrect(fgColor.rgb);*/
|
alpha = gammaCorrect(uBGColor.rgb, alpha);
|
||||||
|
|
||||||
// Finish.
|
// Finish.
|
||||||
oFragColor = fgColor;
|
oFragColor = vec4(mix(uBGColor.rgb, uFGColor.rgb, alpha), 1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,17 +12,13 @@
|
||||||
// expects.
|
// expects.
|
||||||
uniform sampler2D uGammaLUT;
|
uniform sampler2D uGammaLUT;
|
||||||
|
|
||||||
// The background color to blend against. Zero if no gamma correction is to be
|
float gammaCorrectChannel(float bgColor, float fgColor) {
|
||||||
// performed.
|
return texture(uGammaLUT, vec2(fgColor, 1.0 - bgColor)).r;
|
||||||
uniform vec4 uGammaCorrectionBGColor;
|
|
||||||
|
|
||||||
float gammaCorrectChannel(float fgColor) {
|
|
||||||
return texture(uGammaLUT, vec2(fgColor, 1.0 - uGammaCorrectionBGColor)).r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// `fgColor` is in linear space.
|
// `fgColor` is in linear space.
|
||||||
vec3 gammaCorrect(vec3 fgColor) {
|
vec3 gammaCorrect(vec3 bgColor, vec3 fgColor) {
|
||||||
return vec3(gammaCorrectChannel(fgColor.r),
|
return vec3(gammaCorrectChannel(bgColor.r, fgColor.r),
|
||||||
gammaCorrectChannel(fgColor.g),
|
gammaCorrectChannel(bgColor.g, fgColor.g),
|
||||||
gammaCorrectChannel(fgColor.b));
|
gammaCorrectChannel(bgColor.b, fgColor.b));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue