init
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
1145
Cargo.lock
generated
Normal file
1145
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "learn_gl"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gl = "0.14.0"
|
||||||
|
glfw = "0.61.0"
|
||||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod render_timer;
|
||||||
143
src/main.rs
Normal file
143
src/main.rs
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
use std::{
|
||||||
|
ptr::{null, null_mut},
|
||||||
|
str::from_utf8,
|
||||||
|
};
|
||||||
|
|
||||||
|
use glfw::{Action, Context, Key};
|
||||||
|
use learn_gl::render_timer::RenderTimer;
|
||||||
|
fn main() {
|
||||||
|
let default_width = 500;
|
||||||
|
let default_height = 500;
|
||||||
|
|
||||||
|
let mut glfw = glfw::init(glfw::fail_on_errors).expect("msg");
|
||||||
|
let (mut window, events) = glfw
|
||||||
|
.create_window(
|
||||||
|
default_width,
|
||||||
|
default_height,
|
||||||
|
"learn_gl",
|
||||||
|
glfw::WindowMode::Windowed,
|
||||||
|
)
|
||||||
|
.expect("msg");
|
||||||
|
|
||||||
|
window.set_key_polling(true);
|
||||||
|
window.make_current();
|
||||||
|
|
||||||
|
gl::load_with(|s| glfw.get_proc_address_raw(s).unwrap() as *const _);
|
||||||
|
// gl::load_with(|s| window.get_proc_address(s).unwrap() as *const _);
|
||||||
|
|
||||||
|
unsafe { gl::Viewport(0, 0, default_width as _, default_height as _) };
|
||||||
|
window.set_framebuffer_size_callback(|_windows, width, height| {
|
||||||
|
unsafe { gl::Viewport(0, 0, width as _, height as _) };
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut render_timer = RenderTimer::new();
|
||||||
|
|
||||||
|
// 编译着色器
|
||||||
|
let vs_src = include_bytes!(".\\shaders\\vs.glsl");
|
||||||
|
let vs_ptr = vs_src.as_ptr() as *const i8;
|
||||||
|
let vs = unsafe { gl::CreateShader(gl::VERTEX_SHADER) };
|
||||||
|
unsafe { gl::ShaderSource(vs, 1, &vs_ptr as _, null()) };
|
||||||
|
unsafe { gl::CompileShader(vs) };
|
||||||
|
let mut success = 0;
|
||||||
|
unsafe { gl::GetShaderiv(vs, gl::COMPILE_STATUS, &mut success) };
|
||||||
|
if success != 0 {
|
||||||
|
let mut log = [0; 512];
|
||||||
|
unsafe { gl::GetShaderInfoLog(vs, 512, core::ptr::null_mut(), log.as_mut_ptr()) };
|
||||||
|
let log_u8: [u8; 512] = unsafe { std::mem::transmute(log) };
|
||||||
|
println!("{}", from_utf8(&log_u8).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let fs_src = include_bytes!(".\\shaders\\fs.glsl");
|
||||||
|
let fs_ptr = fs_src.as_ptr() as *const i8;
|
||||||
|
let fs = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) };
|
||||||
|
unsafe { gl::ShaderSource(fs, 1, &fs_ptr as _, null()) };
|
||||||
|
unsafe { gl::CompileShader(fs) };
|
||||||
|
let mut success = 0;
|
||||||
|
unsafe { gl::GetShaderiv(fs, gl::COMPILE_STATUS, &mut success) };
|
||||||
|
if success != 0 {
|
||||||
|
let mut log = [0; 512];
|
||||||
|
unsafe { gl::GetShaderInfoLog(fs, 512, core::ptr::null_mut(), log.as_mut_ptr()) };
|
||||||
|
let log_u8: [u8; 512] = unsafe { std::mem::transmute(log) };
|
||||||
|
println!("{}", from_utf8(&log_u8).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 链接着色器
|
||||||
|
let sp = unsafe { gl::CreateProgram() };
|
||||||
|
unsafe { gl::AttachShader(sp, vs) };
|
||||||
|
unsafe { gl::AttachShader(sp, fs) };
|
||||||
|
unsafe { gl::LinkProgram(sp) };
|
||||||
|
let mut success = 0;
|
||||||
|
unsafe { gl::GetProgramiv(sp, gl::LINK_STATUS, &mut success) };
|
||||||
|
if success != 0 {
|
||||||
|
let mut log = [0; 512];
|
||||||
|
unsafe { gl::GetProgramInfoLog(sp, 512, null_mut(), log.as_mut_ptr()) };
|
||||||
|
let log_u8: [u8; 512] = unsafe { std::mem::transmute(log) };
|
||||||
|
println!("{}", from_utf8(&log_u8).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用程序和删除着色器
|
||||||
|
unsafe { gl::UseProgram(sp) };
|
||||||
|
unsafe { gl::DeleteShader(vs) };
|
||||||
|
unsafe { gl::DeleteShader(fs) };
|
||||||
|
|
||||||
|
// 创建VAO
|
||||||
|
let mut vao = 0;
|
||||||
|
unsafe { gl::GenVertexArrays(1, &mut vao) };
|
||||||
|
unsafe { gl::BindVertexArray(vao) };
|
||||||
|
|
||||||
|
// 创建VBO
|
||||||
|
let a: [f32; _] = [-0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0];
|
||||||
|
let mut vbo: u32 = 0;
|
||||||
|
unsafe { gl::GenBuffers(1, &mut vbo) };
|
||||||
|
unsafe { gl::BindBuffer(gl::ARRAY_BUFFER, vbo) };
|
||||||
|
unsafe {
|
||||||
|
gl::BufferData(
|
||||||
|
gl::ARRAY_BUFFER,
|
||||||
|
size_of_val(&a) as _,
|
||||||
|
a.as_ptr() as _,
|
||||||
|
gl::STATIC_DRAW,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
// 链接顶点属性
|
||||||
|
unsafe {
|
||||||
|
gl::VertexAttribPointer(
|
||||||
|
0,
|
||||||
|
3,
|
||||||
|
gl::FLOAT,
|
||||||
|
gl::FALSE,
|
||||||
|
(3 * size_of::<f32>()) as _,
|
||||||
|
0 as _,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
unsafe { gl::EnableVertexAttribArray(0) };
|
||||||
|
|
||||||
|
// 渲染循环
|
||||||
|
while !window.should_close() {
|
||||||
|
glfw.poll_events();
|
||||||
|
for (_, event) in glfw::flush_messages(&events) {
|
||||||
|
handle_window_event(&mut window, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
render(&mut render_timer, sp ,vao);
|
||||||
|
|
||||||
|
window.swap_buffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
|
||||||
|
match event {
|
||||||
|
glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => window.set_should_close(true),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(render_timer: &mut RenderTimer, sp: u32, vao: u32) {
|
||||||
|
let t = render_timer.time_count() as f32 / 1000.0 as f32;
|
||||||
|
unsafe { gl::ClearColor(t.sin() * 0.5 + 1.0, t.cos() * 0.5 + 1.0, 0.3, 1.0) };
|
||||||
|
unsafe { gl::Clear(gl::COLOR_BUFFER_BIT) };
|
||||||
|
|
||||||
|
unsafe { gl::UseProgram(sp) };
|
||||||
|
unsafe { gl::BindVertexArray(vao) };
|
||||||
|
unsafe { gl::DrawArrays(gl::TRIANGLES, 0, 3) };
|
||||||
|
}
|
||||||
25
src/render_timer.rs
Normal file
25
src/render_timer.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
pub struct RenderTimer {
|
||||||
|
create_time: Instant,
|
||||||
|
last_check: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderTimer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
RenderTimer {
|
||||||
|
create_time: std::time::Instant::now(),
|
||||||
|
last_check: Instant::now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn time_count(&mut self) -> u128 {
|
||||||
|
self.create_time.elapsed().as_millis()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn elapsed(&mut self) -> u128 {
|
||||||
|
let elapsed = self.last_check.elapsed();
|
||||||
|
self.last_check = Instant::now();
|
||||||
|
elapsed.as_millis()
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/shaders/fs.glsl
Normal file
7
src/shaders/fs.glsl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
7
src/shaders/vs.glsl
Normal file
7
src/shaders/vs.glsl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user