added initial code
This commit is contained in:
parent
e582b8f030
commit
714a10a7ea
2 changed files with 262 additions and 1 deletions
|
@ -4,3 +4,9 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
glutin = "0.32.2"
|
||||||
|
glutin-winit = "0.5.0"
|
||||||
|
winit = "0.30.9"
|
||||||
|
raw-window-handle = "0.6.2"
|
||||||
|
bytemuck = "1.22.0"
|
||||||
|
glow = "0.16.0"
|
||||||
|
|
257
src/main.rs
257
src/main.rs
|
@ -1,3 +1,258 @@
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use glow::HasContext;
|
||||||
|
use glutin::{
|
||||||
|
config::{ConfigSurfaceTypes, ConfigTemplateBuilder},
|
||||||
|
context::{ContextAttributesBuilder, GlProfile},
|
||||||
|
display::GetGlDisplay,
|
||||||
|
prelude::*,
|
||||||
|
surface::{SurfaceAttributesBuilder, WindowSurface},
|
||||||
|
};
|
||||||
|
use glutin_winit::DisplayBuilder;
|
||||||
|
use raw_window_handle::HasRawWindowHandle;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use winit::{
|
||||||
|
event::{Event, WindowEvent},
|
||||||
|
event_loop::{ControlFlow, EventLoop},
|
||||||
|
window::Window,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
// Create an event loop
|
||||||
|
let event_loop = EventLoop::new().unwrap();
|
||||||
|
event_loop.set_control_flow(ControlFlow::Poll);
|
||||||
|
|
||||||
|
// Create configuration for glutin
|
||||||
|
let template = ConfigTemplateBuilder::new()
|
||||||
|
.with_alpha_size(8)
|
||||||
|
.with_transparency(false)
|
||||||
|
.with_surface_type(ConfigSurfaceTypes::WINDOW);
|
||||||
|
|
||||||
|
let window_attributes = Window::default_attributes();
|
||||||
|
|
||||||
|
// Create window and OpenGL context
|
||||||
|
let display_builder = DisplayBuilder::new().with_window_attributes(Some(window_attributes));
|
||||||
|
|
||||||
|
let (window, gl_config) = display_builder
|
||||||
|
.build(&event_loop, template, |configs| {
|
||||||
|
configs
|
||||||
|
.reduce(|accum, config| {
|
||||||
|
let transparency_check = config.supports_transparency().unwrap_or(false)
|
||||||
|
&& !accum.supports_transparency().unwrap_or(false);
|
||||||
|
|
||||||
|
if transparency_check || config.num_samples() > accum.num_samples() {
|
||||||
|
config
|
||||||
|
} else {
|
||||||
|
accum
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.expect("Failed to create window and GL config");
|
||||||
|
|
||||||
|
let window = window.expect("Window creation failed");
|
||||||
|
|
||||||
|
// Create OpenGL context attributes
|
||||||
|
let context_attributes = ContextAttributesBuilder::new()
|
||||||
|
.with_profile(GlProfile::Core)
|
||||||
|
.build(window.raw_window_handle().ok());
|
||||||
|
|
||||||
|
// Create the OpenGL surface attributes
|
||||||
|
let surface_attributes = SurfaceAttributesBuilder::<WindowSurface>::new().build(
|
||||||
|
window.raw_window_handle().unwrap(),
|
||||||
|
std::num::NonZeroU32::new(800).unwrap(),
|
||||||
|
std::num::NonZeroU32::new(600).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create surface and context
|
||||||
|
let display = gl_config.display();
|
||||||
|
let gl_surface = unsafe {
|
||||||
|
display
|
||||||
|
.create_window_surface(&gl_config, &surface_attributes)
|
||||||
|
.expect("Failed to create surface")
|
||||||
|
};
|
||||||
|
|
||||||
|
let gl_context = unsafe {
|
||||||
|
display
|
||||||
|
.create_context(&gl_config, &context_attributes)
|
||||||
|
.expect("Failed to create context")
|
||||||
|
.make_current(&gl_surface)
|
||||||
|
.expect("Failed to make context current")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load OpenGL functions using glow
|
||||||
|
let gl = unsafe {
|
||||||
|
glow::Context::from_loader_function(|s| {
|
||||||
|
display.get_proc_address(&CString::new(s).unwrap()) as *const _
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize OpenGL state
|
||||||
|
unsafe {
|
||||||
|
gl.clear_color(0.2, 0.3, 0.3, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create shader program and resources
|
||||||
|
let (program, vao) = unsafe {
|
||||||
|
// Vertex Shader
|
||||||
|
let vertex_shader = gl
|
||||||
|
.create_shader(glow::VERTEX_SHADER)
|
||||||
|
.expect("Cannot create shader");
|
||||||
|
let vertex_shader_src = r#"
|
||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
layout (location = 1) in vec3 aColor;
|
||||||
|
out vec3 ourColor;
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(aPos, 1.0);
|
||||||
|
ourColor = aColor;
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
gl.shader_source(vertex_shader, vertex_shader_src);
|
||||||
|
gl.compile_shader(vertex_shader);
|
||||||
|
|
||||||
|
// Check for shader compilation errors
|
||||||
|
if !gl.get_shader_compile_status(vertex_shader) {
|
||||||
|
let info = gl.get_shader_info_log(vertex_shader);
|
||||||
|
panic!("Shader compilation error: {}", info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fragment Shader
|
||||||
|
let fragment_shader = gl
|
||||||
|
.create_shader(glow::FRAGMENT_SHADER)
|
||||||
|
.expect("Cannot create shader");
|
||||||
|
let fragment_shader_src = r#"
|
||||||
|
#version 330 core
|
||||||
|
in vec3 ourColor;
|
||||||
|
out vec4 FragColor;
|
||||||
|
void main() {
|
||||||
|
FragColor = vec4(ourColor, 1.0);
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
gl.shader_source(fragment_shader, fragment_shader_src);
|
||||||
|
gl.compile_shader(fragment_shader);
|
||||||
|
|
||||||
|
// Check for shader compilation errors
|
||||||
|
if !gl.get_shader_compile_status(fragment_shader) {
|
||||||
|
let info = gl.get_shader_info_log(fragment_shader);
|
||||||
|
panic!("Shader compilation error: {}", info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link shaders into a program
|
||||||
|
let program = gl.create_program().expect("Cannot create program");
|
||||||
|
gl.attach_shader(program, vertex_shader);
|
||||||
|
gl.attach_shader(program, fragment_shader);
|
||||||
|
gl.link_program(program);
|
||||||
|
|
||||||
|
// Check for linking errors
|
||||||
|
if !gl.get_program_link_status(program) {
|
||||||
|
let info = gl.get_program_info_log(program);
|
||||||
|
panic!("Program linking error: {}", info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the shaders as they're linked into our program now and no longer necessary
|
||||||
|
gl.delete_shader(vertex_shader);
|
||||||
|
gl.delete_shader(fragment_shader);
|
||||||
|
|
||||||
|
// Set up vertex data and buffers
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// Triangle vertices with positions and colors (x, y, z, r, g, b)
|
||||||
|
let vertices: [f32; 18] = [
|
||||||
|
// positions // colors
|
||||||
|
0.5, -0.5, 0.0, 1.0, 0.0, 0.0, // bottom right
|
||||||
|
-0.5, -0.5, 0.0, 0.0, 1.0, 0.0, // bottom left
|
||||||
|
0.0, 0.5, 0.0, 0.0, 0.0, 1.0, // top
|
||||||
|
];
|
||||||
|
|
||||||
|
// Create a Vertex Array Object (VAO)
|
||||||
|
let vao = gl.create_vertex_array().expect("Cannot create VAO");
|
||||||
|
gl.bind_vertex_array(Some(vao));
|
||||||
|
|
||||||
|
// Create a Vertex Buffer Object (VBO)
|
||||||
|
let vbo = gl.create_buffer().expect("Cannot create buffer");
|
||||||
|
gl.bind_buffer(glow::ARRAY_BUFFER, Some(vbo));
|
||||||
|
|
||||||
|
// Copy the vertex data to the buffer
|
||||||
|
gl.buffer_data_u8_slice(
|
||||||
|
glow::ARRAY_BUFFER,
|
||||||
|
bytemuck::cast_slice(&vertices),
|
||||||
|
glow::STATIC_DRAW,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Position attribute
|
||||||
|
gl.vertex_attrib_pointer_f32(
|
||||||
|
0, // location
|
||||||
|
3, // size (3 floats per vertex position)
|
||||||
|
glow::FLOAT, // type
|
||||||
|
false, // normalized
|
||||||
|
6 * std::mem::size_of::<f32>() as i32, // stride
|
||||||
|
0, // offset
|
||||||
|
);
|
||||||
|
gl.enable_vertex_attrib_array(0);
|
||||||
|
|
||||||
|
// Color attribute
|
||||||
|
gl.vertex_attrib_pointer_f32(
|
||||||
|
1, // location
|
||||||
|
3, // size (3 floats per vertex color)
|
||||||
|
glow::FLOAT, // type
|
||||||
|
false, // normalized
|
||||||
|
6 * std::mem::size_of::<f32>() as i32, // stride
|
||||||
|
3 * std::mem::size_of::<f32>() as i32, // offset
|
||||||
|
);
|
||||||
|
gl.enable_vertex_attrib_array(1);
|
||||||
|
|
||||||
|
// Unbind the VAO and VBO
|
||||||
|
gl.bind_vertex_array(None);
|
||||||
|
gl.bind_buffer(glow::ARRAY_BUFFER, None);
|
||||||
|
|
||||||
|
(program, vao)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Run the event loop
|
||||||
|
event_loop
|
||||||
|
.run(move |event, event_loop| {
|
||||||
|
match event {
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
|
WindowEvent::CloseRequested => event_loop.exit(),
|
||||||
|
WindowEvent::Resized(size) => {
|
||||||
|
// Update the surface size
|
||||||
|
gl_surface.resize(
|
||||||
|
&gl_context,
|
||||||
|
std::num::NonZeroU32::new(size.width).unwrap(),
|
||||||
|
std::num::NonZeroU32::new(size.height).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update the viewport
|
||||||
|
unsafe {
|
||||||
|
gl.viewport(0, 0, size.width as i32, size.height as i32);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.request_redraw();
|
||||||
|
}
|
||||||
|
WindowEvent::RedrawRequested => {
|
||||||
|
// Clear the screen
|
||||||
|
unsafe {
|
||||||
|
gl.clear(glow::COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
// Draw our triangle
|
||||||
|
gl.use_program(Some(program));
|
||||||
|
gl.bind_vertex_array(Some(vao));
|
||||||
|
gl.draw_arrays(glow::TRIANGLES, 0, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap buffers
|
||||||
|
gl_surface
|
||||||
|
.swap_buffers(&gl_context)
|
||||||
|
.expect("Failed to swap buffers");
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue