diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 175 |
1 files changed, 90 insertions, 85 deletions
diff --git a/src/main.rs b/src/main.rs index 9f9ad9f..a9bfcf9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,8 @@ mod lerp; -mod number; mod poly; use lerp::Lerp; +use poly::Poly; use std::ffi::{CStr, CString}; @@ -25,6 +25,92 @@ fn shader_from_source(source: &CStr, shader_type: GLenum) -> GLuint { } } +fn compile_bezier_shader(a: Poly, b: Poly) -> GLuint { + let vertex_shader_source = b" + #version 410 core + layout (location = 0) in vec3 aPos; + + void main() { + gl_Position = vec4(aPos.xyz, 1.0); + } + " + .to_vec(); + + let fragment_shader_source = format!( + " + #version 410 core + out vec4 FragColor; + + float pa[{sa}] = float[{sa}]({pa}); + float pb[{sb}] = float[{sb}]({pb}); + + float eval_a(float[{sa}] v, float t) {{ + float result = 0.0; + for (int i = 0; i < {sa}; i++) {{ + result += v[i] * pow(t, i); + }} + return result; + }} + + float eval_b(float[{sb}] v, float t) {{ + float result = 0.0; + for (int i = 0; i < {sb}; i++) {{ + result += v[i] * pow(t, i); + }} + return result; + }} + + float inside(vec2 pos) {{ + float res = 100; + float thr = 32; + float closest = 1000000; + float t = 0.0; + while (t < 1.0) {{ + float step = t + 1.0 / res; + vec2 a = vec2(eval_a(pa, t), eval_b(pb, t)); + vec2 b = vec2(eval_a(pa, step), eval_b(pb, step)); + float c = pow(length(a - b), 2); + float d = distance(pos, a + clamp(dot(pos - a, b - a) / c, 0, 1) * (b - a)); + if (d < closest) {{ + closest = d; + }} + t = step; + }} + return 1 - closest / thr; + }} + + void main() {{ + float r = inside(gl_FragCoord.xy); + FragColor = vec4(r * 0.8, r * 0.2, r, 1.0); + }} + ", + sa = a.degree() + 1, + sb = b.degree() + 1, + pa = &a, + pb = &b + ) + .into_bytes(); + + let shader_program: GLuint; + unsafe { + let vertex_shader = shader_from_source( + &CString::from_vec_unchecked(vertex_shader_source), + gl::VERTEX_SHADER, + ); + let fragment_shader = shader_from_source( + &CString::from_vec_unchecked(fragment_shader_source), + gl::FRAGMENT_SHADER, + ); + shader_program = gl::CreateProgram(); + gl::AttachShader(shader_program, vertex_shader); + gl::AttachShader(shader_program, fragment_shader); + gl::LinkProgram(shader_program); + gl::DeleteShader(vertex_shader); + gl::DeleteShader(fragment_shader); + } + shader_program +} + fn main() { let a = lerp::lp(Lerp::new(vec![200.0, 500.0, 500.0])); let b = lerp::lp(Lerp::new(vec![200.0, 500.0, 200.0])); @@ -56,75 +142,10 @@ fn main() { } let vertices: [f32; 18] = [ - 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, - 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 1.0, 0.0, + 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0, -1.0, 1.0, + 0.0, ]; - let vertex_shader_source = b" - #version 410 core - layout (location = 0) in vec3 aPos; - - void main() { - gl_Position = vec4(aPos.xyz, 1.0); - } - " - .to_vec(); - - let fragment_shader_source = String::from(format!( - " -#version 410 core -out vec4 FragColor; - -float pa[{sa}] = float[{sa}]({pa}); -float pb[{sb}] = float[{sb}]({pb}); - -float eval_a(float[{sa}] v, float t) {{ - float result = 0.0; - for (int i = 0; i < {sa}; i++) {{ - result += v[i] * pow(t, i); - }} - return result; -}} - -float eval_b(float[{sb}] v, float t) {{ - float result = 0.0; - for (int i = 0; i < {sb}; i++) {{ - result += v[i] * pow(t, i); - }} - return result; -}} - -float inside(vec2 pos) {{ - float res = 100; - float thr = 32; - float closest = 1000000; - float t = 0.0; - while (t < 1.0) {{ - float step = t + 1.0 / res; - vec2 a = vec2(eval_a(pa, t), eval_b(pb, t)); - vec2 b = vec2(eval_a(pa, step), eval_b(pb, step)); - float c = pow(length(a - b), 2); - float d = distance(pos, a + clamp(dot(pos - a, b - a) / c, 0, 1) * (b - a)); - if (d < closest) {{ - closest = d; - }} - t = step; - }} - return 1 - closest / thr; -}} - -void main() {{ - float r = inside(gl_FragCoord.xy); - FragColor = vec4(r * 0.8, r * 0.2, r, 1.0); -}} - ", - sa = a.degree() + 1, - sb = b.degree() + 1, - pa = &a, - pb = &b - )) - .into_bytes(); - let mut vbo: GLuint = 0; let mut vao: GLuint = 0; unsafe { @@ -149,23 +170,7 @@ void main() {{ gl::EnableVertexAttribArray(0); } - let mut shader_program: GLuint = 0; - unsafe { - let vertex_shader = shader_from_source( - &CString::from_vec_unchecked(vertex_shader_source), - gl::VERTEX_SHADER, - ); - let fragment_shader = shader_from_source( - &CString::from_vec_unchecked(fragment_shader_source), - gl::FRAGMENT_SHADER, - ); - shader_program = gl::CreateProgram(); - gl::AttachShader(shader_program, vertex_shader); - gl::AttachShader(shader_program, fragment_shader); - gl::LinkProgram(shader_program); - gl::DeleteShader(vertex_shader); - gl::DeleteShader(fragment_shader); - } + let shader_program = compile_bezier_shader(a, b); let mut event_pump = sdl_context.event_pump().unwrap(); 'running: loop { |