Merge pull request 'new commit for Porting to Glow' (#1) from glowPort into master
Reviewed-on: #1ObjectDef
commit
e363da01b5
|
@ -8,8 +8,8 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
field-offset = "0.3.4"
|
field-offset = "0.3.4"
|
||||||
image = "0.24.5"
|
image = "0.24.5"
|
||||||
gl = "0.14.0"
|
|
||||||
cgmath = "0.18.0"
|
cgmath = "0.18.0"
|
||||||
tobj = "2.0.0"
|
tobj = "2.0.0"
|
||||||
|
glow = "0.12.1"
|
||||||
[dependencies.glfw]
|
[dependencies.glfw]
|
||||||
version = "*"
|
version = "*"
|
||||||
|
|
33
src/main.rs
33
src/main.rs
|
@ -3,10 +3,12 @@ use glfw;
|
||||||
use glfw::{Action, Context, Key};
|
use glfw::{Action, Context, Key};
|
||||||
use cgmath::{Matrix4, vec3, Point3, Deg, perspective};
|
use cgmath::{Matrix4, vec3, Point3, Deg, perspective};
|
||||||
use cgmath::prelude::*;
|
use cgmath::prelude::*;
|
||||||
|
use std::rc::Rc;
|
||||||
const SCR_WIDTH: u32 = 1600;
|
const SCR_WIDTH: u32 = 1600;
|
||||||
const SCR_HEIGHT: u32 = 900;
|
const SCR_HEIGHT: u32 = 900;
|
||||||
const TITLE: &str = "GLFWtest";
|
const TITLE: &str = "GLFWtest";
|
||||||
|
|
||||||
|
use glow::*;
|
||||||
|
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -25,8 +27,8 @@ fn main() {
|
||||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
|
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
|
||||||
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
||||||
glfw.window_hint(glfw::WindowHint::Resizable(false));
|
glfw.window_hint(glfw::WindowHint::Resizable(false));
|
||||||
glfw.window_hint(glfw::WindowHint::TransparentFramebuffer(true));
|
glfw.window_hint(glfw::WindowHint::TransparentFramebuffer(false));
|
||||||
glfw.window_hint(glfw::WindowHint::Decorated(false));
|
glfw.window_hint(glfw::WindowHint::Decorated(true));
|
||||||
|
|
||||||
let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap();
|
let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap();
|
||||||
|
|
||||||
|
@ -54,14 +56,14 @@ fn main() {
|
||||||
let mut deltaTime: f32; // time between current frame and last frame
|
let mut deltaTime: f32; // time between current frame and last frame
|
||||||
let mut lastFrame: f32 = 0.0;
|
let mut lastFrame: f32 = 0.0;
|
||||||
|
|
||||||
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
|
//gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
|
||||||
|
let gl = std::rc::Rc::new(unsafe{glow::Context::from_loader_function(|s| window.get_proc_address(s) as *const _)});
|
||||||
let (ourshader, ourModel) = unsafe {
|
let (ourshader, ourModel) = unsafe {
|
||||||
gl::Enable(gl::DEPTH_TEST);
|
gl.enable(glow::DEPTH_TEST);
|
||||||
|
|
||||||
let ourShader = shader::shader::new("model");
|
let ourShader = shader::shader::new("model", Rc::clone(&gl));
|
||||||
|
|
||||||
let ourModel = model::Model::new("resources/models/TestCarModel/CarW4.obj");
|
let ourModel = model::Model::new("resources/models/TestCarModel/CarW4.obj", Rc::clone(&gl));
|
||||||
|
|
||||||
(ourShader, ourModel)
|
(ourShader, ourModel)
|
||||||
};
|
};
|
||||||
|
@ -71,7 +73,6 @@ fn main() {
|
||||||
let projection: Matrix4<f32> = perspective(Deg(45.0), SCR_WIDTH as f32/ SCR_HEIGHT as f32, 0.1, 100.0);
|
let projection: Matrix4<f32> = perspective(Deg(45.0), SCR_WIDTH as f32/ SCR_HEIGHT as f32, 0.1, 100.0);
|
||||||
println!("entering main loop");
|
println!("entering main loop");
|
||||||
|
|
||||||
unsafe {gl::StencilOp(gl::KEEP, gl::KEEP, gl::REPLACE);}
|
|
||||||
while !window.should_close() {
|
while !window.should_close() {
|
||||||
let currentFrame = glfw.get_time() as f32;
|
let currentFrame = glfw.get_time() as f32;
|
||||||
deltaTime = currentFrame - lastFrame;
|
deltaTime = currentFrame - lastFrame;
|
||||||
|
@ -80,24 +81,23 @@ fn main() {
|
||||||
processInput(&mut window, deltaTime, &mut camera);
|
processInput(&mut window, deltaTime, &mut camera);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::Enable(gl::DEPTH_TEST);
|
gl.enable(glow::DEPTH_TEST);
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
|
gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT);
|
||||||
gl::ClearColor(0.0, 0.0, 0.0, 0.0);
|
|
||||||
|
|
||||||
// outline
|
// outline
|
||||||
|
|
||||||
ourshader.Use();
|
ourshader.Use();
|
||||||
let Projection: Matrix4<f32> = perspective(Deg(camera.Zoom), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0);
|
let Projection: Matrix4<f32> = perspective(Deg(camera.Zoom), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0);
|
||||||
let view = camera.GetViewMatrix();
|
let view = camera.GetViewMatrix();
|
||||||
ourshader.setMat4(&CString::new("projection").unwrap(), &projection);
|
ourshader.setMat4("projection", &projection);
|
||||||
ourshader.setMat4(&CString::new("view").unwrap(), &view);
|
ourshader.setMat4("view", &view);
|
||||||
|
|
||||||
|
|
||||||
//let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -0.3, 0.0));
|
//let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -0.3, 0.0));
|
||||||
let mut model: Matrix4<f32> = Matrix4::from_axis_angle(vec3(0.0, -1.0, 0.0).normalize(),
|
let mut model: Matrix4<f32> = Matrix4::from_axis_angle(vec3(0.0, -1.0, 0.0).normalize(),
|
||||||
cgmath::Rad(glfw.get_time() as f32));
|
cgmath::Rad(glfw.get_time() as f32));
|
||||||
model = model * Matrix4::from_scale(0.2);
|
model = model * Matrix4::from_scale(0.2);
|
||||||
ourshader.setMat4(&CString::new("model").unwrap(), &model);
|
ourshader.setMat4("model", &model);
|
||||||
|
|
||||||
ourModel.Draw(&ourshader);
|
ourModel.Draw(&ourshader);
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>,
|
fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>,
|
||||||
firstMouse: &mut bool,
|
firstMouse: &mut bool,
|
||||||
lastX: &mut f32,
|
lastX: &mut f32,
|
||||||
|
@ -142,7 +142,7 @@ fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>,
|
||||||
glfw::WindowEvent::FramebufferSize(width, height) => {
|
glfw::WindowEvent::FramebufferSize(width, height) => {
|
||||||
// make sure the viewport matches the new window dimensions; note that width and
|
// make sure the viewport matches the new window dimensions; note that width and
|
||||||
// height will be significantly larger than specified on retina displays.
|
// height will be significantly larger than specified on retina displays.
|
||||||
unsafe { gl::Viewport(0, 0, width, height) }
|
unsafe { gl.viewport(0, 0, width, height) }
|
||||||
}
|
}
|
||||||
glfw::WindowEvent::CursorPos(xpos, ypos) => {
|
glfw::WindowEvent::CursorPos(xpos, ypos) => {
|
||||||
let (xpos, ypos) = (xpos as f32, ypos as f32);
|
let (xpos, ypos) = (xpos as f32, ypos as f32);
|
||||||
|
@ -167,3 +167,4 @@ fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
56
src/model.rs
56
src/model.rs
|
@ -3,10 +3,10 @@
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::rc::Rc;
|
||||||
use cgmath::{vec2, vec3};
|
use cgmath::{vec2, vec3};
|
||||||
use gl;
|
|
||||||
use image;
|
use image;
|
||||||
|
use glow::*;
|
||||||
use image::DynamicImage::*;
|
use image::DynamicImage::*;
|
||||||
use image::GenericImage;
|
use image::GenericImage;
|
||||||
use tobj;
|
use tobj;
|
||||||
|
@ -24,20 +24,21 @@ pub struct Model {
|
||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
/// constructor, expects a filepath to a 3D model.
|
/// constructor, expects a filepath to a 3D model.
|
||||||
pub fn new(path: &str) -> Model {
|
pub fn new(path: &str, gl: std::rc::Rc<glow::Context>) -> Model {
|
||||||
let mut model = Model::default();
|
let mut model = Model::default();
|
||||||
model.loadModel(path);
|
model.loadModel(path, Rc::clone(&gl));
|
||||||
model
|
model
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Draw(&self, shader: &shader) {
|
pub fn Draw(&self, shader: &shader) {
|
||||||
for mesh in &self.meshes {
|
for mesh in &self.meshes {
|
||||||
|
|
||||||
unsafe { mesh.Draw(shader); }
|
unsafe { mesh.Draw(shader); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loads a model from file and stores the resulting meshes in the meshes vector.
|
// loads a model from file and stores the resulting meshes in the meshes vector.
|
||||||
fn loadModel(&mut self, path: &str) {
|
fn loadModel(&mut self, path: &str, gl: std::rc::Rc<glow::Context>) {
|
||||||
let path = Path::new(path);
|
let path = Path::new(path);
|
||||||
|
|
||||||
// retrieve the directory path of the filepath
|
// retrieve the directory path of the filepath
|
||||||
|
@ -53,9 +54,6 @@ impl Model {
|
||||||
let mut vertices: Vec<Vertex> = Vec::with_capacity(num_vertices);
|
let mut vertices: Vec<Vertex> = Vec::with_capacity(num_vertices);
|
||||||
let indices: Vec<u32> = mesh.indices.clone();
|
let indices: Vec<u32> = mesh.indices.clone();
|
||||||
|
|
||||||
println!("num vertices = {}", num_vertices);
|
|
||||||
println!("num normals = {}", &mesh.normals.len());
|
|
||||||
println!("num TexCoords = {}", &mesh.texcoords.len());
|
|
||||||
let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords);
|
let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords);
|
||||||
for i in 0..num_vertices {
|
for i in 0..num_vertices {
|
||||||
vertices.push(Vertex {
|
vertices.push(Vertex {
|
||||||
|
@ -73,28 +71,28 @@ impl Model {
|
||||||
|
|
||||||
// 1. diffuse map
|
// 1. diffuse map
|
||||||
if !material.diffuse_texture.is_empty() {
|
if !material.diffuse_texture.is_empty() {
|
||||||
let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse");
|
let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse", Rc::clone(&gl));
|
||||||
textures.push(texture);
|
textures.push(texture);
|
||||||
}
|
}
|
||||||
// 2. specular map
|
// 2. specular map
|
||||||
if !material.specular_texture.is_empty() {
|
if !material.specular_texture.is_empty() {
|
||||||
let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular");
|
let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular", Rc::clone(&gl));
|
||||||
textures.push(texture);
|
textures.push(texture);
|
||||||
}
|
}
|
||||||
// 3. normal map
|
// 3. normal map
|
||||||
if !material.normal_texture.is_empty() {
|
if !material.normal_texture.is_empty() {
|
||||||
let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal");
|
let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal", Rc::clone(&gl));
|
||||||
textures.push(texture);
|
textures.push(texture);
|
||||||
}
|
}
|
||||||
// NOTE: no height maps
|
// NOTE: no height maps
|
||||||
}
|
}
|
||||||
|
|
||||||
self.meshes.push(Mesh::new(vertices, indices, textures));
|
self.meshes.push(Mesh::new(vertices, indices, textures, Rc::clone(&gl)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loadMaterialTexture(&mut self, path: &str, typeName: &str) -> Texture {
|
fn loadMaterialTexture(&mut self, path: &str, typeName: &str, gl: Rc<glow::Context>) -> Texture {
|
||||||
{
|
{
|
||||||
let texture = self.textures_loaded.iter().find(|t| t.path == path);
|
let texture = self.textures_loaded.iter().find(|t| t.path == path);
|
||||||
if let Some(texture) = texture {
|
if let Some(texture) = texture {
|
||||||
|
@ -103,7 +101,7 @@ impl Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
let texture = Texture {
|
let texture = Texture {
|
||||||
id: unsafe { TextureFromFile(path, &self.directory) },
|
id: unsafe { TextureFromFile(path, &self.directory, std::rc::Rc::clone(&gl)) },
|
||||||
type_: typeName.into(),
|
type_: typeName.into(),
|
||||||
path: path.into()
|
path: path.into()
|
||||||
};
|
};
|
||||||
|
@ -112,33 +110,31 @@ impl Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn TextureFromFile(path: &str, directory: &str) -> u32 {
|
unsafe fn TextureFromFile(path: &str, directory: &str, gl: Rc<glow::Context>) -> glow::NativeTexture {
|
||||||
let filename = format!("{}/{}", directory, path);
|
let filename = format!("{}/{}", directory, path);
|
||||||
|
|
||||||
let mut textureID = 0;
|
let mut textureID = gl.create_texture().unwrap();
|
||||||
gl::GenTextures(1, &mut textureID);
|
|
||||||
|
|
||||||
let img = image::open(&Path::new(&filename)).expect("Texture failed to load");
|
let img = image::open(&Path::new(&filename)).expect("Texture failed to load");
|
||||||
let img = img.flipv();
|
let img = img.flipv();
|
||||||
let format = match img {
|
let format = match img {
|
||||||
ImageLuma8(_) => gl::RED,
|
ImageLuma8(_) => glow::RED,
|
||||||
ImageLumaA8(_) => gl::RG,
|
ImageLumaA8(_) => glow::RG,
|
||||||
ImageRgb8(_) => gl::RGB,
|
ImageRgb8(_) => glow::RGB,
|
||||||
ImageRgba8(_) => gl::RGBA,
|
ImageRgba8(_) => glow::RGBA,
|
||||||
_ => panic!("really weird image type"),
|
_ => panic!("really weird image type"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = img.as_bytes();
|
let data = img.as_bytes();
|
||||||
|
|
||||||
gl::BindTexture(gl::TEXTURE_2D, textureID);
|
gl.bind_texture(glow::TEXTURE_2D, Some(textureID));
|
||||||
gl::TexImage2D(gl::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
|
gl.tex_image_2d(glow::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
|
||||||
0, format, gl::UNSIGNED_BYTE, &data[0] as *const u8 as *const c_void);
|
0, format, glow::UNSIGNED_BYTE, Some(&data));
|
||||||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
gl.generate_mipmap(glow::TEXTURE_2D);
|
||||||
|
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
|
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
|
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_T, glow::REPEAT as i32);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR as i32);
|
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::LINEAR_MIPMAP_LINEAR as i32);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
|
gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::LINEAR as i32);
|
||||||
|
|
||||||
textureID
|
textureID
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::ptr;
|
||||||
|
|
||||||
use cgmath::{ Vector3, Vector2 };
|
use cgmath::{ Vector3, Vector2 };
|
||||||
use cgmath::prelude::*;
|
use cgmath::prelude::*;
|
||||||
use gl;
|
use glow::*;
|
||||||
use field_offset::offset_of;
|
use field_offset::offset_of;
|
||||||
|
|
||||||
use crate::shader::shader;
|
use crate::shader::shader;
|
||||||
|
@ -43,7 +43,7 @@ impl Default for Vertex {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Texture {
|
pub struct Texture {
|
||||||
pub id: u32,
|
pub id: glow::NativeTexture,
|
||||||
pub type_: String,
|
pub type_: String,
|
||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
@ -53,22 +53,27 @@ pub struct Mesh {
|
||||||
pub vertices: Vec<Vertex>,
|
pub vertices: Vec<Vertex>,
|
||||||
pub indices: Vec<u32>,
|
pub indices: Vec<u32>,
|
||||||
pub textures: Vec<Texture>,
|
pub textures: Vec<Texture>,
|
||||||
pub VAO: u32,
|
pub VAO: Option<glow::VertexArray>,
|
||||||
|
|
||||||
/* Render data */
|
/* Render data */
|
||||||
VBO: u32,
|
VBO: Option<glow::Buffer>,
|
||||||
EBO: u32,
|
EBO: Option<glow::Buffer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
pub fn new(vertices: Vec<Vertex>, indices: Vec<u32>, textures: Vec<Texture>) -> Mesh {
|
pub fn new(vertices: Vec<Vertex>, indices: Vec<u32>, textures: Vec<Texture>,gl: std::rc::Rc<glow::Context>) -> Mesh {
|
||||||
let mut mesh = Mesh {
|
|
||||||
vertices, indices, textures,
|
|
||||||
VAO: 0, VBO: 0, EBO: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let mut mesh =
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
Mesh {
|
||||||
|
vertices, indices, textures,
|
||||||
|
VAO: None, VBO: None, EBO: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
// now that we have all the required data, set the vertex buffers and its attribute pointers.
|
// now that we have all the required data, set the vertex buffers and its attribute pointers.
|
||||||
unsafe { mesh.setupMesh() }
|
unsafe { mesh.setupMesh(gl) }
|
||||||
mesh
|
mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +85,7 @@ impl Mesh {
|
||||||
let mut normalNr = 0;
|
let mut normalNr = 0;
|
||||||
let mut heightNr = 0;
|
let mut heightNr = 0;
|
||||||
for (i, texture) in self.textures.iter().enumerate() {
|
for (i, texture) in self.textures.iter().enumerate() {
|
||||||
gl::ActiveTexture(gl::TEXTURE0 + i as u32); // active proper texture unit before binding
|
shader.gl.active_texture(glow::TEXTURE0 + i as u32); // active proper texture unit before binding
|
||||||
// retrieve texture number (the N in diffuse_textureN)
|
// retrieve texture number (the N in diffuse_textureN)
|
||||||
let name = &texture.type_;
|
let name = &texture.type_;
|
||||||
let number = match name.as_str() {
|
let number = match name.as_str() {
|
||||||
|
@ -103,60 +108,66 @@ impl Mesh {
|
||||||
_ => panic!("unknown texture type")
|
_ => panic!("unknown texture type")
|
||||||
};
|
};
|
||||||
// now set the sampler to the correct texture unit
|
// now set the sampler to the correct texture unit
|
||||||
let sampler = CString::new(format!("{}{}", name, number)).unwrap();
|
let sampler = format!("{}{}", name, number);
|
||||||
gl::Uniform1i(gl::GetUniformLocation(shader.ID, sampler.as_ptr()), i as i32);
|
shader.setInt(&sampler, i as i32);
|
||||||
|
//shader.gl.uniform_1_i32(shader.gl.get_uniform_location(shader.ID, &sampler).as_ref(), i as i32);
|
||||||
// and finally bind the texture
|
// and finally bind the texture
|
||||||
gl::BindTexture(gl::TEXTURE_2D, texture.id);
|
shader.gl.bind_texture(glow::TEXTURE_2D, Some(texture.id));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw mesh
|
// draw mesh
|
||||||
gl::BindVertexArray(self.VAO);
|
shader.gl.bind_vertex_array(self.VAO);
|
||||||
gl::DrawElements(gl::TRIANGLES, self.indices.len() as i32, gl::UNSIGNED_INT, ptr::null());
|
shader.gl.draw_elements(glow::TRIANGLES, self.indices.len() as i32, glow::UNSIGNED_INT, 0);
|
||||||
gl::BindVertexArray(0);
|
shader.gl.bind_vertex_array(None);
|
||||||
|
|
||||||
// always good practice to set everything back to defaults once configured.
|
// always good practice to set everything back to defaults once configured.
|
||||||
gl::ActiveTexture(gl::TEXTURE0);
|
shader.gl.active_texture(glow::TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn setupMesh(&mut self) {
|
unsafe fn setupMesh(&mut self, gl: std::rc::Rc<glow::Context>) {
|
||||||
|
|
||||||
|
self.VAO = Some(gl.create_vertex_array().unwrap());
|
||||||
|
self.VBO = Some(gl.create_buffer().unwrap());
|
||||||
|
self.EBO = Some(gl.create_buffer().unwrap());
|
||||||
|
|
||||||
|
gl.bind_vertex_array(self.VAO);
|
||||||
// create buffers/arrays
|
// create buffers/arrays
|
||||||
gl::GenVertexArrays(1, &mut self.VAO);
|
gl.bind_buffer(glow::ARRAY_BUFFER, self.VBO);
|
||||||
gl::GenBuffers(1, &mut self.VBO);
|
|
||||||
gl::GenBuffers(1, &mut self.EBO);
|
|
||||||
|
|
||||||
gl::BindVertexArray(self.VAO);
|
println!("vertices.len is: {}", self.vertices.len());
|
||||||
// load data into vertex buffers
|
let data = core::slice::from_raw_parts(
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, self.VBO);
|
self.vertices.as_ptr() as *const u8,
|
||||||
// A great thing about structs with repr(C) is that their memory layout is sequential for all its items.
|
self.vertices.len() * core::mem::size_of::<Vertex>(),
|
||||||
// The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which
|
);
|
||||||
// again translates to 3/2 floats which translates to a byte array.
|
|
||||||
let size = (self.vertices.len() * size_of::<Vertex>()) as isize;
|
|
||||||
let data = &self.vertices[0] as *const Vertex as *const c_void;
|
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, size, data, gl::STATIC_DRAW);
|
|
||||||
|
|
||||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.EBO);
|
gl.named_buffer_data_u8_slice(self.VBO.unwrap(), data, glow::STATIC_DRAW);
|
||||||
let size = (self.indices.len() * size_of::<u32>()) as isize;
|
|
||||||
let data = &self.indices[0] as *const u32 as *const c_void;
|
|
||||||
gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, size, data, gl::STATIC_DRAW);
|
gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, self.EBO);
|
||||||
|
let data = core::slice::from_raw_parts(
|
||||||
|
self.indices.as_ptr() as *const u8,
|
||||||
|
self.indices.len() * core::mem::size_of::<u32>(),
|
||||||
|
);
|
||||||
|
gl.named_buffer_data_u8_slice(self.EBO.unwrap(), data, glow::STATIC_DRAW);
|
||||||
|
|
||||||
// set the vertex attribute pointers
|
// set the vertex attribute pointers
|
||||||
let size = size_of::<Vertex>() as i32;
|
let size = size_of::<Vertex>() as i32;
|
||||||
// vertex Positions
|
// vertex Positions
|
||||||
gl::EnableVertexAttribArray(0);
|
gl.enable_vertex_attrib_array(0);
|
||||||
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Position).get_byte_offset() as *const c_void);
|
gl.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, size, 0);
|
||||||
// vertex normals
|
// vertex normals
|
||||||
gl::EnableVertexAttribArray(1);
|
gl.enable_vertex_attrib_array(1);
|
||||||
gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Normal).get_byte_offset() as *const c_void);
|
gl.vertex_attrib_pointer_f32(1, 3, glow::FLOAT, false, size, 3*4);
|
||||||
// vertex texture coords
|
// vertex texture coords
|
||||||
gl::EnableVertexAttribArray(2);
|
gl.enable_vertex_attrib_array(2);
|
||||||
gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => TexCoords).get_byte_offset() as *const c_void);
|
gl.vertex_attrib_pointer_f32(2, 2, glow::FLOAT, false, size, 6*4);
|
||||||
// vertex tangent
|
// vertex tangent
|
||||||
gl::EnableVertexAttribArray(3);
|
gl.enable_vertex_attrib_array(3);
|
||||||
gl::VertexAttribPointer(3, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Tangent).get_byte_offset() as *const c_void);
|
gl.vertex_attrib_pointer_f32(3, 3, glow::FLOAT, false, size, 8*4);
|
||||||
// vertex bitangent
|
// vertex bitangent
|
||||||
gl::EnableVertexAttribArray(4);
|
gl.enable_vertex_attrib_array(4);
|
||||||
gl::VertexAttribPointer(4, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex => Bitangent).get_byte_offset() as *const c_void);
|
gl.vertex_attrib_pointer_f32(4, 3, glow::FLOAT, false, size, 11*4);
|
||||||
|
|
||||||
gl::BindVertexArray(0);
|
gl.bind_vertex_array(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
165
src/shader.rs
165
src/shader.rs
|
@ -1,14 +1,14 @@
|
||||||
|
|
||||||
use gl;
|
use glow::*;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::ffi::{CString, CStr};
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use cgmath::prelude::*;
|
|
||||||
/// Shader Struct for creating and using shaders in the Context of engine
|
/// Shader Struct for creating and using shaders in the Context of engine
|
||||||
///
|
///
|
||||||
pub struct shader {
|
pub struct shader {
|
||||||
|
|
||||||
pub ID: gl::types::GLuint,
|
pub ID: NativeProgram,
|
||||||
|
pub gl: Rc<glow::Context>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,122 +21,113 @@ use cgmath::prelude::*;
|
||||||
/// `new(String::from("Example"))`
|
/// `new(String::from("Example"))`
|
||||||
/// if the String given was "Example" the Program expects both shaders to be in the directory "resources/shaders/Example/"
|
/// if the String given was "Example" the Program expects both shaders to be in the directory "resources/shaders/Example/"
|
||||||
/// with the vertex shader being called "shader.vert" and fragment "shader.frag"
|
/// with the vertex shader being called "shader.vert" and fragment "shader.frag"
|
||||||
pub fn new(path: &str) -> shader
|
pub fn new(path: &str, gl: Rc<glow::Context>) -> shader
|
||||||
{
|
{
|
||||||
//read file contents
|
//read file contents
|
||||||
let VERT_SHADER = fs::read_to_string(format!("resources/shaders/{path}/shader.vert")).unwrap();
|
let VERT_SHADER = fs::read_to_string(format!("resources/shaders/{path}/shader.vert")).unwrap();
|
||||||
let FRAG_SHADER = std::fs::read_to_string(format!("resources/shaders/{path}/shader.frag")).unwrap();
|
let FRAG_SHADER = fs::read_to_string(format!("resources/shaders/{path}/shader.frag")).unwrap();
|
||||||
|
|
||||||
//create vertex shader
|
//create vertex shader
|
||||||
let vertex_shader = unsafe {gl::CreateShader(gl::VERTEX_SHADER) };
|
let vertex_shader = unsafe {gl.create_shader(glow::VERTEX_SHADER).unwrap() };
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::ShaderSource(vertex_shader, 1, &VERT_SHADER.as_bytes().as_ptr().cast(), &VERT_SHADER.len().try_into().unwrap());
|
gl.shader_source(vertex_shader, &VERT_SHADER);
|
||||||
gl::CompileShader(vertex_shader);
|
gl.compile_shader(vertex_shader);
|
||||||
}
|
|
||||||
//error Checking
|
|
||||||
let mut success = 0;
|
|
||||||
unsafe {
|
|
||||||
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
|
|
||||||
if success == 0 {
|
|
||||||
let mut log_len = 0_i32;
|
|
||||||
|
|
||||||
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
}
|
||||||
gl::GetShaderInfoLog(vertex_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
// create fragment shader
|
||||||
v.set_len(log_len.try_into().unwrap());
|
let fragment_shader = unsafe{gl.create_shader(glow::FRAGMENT_SHADER).unwrap()};
|
||||||
panic!("Vertex Shader Compile Error: {}", String::from_utf8_lossy(&v));
|
unsafe {
|
||||||
|
gl.shader_source(fragment_shader, &FRAG_SHADER);
|
||||||
|
gl.compile_shader(fragment_shader);
|
||||||
|
if !gl.get_shader_compile_status(fragment_shader) {
|
||||||
|
panic!("Error, Compiling Fragment Shader: {}", gl.get_shader_info_log(fragment_shader));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
|
let shader_program = gl.create_program().unwrap();
|
||||||
gl::ShaderSource(fragment_shader, 1, &FRAG_SHADER.as_bytes().as_ptr().cast(), &FRAG_SHADER.len().try_into().unwrap());
|
|
||||||
gl::CompileShader(fragment_shader);
|
|
||||||
|
|
||||||
let mut success = 0;
|
gl.attach_shader(shader_program, vertex_shader);
|
||||||
gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
|
gl.attach_shader(shader_program, fragment_shader);
|
||||||
if success == 0 {
|
gl.link_program(shader_program);
|
||||||
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
if !gl.get_program_link_status(shader_program) {
|
||||||
let mut log_len = 0_i32;
|
panic!("Error, Linking Shader Program {}", gl.get_program_info_log(shader_program));
|
||||||
gl::GetShaderInfoLog(fragment_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
|
||||||
v.set_len(log_len.try_into().unwrap());
|
|
||||||
panic!("Fragment Shader Compile Error: {}", String::from_utf8_lossy(&v));
|
|
||||||
}
|
}
|
||||||
|
gl.detach_shader(shader_program, vertex_shader);
|
||||||
|
gl.detach_shader(shader_program, fragment_shader);
|
||||||
|
gl.delete_shader(vertex_shader);
|
||||||
|
gl.delete_shader(fragment_shader);
|
||||||
|
|
||||||
let shader_program = gl::CreateProgram();
|
|
||||||
|
|
||||||
gl::AttachShader(shader_program, vertex_shader);
|
|
||||||
gl::AttachShader(shader_program, fragment_shader);
|
|
||||||
gl::LinkProgram(shader_program);
|
|
||||||
|
|
||||||
let mut success = 0;
|
|
||||||
gl::GetProgramiv(shader_program, gl::LINK_STATUS, &mut success);
|
|
||||||
if success == 0 {
|
|
||||||
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
|
||||||
let mut log_len = 0_i32;
|
|
||||||
gl::GetProgramInfoLog(shader_program, 1024, &mut log_len, v.as_mut_ptr().cast());
|
|
||||||
v.set_len(log_len.try_into().unwrap());
|
|
||||||
panic!("Program Link Error: {}", String::from_utf8_lossy(&v));
|
|
||||||
}
|
|
||||||
|
|
||||||
gl::DetachShader(shader_program, vertex_shader);
|
|
||||||
gl::DetachShader(shader_program, fragment_shader);
|
|
||||||
gl::DeleteShader(vertex_shader);
|
|
||||||
gl::DeleteShader(fragment_shader);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// return program
|
|
||||||
shader {
|
shader {
|
||||||
ID: shader_program,
|
ID: shader_program,
|
||||||
}
|
gl: Rc::clone(&gl),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return program
|
||||||
|
|
||||||
/// uses Shader
|
/// uses Shader
|
||||||
pub fn Use(&self)
|
pub fn Use(&self)
|
||||||
{
|
{
|
||||||
unsafe {gl::UseProgram(self.ID);}
|
unsafe {self.gl.use_program(Some(self.ID));}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOILERPLATE JUMPSCARE
|
// BOILERPLATE JUMPSCARE
|
||||||
pub fn setBool(&self, name: &CStr, value: bool )
|
/*
|
||||||
{unsafe {gl::Uniform1i(gl::GetUniformLocation(self.ID, name.as_ptr()), value as i32);}}
|
pub fn setBool(&self, name: &str, value: bool )
|
||||||
|
{unsafe {self.gl.uniform_1_bool(self.gl.get_uniform_location(self.ID, name).as_ref(), value);}}
|
||||||
|
*/
|
||||||
|
pub fn setInt(&self, name: &str, value: i32 )
|
||||||
|
{unsafe {self.gl.uniform_1_i32(self.gl.get_uniform_location(self.ID, name).as_ref(), value);}}
|
||||||
|
|
||||||
pub fn setInt(&self, name: &CStr, value: u32 )
|
pub fn setFloat(&self, name: &str, value: f32 )
|
||||||
{unsafe {gl::Uniform1i(gl::GetUniformLocation(self.ID, name.as_ptr()), value as i32);}}
|
{unsafe {self.gl.uniform_1_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), value);}}
|
||||||
|
|
||||||
pub fn setFloat(&self, name: &CStr, value: f32 )
|
pub fn setVector2(&self, name: &str, value: cgmath::Vector2<f32> )
|
||||||
{unsafe {gl::Uniform1f(gl::GetUniformLocation(self.ID, name.as_ptr()), value as f32);}}
|
{unsafe {self.gl.uniform_2_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), value[0], value[1]);}}
|
||||||
|
|
||||||
pub fn setVec2(&self, name: &CStr, value: &cgmath::Vector2<f32> )
|
pub fn setVector2d(&self, name: &str, x: f32, y: f32)
|
||||||
{unsafe {gl::Uniform2fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());}}
|
{unsafe {self.gl.uniform_2_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), x, y);}}
|
||||||
|
|
||||||
pub fn setVector2d(&self, name: &CStr, x: f32, y: f32)
|
pub fn setVector3(&self, name: &str, value: cgmath::Vector3<f32> )
|
||||||
{unsafe {gl::Uniform2f(gl::GetUniformLocation(self.ID, name.as_ptr()), x, y);}}
|
{unsafe {self.gl.uniform_3_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), value[0], value[1], value[2]);}}
|
||||||
|
|
||||||
pub fn setVector3(&self, name: &CStr, value: cgmath::Vector3<f32> )
|
pub fn setVector3d(&self, name: &str, x: f32, y: f32, z: f32 )
|
||||||
{unsafe {gl::Uniform3fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());}}
|
{unsafe {self.gl.uniform_3_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), x, y, z);}}
|
||||||
|
|
||||||
pub fn setVector3d(&self, name: &CStr, x: f32, y: f32, z: f32 )
|
pub fn setVector4(&self, name: &str, value: &cgmath::Vector4<f32> )
|
||||||
{unsafe {gl::Uniform3f(gl::GetUniformLocation(self.ID, name.as_ptr()), x, y, z);}}
|
{unsafe {self.gl.uniform_4_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), value[0], value[1], value[2], value[3]);}}
|
||||||
|
|
||||||
pub fn setVector4(&self, name: &CStr, value: &cgmath::Vector4<f32> )
|
pub fn setVector4d(&self, name: &str, x: f32, y: f32, z: f32, w: f32)
|
||||||
{unsafe {gl::Uniform4fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());}}
|
{unsafe {self.gl.uniform_4_f32(self.gl.get_uniform_location(self.ID, name).as_ref(), x, y, z, w);}}
|
||||||
|
|
||||||
pub fn setVector4d(&self, name: &CStr, x: f32, y: f32, z: f32, w: f32)
|
//pub fn setMat2(&self, name: &str, value: cgmath::Matrix2<f32>)
|
||||||
{unsafe {gl::Uniform4f(gl::GetUniformLocation(self.ID, name.as_ptr()), x, y, z, w);}}
|
|
||||||
|
|
||||||
pub fn setMat2(&self, name: &CStr, value: &cgmath::Matrix2<f32>)
|
pub fn setMat3(&self, name: &str, value: cgmath::Matrix3<f32>)
|
||||||
{unsafe {gl::UniformMatrix2fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, value.as_ptr());}}
|
{
|
||||||
|
let nums = vec![value.x.x, value.x.y, value.x.z,
|
||||||
pub fn setMat3(&self, name: &CStr, value: &cgmath::Matrix3<f32>)
|
value.y.x, value.y.y, value.y.z,
|
||||||
{unsafe {gl::UniformMatrix3fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, value.as_ptr());}}
|
value.z.x, value.z.y, value.z.z];
|
||||||
|
unsafe
|
||||||
pub fn setMat4(&self, name: &CStr, value: &cgmath::Matrix4<f32>)
|
{
|
||||||
{unsafe {gl::UniformMatrix4fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, value.as_ptr());}}
|
self.gl.uniform_matrix_3_f32_slice(self.gl.get_uniform_location(self.ID, name).as_ref(), false, nums.as_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setMat4(&self, name: &str, value: &cgmath::Matrix4<f32>)
|
||||||
|
{
|
||||||
|
let nums = vec![value.x.x, value.x.y, value.x.z, value.x.w,
|
||||||
|
value.y.x, value.y.y, value.y.z, value.y.w,
|
||||||
|
value.z.x, value.z.y, value.z.z, value.z.w,
|
||||||
|
value.w.x, value.w.y, value.w.z, value.w.w];
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
self.gl.uniform_matrix_4_f32_slice(self.gl.get_uniform_location(self.ID, name).as_ref(), false, nums.as_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use glfw;
|
use glfw;
|
||||||
|
|
Loading…
Reference in New Issue