thin_engine/
shaders.rs

1use glium::{uniform, uniforms::*, Program, program::ProgramCreationError, texture::*};
2use crate::Display;
3use glium_types::prelude::*;
4pub use glium_types::shaders::VERTEX;
5
6/// Vertex shader that doesnt change position or uvs. takes in `Vertex` and `TextureCoords`
7/// and outputs `uv`. Intended for use with the screen mesh to draw over
8/// the screen. e.g. with the fxaa shader.
9pub const SCREEN_VERTEX: &str =
10"#version 140
11in vec3 position;
12in vec2 texture_coords;
13out vec2 uv;
14void main() {
15    uv = texture_coords;
16    gl_Position = vec4(position, 1);
17}";
18/// Fragment shader to smooth the harsh edges of a render.
19/// see `fxaa_shader()`
20pub const FXAA: &str = 
21"/**
22For working in thin engine some variables have been changed, same as formatting.
23--
24Basic FXAA implementation based on the code on geeks3d.com with the
25modification that the texture2DLod stuff was removed since it's
26unsupported by WebGL.
27--
28
29From:
30https://github.com/mattdesl/glsl-fxaa
31https://github.com/mitsuhiko/webgl-meincraft
32
33Copyright (c) 2011 by Armin Ronacher.
34
35Some rights reserved.
36
37Redistribution and use in source and binary forms, with or without
38modification, are permitted provided that the following conditions are
39met:
40
41    * Redistributions of source code must retain the above copyright
42      notice, this list of conditions and the following disclaimer.
43
44    * Redistributions in binary form must reproduce the above
45      copyright notice, this list of conditions and the following
46      disclaimer in the documentation and/or other materials provided
47      with the distribution.
48
49    * The names of the contributors may not be used to endorse or
50      promote products derived from this software without specific
51      prior written permission.
52
53THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
56A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
57OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
59LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
63OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64*/
65#version 140
66
67const float FXAA_REDUCE_MIN = 1.0 / 128.0;
68const float FXAA_REDUCE_MUL = 1.0 / 8.0;
69const float FXAA_SPAN_MAX = 8.0;
70
71in vec2 uv;
72out vec4 colour;
73
74uniform sampler2D tex;
75uniform vec2 pixel_size;
76
77//optimized version for mobile, where dependent 
78//texture reads can be a bottleneck
79void main() {
80    vec3 rgbNW = texture(tex, uv + pixel_size*0.5).xyz;
81    vec3 rgbNE = texture(tex, uv + vec2(-pixel_size.x, pixel_size.y)*0.5).xyz;
82    vec3 rgbSW = texture(tex, uv + vec2(pixel_size.x, -pixel_size.y)*0.5).xyz;
83    vec3 rgbSE = texture(tex, uv - pixel_size*0.5).xyz;
84    vec4 texColor = texture(tex, uv);
85    vec3 rgbM  = texColor.xyz;
86    vec3 luma = vec3(0.299, 0.587, 0.114);
87    float lumaNW = dot(rgbNW, luma);
88    float lumaNE = dot(rgbNE, luma);
89    float lumaSW = dot(rgbSW, luma);
90    float lumaSE = dot(rgbSE, luma);
91    float lumaM  = dot(rgbM,  luma);
92    float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
93    float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
94    
95    vec2 dir = vec2(
96        -((lumaNW + lumaNE) - (lumaSW + lumaSE)),
97        ((lumaNW + lumaSW) - (lumaNE + lumaSE))
98    );
99    
100    float dirReduce = max(
101        (lumaNW + lumaNE + lumaSW + lumaSE)*0.25*FXAA_REDUCE_MUL,
102        FXAA_REDUCE_MIN
103    );
104    
105    float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
106    dir = min(
107        vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
108        max(-vec2(FXAA_SPAN_MAX), dir*rcpDirMin)
109    ) * pixel_size;
110    
111    vec3 rgbA = 0.5 * (
112        texture(tex, uv + dir * (1.0 / 3.0 - 0.5)).xyz +
113        texture(tex, uv + dir * (2.0 / 3.0 - 0.5)).xyz
114    );
115    vec3 rgbB = rgbA * 0.5 + 0.25 * (
116        texture(tex, uv + dir * -0.5).xyz +
117        texture(tex, uv + dir * 0.5).xyz
118    );
119
120    float lumaB = dot(rgbB, luma);
121    if ((lumaB < lumaMin) || (lumaB > lumaMax)) {
122        colour = vec4(rgbA, texColor.a);
123    } else {
124        colour = vec4(rgbB, texColor.a);
125    }
126}";
127/// A shader for smoothing jaggerd pixel edges. Use with `fxaa_uniforms` with the input of a
128/// texture. (check simple-fxaa example)
129pub fn fxaa_shader(display: &Display) -> Result<Program, ProgramCreationError> {
130    Program::from_source(display, SCREEN_VERTEX, FXAA, None)
131}
132/// Takes the render results texture and gives the appropiate fxaa uniform values. Use with the fxaa shader.
133pub fn fxaa_uniforms(tex: &Texture2d) -> UniformsStorage<'_, Vec2, UniformsStorage<'_, Sampler<'_, Texture2d>, EmptyUniforms>>{
134    uniform! {
135        tex: Sampler::new(tex),
136        pixel_size: Vec2::ONE / vec2(tex.width() as f32, tex.height() as f32)
137    }
138}