added initial code

This commit is contained in:
Clemens Albrecht 2025-04-11 09:15:24 +02:00
parent e582b8f030
commit 714a10a7ea
2 changed files with 262 additions and 1 deletions

View file

@ -4,3 +4,9 @@ version = "0.1.0"
edition = "2021"
[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"

View file

@ -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() {
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();
}