Created
May 25, 2022 05:06
-
-
Save arthurmco/f8fb35675e21b197b75ff46760ccb001 to your computer and use it in GitHub Desktop.
Rust template for a running OpenGL program
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate gl_generator; | |
use gl_generator::{Api, Fallbacks, GlobalGenerator, Profile, Registry}; | |
use std::env; | |
use std::fs::File; | |
use std::path::Path; | |
fn main() { | |
let dest = env::var("OUT_DIR").unwrap(); | |
let mut file = File::create(&Path::new(&dest).join("bindings.rs")).unwrap(); | |
Registry::new(Api::Gl, (3, 2), Profile::Core, Fallbacks::All, []) | |
.write_bindings(GlobalGenerator, &mut file) | |
.unwrap(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "async-gl-test" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
build = "build.rs" | |
[dependencies] | |
sdl2 = "0.35.2" | |
[build-dependencies] | |
gl_generator = "0.14.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// run with export LIBRARY_PATH=$LIBRARY_PATH:/opt/homebrew/lib | |
use sdl2::event::Event; | |
use sdl2::video::GLProfile; | |
use std::ffi::c_void; | |
use std::mem; | |
type ShaderHandle = u32; | |
mod gl { | |
include!(concat!(env!("OUT_DIR"), "/bindings.rs")); | |
#[derive(Debug)] | |
pub enum APIError { | |
NoError, | |
GLInvalidEnum, | |
GLInvalidValue, | |
GLInvalidOperation, | |
Unknown(u32), | |
} | |
impl From<u32> for APIError { | |
fn from(v: u32) -> Self { | |
match v { | |
0x0 => APIError::NoError, | |
0x500 => APIError::GLInvalidEnum, | |
0x501 => APIError::GLInvalidValue, | |
0x502 => APIError::GLInvalidOperation, | |
v => APIError::Unknown(v), | |
} | |
} | |
} | |
} | |
#[derive(Debug, Copy, Clone)] | |
enum ShaderType { | |
Vertex, | |
Fragment, | |
} | |
fn compile_shader(stype: ShaderType, source: &str) -> Result<ShaderHandle, String> { | |
let mut shader = unsafe { | |
gl::CreateShader(match stype { | |
ShaderType::Vertex => gl::VERTEX_SHADER, | |
ShaderType::Fragment => gl::FRAGMENT_SHADER, | |
}) | |
}; | |
unsafe { | |
if gl::GetError() != 0 { | |
return Err(String::from("Could not create shader handle")); | |
} | |
let source_lens = [source.as_bytes().len() as i32]; | |
gl::ShaderSource( | |
shader, | |
1, | |
&(source.as_bytes().as_ptr() as *const i8), | |
source_lens.as_ptr() as *const i32, | |
); | |
if gl::GetError() != 0 { | |
return Err(String::from("Could not set shader source")); | |
} | |
gl::CompileShader(shader); | |
} | |
let mut res = gl::FALSE as i32; | |
let mut logsize = 0; | |
unsafe { | |
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut res); | |
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut logsize); | |
} | |
if res != gl::TRUE as i32 && logsize > 0 { | |
let mut logdata = vec![0 as u8; logsize as usize + 1]; | |
unsafe { | |
gl::GetShaderInfoLog( | |
shader, | |
logsize, | |
0 as *mut i32, | |
logdata.as_mut_ptr() as *mut i8, | |
); | |
} | |
return Err(format!( | |
"shader {} ({:?}) failed to compile: {}", | |
shader, | |
stype, | |
String::from_utf8_lossy(&logdata) | |
)); | |
} | |
Ok(shader) | |
} | |
fn main() { | |
println!("Hello, world!"); | |
let ctxt = sdl2::init().unwrap(); | |
let video = ctxt.video().unwrap(); | |
video.gl_attr().set_context_major_version(3); | |
video.gl_attr().set_context_minor_version(2); | |
video.gl_attr().set_red_size(8); | |
video.gl_attr().set_green_size(8); | |
video.gl_attr().set_blue_size(8); | |
video.gl_attr().set_alpha_size(8); | |
video.gl_attr().set_context_profile(GLProfile::Core); | |
video.gl_attr().set_accelerated_visual(true); | |
println!("{:?}", video.gl_attr().context_major_version()); | |
let mut window = video | |
.window("test", 800, 600) | |
.position_centered() | |
.opengl() | |
.build() | |
.unwrap(); | |
window.show(); | |
// This variable lifetime represents the lifetime of which you are able | |
// to do gl calls | |
// | |
// When this is dropped, the context will be destroyed. | |
let _glctxt = window.gl_create_context().unwrap(); | |
gl::load_with(|s| video.gl_get_proc_address(s) as *const _); | |
let coords = vec![-1.0 as f32, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, -1.0, 1.0]; | |
let coordsize = coords.len() * mem::size_of::<f32>(); | |
let mut vertbuf = 0; | |
let mut vertvao = 0; | |
unsafe { | |
gl::GenVertexArrays(1, &mut vertvao); | |
gl::BindVertexArray(vertvao); | |
println!("a {:?}", gl::APIError::from(gl::GetError())); | |
gl::GenBuffers(1, &mut vertbuf); | |
println!("g {:?}", gl::APIError::from(gl::GetError())); | |
gl::BindBuffer(gl::ARRAY_BUFFER, vertbuf); | |
println!("b {:?}", gl::APIError::from(gl::GetError())); | |
gl::BufferData( | |
gl::ARRAY_BUFFER, | |
coordsize as isize, | |
coords.as_ptr() as *const c_void, | |
gl::STATIC_DRAW, | |
); | |
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 1, 0 as *const c_void); | |
gl::EnableVertexAttribArray(0); | |
gl::BindVertexArray(0); | |
gl::BindBuffer(gl::ARRAY_BUFFER, 0); | |
println!("d {:?}", gl::APIError::from(gl::GetError())); | |
} | |
let mut sprogram = 0; | |
let mut vshader = compile_shader( | |
ShaderType::Vertex, | |
"#version 150\n\nin vec3 pos;\nvoid main() { gl_Position = vec4(pos, 1.0); }\n", | |
) | |
.unwrap(); | |
let mut fshader = compile_shader( | |
ShaderType::Fragment, | |
"#version 150\n\nout vec3 color;\nvoid main() { color = vec3(1.0, 1.0, 1.0); }\n", | |
) | |
.unwrap(); | |
unsafe { | |
sprogram = gl::CreateProgram(); | |
gl::AttachShader(sprogram, vshader); | |
gl::AttachShader(sprogram, fshader); | |
println!("allshader {:?}", gl::APIError::from(gl::GetError())); | |
gl::LinkProgram(sprogram); | |
println!("allshader {:?}", gl::APIError::from(gl::GetError())); | |
let mut res = gl::FALSE as i32; | |
let mut logsize = 0; | |
gl::GetProgramiv(sprogram, gl::COMPILE_STATUS, &mut res); | |
gl::GetProgramiv(sprogram, gl::INFO_LOG_LENGTH, &mut logsize); | |
if res != gl::TRUE as i32 && logsize > 0 { | |
let mut logdata = vec![0 as u8; logsize as usize + 1]; | |
gl::GetProgramInfoLog( | |
sprogram, | |
logsize, | |
0 as *mut i32, | |
logdata.as_mut_ptr() as *mut i8, | |
); | |
println!( | |
"sprogram {} failed to compile: {}", | |
sprogram, | |
String::from_utf8_lossy(&logdata) | |
); | |
} else { | |
println!("ok {} {}", res, logsize); | |
} | |
} | |
let mut event_pump = ctxt.event_pump().unwrap(); | |
let mut i = 0.001; | |
let mut forward = true; | |
'run: loop { | |
for event in event_pump.poll_iter() { | |
//println!("{:?}", event); | |
match event { | |
Event::Quit { .. } => break 'run, | |
_ => continue, | |
} | |
} | |
unsafe { | |
let _ = gl::GetError(); | |
gl::ClearColor(1.0, i, 0.0, 1.0); | |
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); | |
// println!("allshader {:?}", gl::APIError::from(gl::GetError())); | |
gl::UseProgram(sprogram); | |
gl::BindVertexArray(vertvao); | |
gl::BindBuffer(gl::ARRAY_BUFFER, vertbuf); | |
gl::EnableVertexAttribArray(0); | |
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 0, 0 as *const c_void); | |
gl::ValidateProgram(sprogram); | |
let mut res = gl::FALSE as i32; | |
gl::GetProgramiv(sprogram, gl::VALIDATE_STATUS, &mut res); | |
if res == gl::FALSE as i32 { | |
panic!("Program is not valid!"); | |
} | |
gl::DrawArrays(gl::TRIANGLES, 0, 3); //coords.len() as i32); | |
} | |
i += if forward { 0.002 } else { -0.002 }; | |
if i > 1.0 { | |
forward = false; | |
} | |
if i <= 0.0 { | |
forward = true; | |
} | |
window.gl_swap_window(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment