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 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 message = get_svg_building_message(&built_svg);
|
||||
|
@ -199,9 +199,7 @@ impl<W> DemoApp<W> where W: Window {
|
|||
}
|
||||
|
||||
fn build_scene(&mut self) {
|
||||
let view_box_size = view_box_size(self.ui.mode,
|
||||
&self.window_size,
|
||||
self.ui.subpixel_aa_effect_enabled);
|
||||
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||
|
||||
let render_transform = match self.camera {
|
||||
Camera::ThreeD { ref mut transform, ref mut velocity } => {
|
||||
|
@ -232,6 +230,7 @@ impl<W> DemoApp<W> where W: Window {
|
|||
} else {
|
||||
None
|
||||
},
|
||||
subpixel_aa_enabled: self.ui.subpixel_aa_effect_enabled,
|
||||
barrel_distortion,
|
||||
})).unwrap();
|
||||
}
|
||||
|
@ -254,9 +253,7 @@ impl<W> DemoApp<W> where W: Window {
|
|||
}
|
||||
Event::WindowResized(new_size) => {
|
||||
self.window_size = new_size;
|
||||
let view_box_size = view_box_size(self.ui.mode,
|
||||
&self.window_size,
|
||||
self.ui.subpixel_aa_effect_enabled);
|
||||
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||
self.scene_thread_proxy.set_drawable_size(view_box_size);
|
||||
self.renderer.set_main_framebuffer_size(self.window_size.device_size());
|
||||
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);
|
||||
self.ui.message = get_svg_building_message(&built_svg);
|
||||
|
||||
let view_box_size = view_box_size(self.ui.mode,
|
||||
&self.window_size,
|
||||
self.ui.subpixel_aa_effect_enabled);
|
||||
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||
self.scene_view_box = built_svg.scene.view_box;
|
||||
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 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,
|
||||
self.ui.subpixel_aa_effect_enabled);
|
||||
let view_box_size = view_box_size(self.ui.mode, &self.window_size);
|
||||
let viewport_origin_x = viewport_index as i32 * view_box_size.x();
|
||||
let viewport = RectI32::new(Point2DI32::new(viewport_origin_x, 0), view_box_size);
|
||||
self.renderer.set_viewport(viewport);
|
||||
|
||||
match self.monochrome_scene_color {
|
||||
None => self.renderer.set_render_mode(RenderMode::Multicolor),
|
||||
Some(fill_color) => {
|
||||
Some(fg_color) => {
|
||||
self.renderer.set_render_mode(RenderMode::Monochrome {
|
||||
fill_color: fill_color.to_f32(),
|
||||
gamma_correction_bg_color: if self.ui.gamma_correction_effect_enabled {
|
||||
Some(self.background_color())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
fg_color: fg_color.to_f32(),
|
||||
bg_color: self.background_color().to_f32(),
|
||||
gamma_correction: self.ui.gamma_correction_effect_enabled,
|
||||
defringing_kernel: if self.ui.subpixel_aa_effect_enabled {
|
||||
// TODO(pcwalton): Select FreeType defringing kernel as necessary.
|
||||
Some(DEFRINGING_KERNEL_CORE_GRAPHICS)
|
||||
} else {
|
||||
None
|
||||
|
@ -709,6 +700,7 @@ struct BuildOptions {
|
|||
render_transforms: Vec<RenderTransform>,
|
||||
stem_darkening_font_size: Option<f32>,
|
||||
barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||
subpixel_aa_enabled: bool,
|
||||
}
|
||||
|
||||
struct SceneToMainMsg {
|
||||
|
@ -810,8 +802,6 @@ fn build_scene(scene: &Scene,
|
|||
render_transform: RenderTransform,
|
||||
jobs: Option<usize>)
|
||||
-> BuiltScene {
|
||||
let z_buffer = ZBuffer::new(scene.view_box);
|
||||
|
||||
let render_options = RenderOptions {
|
||||
transform: render_transform,
|
||||
dilation: match build_options.stem_darkening_font_size {
|
||||
|
@ -822,9 +812,13 @@ fn build_scene(scene: &Scene,
|
|||
}
|
||||
},
|
||||
barrel_distortion: build_options.barrel_distortion,
|
||||
subpixel_aa_enabled: build_options.subpixel_aa_enabled,
|
||||
};
|
||||
|
||||
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 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);
|
||||
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();
|
||||
while let Some(batch) = scene_builder.build_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 initial_size = match mode {
|
||||
match mode {
|
||||
Mode::TwoD | Mode::ThreeD => window_drawable_size,
|
||||
Mode::VR => Point2DI32::new(window_drawable_size.x() / 2, window_drawable_size.y()),
|
||||
};
|
||||
if use_subpixel_aa { initial_size.scale_xy(Point2DI32::new(3, 1)) } else { initial_size }
|
||||
}
|
||||
}
|
||||
|
||||
struct Frame {
|
||||
|
|
|
@ -364,6 +364,9 @@ impl Device for GLDevice {
|
|||
fn set_uniform(&self, uniform: &Self::Uniform, data: UniformData) {
|
||||
unsafe {
|
||||
match data {
|
||||
UniformData::Int(value) => {
|
||||
gl::Uniform1i(uniform.location, value); ck();
|
||||
}
|
||||
UniformData::Mat4(data) => {
|
||||
assert_eq!(mem::size_of::<[F32x4; 4]>(), 4 * 4 * 4);
|
||||
let data_ptr: *const F32x4 = data.as_ptr();
|
||||
|
|
|
@ -191,6 +191,7 @@ pub enum ShaderKind {
|
|||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum UniformData {
|
||||
Int(i32),
|
||||
Mat4([F32x4; 4]),
|
||||
Vec2(F32x4),
|
||||
Vec4(F32x4),
|
||||
|
|
|
@ -128,6 +128,7 @@ pub struct RenderOptions {
|
|||
pub transform: RenderTransform,
|
||||
pub dilation: Point2DF32,
|
||||
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||
pub subpixel_aa_enabled: bool,
|
||||
}
|
||||
|
||||
impl RenderOptions {
|
||||
|
@ -136,6 +137,7 @@ impl RenderOptions {
|
|||
transform: self.transform.prepare(bounds),
|
||||
dilation: self.dilation,
|
||||
barrel_distortion: self.barrel_distortion,
|
||||
subpixel_aa_enabled: self.subpixel_aa_enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +207,7 @@ pub struct PreparedRenderOptions {
|
|||
pub transform: PreparedRenderTransform,
|
||||
pub dilation: Point2DF32,
|
||||
pub barrel_distortion: Option<BarrelDistortionCoefficients>,
|
||||
pub subpixel_aa_enabled: bool,
|
||||
}
|
||||
|
||||
impl PreparedRenderOptions {
|
||||
|
@ -222,3 +225,13 @@ pub enum PreparedRenderTransform {
|
|||
Transform2D(Transform2DF32),
|
||||
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 pathfinder_geometry::basic::point::{Point2DI32, Point3DF32};
|
||||
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::{BlendState, BufferTarget, BufferUploadMode, DepthFunc, DepthState, Device};
|
||||
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.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.draw_viewport().size().to_f32().0));
|
||||
self.device.set_uniform(&alpha_tile_program.tile_size_uniform,
|
||||
UniformData::Vec2(I32x4::new(TILE_WIDTH as i32,
|
||||
TILE_HEIGHT as i32,
|
||||
|
@ -349,9 +349,13 @@ impl<D> Renderer<D> where D: Device {
|
|||
0,
|
||||
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,
|
||||
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) {
|
||||
self.bind_draw_framebuffer();
|
||||
|
||||
let solid_tile_vertex_array = self.solid_tile_vertex_array();
|
||||
let solid_tile_program = self.solid_tile_program();
|
||||
|
||||
self.device.bind_vertex_array(&solid_tile_vertex_array.vertex_array);
|
||||
self.device.use_program(&solid_tile_program.program);
|
||||
self.device.set_uniform(&solid_tile_program.framebuffer_size_uniform,
|
||||
UniformData::Vec2(self.viewport.size().0.to_f32x4()));
|
||||
UniformData::Vec2(self.draw_viewport().size().0.to_f32x4()));
|
||||
self.device.set_uniform(&solid_tile_program.tile_size_uniform,
|
||||
UniformData::Vec2(I32x4::new(TILE_WIDTH as i32,
|
||||
TILE_HEIGHT as i32,
|
||||
|
@ -396,9 +402,13 @@ impl<D> Renderer<D> where D: Device {
|
|||
0,
|
||||
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,
|
||||
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) {
|
||||
let (fill_color, defringing_kernel, gamma_correction_bg_color);
|
||||
let (fg_color, bg_color, defringing_kernel, gamma_correction_enabled);
|
||||
match self.render_mode {
|
||||
RenderMode::Multicolor => return,
|
||||
RenderMode::Monochrome {
|
||||
fill_color: fc,
|
||||
defringing_kernel: dk,
|
||||
gamma_correction_bg_color: gcbc,
|
||||
fg_color: fg,
|
||||
bg_color: bg,
|
||||
defringing_kernel: kernel,
|
||||
gamma_correction,
|
||||
} => {
|
||||
fill_color = fc;
|
||||
defringing_kernel = dk;
|
||||
gamma_correction_bg_color = gcbc;
|
||||
fg_color = fg;
|
||||
bg_color = bg;
|
||||
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.set_uniform(&self.postprocess_program.gamma_lut_uniform,
|
||||
UniformData::TextureUnit(1));
|
||||
let gamma_correction_bg_color_uniform = &self.postprocess_program
|
||||
.gamma_correction_bg_color_uniform;
|
||||
match gamma_correction_bg_color {
|
||||
None => {
|
||||
self.device.set_uniform(gamma_correction_bg_color_uniform,
|
||||
UniformData::Vec4(F32x4::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()
|
||||
});
|
||||
self.device.set_uniform(&self.postprocess_program.fg_color_uniform,
|
||||
UniformData::Vec4(fg_color.0));
|
||||
self.device.set_uniform(&self.postprocess_program.bg_color_uniform,
|
||||
UniformData::Vec4(bg_color.0));
|
||||
self.device.set_uniform(&self.postprocess_program.gamma_correction_enabled_uniform,
|
||||
UniformData::Int(gamma_correction_enabled as i32));
|
||||
self.device.draw_arrays(Primitive::TriangleFan, 4, &RenderState::default());
|
||||
}
|
||||
|
||||
fn solid_tile_program(&self) -> &SolidTileProgram<D> {
|
||||
|
@ -543,12 +546,14 @@ impl<D> Renderer<D> where D: Device {
|
|||
return;
|
||||
}
|
||||
|
||||
let source_framebuffer_size = self.draw_viewport().size();
|
||||
match self.postprocess_source_framebuffer {
|
||||
Some(ref framebuffer) if
|
||||
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))
|
||||
}
|
||||
};
|
||||
|
@ -559,8 +564,8 @@ impl<D> Renderer<D> where D: Device {
|
|||
|
||||
fn postprocessing_needed(&self) -> bool {
|
||||
match self.render_mode {
|
||||
RenderMode::Monochrome { ref defringing_kernel, gamma_correction_bg_color, .. } => {
|
||||
defringing_kernel.is_some() || gamma_correction_bg_color.is_some()
|
||||
RenderMode::Monochrome { ref defringing_kernel, gamma_correction, .. } => {
|
||||
defringing_kernel.is_some() || gamma_correction
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
@ -573,6 +578,16 @@ impl<D> Renderer<D> where D: Device {
|
|||
|
||||
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 {
|
||||
|
@ -824,8 +839,6 @@ struct AlphaTileProgram<D> where D: Device {
|
|||
tile_size_uniform: D::Uniform,
|
||||
stencil_texture_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,
|
||||
}
|
||||
|
||||
|
@ -839,9 +852,6 @@ impl<D> AlphaTileProgram<D> where D: Device {
|
|||
let tile_size_uniform = device.get_uniform(&program, "TileSize");
|
||||
let stencil_texture_uniform = device.get_uniform(&program, "StencilTexture");
|
||||
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");
|
||||
AlphaTileProgram {
|
||||
program,
|
||||
|
@ -849,8 +859,6 @@ impl<D> AlphaTileProgram<D> where D: Device {
|
|||
tile_size_uniform,
|
||||
stencil_texture_uniform,
|
||||
stencil_texture_size_uniform,
|
||||
fill_colors_texture_uniform,
|
||||
fill_colors_texture_size_uniform,
|
||||
view_box_origin_uniform,
|
||||
}
|
||||
}
|
||||
|
@ -897,7 +905,9 @@ struct PostprocessProgram<D> where D: Device {
|
|||
framebuffer_size_uniform: D::Uniform,
|
||||
kernel_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 {
|
||||
|
@ -908,8 +918,10 @@ impl<D> PostprocessProgram<D> where D: Device {
|
|||
let framebuffer_size_uniform = device.get_uniform(&program, "FramebufferSize");
|
||||
let kernel_uniform = device.get_uniform(&program, "Kernel");
|
||||
let gamma_lut_uniform = device.get_uniform(&program, "GammaLUT");
|
||||
let gamma_correction_bg_color_uniform = device.get_uniform(&program,
|
||||
"GammaCorrectionBGColor");
|
||||
let gamma_correction_enabled_uniform = device.get_uniform(&program,
|
||||
"GammaCorrectionEnabled");
|
||||
let fg_color_uniform = device.get_uniform(&program, "FGColor");
|
||||
let bg_color_uniform = device.get_uniform(&program, "BGColor");
|
||||
PostprocessProgram {
|
||||
program,
|
||||
source_uniform,
|
||||
|
@ -917,7 +929,9 @@ impl<D> PostprocessProgram<D> where D: Device {
|
|||
framebuffer_size_uniform,
|
||||
kernel_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 {
|
||||
Multicolor,
|
||||
Monochrome {
|
||||
fill_color: ColorF,
|
||||
fg_color: ColorF,
|
||||
bg_color: ColorF,
|
||||
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::z_buffer::ZBuffer;
|
||||
use hashbrown::HashMap;
|
||||
use pathfinder_geometry::basic::point::Point2DF32;
|
||||
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
||||
use pathfinder_geometry::basic::transform2d::Transform2DF32;
|
||||
use pathfinder_geometry::color::ColorU;
|
||||
use pathfinder_geometry::outline::Outline;
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||
|
@ -74,7 +76,7 @@ impl Scene {
|
|||
let outline = self.apply_render_options(&object.outline, &built_options);
|
||||
let mut tiler = Tiler::new(
|
||||
&outline,
|
||||
self.view_box,
|
||||
self.effective_view_box(&built_options),
|
||||
object_index as u16,
|
||||
ShaderId(object.paint.0),
|
||||
z_buffer,
|
||||
|
@ -94,7 +96,7 @@ impl Scene {
|
|||
let outline = self.apply_render_options(&object.outline, &built_options);
|
||||
let mut tiler = Tiler::new(
|
||||
&outline,
|
||||
self.view_box,
|
||||
self.effective_view_box(&built_options),
|
||||
object_index as u16,
|
||||
ShaderId(object.paint.0),
|
||||
z_buffer,
|
||||
|
@ -107,6 +109,8 @@ impl Scene {
|
|||
|
||||
fn apply_render_options(&self, original_outline: &Outline, options: &PreparedRenderOptions)
|
||||
-> Outline {
|
||||
let effective_view_box = self.effective_view_box(options);
|
||||
|
||||
let mut outline;
|
||||
match options.transform {
|
||||
PreparedRenderTransform::Perspective { ref perspective, ref clip_polygon, .. } => {
|
||||
|
@ -121,17 +125,26 @@ impl Scene {
|
|||
if let Some(barrel_distortion) = options.barrel_distortion {
|
||||
outline.barrel_distort(barrel_distortion, perspective.window_size);
|
||||
}
|
||||
|
||||
// TODO(pcwalton): Support subpixel AA in 3D.
|
||||
}
|
||||
}
|
||||
PreparedRenderTransform::Transform2D(ref transform) => {
|
||||
_ => {
|
||||
// TODO(pcwalton): Short circuit.
|
||||
outline = (*original_outline).clone();
|
||||
outline.transform(transform);
|
||||
outline.clip_against_rect(self.view_box);
|
||||
if options.transform.is_2d() || options.subpixel_aa_enabled {
|
||||
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 = (*original_outline).clone();
|
||||
outline.clip_against_rect(self.view_box);
|
||||
outline.transform(&transform);
|
||||
}
|
||||
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
|
||||
// monotonic conversion.
|
||||
outline.prepare_for_tiling(self.view_box);
|
||||
outline.prepare_for_tiling(self.effective_view_box(options));
|
||||
outline
|
||||
}
|
||||
|
||||
|
@ -155,6 +168,15 @@ impl Scene {
|
|||
}
|
||||
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 {
|
||||
|
|
|
@ -17,6 +17,9 @@ precision highp float;
|
|||
|
||||
uniform sampler2D uSource;
|
||||
uniform vec2 uSourceSize;
|
||||
uniform vec4 uFGColor;
|
||||
uniform vec4 uBGColor;
|
||||
uniform int uGammaCorrectionEnabled;
|
||||
|
||||
in vec2 vTexCoord;
|
||||
|
||||
|
@ -32,9 +35,9 @@ float sample1Tap(float offset) {
|
|||
|
||||
void main() {
|
||||
// Apply defringing if necessary.
|
||||
vec4 fgColor;
|
||||
vec3 alpha;
|
||||
if (uKernel.w == 0.0) {
|
||||
fgColor = texture(uSource, vTexCoord);
|
||||
alpha = texture(uSource, vTexCoord).rrr;
|
||||
} else {
|
||||
vec4 alphaLeft, alphaRight;
|
||||
float alphaCenter;
|
||||
|
@ -44,13 +47,13 @@ void main() {
|
|||
float g = convolve7Tap(vec4(alphaLeft.yzw, alphaCenter), alphaRight.xyz);
|
||||
float b = convolve7Tap(vec4(alphaLeft.zw, alphaCenter, alphaRight.x), alphaRight.yzw);
|
||||
|
||||
fgColor = vec4(r);
|
||||
alpha = vec3(r, g, b);
|
||||
}
|
||||
|
||||
// Apply gamma correction if necessary.
|
||||
/*if (uGammaCorrectionBGColor.a > 0.0)
|
||||
fgColor.rgb = gammaCorrect(fgColor.rgb);*/
|
||||
if (uGammaCorrectionEnabled != 0)
|
||||
alpha = gammaCorrect(uBGColor.rgb, alpha);
|
||||
|
||||
// Finish.
|
||||
oFragColor = fgColor;
|
||||
oFragColor = vec4(mix(uBGColor.rgb, uFGColor.rgb, alpha), 1.0);
|
||||
}
|
||||
|
|
|
@ -12,17 +12,13 @@
|
|||
// expects.
|
||||
uniform sampler2D uGammaLUT;
|
||||
|
||||
// The background color to blend against. Zero if no gamma correction is to be
|
||||
// performed.
|
||||
uniform vec4 uGammaCorrectionBGColor;
|
||||
|
||||
float gammaCorrectChannel(float fgColor) {
|
||||
return texture(uGammaLUT, vec2(fgColor, 1.0 - uGammaCorrectionBGColor)).r;
|
||||
float gammaCorrectChannel(float bgColor, float fgColor) {
|
||||
return texture(uGammaLUT, vec2(fgColor, 1.0 - bgColor)).r;
|
||||
}
|
||||
|
||||
// `fgColor` is in linear space.
|
||||
vec3 gammaCorrect(vec3 fgColor) {
|
||||
return vec3(gammaCorrectChannel(fgColor.r),
|
||||
gammaCorrectChannel(fgColor.g),
|
||||
gammaCorrectChannel(fgColor.b));
|
||||
vec3 gammaCorrect(vec3 bgColor, vec3 fgColor) {
|
||||
return vec3(gammaCorrectChannel(bgColor.r, fgColor.r),
|
||||
gammaCorrectChannel(bgColor.g, fgColor.g),
|
||||
gammaCorrectChannel(bgColor.b, fgColor.b));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue