Factor out bits of the postprocessing shader into includes
This commit is contained in:
parent
9025189650
commit
0458d9a7f2
|
@ -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]]
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
Loading…
Reference in New Issue