♻️ Extract texture.rs and add forgotten shader.rs
parent
593784917e
commit
358e139c9c
29
src/main.rs
29
src/main.rs
|
@ -12,10 +12,12 @@ use std::time::{Duration};
|
|||
|
||||
mod iqm;
|
||||
mod shader;
|
||||
mod texture;
|
||||
mod timestep;
|
||||
|
||||
use iqm::Model;
|
||||
use shader::{ShaderProgram, ShaderObject};
|
||||
use texture::Texture;
|
||||
use timestep::TimeStep;
|
||||
|
||||
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 =
|
||||
"
|
||||
#define lowp
|
||||
|
@ -304,7 +282,8 @@ fn main () {
|
|||
})
|
||||
.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 = Model::from_slice (&model_data [..]);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue