Created
September 15, 2019 12:44
-
-
Save hikiko/721ae21b01aa90f0d191ad337a0bfb4b to your computer and use it in GitHub Desktop.
my helloworld in Rust (not proud)
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 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