mini_gl_fb/examples/custom_shaders.rs
2018-05-31 21:58:36 -04:00

124 lines
3.5 KiB
Rust

extern crate mini_gl_fb;
/// Geometry shaders allow you to procedurally generate new geometry from the vertex data.
///
/// This shader takes the two triangles submitted by mini_gl_fb and turns them into a circle!
const geometry_source: &str = r"
#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 8) out;
in vec2 v_uv[];
out vec2 g_uv;
vec2 midpoint(vec2 a, vec2 b) {
return (a + b) / 2.0;
}
void main() {
// n.b., the way we do this relies almost entirely on what we know about the internals of
// mini_gl_fb, so you will need to refer to the source if you want to play with this stuff.
vec4 center = vec4(0.0, 0.0, 0.0, 1.0);
// for the first triangle, the second (index 1) vertex is the top left
// for the second triangle, it is the bottom right. we will treat that like a direction!
vec2 dir = gl_in[1].gl_Position.xy;
// we are turning each triangle into 4 triangles, which we output in triangle strips
// (remember this shader will get run twice, once for each input triangle)
vec4 top_left = vec4(normalize(vec2(dir.x, -dir.y)), 0.0, 1.0);
vec4 left = vec4(sign(dir.x), 0.0, 0.0, 1.0);
vec4 bottom_left = vec4(normalize(dir), 0.0, 1.0);
vec4 bottom = vec4(0.0, sign(dir.y), 0.0, 1.0);
vec4 bottom_right = vec4(normalize(vec2(-dir.x, dir.y)), 0.0, 1.0);
gl_Position = top_left;
g_uv = v_uv[0];
EmitVertex();
gl_Position = left;
g_uv = midpoint(v_uv[0], v_uv[1]);
EmitVertex();
gl_Position = center;
g_uv = midpoint(v_uv[0], v_uv[2]);
EmitVertex();
gl_Position = bottom_left;
g_uv = v_uv[1];
EmitVertex();
EndPrimitive();
gl_Position = bottom_left;
g_uv = v_uv[1];
EmitVertex();
gl_Position = bottom;
g_uv = midpoint(v_uv[1], v_uv[2]);
EmitVertex();
gl_Position = center;
g_uv = midpoint(v_uv[0], v_uv[2]);
EmitVertex();
gl_Position = bottom_right;
g_uv = v_uv[2];
EmitVertex();
EndPrimitive();
}
";
const fragment_source: &str = r"
#version 330 core
in vec2 g_uv;
out vec4 frag_color;
// this is the texture uploaded by calls to `update_buffer`
uniform sampler2D u_tex0;
void main() {
vec4 sample = texture(u_tex0, g_uv);
vec4 color;
if (sample.r == 1.0) {
color = sample;
} else {
// render the uv coords as color otherwise
color = vec4(g_uv, 0.0, 1.0);
}
frag_color = color;
}
";
extern crate gl;
fn main() {
let width = 800;
let height = 600;
let mut fb = mini_gl_fb::gotta_go_fast("Hello shaders!", width, height);
let mut buffer = vec![[128u8, 0, 0, 255]; (width * height) as usize];
// let's write a red line into the buffer roughly along the diagonal (misses many pixels)
for i in 0..100 {
let j = i as f32 / 100.0;
let index = ((width as f32) * j * ((height as f32) + 1.0)).floor() as usize;
buffer[index] = [255, 0, 0, 255];
}
// Let's keep using the default vertex shader
// fb.use_vertex_shader(...);
fb.use_geometry_shader(geometry_source);
fb.use_fragment_shader(fragment_source);
fb.update_buffer(&buffer);
fb.persist_and_redraw(true);
}