mirror of https://github.com/Leinnan/doppler.git
Transformations
This commit is contained in:
parent
4b606801ae
commit
1b4f2793ce
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// settings
|
||||
pub const SCR_WIDTH: u32 = 1280;
|
||||
pub const SCR_HEIGHT: u32 = 720;
|
||||
|
|
@ -6,15 +5,31 @@ pub const SCR_HEIGHT: u32 = 720;
|
|||
pub const VERTEX_SHADER_SRC: &str = r#"
|
||||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos;
|
||||
void main() {
|
||||
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
|
||||
layout (location = 1) in vec2 aTexCoord;
|
||||
|
||||
out vec2 TexCoord;
|
||||
|
||||
uniform mat4 transform;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = transform * vec4(aPos, 1.0);
|
||||
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
|
||||
}
|
||||
"#;
|
||||
|
||||
pub const FRAGMENT_SHADER_SRC: &str = r#"
|
||||
#version 330 core
|
||||
out vec4 FragColor;
|
||||
void main() {
|
||||
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
|
||||
|
||||
in vec3 ourColor;
|
||||
in vec2 TexCoord;
|
||||
|
||||
// texture sampler
|
||||
uniform sampler2D texture1;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(texture1, TexCoord);
|
||||
}
|
||||
"#;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#![macro_use]
|
||||
|
||||
/// Macro to get c strings from literals without runtime overhead
|
||||
/// Literal must not contain any interior nul bytes!
|
||||
macro_rules! c_str {
|
||||
($literal:expr) => {
|
||||
std::ffi::CStr::from_bytes_with_nul_unchecked(concat!($literal, "\0").as_bytes())
|
||||
};
|
||||
}
|
||||
|
||||
/// Get offset to struct member, similar to `offset_of` in C/C++
|
||||
/// From https://stackoverflow.com/questions/40310483/how-to-get-pointer-offset-in-bytes/40310851#40310851
|
||||
macro_rules! offset_of {
|
||||
($ty:ty, $field:ident) => {
|
||||
&(*(ptr::null() as *const $ty)).$field as *const _ as usize
|
||||
};
|
||||
}
|
||||
149
src/main.rs
149
src/main.rs
|
|
@ -1,17 +1,26 @@
|
|||
extern crate glfw;
|
||||
use self::glfw::{Context, Key, Action};
|
||||
use self::glfw::{Action, Context, Key};
|
||||
|
||||
extern crate gl;
|
||||
use self::gl::types::*;
|
||||
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use std::mem;
|
||||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
extern crate image;
|
||||
use image::GenericImage;
|
||||
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::{vec3, Matrix4, Rad};
|
||||
|
||||
mod consts;
|
||||
mod macros;
|
||||
mod shader;
|
||||
|
||||
pub fn main() {
|
||||
|
|
@ -19,13 +28,21 @@ pub fn main() {
|
|||
// ------------------------------
|
||||
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
|
||||
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
|
||||
glfw::OpenGlProfileHint::Core,
|
||||
));
|
||||
#[cfg(target_os = "macos")]
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
let (mut window, events) = glfw.create_window(consts::SCR_WIDTH, consts::SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
|
||||
let (mut window, events) = glfw
|
||||
.create_window(
|
||||
consts::SCR_WIDTH,
|
||||
consts::SCR_HEIGHT,
|
||||
"chRustedGL",
|
||||
glfw::WindowMode::Windowed,
|
||||
)
|
||||
.expect("Failed to create GLFW window");
|
||||
|
||||
window.make_current();
|
||||
|
|
@ -36,46 +53,63 @@ pub fn main() {
|
|||
// ---------------------------------------
|
||||
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
|
||||
|
||||
|
||||
let (shaderObject, VAO) = unsafe {
|
||||
let vShaderCode = CString::new(consts::VERTEX_SHADER_SRC.as_bytes()).unwrap();
|
||||
let fShaderCode = CString::new(consts::FRAGMENT_SHADER_SRC.as_bytes()).unwrap();
|
||||
let shader = crate::shader::Shader::new(vShaderCode, fShaderCode);
|
||||
let (shader_object, vao, vbo, ebo, texture) = unsafe {
|
||||
let v_shader = CString::new(consts::VERTEX_SHADER_SRC.as_bytes()).unwrap();
|
||||
let f_shader = CString::new(consts::FRAGMENT_SHADER_SRC.as_bytes()).unwrap();
|
||||
let shader = crate::shader::Shader::new(v_shader, f_shader);
|
||||
// set up vertex data (and buffer(s)) and configure vertex attributes
|
||||
// ------------------------------------------------------------------
|
||||
// HINT: type annotation is crucial since default for float literals is f64
|
||||
let vertices: [f32; 12] = [
|
||||
0.5, 0.5, 0.0, // top right
|
||||
0.5, -0.5, 0.0, // bottom right
|
||||
-0.5, -0.5, 0.0, // bottom left
|
||||
-0.5, 0.5, 0.0 // top left
|
||||
let vertices: [f32; 20] = [
|
||||
// positions // texture coords
|
||||
0.5, 0.5, 0.0, 1.0, 1.0, // top right
|
||||
0.5, -0.5, 0.0, 1.0, 0.0, // bottom right
|
||||
-0.5, -0.5, 0.0, 0.0, 0.0, // bottom left
|
||||
-0.5, 0.5, 0.0, 0.0, 1.0, // top left
|
||||
];
|
||||
let indices = [ // note that we start from 0!
|
||||
let indices = [
|
||||
// note that we start from 0!
|
||||
0, 1, 3, // first Triangle
|
||||
1, 2, 3 // second Triangle
|
||||
1, 2, 3, // second Triangle
|
||||
];
|
||||
|
||||
let (mut VBO, mut VAO, mut EBO) = (0, 0, 0);
|
||||
gl::GenVertexArrays(1, &mut VAO);
|
||||
gl::GenBuffers(1, &mut VBO);
|
||||
gl::GenBuffers(1, &mut EBO);
|
||||
let (mut vbo, mut vao, mut ebo) = (0, 0, 0);
|
||||
gl::GenVertexArrays(1, &mut vao);
|
||||
gl::GenBuffers(1, &mut vbo);
|
||||
gl::GenBuffers(1, &mut ebo);
|
||||
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
|
||||
gl::BindVertexArray(VAO);
|
||||
gl::BindVertexArray(vao);
|
||||
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, VBO);
|
||||
gl::BufferData(gl::ARRAY_BUFFER,
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
|
||||
gl::BufferData(
|
||||
gl::ARRAY_BUFFER,
|
||||
(vertices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
|
||||
&vertices[0] as *const f32 as *const c_void,
|
||||
gl::STATIC_DRAW);
|
||||
gl::STATIC_DRAW,
|
||||
);
|
||||
|
||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, EBO);
|
||||
gl::BufferData(gl::ELEMENT_ARRAY_BUFFER,
|
||||
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
|
||||
gl::BufferData(
|
||||
gl::ELEMENT_ARRAY_BUFFER,
|
||||
(indices.len() * mem::size_of::<GLfloat>()) as GLsizeiptr,
|
||||
&indices[0] as *const i32 as *const c_void,
|
||||
gl::STATIC_DRAW);
|
||||
gl::STATIC_DRAW,
|
||||
);
|
||||
|
||||
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 3 * mem::size_of::<GLfloat>() as GLsizei, ptr::null());
|
||||
let stride = 5 * mem::size_of::<GLfloat>() as GLsizei;
|
||||
// position attribute
|
||||
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, stride, ptr::null());
|
||||
gl::EnableVertexAttribArray(0);
|
||||
// texture coord attribute
|
||||
gl::VertexAttribPointer(
|
||||
1,
|
||||
2,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
stride,
|
||||
(3 * mem::size_of::<GLfloat>()) as *const c_void,
|
||||
);
|
||||
gl::EnableVertexAttribArray(1);
|
||||
|
||||
// note that this is allowed, the call to gl::VertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||
|
|
@ -90,14 +124,41 @@ pub fn main() {
|
|||
// uncomment this call to draw in wireframe polygons.
|
||||
// gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
|
||||
|
||||
(shader, VAO)
|
||||
// -------------------------
|
||||
let mut texture = 0;
|
||||
gl::GenTextures(1, &mut texture);
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture); // all upcoming GL_TEXTURE_2D operations now have effect on this texture object
|
||||
// set the texture wrapping parameters
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32); // set texture wrapping to gl::REPEAT (default wrapping method)
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
|
||||
// set texture filtering parameters
|
||||
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);
|
||||
// load image, create texture and generate mipmaps
|
||||
let img = image::open(&Path::new("resources/garlic_dog_space.jpg"))
|
||||
.expect("Failed to load texture");
|
||||
let flipped = img.flipv();
|
||||
let data = flipped.raw_pixels();
|
||||
gl::TexImage2D(
|
||||
gl::TEXTURE_2D,
|
||||
0,
|
||||
gl::RGB as i32,
|
||||
img.width() as i32,
|
||||
img.height() as i32,
|
||||
0,
|
||||
gl::RGB,
|
||||
gl::UNSIGNED_BYTE,
|
||||
&data[0] as *const u8 as *const c_void,
|
||||
);
|
||||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
||||
(shader, vao, vbo, ebo, texture)
|
||||
};
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
let color_r = 0.3;
|
||||
let color_g = 0.3;
|
||||
let color_b = 0.6;
|
||||
let color_r = 0.188;
|
||||
let color_g = 0.22;
|
||||
let color_b = 0.235;
|
||||
while !window.should_close() {
|
||||
// events
|
||||
// -----
|
||||
|
|
@ -109,9 +170,19 @@ pub fn main() {
|
|||
gl::ClearColor(color_r, color_g, color_b, 1.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
|
||||
// draw our first triangle
|
||||
shaderObject.useProgram();
|
||||
gl::BindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture);
|
||||
// create transformations
|
||||
let mut transform: Matrix4<f32> = Matrix4::identity();
|
||||
transform = transform * Matrix4::<f32>::from_translation(vec3(0.5, -0.5, 0.0));
|
||||
transform = transform * Matrix4::<f32>::from_angle_z(Rad(glfw.get_time() as f32));
|
||||
|
||||
// get matrix's uniform location and set matrix
|
||||
shader_object.useProgram();
|
||||
let transform_loc =
|
||||
gl::GetUniformLocation(shader_object.ID, c_str!("transform").as_ptr());
|
||||
gl::UniformMatrix4fv(transform_loc, 1, gl::FALSE, transform.as_ptr());
|
||||
|
||||
gl::BindVertexArray(vao); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
|
||||
gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +202,9 @@ fn process_events(window: &mut glfw::Window, events: &Receiver<(f64, glfw::Windo
|
|||
// height will be significantly larger than specified on retina displays.
|
||||
unsafe { gl::Viewport(0, 0, width, height) }
|
||||
}
|
||||
glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => window.set_should_close(true),
|
||||
glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
|
||||
window.set_should_close(true)
|
||||
}
|
||||
glfw::WindowEvent::Key(_, _, Action::Press, _) => println!("Other key pressed"),
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(non_snake_case)]
|
||||
use std::ffi::{CString, CStr};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::ptr;
|
||||
|
|
@ -8,8 +8,8 @@ use std::str;
|
|||
use gl;
|
||||
use gl::types::*;
|
||||
|
||||
use cgmath::{Matrix, Matrix4, Vector3};
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::{Matrix, Matrix4, Vector3};
|
||||
|
||||
pub struct Shader {
|
||||
pub ID: u32,
|
||||
|
|
@ -19,7 +19,6 @@ pub struct Shader {
|
|||
/// a few more setters for uniforms)
|
||||
#[allow(dead_code)]
|
||||
impl Shader {
|
||||
|
||||
pub fn new(vShaderCode: CString, fShaderCode: CString) -> Shader {
|
||||
let mut shader = Shader { ID: 0 };
|
||||
|
||||
|
|
@ -52,10 +51,10 @@ impl Shader {
|
|||
|
||||
pub fn from_file(vertexPath: &str, fragmentPath: &str) -> Shader {
|
||||
// 1. retrieve the vertex/fragment source code from filesystem
|
||||
let mut vShaderFile = File::open(vertexPath)
|
||||
.unwrap_or_else(|_| panic!("Failed to open {}", vertexPath));
|
||||
let mut fShaderFile = File::open(fragmentPath)
|
||||
.unwrap_or_else(|_| panic!("Failed to open {}", fragmentPath));
|
||||
let mut vShaderFile =
|
||||
File::open(vertexPath).unwrap_or_else(|_| panic!("Failed to open {}", vertexPath));
|
||||
let mut fShaderFile =
|
||||
File::open(fragmentPath).unwrap_or_else(|_| panic!("Failed to open {}", fragmentPath));
|
||||
let mut vertexCode = String::new();
|
||||
let mut fragmentCode = String::new();
|
||||
vShaderFile
|
||||
|
|
@ -92,7 +91,11 @@ impl Shader {
|
|||
}
|
||||
/// ------------------------------------------------------------------------
|
||||
pub unsafe fn setVector3(&self, name: &CStr, value: &Vector3<f32>) {
|
||||
gl::Uniform3fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, value.as_ptr());
|
||||
gl::Uniform3fv(
|
||||
gl::GetUniformLocation(self.ID, name.as_ptr()),
|
||||
1,
|
||||
value.as_ptr(),
|
||||
);
|
||||
}
|
||||
/// ------------------------------------------------------------------------
|
||||
pub unsafe fn setVec3(&self, name: &CStr, x: f32, y: f32, z: f32) {
|
||||
|
|
@ -100,7 +103,12 @@ impl Shader {
|
|||
}
|
||||
/// ------------------------------------------------------------------------
|
||||
pub unsafe fn setMat4(&self, name: &CStr, mat: &Matrix4<f32>) {
|
||||
gl::UniformMatrix4fv(gl::GetUniformLocation(self.ID, name.as_ptr()), 1, gl::FALSE, mat.as_ptr());
|
||||
gl::UniformMatrix4fv(
|
||||
gl::GetUniformLocation(self.ID, name.as_ptr()),
|
||||
1,
|
||||
gl::FALSE,
|
||||
mat.as_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
/// utility function for checking shader compilation/linking errors.
|
||||
|
|
@ -112,36 +120,48 @@ impl Shader {
|
|||
if type_ != "PROGRAM" {
|
||||
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success);
|
||||
if success != gl::TRUE as GLint {
|
||||
gl::GetShaderInfoLog(shader, 1024, ptr::null_mut(), infoLog.as_mut_ptr() as *mut GLchar);
|
||||
println!("ERROR::SHADER_COMPILATION_ERROR of type: {}\n{}\n \
|
||||
gl::GetShaderInfoLog(
|
||||
shader,
|
||||
1024,
|
||||
ptr::null_mut(),
|
||||
infoLog.as_mut_ptr() as *mut GLchar,
|
||||
);
|
||||
println!(
|
||||
"ERROR::SHADER_COMPILATION_ERROR of type: {}\n{}\n \
|
||||
-- --------------------------------------------------- -- ",
|
||||
type_,
|
||||
str::from_utf8(&infoLog).unwrap());
|
||||
str::from_utf8(&infoLog).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
gl::GetProgramiv(shader, gl::LINK_STATUS, &mut success);
|
||||
if success != gl::TRUE as GLint {
|
||||
gl::GetProgramInfoLog(shader, 1024, ptr::null_mut(), infoLog.as_mut_ptr() as *mut GLchar);
|
||||
println!("ERROR::PROGRAM_LINKING_ERROR of type: {}\n{}\n \
|
||||
gl::GetProgramInfoLog(
|
||||
shader,
|
||||
1024,
|
||||
ptr::null_mut(),
|
||||
infoLog.as_mut_ptr() as *mut GLchar,
|
||||
);
|
||||
println!(
|
||||
"ERROR::PROGRAM_LINKING_ERROR of type: {}\n{}\n \
|
||||
-- --------------------------------------------------- -- ",
|
||||
type_,
|
||||
str::from_utf8(&infoLog).unwrap());
|
||||
str::from_utf8(&infoLog).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Only used in 4.9 Geometry shaders - ignore until then (shader.h in original C++)
|
||||
pub fn with_geometry_shader(vertexPath: &str, fragmentPath: &str, geometryPath: &str) -> Self {
|
||||
let mut shader = Shader { ID: 0 };
|
||||
// 1. retrieve the vertex/fragment source code from filesystem
|
||||
let mut vShaderFile = File::open(vertexPath)
|
||||
.unwrap_or_else(|_| panic!("Failed to open {}", vertexPath));
|
||||
let mut fShaderFile = File::open(fragmentPath)
|
||||
.unwrap_or_else(|_| panic!("Failed to open {}", fragmentPath));
|
||||
let mut gShaderFile = File::open(geometryPath)
|
||||
.unwrap_or_else(|_| panic!("Failed to open {}", geometryPath));
|
||||
let mut vShaderFile =
|
||||
File::open(vertexPath).unwrap_or_else(|_| panic!("Failed to open {}", vertexPath));
|
||||
let mut fShaderFile =
|
||||
File::open(fragmentPath).unwrap_or_else(|_| panic!("Failed to open {}", fragmentPath));
|
||||
let mut gShaderFile =
|
||||
File::open(geometryPath).unwrap_or_else(|_| panic!("Failed to open {}", geometryPath));
|
||||
let mut vertexCode = String::new();
|
||||
let mut fragmentCode = String::new();
|
||||
let mut geometryCode = String::new();
|
||||
|
|
|
|||
Loading…
Reference in New Issue