gl-struct 0.0.1

Safe but transparent wrappers for the OpenGL API


#![recursion_limit="512"]

extern crate gl_struct;
extern crate glfw;
extern crate gl;
extern crate rand;

use gl_struct::*;
use gl_struct::glsl_type::*;

// use std::f32::consts::PI;

glsl!{$

    pub mod ParticleShader {
        @Vertex
            #version 140
            attribute vec4 pos;
            out float distance;
            void main() {
                distance = length(pos.xy);
                gl_Position = pos;
            }

        @Fragment
            #version 140
            in float distance;
            void main() {
                gl_FragColor = vec4(1, 1-distance, 0, 1);
            }

    }

    pub mod ParticleUpdator {

        @Compute

            #version 440

            layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;

            layout(std430) buffer Positions {
                vec4 pos[];
            };



            void main() {
                const float dt = 0.001;
                // const float dt = 0.00025;
                const mat2 rot = mat2(vec2(0,1), vec2(-1,0));
                vec2 yn = pos[gl_GlobalInvocationID.x].xy;

                vec2 k1 = dt * normalize(rot * (yn));
                vec2 k2 = dt * normalize(rot * (yn + k1/2.0));
                vec2 k3 = dt * normalize(rot * (yn + k2/2.0));
                vec2 k4 = dt * normalize(rot * (yn + k3));

                // pos[gl_GlobalInvocationID.x].xy += k1;
                // pos[gl_GlobalInvocationID.x].xy += k2;
                pos[gl_GlobalInvocationID.x].xy += (k1 + 2*k2 + 2*k3 + k4) / 6;
            }

    }

}


fn main() {

    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    let width = 640;
    let height = 480;

    let mut window = glfw.create_window(width, height, "Compute test", glfw::WindowMode::Windowed).unwrap().0;

    glfw::Context::make_current(&mut window);
    window.set_key_polling(true);
    glfw.set_swap_interval(glfw::SwapInterval::Adaptive);

    let gl_provider = unsafe {
        GLProvider::load(|s| ::std::mem::transmute(glfw.get_proc_address_raw(s)))
    };
    let mut context = Context::init(&gl_provider);
    let shader = ParticleShader::init(&gl_provider).unwrap();
    let computer = ParticleUpdator::init(&gl_provider).unwrap();

    let num = 20000;
    let mut points = Vec::with_capacity(num);
    for _i in 0..num {
        points.push([rand::random::<f32>() * 2.0 - 1.0, rand::random::<f32>() * 2.0 - 1.0, 0.0, 1.0].into());
    }
    let mut particles: Buffer<[vec4], _> = Buffer::immut_from(&gl_provider, points.into_boxed_slice());

    unsafe {
        let (w, h) = (width as i32, height as i32);
        if w > h {
            gl::Viewport((w-h)/2,0,h,h);
        } else {
            gl::Viewport(0,(h-w)/2,w,w);
        }
        gl::Disable(gl::CULL_FACE);
        gl::Disable(gl::DEPTH_TEST);
        gl::Disable(gl::BLEND);
    }

    while !window.should_close() {
        // let start = ::std::time::Instant::now();

        glfw::Context::swap_buffers(&mut window);
        glfw.poll_events();

        unsafe {
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
            gl::ClearColor(1.0,1.0,1.0,0.0);
        }

        let p = particles.len();

        computer.compute(p as u32, 1, 1, &mut particles);
        shader.draw(&mut context, DrawMode::Points, p, Attribute::Array(particles.as_attrib_array()));

        // ::std::thread::sleep(::std::time::Duration::from_millis(300));

        // println!("{:?}", ::std::time::Instant::now() - start);

    }



}