♻️ Extract texture.rs and add forgotten shader.rs

main
_ 2020-02-16 23:07:32 +00:00
parent 593784917e
commit 358e139c9c
3 changed files with 201 additions and 25 deletions

View File

@ -12,10 +12,12 @@ use std::time::{Duration};
mod iqm; mod iqm;
mod shader; mod shader;
mod texture;
mod timestep; mod timestep;
use iqm::Model; use iqm::Model;
use shader::{ShaderProgram, ShaderObject}; use shader::{ShaderProgram, ShaderObject};
use texture::Texture;
use timestep::TimeStep; use timestep::TimeStep;
pub fn load_small_file <P> (name: P) -> Vec <u8> pub fn load_small_file <P> (name: P) -> Vec <u8>
@ -47,30 +49,6 @@ where V: Into <Vec3>
)) ))
} }
pub fn ugly_load_texture <P> (name: P) -> u32
where P: AsRef <Path>
{
let decoder = png::Decoder::new (File::open (name).unwrap ());
let (info, mut reader) = decoder.read_info ().unwrap ();
// Allocate the output buffer.
let mut buf = vec! [0; info.buffer_size ()];
// Read the next frame. Currently this function should only called once.
// The default options
reader.next_frame (&mut buf).unwrap ();
unsafe {
gl::BindTexture (gl::TEXTURE_2D, 1);
gl::TexImage2D (gl::TEXTURE_2D, 0, gl::RGBA.try_into ().unwrap (), 1024, 1024, 0, gl::RGBA, gl::UNSIGNED_BYTE, &buf [0] as *const u8 as *const c_void);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
}
1
}
const VERT_SHADER_SRC: &str = const VERT_SHADER_SRC: &str =
" "
#define lowp #define lowp
@ -304,7 +282,8 @@ fn main () {
}) })
.collect (); .collect ();
let texture = ugly_load_texture ("sky.png"); let texture = Texture::from_file ("sky.png");
texture.bind ();
let model_data = load_small_file ("pumpking.iqm"); let model_data = load_small_file ("pumpking.iqm");
let model = Model::from_slice (&model_data [..]); let model = Model::from_slice (&model_data [..]);

133
src/shader.rs Normal file
View File

@ -0,0 +1,133 @@
use std::convert::TryInto;
use std::ffi::CStr;
pub struct ShaderObject {
id: u32,
}
impl ShaderObject {
pub fn id (&self) -> u32 {
self.id
}
pub fn new (shader_type: u32, source: &str) -> Result <ShaderObject, String>
{
let id = unsafe {
gl::CreateShader (shader_type)
};
let sources = [
source.as_ptr () as *const i8,
];
let lengths = [
source.len ().try_into ().unwrap (),
];
let success = unsafe {
gl::ShaderSource (id, sources.len ().try_into ().unwrap (), sources.as_ptr (), lengths.as_ptr ());
gl::CompileShader (id);
let mut success = 0;
gl::GetShaderiv (id, gl::COMPILE_STATUS, &mut success);
success == 1
};
if success {
Ok (ShaderObject {
id,
})
}
else {
let mut info_log = vec! [0u8; 4096];
let mut log_length = 0;
unsafe {
gl::GetShaderInfoLog (id, (info_log.len () - 1).try_into ().unwrap (), &mut log_length, info_log.as_mut_ptr () as *mut i8);
}
info_log.truncate (log_length.try_into ().unwrap ());
let info = String::from_utf8 (info_log).unwrap ();
Err (info)
}
}
}
impl Drop for ShaderObject {
fn drop (&mut self) {
unsafe {
gl::DeleteShader (self.id);
}
}
}
pub struct ShaderProgram {
id: u32,
}
impl ShaderProgram {
pub fn new (vert: &ShaderObject, frag: &ShaderObject)
-> Result <ShaderProgram, String>
{
let id = unsafe {
gl::CreateProgram ()
};
unsafe {
gl::AttachShader (id, vert.id ());
gl::AttachShader (id, frag.id ());
gl::LinkProgram (id);
}
let success = unsafe {
let mut success = 0;
gl::GetProgramiv (id, gl::LINK_STATUS, &mut success);
success == 1
};
if success {
Ok (ShaderProgram {
id,
})
}
else {
let mut info_log = vec! [0u8; 4096];
let mut log_length = 0;
unsafe {
gl::GetProgramInfoLog (id, (info_log.len () - 1).try_into ().unwrap (), &mut log_length, info_log.as_mut_ptr () as *mut i8);
}
info_log.truncate (log_length.try_into ().unwrap ());
let info = String::from_utf8 (info_log).unwrap ();
Err (info)
}
}
pub fn get_uniform_location (&self, name: &CStr) -> i32 {
unsafe {
gl::UseProgram (self.id);
gl::GetUniformLocation (self.id, name.as_ptr ())
}
}
pub fn get_attribute_location (&self, name: &CStr) -> i32 {
unsafe {
gl::UseProgram (self.id);
gl::GetAttribLocation (self.id, name.as_ptr ())
}
}
}
impl Drop for ShaderProgram {
fn drop (&mut self) {
unsafe {
gl::DeleteProgram (self.id);
}
}
}

64
src/texture.rs Normal file
View File

@ -0,0 +1,64 @@
use std::convert::TryInto;
use std::ffi::c_void;
use std::fs::File;
use std::path::Path;
pub struct Texture {
id: u32,
}
impl Texture {
pub fn from_file <P> (name: P) -> Texture
where P: AsRef <Path>
{
let decoder = png::Decoder::new (File::open (name).unwrap ());
let (info, mut reader) = decoder.read_info ().unwrap ();
// Allocate the output buffer.
let mut buf = vec! [0; info.buffer_size ()];
// Read the next frame. Currently this function should only called once.
// The default options
reader.next_frame (&mut buf).unwrap ();
let id = unsafe {
let mut id = 0;
gl::GenTextures (1, &mut id);
assert! (id != 0);
gl::BindTexture (gl::TEXTURE_2D, id);
gl::TexImage2D (gl::TEXTURE_2D, 0, gl::RGBA.try_into ().unwrap (), 1024, 1024, 0, gl::RGBA, gl::UNSIGNED_BYTE, &buf [0] as *const u8 as *const c_void);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
gl::TexParameteri (gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
id
};
Texture {
id,
}
}
pub fn bind (&self) {
unsafe {
gl::BindTexture (gl::TEXTURE_2D, self.id);
}
}
}
impl Drop for Texture {
fn drop (&mut self)
{
if self.id == 0 {
return;
}
unsafe {
gl::DeleteTextures (1, &mut self.id);
}
self.id = 0;
}
}