dev
This commit is contained in:
parent
03643e15ad
commit
120447eacf
3 changed files with 293 additions and 0 deletions
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "rust_opengl_helloworld"
|
||||||
|
version = "1.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gl = "0.14.0"
|
||||||
|
glfw = { version = "0.57.0", features = ["wayland"] }
|
||||||
|
#bytemuck = "1"
|
||||||
|
#ogl33 = { version = "0.2.0", features = ["debug_error_checks"]}
|
||||||
|
#beryllium = "0.13.3"
|
9
config.toml
Normal file
9
config.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[build]
|
||||||
|
rustflags = ["-C", "target-feature=+crt-static"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = 'z' # Optimize for size
|
||||||
|
lto = true # Enable link-time optimization
|
||||||
|
codegen-units = 1 # Reduce number of codegen units to increase optimizations
|
||||||
|
panic = 'abort' # Abort on panic
|
||||||
|
strip = true # Strip symbols from binary*
|
273
src/main.rs
Normal file
273
src/main.rs
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use glfw;
|
||||||
|
use glfw::Context;
|
||||||
|
use gl;
|
||||||
|
|
||||||
|
const WIDTH: u32 = 480;
|
||||||
|
const HEIGHT: u32 = 320;
|
||||||
|
const TITLE: &str = "Hello From OpenGL World!";
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
use glfw::fail_on_errors;
|
||||||
|
let mut glfw = glfw::init(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::OpenGlForwardCompat(true));
|
||||||
|
glfw.window_hint(glfw::WindowHint::Resizable(true));
|
||||||
|
|
||||||
|
let (mut window, events) = glfw.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap();
|
||||||
|
let (screen_width, screen_height) = window.get_framebuffer_size();
|
||||||
|
|
||||||
|
window.make_current();
|
||||||
|
window.set_key_polling(true);
|
||||||
|
window.set_pos_polling(true);
|
||||||
|
window.set_all_polling(true);
|
||||||
|
window.set_size_polling(true);
|
||||||
|
window.set_close_polling(true);
|
||||||
|
window.set_refresh_polling(true);
|
||||||
|
window.set_focus_polling(true);
|
||||||
|
window.set_iconify_polling(true);
|
||||||
|
window.set_framebuffer_size_polling(true);
|
||||||
|
window.set_char_polling(true);
|
||||||
|
window.set_char_mods_polling(true);
|
||||||
|
window.set_mouse_button_polling(true);
|
||||||
|
window.set_cursor_pos_polling(true);
|
||||||
|
window.set_cursor_enter_polling(true);
|
||||||
|
window.set_scroll_polling(true);
|
||||||
|
window.set_maximize_polling(true);
|
||||||
|
window.set_content_scale_polling(true);
|
||||||
|
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::Viewport(0, 0, screen_width, screen_height);
|
||||||
|
clear_color(Color(0.4, 0.4, 0.4, 1.0));
|
||||||
|
}
|
||||||
|
// -------------------------------------------
|
||||||
|
|
||||||
|
const VERT_SHADER: &str = "#version 330 core
|
||||||
|
layout (location = 0) in vec3 position;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(position, 1.0);
|
||||||
|
// gl_Position = vec4(position.xyz, 1.0);
|
||||||
|
// gl_Position = vec4(position.x, position.y, position.z, 1.0);
|
||||||
|
}";
|
||||||
|
|
||||||
|
const FRAG_SHADER: &str = "#version 330 core
|
||||||
|
out vec4 Color;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
Color = vec4(0.9, 0.5, 0.2, 1.0);
|
||||||
|
}";
|
||||||
|
|
||||||
|
let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) };
|
||||||
|
unsafe {
|
||||||
|
gl::ShaderSource(vertex_shader, 1, &VERT_SHADER.as_bytes().as_ptr().cast(), &VERT_SHADER.len().try_into().unwrap());
|
||||||
|
gl::CompileShader(vertex_shader);
|
||||||
|
|
||||||
|
let mut success = 0;
|
||||||
|
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
|
||||||
|
if success == 0 {
|
||||||
|
let mut log_len = 0_i32;
|
||||||
|
// gl::GetShaderiv(vertex_shader, gl::INFO_LOG_LENGTH, &mut log_len);
|
||||||
|
// let mut v: Vec<u8> = Vec::with_capacity(log_len as usize);
|
||||||
|
// gl::GetShaderInfoLog(vertex_shader, log_len, &mut log_len, v.as_mut_ptr().cast());
|
||||||
|
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
||||||
|
gl::GetShaderInfoLog(vertex_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
||||||
|
v.set_len(log_len.try_into().unwrap());
|
||||||
|
panic!("Vertex Shader Compile Error: {}", String::from_utf8_lossy(&v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fragment_shader = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) };
|
||||||
|
unsafe {
|
||||||
|
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::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
|
||||||
|
if success == 0 {
|
||||||
|
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
||||||
|
let mut log_len = 0_i32;
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let shader_program = unsafe { gl::CreateProgram() };
|
||||||
|
unsafe {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
let vertecies = [
|
||||||
|
-0.5f32, -0.5, 0.0,
|
||||||
|
0.5, -0.5, 0.0,
|
||||||
|
0.0, 0.5, 0.0,
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut vao = 0;
|
||||||
|
unsafe { gl::GenVertexArrays(1, &mut vao) };
|
||||||
|
|
||||||
|
let mut vbo = 0;
|
||||||
|
unsafe { gl::GenBuffers(1, &mut vbo) };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::BindVertexArray(vao);
|
||||||
|
|
||||||
|
gl::BindBuffer(gl::ARRAY_BUFFER, vbo);
|
||||||
|
gl::BufferData(gl::ARRAY_BUFFER, std::mem::size_of_val(&vertecies) as isize, vertecies.as_ptr().cast(), gl::STATIC_DRAW);
|
||||||
|
|
||||||
|
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, 3 * std::mem::size_of::<f32>() as i32, 0 as *const _);
|
||||||
|
gl::EnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
|
gl::BindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------
|
||||||
|
println!("OpenGL version: {}", gl_get_string(gl::VERSION));
|
||||||
|
println!("GLSL version: {}", gl_get_string(gl::SHADING_LANGUAGE_VERSION));
|
||||||
|
|
||||||
|
|
||||||
|
while !window.should_close() {
|
||||||
|
glfw.poll_events();
|
||||||
|
for (time, event) in glfw::flush_messages(&events) {
|
||||||
|
glfw_handle_event(&mut window, time, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_color(Color(0.3, 0.4, 0.6, 1.0));
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gl::UseProgram(shader_program);
|
||||||
|
gl::BindVertexArray(vao);
|
||||||
|
|
||||||
|
gl::DrawArrays(gl::TRIANGLES, 0, 3);
|
||||||
|
|
||||||
|
gl::BindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.swap_buffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Color(f32, f32, f32, f32);
|
||||||
|
|
||||||
|
pub fn clear_color(c: Color) {
|
||||||
|
unsafe { gl::ClearColor(c.0, c.1, c.2, c.3) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gl_get_string<'a>(name: gl::types::GLenum) -> &'a str {
|
||||||
|
let v = unsafe { gl::GetString(name) };
|
||||||
|
let v: &std::ffi::CStr = unsafe { std::ffi::CStr::from_ptr(v as *const i8) };
|
||||||
|
v.to_str().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn glfw_handle_event(window: &mut glfw::Window, time: f64, event: glfw::WindowEvent) {
|
||||||
|
use glfw::WindowEvent as Event;
|
||||||
|
use glfw::Key;
|
||||||
|
use glfw::Action;
|
||||||
|
|
||||||
|
match event {
|
||||||
|
Event::Pos(x, y) => {
|
||||||
|
window.set_title(&format!("Time: {:?}, Window pos: ({:?}, {:?})", time, x, y))
|
||||||
|
}
|
||||||
|
Event::Size(w, h) => window.set_title(&format!(
|
||||||
|
"Time: {:?}, Window size: ({:?}, {:?})",
|
||||||
|
time, w, h
|
||||||
|
)),
|
||||||
|
Event::Close => println!("Time: {:?}, Window close requested.", time),
|
||||||
|
Event::Refresh => {
|
||||||
|
println!("Time: {:?}, Window refresh callback triggered.", time)
|
||||||
|
}
|
||||||
|
Event::Focus(true) => println!("Time: {:?}, Window focus gained.", time),
|
||||||
|
Event::Focus(false) => println!("Time: {:?}, Window focus lost.", time),
|
||||||
|
Event::Iconify(true) => println!("Time: {:?}, Window was minimised", time),
|
||||||
|
Event::Iconify(false) => println!("Time: {:?}, Window was maximised.", time),
|
||||||
|
Event::FramebufferSize(w, h) => {
|
||||||
|
unsafe {
|
||||||
|
gl::Viewport(0, 0, w, h);
|
||||||
|
}
|
||||||
|
println!("Time: {:?}, Framebuffer size: ({:?}, {:?})", time, w, h)
|
||||||
|
}
|
||||||
|
Event::Char(character) => {
|
||||||
|
println!("Time: {:?}, Character: {:?}", time, character)
|
||||||
|
}
|
||||||
|
Event::CharModifiers(character, mods) => println!(
|
||||||
|
"Time: {:?}, Character: {:?}, Modifiers: [{:?}]",
|
||||||
|
time, character, mods
|
||||||
|
),
|
||||||
|
Event::MouseButton(btn, action, mods) => println!(
|
||||||
|
"Time: {:?}, Button: {:?}, Action: {:?}, Modifiers: [{:?}]",
|
||||||
|
time,
|
||||||
|
glfw::DebugAliases(btn),
|
||||||
|
action,
|
||||||
|
mods
|
||||||
|
),
|
||||||
|
Event::CursorPos(xpos, ypos) => window.set_title(&format!(
|
||||||
|
"Time: {:?}, Cursor position: ({:?}, {:?})",
|
||||||
|
time, xpos, ypos
|
||||||
|
)),
|
||||||
|
Event::CursorEnter(true) => {
|
||||||
|
println!("Time: {:?}, Cursor entered window.", time)
|
||||||
|
}
|
||||||
|
Event::CursorEnter(false) => println!("Time: {:?}, Cursor left window.", time),
|
||||||
|
Event::Scroll(x, y) => window.set_title(&format!(
|
||||||
|
"Time: {:?}, Scroll offset: ({:?}, {:?})",
|
||||||
|
time, x, y
|
||||||
|
)),
|
||||||
|
/*Event::Key(key, scancode, action, mods) => {
|
||||||
|
println!(
|
||||||
|
"Time: {:?}, Key: {:?}, ScanCode: {:?}, Action: {:?}, Modifiers: [{:?}]",
|
||||||
|
time, key, scancode, action, mods
|
||||||
|
);
|
||||||
|
match (key, action) {
|
||||||
|
(Key::Escape, Action::Press) => window.set_should_close(true),
|
||||||
|
(Key::R, Action::Press) => {
|
||||||
|
// Resize should cause the window to "refresh"
|
||||||
|
let (window_width, window_height) = window.get_size();
|
||||||
|
window.set_size(window_width + 1, window_height);
|
||||||
|
window.set_size(window_width, window_height);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
Event::FileDrop(paths) => {
|
||||||
|
println!("Time: {:?}, Files dropped: {:?}", time, paths)
|
||||||
|
}
|
||||||
|
Event::Maximize(maximized) => {
|
||||||
|
println!("Time: {:?}, Window maximized: {:?}.", time, maximized)
|
||||||
|
}
|
||||||
|
Event::ContentScale(xscale, yscale) => println!(
|
||||||
|
"Time: {:?}, Content scale x: {:?}, Content scale y: {:?}",
|
||||||
|
time, xscale, yscale
|
||||||
|
),
|
||||||
|
Event::Key(Key::Escape, _, Action::Press, _) => {
|
||||||
|
window.set_should_close(true);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue