Add use_post_process_shader support

This commit is contained in:
shivshank 2018-07-28 14:56:48 -04:00
parent 03f17314ad
commit 5e006a73ac
4 changed files with 65 additions and 5 deletions

View file

@ -79,7 +79,7 @@ pub fn init_framebuffer(
};
let sampler_location = unsafe {
let location = gl::GetUniformLocation(program, b"u_tex0\0".as_ptr() as *const _);
let location = gl::GetUniformLocation(program, b"u_buffer\0".as_ptr() as *const _);
gl::UseProgram(program);
gl::Uniform1i(location, 0);
gl::UseProgram(0);
@ -323,6 +323,11 @@ impl Framebuffer {
self.relink_program();
}
pub fn use_post_process_shader(&mut self, source: &str) {
let source = make_post_process_shader(source);
self.use_fragment_shader(&source);
}
pub fn use_geometry_shader(&mut self, source: &str) {
rebuild_shader(&mut self.geometry_shader, gl::GEOMETRY_SHADER, source);
self.relink_program();
@ -455,6 +460,27 @@ fn create_texture() -> GLuint {
}
}
fn make_post_process_shader(source: &str) -> String {
format!(
"
#version 330 core
in vec2 v_uv;
out vec4 r_frag_color;
uniform sampler2D u_buffer;
{}
void main() {{
main_image(r_frag_color, v_uv);
}}
",
source,
)
}
fn rebuild_shader(shader: &mut Option<GLuint>, kind: GLenum, source: &str) {
if let Some(shader) = *shader {
unsafe {

View file

@ -4,8 +4,8 @@ in vec2 v_uv;
out vec4 frag_color;
uniform sampler2D u_tex0;
uniform sampler2D u_buffer;
void main() {
frag_color = texture(u_tex0, v_uv);
frag_color = texture(u_buffer, v_uv);
}

View file

@ -4,8 +4,8 @@ in vec2 v_uv;
out vec4 frag_color;
uniform sampler2D u_tex0;
uniform sampler2D u_buffer;
void main() {
frag_color = texture(u_tex0, v_uv).rrra;
frag_color = texture(u_buffer, v_uv).rrra;
}

View file

@ -188,6 +188,40 @@ impl MiniGlFb {
self.internal.redraw();
}
/// Use a custom post process shader written in GLSL (version 330 core).
///
/// The interface is unapologetically similar to ShaderToy's. It works by inserting your code
/// (it is implemented as literal substitution) into a supplied fragment shader and calls
/// a function `main_image` that it assumes you define.
///
/// # Example usage
///
/// The behavior of the default fragment shader can be emulated by the following:
///
/// ```rust
/// fb.use_post_process_shader("
/// void main_image( out vec4 r_frag_color, in vec2 v_uv ) {
/// r_frag_color = texture(u_buffer, v_uv);
/// }
/// ");
/// ```
///
/// Regardless of the format of your buffer, the internal texture is always stored as RGBA,
/// so sampling u_buffer will yield a vec4 representing an RGBA color. The built in grayscale
/// shader, for instance, only stores Red components, and then uses the red component for the
/// green and blue components to create gray.
///
/// The output color is determined by the value of the first output parameter, `r_frag_color`.
/// Your buffer is accessible as a 2D sampler uniform named `u_buffer`. The first input
/// parameter `v_uv` is a vec2 UV coordinate. UV (0, 0) represents the upper left of the screen
/// and (1, 1) represents the bottom right.
///
/// An API for exposing more built in and custom uniforms is planned, along with support for
/// an arbitrary number of render targets and possibly more user supplied textures.
pub fn use_post_process_shader(&mut self, source: &str) {
self.internal.fb.use_post_process_shader(source);
}
/// Changes the format of the image buffer.
///
/// OpenGL will interpret any missing components as 0, except the alpha which it will assume is