Skip to content

Instantly share code, notes, and snippets.

@hikiko
Created September 15, 2019 12:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hikiko/721ae21b01aa90f0d191ad337a0bfb4b to your computer and use it in GitHub Desktop.
Save hikiko/721ae21b01aa90f0d191ad337a0bfb4b to your computer and use it in GitHub Desktop.
my helloworld in Rust (not proud)
extern crate sdl2;
extern crate gl;
extern crate image;
use sdl2::video::GLProfile;
use gl::types::*;
use image::GenericImageView;
static WIN_W : u32 = 800;
static WIN_H : u32 = 800;
static VERTEX_DATA : [GLfloat; 12] = [
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5,
-0.5, -0.5,
0.5, 0.5,
-0.5, 0.5
];
static TEX_DATA : [GLfloat; 12] = [
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 1.0,
1.0, 0.0,
0.0, 0.0
];
static NUM_VERTICES : GLint = 6;
static VERTEX_LOC : u32 = 0;
static TEX_LOC : u32 = 1;
static VS : &'static str =
"#version 130\n\
in vec4 pos;\n\
in vec2 in_tex_coord;\n\
out vec2 tex_coord;\n\
void main() {\n\
gl_Position = pos;\n\
tex_coord = in_tex_coord;\n\
}";
static FS : &'static str =
"#version 130\n\
uniform sampler2D tex;\n\
in vec2 tex_coord;\n\
out vec4 color;\n\
void main() {\n\
color = texture2D(tex, tex_coord);\n\
}";
fn compile_sdr(src: &str, stage:GLenum) -> GLuint {
let shader;
unsafe {
shader = gl::CreateShader(stage);
let s = std::ffi::CString::new(src).expect("CString::new failed");;
gl::ShaderSource(shader, 1, &s.as_ptr(), std::ptr::null());
gl::CompileShader(shader);
// status
let mut status = gl::FALSE as GLint;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
// error handling
if status != (gl::TRUE as GLint) {
let mut len = 0;
gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
let mut buf: Vec<u8> = Vec::with_capacity((len + 1) as usize);
buf.extend([b' '].iter().cycle().take(len as usize));
let err: std::ffi::CString = std::ffi::CString::from_vec_unchecked(buf);
gl::GetShaderInfoLog(shader, len, std::ptr::null_mut(),
err.as_ptr() as *mut GLchar);
println!("{}", err.to_str().unwrap());
}
}
shader
}
fn link_sdr_prog(vs: GLuint, fs: GLuint) -> GLuint {
unsafe {
let sdr_prog = gl::CreateProgram();
gl::AttachShader(sdr_prog, vs);
gl::AttachShader(sdr_prog, fs);
gl::LinkProgram(sdr_prog);
let mut status = gl::FALSE as GLint;
gl::GetProgramiv(sdr_prog, gl::LINK_STATUS, &mut status);
if status != (gl::TRUE as GLint) {
let mut len: GLint = 0;
gl::GetProgramiv(sdr_prog, gl::INFO_LOG_LENGTH, &mut len);
let mut buf: Vec<u8> = Vec::with_capacity((len + 1) as usize);
buf.extend([b' '].iter().cycle().take(len as usize));
let err: std::ffi::CString = std::ffi::CString::from_vec_unchecked(buf);
gl::GetProgramInfoLog(sdr_prog, len, std::ptr::null_mut(), err.as_ptr() as *mut GLchar);
println!("{}", err.to_str().unwrap());
}
sdr_prog
}
}
fn gen_tex(fname : String, _id : &mut GLuint) {
let img : image::DynamicImage = image::open(&std::path::Path::new(&fname)).ok().expect("Can't open image.\n");
let (_w, _h) = img.dimensions();
unsafe {
gl::GenTextures(1, _id);
gl::BindTexture(gl::TEXTURE_2D, *_id);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32,
_w as i32, _h as i32, 0,
gl::RGBA, gl::UNSIGNED_BYTE,
img.to_rgba().into_raw().as_ptr() as *const std::ffi::c_void);
gl::BindTexture(gl::TEXTURE_2D, 0);
}
}
fn main() {
//TODO FIXME init
let sdl_ctx = sdl2::init().unwrap();
let vid_sys = sdl_ctx.video().unwrap();
let gl_attr = vid_sys.gl_attr();
gl_attr.set_context_profile(GLProfile::Core);
let win = vid_sys
.window("foobar", WIN_W, WIN_H)
.opengl() // add opengl flag
.resizable()
.build()
.unwrap();
let _gl_ctx = win.gl_create_context().unwrap();
let _gl = gl::load_with(|s| vid_sys.gl_get_proc_address(s) as
*const std::os::raw::c_void);
let mut vao = 1;
let mut vbo_pos = 1;
let mut vbo_tex = 2;
let sprog;
let fs;
let vs;
let mut tex_igalia : GLuint = 1;
let mut tex_guadec : GLuint = 2;
let mut tex_sel = tex_igalia;
let mut uloc_stex : GLint = -1;
gen_tex("data/igalia.png".to_string(), &mut tex_igalia);
gen_tex("data/guadec.png".to_string(), &mut tex_guadec);
unsafe {
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
gl::Enable(gl::BLEND);
gl::BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
gl::GenVertexArrays(1, &mut vao);
gl::BindVertexArray(vao);
gl::GenBuffers(1, &mut vbo_pos);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo_pos);
gl::BufferData(gl::ARRAY_BUFFER, (VERTEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
std::mem::transmute(&VERTEX_DATA[0]),
gl::STATIC_DRAW);
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
gl::GenBuffers(1, &mut vbo_tex);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo_tex);
gl::BufferData(gl::ARRAY_BUFFER, (TEX_DATA.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
std::mem::transmute(&TEX_DATA[0]),
gl::STATIC_DRAW);
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
vs = compile_sdr(VS, gl::VERTEX_SHADER);
fs = compile_sdr(FS, gl::FRAGMENT_SHADER);
sprog = link_sdr_prog(vs, fs);
gl::UseProgram(sprog);
}
let mut event_pump = sdl_ctx.event_pump().unwrap();
'main: loop {
for event in event_pump.poll_iter() {
// handle user input here
match event {
sdl2::event::Event::Quit {..} |
sdl2::event::Event::KeyDown {keycode:
Some(sdl2::keyboard::Keycode::Escape), ..} =>
break 'main,
sdl2::event::Event::KeyDown {keycode:
Some(sdl2::keyboard::Keycode::I), ..} =>
tex_sel = tex_igalia,
sdl2::event::Event::KeyDown {keycode:
Some(sdl2::keyboard::Keycode::G), ..} =>
tex_sel = tex_guadec,
_ => {},
}
}
//TODO FIXME: display
unsafe {
let uni_str = std::ffi::CString::new("tex").unwrap();
uloc_stex = gl::GetUniformLocation(sprog, uni_str.as_ptr());
if uloc_stex > -1 {
gl::Uniform1i(uloc_stex, tex_sel as i32);
}
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::Viewport(0, 0, WIN_W as i32, WIN_H as i32);
/* pos */
gl::EnableVertexAttribArray(VERTEX_LOC);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo_pos);
gl::VertexAttribPointer(VERTEX_LOC, 2,
gl::FLOAT, gl::FALSE,
0 as i32, std::ptr::null());
/* tex coords */
gl::EnableVertexAttribArray(TEX_LOC);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo_tex);
gl::VertexAttribPointer(TEX_LOC, 2,
gl::FLOAT, gl::FALSE,
0 as i32, std::ptr::null());
gl::ActiveTexture(gl::TEXTURE0 + tex_sel);
gl::BindTexture(gl::TEXTURE_2D, tex_sel);
gl::DrawArrays(gl::TRIANGLES, 0, NUM_VERTICES);
}
win.gl_swap_window();
}
//TODO FIXME: cleanup
unsafe {
gl::DeleteProgram(sprog);
gl::DeleteShader(vs);
gl::DeleteShader(fs);
gl::DeleteBuffers(1, &vbo_pos);
gl::DeleteBuffers(1, &vbo_tex);
gl::DeleteVertexArrays(1, &vao);
gl::DeleteTextures(1, &tex_igalia);
gl::DeleteTextures(1, &tex_guadec);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment