Skip to content

Instantly share code, notes, and snippets.

@newvertex
Created August 5, 2021 12:54
Show Gist options
  • Save newvertex/ac6eda7713b803418645b85e38950308 to your computer and use it in GitHub Desktop.
Save newvertex/ac6eda7713b803418645b85e38950308 to your computer and use it in GitHub Desktop.
Basic triangle in Rust lang with GLFW and OpenGL
use std::convert::TryInto;
use glfw;
use glfw::Context;
use gl;
const WIDTH: u32 = 480;
const HEIGHT: u32 = 320;
const TITLE: &str = "Hello From OpenGL World!";
fn main() {
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
glfw.window_hint(glfw::WindowHint::Resizable(false));
let (mut window, events) = glfw.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap();
let (screen_width, screen_height) = window.get_framebuffer_size();
window.make_current();
window.set_key_polling(true);
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
unsafe {
gl::Viewport(0, 0, screen_width, screen_height);
clear_color(Color(0.4, 0.4, 0.4, 1.0));
}
// -------------------------------------------
const VERT_SHADER: &str = "#version 330 core
layout (location = 0) in vec3 position;
void main()
{
gl_Position = vec4(position, 1.0);
// gl_Position = vec4(position.xyz, 1.0);
// gl_Position = vec4(position.x, position.y, position.z, 1.0);
}";
const FRAG_SHADER: &str = "#version 330 core
out vec4 Color;
void main()
{
Color = vec4(0.9, 0.5, 0.2, 1.0);
}";
let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) };
unsafe {
gl::ShaderSource(vertex_shader, 1, &VERT_SHADER.as_bytes().as_ptr().cast(), &VERT_SHADER.len().try_into().unwrap());
gl::CompileShader(vertex_shader);
let mut success = 0;
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
if success == 0 {
let mut log_len = 0_i32;
// gl::GetShaderiv(vertex_shader, gl::INFO_LOG_LENGTH, &mut log_len);
// let mut v: Vec<u8> = Vec::with_capacity(log_len as usize);
// gl::GetShaderInfoLog(vertex_shader, log_len, &mut log_len, v.as_mut_ptr().cast());
let mut v: Vec<u8> = Vec::with_capacity(1024);
gl::GetShaderInfoLog(vertex_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
v.set_len(log_len.try_into().unwrap());
panic!("Vertex Shader Compile Error: {}", String::from_utf8_lossy(&v));
}
}
let fragment_shader = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) };
unsafe {
gl::ShaderSource(fragment_shader, 1, &FRAG_SHADER.as_bytes().as_ptr().cast(), &FRAG_SHADER.len().try_into().unwrap());
gl::CompileShader(fragment_shader);
let mut success = 0;
gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
if success == 0 {
let mut v: Vec<u8> = Vec::with_capacity(1024);
let mut log_len = 0_i32;
gl::GetShaderInfoLog(fragment_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
v.set_len(log_len.try_into().unwrap());
panic!("Fragment Shader Compile Error: {}", String::from_utf8_lossy(&v));
}
}
let shader_program = unsafe { gl::CreateProgram() };
unsafe {
gl::AttachShader(shader_program, vertex_shader);
gl::AttachShader(shader_program, fragment_shader);
gl::LinkProgram(shader_program);
let mut success = 0;
gl::GetProgramiv(shader_program, gl::LINK_STATUS, &mut success);
if success == 0 {
let mut v: Vec<u8> = Vec::with_capacity(1024);
let mut log_len = 0_i32;
gl::GetProgramInfoLog(shader_program, 1024, &mut log_len, v.as_mut_ptr().cast());
v.set_len(log_len.try_into().unwrap());
panic!("Program Link Error: {}", String::from_utf8_lossy(&v));
}
gl::DetachShader(shader_program, vertex_shader);
gl::DetachShader(shader_program, fragment_shader);
gl::DeleteShader(vertex_shader);
gl::DeleteShader(fragment_shader);
}
let vertecies = [
-0.5f32, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0,
];
let mut vao = 0;
unsafe { gl::GenVertexArrays(1, &mut vao) };
let mut vbo = 0;
unsafe { gl::GenBuffers(1, &mut vbo) };
unsafe {
gl::BindVertexArray(vao);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
gl::BufferData(gl::ARRAY_BUFFER, std::mem::size_of_val(&vertecies) as isize, vertecies.as_ptr().cast(), gl::STATIC_DRAW);
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 3 * std::mem::size_of::<f32>() as i32, 0 as *const _);
gl::EnableVertexAttribArray(0);
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
gl::BindVertexArray(0);
}
// -------------------------------------------
println!("OpenGL version: {}", gl_get_string(gl::VERSION));
println!("GLSL version: {}", gl_get_string(gl::SHADING_LANGUAGE_VERSION));
while !window.should_close() {
glfw.poll_events();
for (_, event) in glfw::flush_messages(&events) {
glfw_handle_event(&mut window, event);
}
clear_color(Color(0.3, 0.4, 0.6, 1.0));
unsafe {
gl::Clear(gl::COLOR_BUFFER_BIT);
}
unsafe {
gl::UseProgram(shader_program);
gl::BindVertexArray(vao);
gl::DrawArrays(gl::TRIANGLES, 0, 3);
gl::BindVertexArray(0);
}
window.swap_buffers();
}
}
pub struct Color(f32, f32, f32, f32);
pub fn clear_color(c: Color) {
unsafe { gl::ClearColor(c.0, c.1, c.2, c.3) }
}
pub fn gl_get_string<'a>(name: gl::types::GLenum) -> &'a str {
let v = unsafe { gl::GetString(name) };
let v: &std::ffi::CStr = unsafe { std::ffi::CStr::from_ptr(v as *const i8) };
v.to_str().unwrap()
}
fn glfw_handle_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
use glfw::WindowEvent as Event;
use glfw::Key;
use glfw::Action;
match event {
Event::Key(Key::Escape, _, Action::Press, _) => {
window.set_should_close(true);
},
_ => {},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment