Advertisement
cjburkey01

GLFW

Nov 15th, 2019
435
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 6.06 KB | None | 0 0
  1. #[macro_use]
  2. extern crate render_derive;
  3.  
  4. use crate::render::{Vertex, VertexArray, VertexAttrib};
  5. use gl::types::{GLushort, GLvoid};
  6. use glfw::{
  7.     Action, Context, Glfw, Key, OpenGlProfileHint, SwapInterval, Window, WindowEvent, WindowHint,
  8. };
  9. use render::{Buffer, Shader, ShaderProgram};
  10. use std::ffi::CString;
  11. use std::ops::Deref;
  12. use std::rc::Rc;
  13. use std::sync::mpsc::Receiver;
  14. use std::time::SystemTime;
  15.  
  16. #[allow(clippy::all)]
  17. pub mod gl {
  18.     // Include the generated OpenGL bindings
  19.     include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
  20. }
  21.  
  22. pub mod render;
  23.  
  24. #[derive(Clone)]
  25. pub struct Gl {
  26.     inner: Rc<gl::Gl>,
  27. }
  28.  
  29. impl Gl {
  30.     pub fn load_with<F>(loadfn: F) -> Self
  31.     where
  32.         F: FnMut(&'static str) -> *const GLvoid,
  33.    {
  34.        Self {
  35.            inner: Rc::new(gl::Gl::load_with(loadfn)),
  36.        }
  37.    }
  38. }
  39.  
  40. impl Deref for Gl {
  41.    type Target = gl::Gl;
  42.  
  43.    fn deref(&self) -> &Self::Target {
  44.        &self.inner
  45.    }
  46. }
  47.  
  48. fn main() {
  49.    println!("Hello, world!");
  50.  
  51.    // Initialize GLFW
  52.    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).expect("failed to initialize GLFW");
  53.  
  54.    // Initialize OpenGL window hints
  55.    // Make sure we tell the window to use OpenGL 3.3 Core (and forward
  56.    // compatible)
  57.    glfw.window_hint(WindowHint::ContextVersion(3, 3));
  58.    glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
  59.    glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
  60.  
  61.    // Create the window and the events system
  62.    let (mut window, events) = glfw
  63.        .create_window(300, 300, "Window", glfw::WindowMode::Windowed)
  64.        .expect("failed to create GLFW window");
  65.    window.set_key_polling(true);
  66.  
  67.    // Make the window's context current
  68.     window.make_current();
  69.  
  70.     // Tell OpenGL how to access methods and get an instance of the Gl struct
  71.     let gl = Gl::load_with(|s| window.get_proc_address(s) as *const _);
  72.  
  73.     // Enable V-Sync
  74.     glfw.set_swap_interval(SwapInterval::Sync(1));
  75.  
  76.     // Set the background color
  77.     unsafe {
  78.         gl.ClearColor(0.5f32, 0.5f32, 0.5f32, 1.0f32);
  79.     }
  80.  
  81.     // Start the game loop
  82.     game_loop(glfw, window, events, gl);
  83. }
  84.  
  85. fn game_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, WindowEvent)>, gl: Gl) {
  86.     let mut last_print_time = SystemTime::now();
  87.     let mut frames = 0;
  88.  
  89.     let shader = init_shaders(&gl);
  90.  
  91.     let vao = VertexArray::new(&gl);
  92.     vao.bind();
  93.  
  94.     let mut vbo = Buffer::new(&gl);
  95.     let vertex_data: Vec<Vertex> = vec![
  96.         // Bottom left
  97.         Vertex::new((-0.5, -0.5, 0.0).into(), (1.0, 0.0, 0.0).into()),
  98.         // Top left
  99.         Vertex::new((-0.5, 0.5, 0.0).into(), (1.0, 1.0, 0.0).into()),
  100.         // Top right
  101.         Vertex::new((0.5, 0.5, 0.0).into(), (0.0, 1.0, 0.0).into()),
  102.         // Bottom right
  103.         Vertex::new((0.5, -0.5, 0.0).into(), (0.0, 0.0, 1.0).into()),
  104.     ];
  105.     vbo.buffer(gl::ARRAY_BUFFER, gl::STATIC_DRAW, vertex_data);
  106.     vbo.bind(gl::ARRAY_BUFFER);
  107.     Vertex::setup_attrib_pointer(&gl);
  108.     vbo.unbind(gl::ARRAY_BUFFER);
  109.  
  110.     let mut ebo = Buffer::new(&gl);
  111.     let element_data: Vec<GLushort> = vec![0, 1, 2, 0, 2, 3];
  112.     ebo.buffer(gl::ELEMENT_ARRAY_BUFFER, gl::STATIC_DRAW, element_data);
  113.  
  114.     vao.unbind();
  115.  
  116.     // Keep looping until the user tries to close the window
  117.     while !window.should_close() {
  118.         // Poll for new events and handle all of them
  119.         glfw.poll_events();
  120.         for (_, event) in glfw::flush_messages(&events) {
  121.             println!("{:?}", event);
  122.             handle_window_event(&gl, &mut window, event);
  123.         }
  124.  
  125.         // Update frame counter
  126.         let current_loop_time = SystemTime::now();
  127.         if current_loop_time
  128.             .duration_since(last_print_time)
  129.             .unwrap()
  130.             .as_secs()
  131.             >= 1
  132.         {
  133.             last_print_time = current_loop_time;
  134.             window.set_title(&format!("Citey | {} fps", frames));
  135.             frames = 0;
  136.         }
  137.  
  138.         // Clear the screen
  139.         unsafe {
  140.             gl.Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
  141.         }
  142.  
  143.         // Draw a triangle
  144.         {
  145.             shader.bind();
  146.             vao.bind();
  147.             ebo.bind(gl::ELEMENT_ARRAY_BUFFER);
  148.             unsafe { gl.EnableVertexAttribArray(0) };
  149.             unsafe { gl.EnableVertexAttribArray(1) };
  150.             unsafe { gl.DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_SHORT, std::ptr::null()) };
  151.             unsafe { gl.DisableVertexAttribArray(1) };
  152.             unsafe { gl.DisableVertexAttribArray(0) };
  153.             ebo.unbind(gl::ELEMENT_ARRAY_BUFFER);
  154.             vao.unbind();
  155.             shader.unbind();
  156.         }
  157.  
  158.         // Display changes in the window
  159.         window.swap_buffers();
  160.  
  161.         // Increment frame counter
  162.         frames += 1;
  163.     }
  164. }
  165.  
  166. fn handle_window_event(gl: &Gl, window: &mut glfw::Window, event: glfw::WindowEvent) {
  167.     match event {
  168.         glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => window.set_should_close(true),
  169.         glfw::WindowEvent::FramebufferSize(w, h) => unsafe { gl.Viewport(0, 0, w, h) },
  170.         _ => {}
  171.     }
  172. }
  173.  
  174. fn init_shaders(gl: &Gl) -> ShaderProgram {
  175.     const VERT_SHADER: &str =
  176.         "#version 330 core\n\nlayout(location = 0) in vec3 vertPos;\nlayout(location = 1) in vec3 color;\n\nout vec3 vertColor;\n\nvoid main() {\n\tgl_Position = vec4(vertPos, 1.0);\n\tvertColor = color;\n}\n";
  177.     const FRAG_SHADER: &str =
  178.         "#version 330 core\n\nin vec3 vertColor;\n\nout vec4 fragColor;\n\nvoid main() {\n\tfragColor = vec4(vertColor, 1.0);\n}\n";
  179.  
  180.     let vert_shader =
  181.         Shader::new_from_source(&gl, gl::VERTEX_SHADER, &CString::new(VERT_SHADER).unwrap())
  182.             .expect("failed to compile vertex shader");
  183.     let frag_shader = Shader::new_from_source(
  184.         &gl,
  185.         gl::FRAGMENT_SHADER,
  186.         &CString::new(FRAG_SHADER).unwrap(),
  187.     )
  188.     .expect("failed to compile fragment shader");
  189.  
  190.     ShaderProgram::new_from_shaders(&gl, vec![vert_shader, frag_shader])
  191.         .expect("failed to link shader program")
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement