Factor out bits of the postprocessing shader into includes

This commit is contained in:
Patrick Walton 2019-03-18 21:40:10 -07:00
parent 9025189650
commit 0458d9a7f2
9 changed files with 103 additions and 51 deletions

1
Cargo.lock generated
View File

@ -691,6 +691,7 @@ dependencies = [
"image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pathfinder_geometry 0.3.0", "pathfinder_geometry 0.3.0",
"pathfinder_simd 0.3.0", "pathfinder_simd 0.3.0",
"rustache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]

View File

@ -209,9 +209,16 @@ impl Device for GLDevice {
texture texture
} }
fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind) -> GLShader { fn create_shader_from_source(&self,
name: &str,
source: &[u8],
kind: ShaderKind,
mut template_input: HashBuilder)
-> GLShader {
// FIXME(pcwalton): Do this once and cache it.
let glsl_version_spec = self.version.to_glsl_version_spec(); let glsl_version_spec = self.version.to_glsl_version_spec();
let template_input = HashBuilder::new().insert("version", glsl_version_spec); template_input = template_input.insert("version", glsl_version_spec);
let mut output = Cursor::new(vec![]); let mut output = Cursor::new(vec![]);
template_input.render(str::from_utf8(source).unwrap(), &mut output).unwrap(); template_input.render(str::from_utf8(source).unwrap(), &mut output).unwrap();
let source = output.into_inner(); let source = output.into_inner();

View File

@ -5,6 +5,7 @@ authors = ["Patrick Walton <pcwalton@mimiga.net>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
rustache = "0.1"
[dependencies.image] [dependencies.image]
version = "0.21" version = "0.21"

View File

@ -15,10 +15,7 @@ use image::ImageFormat;
use pathfinder_geometry::basic::point::Point2DI32; use pathfinder_geometry::basic::point::Point2DI32;
use pathfinder_geometry::basic::rect::RectI32; use pathfinder_geometry::basic::rect::RectI32;
use pathfinder_simd::default::F32x4; use pathfinder_simd::default::F32x4;
use std::env; use rustache::HashBuilder;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
pub mod resources; pub mod resources;
@ -36,7 +33,11 @@ pub trait Device {
fn create_texture(&self, format: TextureFormat, size: Point2DI32) -> Self::Texture; fn create_texture(&self, format: TextureFormat, size: Point2DI32) -> Self::Texture;
fn create_texture_from_data(&self, size: Point2DI32, data: &[u8]) -> Self::Texture; fn create_texture_from_data(&self, size: Point2DI32, data: &[u8]) -> Self::Texture;
fn create_shader_from_source(&self, name: &str, source: &[u8], kind: ShaderKind) fn create_shader_from_source(&self,
name: &str,
source: &[u8],
kind: ShaderKind,
template_input: HashBuilder)
-> Self::Shader; -> Self::Shader;
fn create_vertex_array(&self) -> Self::VertexArray; fn create_vertex_array(&self) -> Self::VertexArray;
fn create_program_from_shaders(&self, fn create_program_from_shaders(&self,
@ -108,7 +109,17 @@ pub trait Device {
-> Self::Shader { -> Self::Shader {
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();
self.create_shader_from_source(name, &source, kind)
let mut load_include_post_convolve = |_| load_shader_include(resources, "post_convolve");
let mut load_include_post_gamma_correct =
|_| load_shader_include(resources, "post_gamma_correct");
let template_input =
HashBuilder::new().insert_lambda("include_post_convolve",
&mut load_include_post_convolve)
.insert_lambda("include_post_gamma_correct",
&mut load_include_post_gamma_correct);
self.create_shader_from_source(name, &source, kind, template_input)
} }
fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program { fn create_program(&self, resources: &dyn ResourceLoader, name: &str) -> Self::Program {
@ -242,3 +253,8 @@ impl Default for StencilFunc {
StencilFunc::Always StencilFunc::Always
} }
} }
fn load_shader_include(resources: &dyn ResourceLoader, include_name: &str) -> String {
let resource = resources.slurp(&format!("shaders/{}.inc.glsl", include_name)).unwrap();
String::from_utf8_lossy(&resource).to_string()
}

View File

@ -12,7 +12,6 @@
//! //!
//! We can't always count on a filesystem being present. //! We can't always count on a filesystem being present.
use crate::ShaderKind;
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::io::{Error as IOError, Read}; use std::io::{Error as IOError, Read};
@ -29,7 +28,7 @@ pub struct FilesystemResourceLoader {
} }
impl FilesystemResourceLoader { impl FilesystemResourceLoader {
pub fn new(root: PathBuf) -> FilesystemResourceLoader { pub fn locate() -> FilesystemResourceLoader {
let mut parent_directory = env::current_dir().unwrap(); let mut parent_directory = env::current_dir().unwrap();
loop { loop {
// So ugly :( // So ugly :(
@ -52,10 +51,6 @@ impl FilesystemResourceLoader {
panic!("No suitable `resources/` directory found!"); panic!("No suitable `resources/` directory found!");
} }
pub fn locate() -> FilesystemResourceLoader {
FilesystemResourceLoader::new(env::current_dir().unwrap())
}
} }
impl ResourceLoader for FilesystemResourceLoader { impl ResourceLoader for FilesystemResourceLoader {

View File

@ -70,7 +70,6 @@ pub struct Renderer<D> where D: Device {
// Extra info // Extra info
viewport: RectI32, viewport: RectI32,
main_framebuffer_size: Point2DI32,
postprocess_options: PostprocessOptions, postprocess_options: PostprocessOptions,
use_depth: bool, use_depth: bool,
} }
@ -150,7 +149,6 @@ impl<D> Renderer<D> where D: Device {
debug_ui, debug_ui,
viewport, viewport,
main_framebuffer_size,
postprocess_options: PostprocessOptions::default(), postprocess_options: PostprocessOptions::default(),
use_depth: false, use_depth: false,
} }

View File

@ -1,6 +1,6 @@
#version {{version}} #version {{version}}
// pathfinder/demo/shaders/post.fs.glsl // pathfinder/resources/shaders/post.fs.glsl
// //
// Copyright © 2019 The Pathfinder Project Developers. // Copyright © 2019 The Pathfinder Project Developers.
// //
@ -16,51 +16,20 @@
precision highp float; precision highp float;
uniform sampler2D uSource; uniform sampler2D uSource;
uniform sampler2D uGammaLUT;
uniform vec2 uFramebufferSize; uniform vec2 uFramebufferSize;
// Zero if no subpixel AA is to be performed.
uniform vec4 uKernel;
// Zero if no gamma correction is to be performed.
uniform vec4 uGammaCorrectionBGColor;
in vec2 vTexCoord; in vec2 vTexCoord;
out vec4 oFragColor; out vec4 oFragColor;
float gammaCorrectChannel(float fgColor) { {{{include_post_gamma_correct}}}
return texture(uGammaLUT, vec2(fgColor, 1.0 - uGammaCorrectionBGColor)).r; {{{include_post_convolve}}}
}
// `fgColor` is in linear space.
vec3 gammaCorrect(vec3 fgColor) {
return vec3(gammaCorrectChannel(fgColor.r),
gammaCorrectChannel(fgColor.g),
gammaCorrectChannel(fgColor.b));
}
// Convolve horizontally in this pass.
float sample1Tap(float offset) { float sample1Tap(float offset) {
return texture(uSource, vec2(vTexCoord.x + offset, vTexCoord.y)).r; return texture(uSource, vec2(vTexCoord.x + offset, vTexCoord.y)).r;
} }
void sample9Tap(out vec4 outAlphaLeft,
out float outAlphaCenter,
out vec4 outAlphaRight,
float onePixel) {
outAlphaLeft = vec4(uKernel.x > 0.0 ? sample1Tap(-4.0 * onePixel) : 0.0,
sample1Tap(-3.0 * onePixel),
sample1Tap(-2.0 * onePixel),
sample1Tap(-1.0 * onePixel));
outAlphaCenter = sample1Tap(0.0);
outAlphaRight = vec4(sample1Tap(1.0 * onePixel),
sample1Tap(2.0 * onePixel),
sample1Tap(3.0 * onePixel),
uKernel.x > 0.0 ? sample1Tap(4.0 * onePixel) : 0.0);
}
float convolve7Tap(vec4 alpha0, vec3 alpha1) {
return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx);
}
void main() { void main() {
// Apply defringing if necessary. // Apply defringing if necessary.
vec4 fgColor = texture(uSource, vTexCoord); vec4 fgColor = texture(uSource, vTexCoord);

View File

@ -0,0 +1,37 @@
// pathfinder/resources/shaders/post_convolve.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.
// Zero if no convolution is to be performed.
uniform vec4 uKernel;
// This function is expected to return the alpha value of the pixel at the
// given offset in pixels. Offset 0.0 represents the current pixel.
float sample1Tap(float offset);
// Samples 9 taps around the current pixel.
void sample9Tap(out vec4 outAlphaLeft,
out float outAlphaCenter,
out vec4 outAlphaRight,
float onePixel) {
outAlphaLeft = vec4(uKernel.x > 0.0 ? sample1Tap(-4.0 * onePixel) : 0.0,
sample1Tap(-3.0 * onePixel),
sample1Tap(-2.0 * onePixel),
sample1Tap(-1.0 * onePixel));
outAlphaCenter = sample1Tap(0.0);
outAlphaRight = vec4(sample1Tap(1.0 * onePixel),
sample1Tap(2.0 * onePixel),
sample1Tap(3.0 * onePixel),
uKernel.x > 0.0 ? sample1Tap(4.0 * onePixel) : 0.0);
}
// Convolves 7 values with the kernel.
float convolve7Tap(vec4 alpha0, vec3 alpha1) {
return dot(alpha0, uKernel) + dot(alpha1, uKernel.zyx);
}

View File

@ -0,0 +1,28 @@
// pathfinder/resources/shaders/post_gamma_correct.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.
// The lookup table for gamma correction, in the same format WebRender
// 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;
}
// `fgColor` is in linear space.
vec3 gammaCorrect(vec3 fgColor) {
return vec3(gammaCorrectChannel(fgColor.r),
gammaCorrectChannel(fgColor.g),
gammaCorrectChannel(fgColor.b));
}