Compare commits
2 Commits
0cf7d5eb43
...
5910390865
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5910390865 | ||
|
|
13687bee1b |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
*/target
|
||||
*/out
|
||||
|
||||
1835
Cargo.lock
generated
1835
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
17
Cargo.toml
17
Cargo.toml
@ -1,17 +0,0 @@
|
||||
[package]
|
||||
name = "proj"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
dotenvy = "0.15.7"
|
||||
gl = "0.14.0"
|
||||
glutin = "0.32.3"
|
||||
glutin-winit = "0.5.0"
|
||||
raw-window-handle = "0.6.2"
|
||||
winit = "0.30.12"
|
||||
|
||||
[build-dependencies]
|
||||
dotenvy = "0.15.7"
|
||||
gl_generator = "0.14"
|
||||
cfg_aliases = "0.2.1"
|
||||
41
build.rs
41
build.rs
@ -1,41 +0,0 @@
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use cfg_aliases::cfg_aliases;
|
||||
use gl_generator::{Api, Fallbacks, Profile, Registry, StructGenerator};
|
||||
|
||||
fn main() {
|
||||
// XXX this is taken from glutin/build.rs.
|
||||
dotenvy::dotenv().ok();
|
||||
|
||||
// Setup alias to reduce `cfg` boilerplate.
|
||||
cfg_aliases! {
|
||||
// Systems.
|
||||
android_platform: { target_os = "android" },
|
||||
wasm_platform: { target_family = "wasm" },
|
||||
macos_platform: { target_os = "macos" },
|
||||
ios_platform: { target_os = "ios" },
|
||||
apple: { any(ios_platform, macos_platform) },
|
||||
free_unix: { all(unix, not(apple), not(android_platform)) },
|
||||
|
||||
// Native displays.
|
||||
x11_platform: { all(feature = "x11", free_unix, not(wasm_platform)) },
|
||||
wayland_platform: { all(feature = "wayland", free_unix, not(wasm_platform)) },
|
||||
|
||||
// Backends.
|
||||
egl_backend: { all(feature = "egl", any(windows, unix), not(apple), not(wasm_platform)) },
|
||||
glx_backend: { all(feature = "glx", x11_platform, not(wasm_platform)) },
|
||||
wgl_backend: { all(feature = "wgl", windows, not(wasm_platform)) },
|
||||
cgl_backend: { all(macos_platform, not(wasm_platform)) },
|
||||
}
|
||||
|
||||
let dest = PathBuf::from(&env::var("OUT_DIR").unwrap());
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let mut file = File::create(dest.join("gl_bindings.rs")).unwrap();
|
||||
Registry::new(Api::Gles2, (3, 0), Profile::Core, Fallbacks::All, [])
|
||||
.write_bindings(StructGenerator, &mut file)
|
||||
.unwrap();
|
||||
}
|
||||
235
gl_rust/Cargo.lock
generated
Normal file
235
gl_rust/Cargo.lock
generated
Normal file
@ -0,0 +1,235 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.72.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.182"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proj"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"dotenvy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
11
gl_rust/Cargo.toml
Normal file
11
gl_rust/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "proj"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
dotenvy = "0.15.7"
|
||||
|
||||
[build-dependencies]
|
||||
dotenvy = "0.15.7"
|
||||
bindgen = "0.72.1"
|
||||
15
gl_rust/build.rs
Normal file
15
gl_rust/build.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use bindgen::Builder;
|
||||
|
||||
fn main() {
|
||||
// XXX this is taken from glutin/build.rs.
|
||||
dotenvy::dotenv().ok();
|
||||
|
||||
let bindings_header = "../glc/src/glc_api.h";
|
||||
|
||||
let bindings = Builder::default().header(bindings_header).generate().unwrap();
|
||||
|
||||
bindings.write_to_file("./src/glc.rs").unwrap();
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed={bindings_header}");
|
||||
}
|
||||
0
gl_rust/src/app/app.rs
Normal file
0
gl_rust/src/app/app.rs
Normal file
85
gl_rust/src/app/renderer.rs
Normal file
85
gl_rust/src/app/renderer.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use crate::models::{self, Model, ModelData, RenderObject, Scene, ShaderSource};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::{ CStr, CString };
|
||||
use crate::glc;
|
||||
|
||||
pub struct Renderer {
|
||||
shaders: HashMap<String, glc::GpuUint>,
|
||||
scenes: HashMap<String, Scene>
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
shaders: HashMap::new(),
|
||||
scenes: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_shader(shader_kind: glc::GpuShaderType, source: &[i8]) -> glc::GpuShaderHandle {
|
||||
unsafe {
|
||||
let shader = glc::gpu_shader_compile(source.as_ptr(), shader_kind);
|
||||
shader
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_shader(&self, shader_src: &ShaderSource) -> glc::GpuProgram {
|
||||
unsafe {
|
||||
program
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_shader(&mut self, name: &str, shader: gl::types::GLuint) {
|
||||
if let None = self.shaders.get(name) {
|
||||
self.shaders.insert(name.to_string(), shader);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_shader(&self, name: &str) -> Option<&gl::types::GLuint> {
|
||||
self.shaders.get(name)
|
||||
}
|
||||
|
||||
pub fn remove_shader(&mut self, name: &str) {
|
||||
self.shaders.remove(name);
|
||||
}
|
||||
|
||||
pub fn resize(&self, width: i32, height: i32) {
|
||||
unsafe {
|
||||
self.gl.Viewport(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_object(&self, obj: &RenderObject, shader: glc::GpuShaderHandle) {
|
||||
unsafe {
|
||||
|
||||
self.UseProgram(shader);
|
||||
|
||||
self.BindBuffer(gl::ARRAY_BUFFER, obj.vbo);
|
||||
self.BindVertexArray(obj.vao);
|
||||
|
||||
self.DrawArrays(gl::TRIANGLES, 0, obj.vertex_count);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, current_scene: &String) {
|
||||
unsafe {
|
||||
glc::gpu_clear(1.0, 1.0, 1.0, 0.9);
|
||||
}
|
||||
|
||||
if let Some(scene) = self.scenes.get(current_scene) {
|
||||
for model in scene.models {
|
||||
self.draw_object(obj, *shader);
|
||||
}
|
||||
} else {
|
||||
eprintln!("Unknown Scene Requested: {}", current_scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Renderer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.shaders.values().for_each(|shader| glc::gpu_program_destroy(shader));
|
||||
}
|
||||
}
|
||||
}
|
||||
10271
gl_rust/src/gl_c.rs
Normal file
10271
gl_rust/src/gl_c.rs
Normal file
File diff suppressed because it is too large
Load Diff
8192
gl_rust/src/glc.rs
Normal file
8192
gl_rust/src/glc.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -18,10 +18,11 @@ pub mod models {
|
||||
pub mod app {
|
||||
pub mod renderer;
|
||||
pub mod app;
|
||||
pub mod gl;
|
||||
}
|
||||
|
||||
pub mod shaders {
|
||||
pub mod shaders;
|
||||
pub use shaders::*;
|
||||
}
|
||||
|
||||
pub mod glc;
|
||||
@ -20,7 +20,7 @@ fn main() {
|
||||
|
||||
let scene_data = ModelData {
|
||||
name: "home".to_string(),
|
||||
objects_data: vec![(mesh, shader_src)]
|
||||
meshes: vec![(mesh)]
|
||||
};
|
||||
|
||||
let mut app = App::new(scene_data);
|
||||
@ -1,4 +1,3 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::models::Material;
|
||||
|
||||
use super::Vertex;
|
||||
311
glc/lib/include/KHR/khrplatform.h
Normal file
311
glc/lib/include/KHR/khrplatform.h
Normal file
@ -0,0 +1,311 @@
|
||||
#ifndef __khrplatform_h_
|
||||
#define __khrplatform_h_
|
||||
|
||||
/*
|
||||
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
/* Khronos platform-specific types and definitions.
|
||||
*
|
||||
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||
* The last semantic modification to khrplatform.h was at commit ID:
|
||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||
*
|
||||
* Adopters may modify this file to suit their platform. Adopters are
|
||||
* encouraged to submit platform specific modifications to the Khronos
|
||||
* group so that they can be included in future versions of this file.
|
||||
* Please submit changes by filing pull requests or issues on
|
||||
* the EGL Registry repository linked above.
|
||||
*
|
||||
*
|
||||
* See the Implementer's Guidelines for information about where this file
|
||||
* should be located on your system and for more details of its use:
|
||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||
*
|
||||
* This file should be included as
|
||||
* #include <KHR/khrplatform.h>
|
||||
* by Khronos client API header files that use its types and defines.
|
||||
*
|
||||
* The types in khrplatform.h should only be used to define API-specific types.
|
||||
*
|
||||
* Types defined in khrplatform.h:
|
||||
* khronos_int8_t signed 8 bit
|
||||
* khronos_uint8_t unsigned 8 bit
|
||||
* khronos_int16_t signed 16 bit
|
||||
* khronos_uint16_t unsigned 16 bit
|
||||
* khronos_int32_t signed 32 bit
|
||||
* khronos_uint32_t unsigned 32 bit
|
||||
* khronos_int64_t signed 64 bit
|
||||
* khronos_uint64_t unsigned 64 bit
|
||||
* khronos_intptr_t signed same number of bits as a pointer
|
||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||
* khronos_ssize_t signed size
|
||||
* khronos_usize_t unsigned size
|
||||
* khronos_float_t signed 32 bit floating point
|
||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||
* nanoseconds
|
||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||
* only be used as a base type when a client API's boolean type is
|
||||
* an enum. Client APIs which use an integer or other type for
|
||||
* booleans cannot use this as the base type for their boolean.
|
||||
*
|
||||
* Tokens defined in khrplatform.h:
|
||||
*
|
||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||
*
|
||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||
*
|
||||
* Calling convention macros defined in this file:
|
||||
* KHRONOS_APICALL
|
||||
* KHRONOS_APIENTRY
|
||||
* KHRONOS_APIATTRIBUTES
|
||||
*
|
||||
* These may be used in function prototypes as:
|
||||
*
|
||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||
* int arg1,
|
||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||
*/
|
||||
|
||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||
# define KHRONOS_STATIC 1
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APICALL
|
||||
*-------------------------------------------------------------------------
|
||||
* This precedes the return type of the function in the function prototype.
|
||||
*/
|
||||
#if defined(KHRONOS_STATIC)
|
||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||
* header compatible with static linking. */
|
||||
# define KHRONOS_APICALL
|
||||
#elif defined(_WIN32)
|
||||
# define KHRONOS_APICALL __declspec(dllimport)
|
||||
#elif defined (__SYMBIAN32__)
|
||||
# define KHRONOS_APICALL IMPORT_C
|
||||
#elif defined(__ANDROID__)
|
||||
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||
#else
|
||||
# define KHRONOS_APICALL
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIENTRY
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the return type of the function and precedes the function
|
||||
* name in the function prototype.
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||
/* Win32 but not WinCE */
|
||||
# define KHRONOS_APIENTRY __stdcall
|
||||
#else
|
||||
# define KHRONOS_APIENTRY
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Definition of KHRONOS_APIATTRIBUTES
|
||||
*-------------------------------------------------------------------------
|
||||
* This follows the closing parenthesis of the function prototype arguments.
|
||||
*/
|
||||
#if defined (__ARMCC_2__)
|
||||
#define KHRONOS_APIATTRIBUTES __softfp
|
||||
#else
|
||||
#define KHRONOS_APIATTRIBUTES
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* basic type definitions
|
||||
*-----------------------------------------------------------------------*/
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||
|
||||
|
||||
/*
|
||||
* Using <stdint.h>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
/*
|
||||
* To support platform where unsigned long cannot be used interchangeably with
|
||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||
* unsigned long long or similar (this results in different C++ name mangling).
|
||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||
* platforms where the size of a pointer is larger than the size of long.
|
||||
*/
|
||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||
#define KHRONOS_USE_INTPTR_T
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(__VMS ) || defined(__sgi)
|
||||
|
||||
/*
|
||||
* Using <inttypes.h>
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||
|
||||
/*
|
||||
* Win32
|
||||
*/
|
||||
typedef __int32 khronos_int32_t;
|
||||
typedef unsigned __int32 khronos_uint32_t;
|
||||
typedef __int64 khronos_int64_t;
|
||||
typedef unsigned __int64 khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif defined(__sun__) || defined(__digital__)
|
||||
|
||||
/*
|
||||
* Sun or Digital
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#if defined(__arch64__) || defined(_LP64)
|
||||
typedef long int khronos_int64_t;
|
||||
typedef unsigned long int khronos_uint64_t;
|
||||
#else
|
||||
typedef long long int khronos_int64_t;
|
||||
typedef unsigned long long int khronos_uint64_t;
|
||||
#endif /* __arch64__ */
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#elif 0
|
||||
|
||||
/*
|
||||
* Hypothetical platform with no float or int64 support
|
||||
*/
|
||||
typedef int khronos_int32_t;
|
||||
typedef unsigned int khronos_uint32_t;
|
||||
#define KHRONOS_SUPPORT_INT64 0
|
||||
#define KHRONOS_SUPPORT_FLOAT 0
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Generic fallback
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef int32_t khronos_int32_t;
|
||||
typedef uint32_t khronos_uint32_t;
|
||||
typedef int64_t khronos_int64_t;
|
||||
typedef uint64_t khronos_uint64_t;
|
||||
#define KHRONOS_SUPPORT_INT64 1
|
||||
#define KHRONOS_SUPPORT_FLOAT 1
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Types that are (so far) the same on all platforms
|
||||
*/
|
||||
typedef signed char khronos_int8_t;
|
||||
typedef unsigned char khronos_uint8_t;
|
||||
typedef signed short int khronos_int16_t;
|
||||
typedef unsigned short int khronos_uint16_t;
|
||||
|
||||
/*
|
||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||
* to be the only LLP64 architecture in current use.
|
||||
*/
|
||||
#ifdef KHRONOS_USE_INTPTR_T
|
||||
typedef intptr_t khronos_intptr_t;
|
||||
typedef uintptr_t khronos_uintptr_t;
|
||||
#elif defined(_WIN64)
|
||||
typedef signed long long int khronos_intptr_t;
|
||||
typedef unsigned long long int khronos_uintptr_t;
|
||||
#else
|
||||
typedef signed long int khronos_intptr_t;
|
||||
typedef unsigned long int khronos_uintptr_t;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
typedef signed long long int khronos_ssize_t;
|
||||
typedef unsigned long long int khronos_usize_t;
|
||||
#else
|
||||
typedef signed long int khronos_ssize_t;
|
||||
typedef unsigned long int khronos_usize_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_FLOAT
|
||||
/*
|
||||
* Float type
|
||||
*/
|
||||
typedef float khronos_float_t;
|
||||
#endif
|
||||
|
||||
#if KHRONOS_SUPPORT_INT64
|
||||
/* Time types
|
||||
*
|
||||
* These types can be used to represent a time interval in nanoseconds or
|
||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||
* time the system booted). The Unadjusted System Time is an unsigned
|
||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||
* may be either signed or unsigned.
|
||||
*/
|
||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dummy value used to pad enum types to 32 bits.
|
||||
*/
|
||||
#ifndef KHRONOS_MAX_ENUM
|
||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enumerated boolean type
|
||||
*
|
||||
* Values other than zero should be considered to be true. Therefore
|
||||
* comparisons should not be made against KHRONOS_TRUE.
|
||||
*/
|
||||
typedef enum {
|
||||
KHRONOS_FALSE = 0,
|
||||
KHRONOS_TRUE = 1,
|
||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||
} khronos_boolean_enum_t;
|
||||
|
||||
#endif /* __khrplatform_h_ */
|
||||
3694
glc/lib/include/glad/glad.h
Normal file
3694
glc/lib/include/glad/glad.h
Normal file
File diff suppressed because it is too large
Load Diff
BIN
glc/lib/libglc.a
Normal file
BIN
glc/lib/libglc.a
Normal file
Binary file not shown.
79
glc/nob.c
Normal file
79
glc/nob.c
Normal file
@ -0,0 +1,79 @@
|
||||
#define NOB_IMPLEMENTATION
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "nob.h"
|
||||
|
||||
#define BUILD_DIR "./build/"
|
||||
#define SRC_DIR "./src/"
|
||||
#define OBJDIR BUILD_DIR"obj/"
|
||||
#define LIB_DIR "./lib/"
|
||||
#define LIB_OUT LIB_DIR"libglc.a"
|
||||
|
||||
Cmd ar_cmd = {0};
|
||||
|
||||
_Bool walk_dir_func(Nob_Walk_Entry e) {
|
||||
printf("Path: %s\n", e.path);
|
||||
if (e.type == NOB_FILE_REGULAR) {
|
||||
size_t input_len = strlen(e.path);
|
||||
if (input_len > 3) {
|
||||
if (strcmp(&e.path[input_len - 2], ".h") != 0) {
|
||||
Cmd cmd = {0};
|
||||
String_Builder sb_out = {0};
|
||||
String_View sv = {0};
|
||||
|
||||
char *path_cpy = strdup(e.path);
|
||||
|
||||
sv = sv_from_cstr(path_cpy);
|
||||
|
||||
size_t l = strlen(e.path);
|
||||
while (--l) {
|
||||
if (e.path[l] == '/') {
|
||||
sv_chop_left(&sv, l + 1);
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
printf("file_name: %s\n", sv.data);
|
||||
|
||||
cmd_append(&cmd, "cc", "-c", "-static");
|
||||
nob_cc_flags(&cmd);
|
||||
|
||||
cmd_append(&cmd, "-o");
|
||||
sb_append_cstr(&sb_out, OBJDIR);
|
||||
sb_append_cstr(&sb_out, sv.data);
|
||||
cmd_append(&cmd, sb_out.items);
|
||||
cmd_append(&cmd, strdup(path_cpy));
|
||||
cmd_run(&cmd);
|
||||
cmd_append(&ar_cmd, strdup(sb_out.items));
|
||||
memset(sb_out.items, 0, sb_out.count);
|
||||
sb_free(sb_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
*e.action = NOB_WALK_CONT;
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
NOB_GO_REBUILD_URSELF(argc, argv);
|
||||
|
||||
if (!nob_mkdir_if_not_exists(BUILD_DIR)) {
|
||||
nob_log(ERROR, "Failed to create %s: %s\n", BUILD_DIR, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!nob_mkdir_if_not_exists(OBJDIR)) {
|
||||
nob_log(ERROR, "Failed to create %s: %s\n", OBJDIR, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *bin_path = BUILD_DIR "main";
|
||||
|
||||
cmd_append(&ar_cmd, "ar", "rcs", LIB_OUT);
|
||||
nob_walk_dir(SRC_DIR, walk_dir_func, .post_order = true);
|
||||
|
||||
cmd_run(&ar_cmd);
|
||||
|
||||
nob_log(INFO, "Starting build...\n");
|
||||
}
|
||||
BIN
glc/nob.old
Executable file
BIN
glc/nob.old
Executable file
Binary file not shown.
1
glc/src/bindings.h
Normal file
1
glc/src/bindings.h
Normal file
@ -0,0 +1 @@
|
||||
#include "glc_api.h"
|
||||
52
glc/src/gl/buffers.c
Normal file
52
glc/src/gl/buffers.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include "../glc.h" // IWYU pragma: keep
|
||||
|
||||
u32 gpu_buffer_create(GpuBuffer *buf, float *vertices, u32 vertex_count, u32 *indices, int idx_count) {
|
||||
u32 vao = 0, vbo = 0, ebo = 0, vao_stride = 0;
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
if (!vertices) return 1;
|
||||
if (!indices) return 2;
|
||||
|
||||
vao_stride = DEFAULT_VERTEX_STRIDE;
|
||||
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertex_count * vao_stride * sizeof(*vertices), vertices, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(*vertices) * vao_stride, (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glGenBuffers(1, &ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_count * vao_stride * sizeof(*indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
buf->vao = vao;
|
||||
buf->vbo = vbo;
|
||||
buf->ebo = ebo;
|
||||
buf->stride = vao_stride;
|
||||
buf->index_count = idx_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpu_buffer_destroy(GpuBuffer *buffer) {
|
||||
if (buffer->vbo != 0) {
|
||||
glDeleteBuffers(1, &buffer->vbo);
|
||||
}
|
||||
if (buffer->ebo != 0) {
|
||||
glDeleteBuffers(1, &buffer->ebo);
|
||||
}
|
||||
if (buffer->vao != 0) {
|
||||
glDeleteVertexArrays(1, &buffer->vao);
|
||||
}
|
||||
}
|
||||
|
||||
void gpu_buffer_draw(GpuBuffer *buf) {
|
||||
glBindVertexArray(buf->vao);
|
||||
glDrawElements(GL_TRIANGLES, buf->index_count, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
6
glc/src/gl/clear.c
Normal file
6
glc/src/gl/clear.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "../glc.h" // IWYU pragma: keep
|
||||
|
||||
void gpu_clear(float r, float g, float b, float a) {
|
||||
glClearColor(r, g, b, a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
25
glc/src/gl/error.c
Normal file
25
glc/src/gl/error.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include "../glc.h" // IWYU pragma: keep
|
||||
|
||||
INTERN
|
||||
void gpu_shader_error_get(uint32_t shader) {
|
||||
int success;
|
||||
char infoLog[512];
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(shader, 512, NULL, infoLog);
|
||||
err("[SHADER_ERROR] Failed to compile shader: %s\n", infoLog);
|
||||
}
|
||||
}
|
||||
|
||||
INTERN
|
||||
void gpu_program_handle_error_get(GpuProgramHandle program) {
|
||||
int success;
|
||||
char info_log[512];
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetProgramInfoLog(program, 512, NULL, info_log);
|
||||
err("[PROGRAM_ERROR] Failed to link program: %s\n", info_log);
|
||||
}
|
||||
}
|
||||
62
glc/src/gl/gpu_program.c
Normal file
62
glc/src/gl/gpu_program.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "../glc.h" // IWYU pragma: keep
|
||||
|
||||
INTERN
|
||||
GpuShaderHandle gpu_shader_compile(char const *src, GpuShaderType type) {
|
||||
uint32_t shader = glCreateShader(type);
|
||||
|
||||
glShaderSource(shader, 1, &src, NULL);
|
||||
glCompileShader(shader);
|
||||
gpu_shader_error_get(shader);
|
||||
|
||||
return shader;
|
||||
|
||||
}
|
||||
|
||||
INTERN
|
||||
GpuProgramHandle gpu_program_handle_link(GpuProgramHandle handle, GpuShaderHandle vertex_shader, GpuShaderHandle fragment_shader) {
|
||||
|
||||
glAttachShader(handle, vertex_shader);
|
||||
glAttachShader(handle, fragment_shader);
|
||||
glLinkProgram(handle);
|
||||
gpu_program_handle_error_get(handle);
|
||||
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
INTERN
|
||||
GpuProgramHandle gpu_program_handle_create(const char *vert_src, const char *frag_src) {
|
||||
GpuShaderHandle vert_shader = gpu_shader_compile(vert_src, GL_VERTEX_SHADER);
|
||||
GpuShaderHandle frag_shader = gpu_shader_compile(frag_src, GL_FRAGMENT_SHADER);
|
||||
GpuProgramHandle handle = glCreateProgram();
|
||||
gpu_program_handle_link(handle, vert_shader, frag_shader);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
API
|
||||
GpuProgram gpu_program_create(const char *vert_src, const char *frag_src) {
|
||||
GpuProgram program = {0};
|
||||
program.handle = gpu_program_handle_create(vert_src, frag_src);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
API
|
||||
void gpu_program_use(GpuProgram *program) {
|
||||
gpu_program_handle_use(program->handle);
|
||||
}
|
||||
|
||||
INTERN
|
||||
void gpu_program_handle_use(GpuProgramHandle handle) {
|
||||
glUseProgram(handle);
|
||||
}
|
||||
|
||||
INTERN
|
||||
void gpu_program_handle_clear() {
|
||||
gpu_program_handle_use(0);
|
||||
}
|
||||
|
||||
|
||||
1833
glc/src/glad.c
Normal file
1833
glc/src/glad.c
Normal file
File diff suppressed because it is too large
Load Diff
5
glc/src/glc.h
Normal file
5
glc/src/glc.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
# include "glc_internal.h"
|
||||
# include "glc_api.h"
|
||||
# include "glc_types.h"
|
||||
23
glc/src/glc_api.h
Normal file
23
glc/src/glc_api.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include "glc_types.h"
|
||||
|
||||
#define API
|
||||
|
||||
/* GPU */
|
||||
|
||||
API GpuProgram gpu_program_create(const char *vert_src, const char *frag_src);
|
||||
API void gpu_program_destroy(GpuProgram *gpu_program);
|
||||
API void gpu_program_use(GpuProgram *program);
|
||||
API void gpu_program_clear();
|
||||
API u32 gpu_buffer_create(GpuBuffer *buf, float *vertices, u32 vertex_count, u32 *indices, int idx_count);
|
||||
API void gpu_buffer_destroy(GpuBuffer *buffer);
|
||||
API void gpu_buffer_draw(GpuBuffer *buffer);
|
||||
API void gpu_clear(float r, float g, float b, float a);
|
||||
|
||||
/* ### PLATFORM ### */
|
||||
|
||||
/* WINDOW */
|
||||
API Window window_create(u32 width, u32 height, const char *title);
|
||||
API void window_destroy(Window *win);
|
||||
API void window_buffers_swap(Window *win);
|
||||
API void window_poll_events(Window *win);
|
||||
31
glc/src/glc_internal.h
Normal file
31
glc/src/glc_internal.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "glc_types.h"
|
||||
|
||||
#include "../lib/include/glad/glad.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define err(...) do { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
#define DEFAULT_VERTEX_STRIDE 3
|
||||
#define INTERN
|
||||
|
||||
extern char const *vertex_shader_src;
|
||||
extern char const *fragment_shader_src;
|
||||
|
||||
/* GPU */
|
||||
|
||||
INTERN GpuShaderHandle gpu_shader_compile(char const *src, GpuShaderType type);
|
||||
INTERN void gpu_shader_error_get(uint32_t shader);
|
||||
|
||||
INTERN GpuProgramHandle gpu_program_handle_create(const char *vert_src, const char *frag_src);
|
||||
INTERN GpuProgramHandle gpu_program_handle_link(GpuProgramHandle handle, GpuShaderHandle vert_shader, GpuShaderHandle frag_shader);
|
||||
INTERN void gpu_program_handle_error_get(GpuProgramHandle program);
|
||||
INTERN void gpu_program_handle_use(GpuProgramHandle handle);
|
||||
|
||||
INTERN void window_framebuffer_size_callback(GLFWwindow *win, int width, int height);
|
||||
|
||||
52
glc/src/glc_types.h
Normal file
52
glc/src/glc_types.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lib/include/glad/glad.h"
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef int16_t i16;
|
||||
typedef int32_t i32;
|
||||
typedef int64_t i64;
|
||||
|
||||
typedef i32 GpuShaderHandle;
|
||||
typedef i32 GpuProgramHandle;
|
||||
|
||||
typedef GLvoid GpuVoid;
|
||||
typedef GLboolean GpuBool;
|
||||
typedef GLbyte GpuByte;
|
||||
typedef GLshort GpuShort;
|
||||
typedef GLsizei GpuSizeI;
|
||||
typedef GLsizeiptr GpuSizeIPtr;
|
||||
typedef GLint GpuInt;
|
||||
typedef GLuint GpuUint;
|
||||
typedef GLfloat GpuFloat;
|
||||
typedef GLdouble GpuDouble;
|
||||
|
||||
typedef enum {
|
||||
FRAGMENT_SHADER = GL_FRAGMENT_SHADER,
|
||||
VERTEX_SHADER = GL_VERTEX_SHADER,
|
||||
} GpuShaderType;
|
||||
|
||||
typedef struct {
|
||||
GpuShaderHandle handle;
|
||||
} GpuProgram;
|
||||
|
||||
typedef struct {
|
||||
GLFWwindow *win;
|
||||
i32 width;
|
||||
i32 height;
|
||||
} Window;
|
||||
|
||||
typedef struct {
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
GLuint ebo;
|
||||
u32 stride;
|
||||
u32 index_count;
|
||||
} GpuBuffer;
|
||||
|
||||
6
glc/src/platform/io/poll_events.c
Normal file
6
glc/src/platform/io/poll_events.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "../../glc.h" // IWYU pragma: keep
|
||||
|
||||
void window_poll_events(Window *win) {
|
||||
(void)win;
|
||||
glfwPollEvents();
|
||||
}
|
||||
6
glc/src/platform/io/process_input.c
Normal file
6
glc/src/platform/io/process_input.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "../../glc.h" // IWYU pragma: keep
|
||||
|
||||
void window_framebuffer_size_callback(GLFWwindow *win, int width, int height) {
|
||||
(void)win;
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
5
glc/src/platform/window/swap_buffer.c
Normal file
5
glc/src/platform/window/swap_buffer.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "../../glc.h" // IWYU pragma: keep
|
||||
|
||||
void window_buffers_swap(Window *win) {
|
||||
glfwSwapBuffers(win->win);
|
||||
}
|
||||
38
glc/src/platform/window/window.c
Normal file
38
glc/src/platform/window/window.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include "../../glc.h" // IWYU pragma: keep
|
||||
|
||||
i32 window_width_get(Window *win) {
|
||||
glfwGetWindowSize(win->win, &win->width, &win->height);
|
||||
return win->width;
|
||||
}
|
||||
|
||||
i32 window_height_get(Window *win) {
|
||||
glfwGetWindowSize(win->win, &win->width, &win->height);
|
||||
return win->height;
|
||||
}
|
||||
|
||||
Window window_create(u32 width, u32 height, const char *title) {
|
||||
glfwInit();
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWwindow *glfw_window = glfwCreateWindow(width, height, title, NULL, NULL);
|
||||
if (glfw_window == NULL) {
|
||||
err("Failed to create GL window\n");
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(glfw_window);
|
||||
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
err("Failed to initialize glad\n");
|
||||
}
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glfwSetFramebufferSizeCallback(glfw_window, (GLFWframebuffersizefun)window_framebuffer_size_callback);
|
||||
return (Window){ glfw_window, width, height };
|
||||
}
|
||||
|
||||
void window_destroy(Window *win) {
|
||||
glfwDestroyWindow(win->win);
|
||||
}
|
||||
245
glrs/Cargo.lock
generated
Normal file
245
glrs/Cargo.lock
generated
Normal file
@ -0,0 +1,245 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.72.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"log",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "glrs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.182"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
11
glrs/Cargo.toml
Normal file
11
glrs/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "glrs"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
cc = "1.2.56"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.72.1"
|
||||
cc = "1.2.56"
|
||||
41
glrs/build.rs
Normal file
41
glrs/build.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use cc;
|
||||
|
||||
fn collect_c_files(dir: &str) -> Vec<std::path::PathBuf> {
|
||||
let mut files = vec![];
|
||||
for entry in std::fs::read_dir(dir).unwrap() {
|
||||
let path = entry.unwrap().path();
|
||||
if path.is_dir() {
|
||||
files.extend(collect_c_files(path.to_str().unwrap()));
|
||||
} else if path.extension().map_or(false, |e| e == "c") {
|
||||
files.push(path);
|
||||
}
|
||||
}
|
||||
files
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let cfiles = collect_c_files("../glc/src");
|
||||
|
||||
cc::Build::new()
|
||||
.files(&cfiles)
|
||||
.compile("glc"); // produces libgl_layer.a
|
||||
|
||||
let bindings = bindgen::Builder::default()
|
||||
.header("../glc/src/glc_api.h")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.unwrap();
|
||||
|
||||
bindings
|
||||
.write_to_file(std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("bindings.rs"))
|
||||
.unwrap();
|
||||
|
||||
let bindings_header = "../glc/src/glc_api.h";
|
||||
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed={bindings_header}");
|
||||
cfiles.iter().for_each(|c| {
|
||||
println!("cargo::rerun-if-changed={}", c.parent().unwrap().to_str().unwrap());
|
||||
});
|
||||
}
|
||||
2
glrs/src/glrs.rs
Normal file
2
glrs/src/glrs.rs
Normal file
@ -0,0 +1,2 @@
|
||||
use crate::glc;
|
||||
|
||||
6
glrs/src/lib.rs
Normal file
6
glrs/src/lib.rs
Normal file
@ -0,0 +1,6 @@
|
||||
pub mod glc {
|
||||
#![allow(non_snake_case, nonstandard_style)]
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
}
|
||||
|
||||
pub mod glrs;
|
||||
196
src/app/app.rs
196
src/app/app.rs
@ -1,196 +0,0 @@
|
||||
use std::num::NonZero;
|
||||
use glutin::config::{ ConfigTemplateBuilder, GetGlConfig };
|
||||
use glutin::context::PossiblyCurrentContext;
|
||||
use glutin::display::GetGlDisplay;
|
||||
use glutin::prelude::{GlDisplay, NotCurrentGlContext, PossiblyCurrentGlContext};
|
||||
use glutin::surface::{GlSurface, Surface, SwapInterval, WindowSurface};
|
||||
use glutin_winit::{DisplayBuilder, GlWindow};
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::KeyEvent;
|
||||
use winit::keyboard::{Key, NamedKey};
|
||||
use winit::window::{ Window, WindowAttributes };
|
||||
use winit::{event, window};
|
||||
|
||||
use crate::app::gl::{gl_config_picker, gl_create_context};
|
||||
use crate::app::renderer::Renderer;
|
||||
use crate::models::ModelData;
|
||||
|
||||
enum GlDisplayCreationState {
|
||||
Builder(Box<DisplayBuilder>),
|
||||
Init
|
||||
}
|
||||
|
||||
struct AppState {
|
||||
gl_surface: Surface<WindowSurface>,
|
||||
window: Window,
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
gl_display: GlDisplayCreationState,
|
||||
gl_context: Option<PossiblyCurrentContext>,
|
||||
template: ConfigTemplateBuilder,
|
||||
|
||||
renderer: Option<Renderer>,
|
||||
current_scene: Option<String>,
|
||||
scene_data: ModelData,
|
||||
|
||||
state: Option<AppState>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(scene_data: ModelData) -> Self {
|
||||
let template = ConfigTemplateBuilder::new()
|
||||
.with_alpha_size(8)
|
||||
.with_transparency(cfg!(target_os = "macos"));
|
||||
|
||||
let display_builder = DisplayBuilder::new().with_window_attributes(Some(window_attributes()));
|
||||
|
||||
Self {
|
||||
template,
|
||||
gl_display: GlDisplayCreationState::Builder(Box::new(display_builder)),
|
||||
gl_context: None,
|
||||
renderer: None,
|
||||
state: None,
|
||||
scene_data,
|
||||
current_scene: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_current_scene(&mut self, current_scene: &str) {
|
||||
self.current_scene = Some(current_scene.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window_attributes() -> WindowAttributes {
|
||||
window::Window::default_attributes()
|
||||
.with_transparent(false)
|
||||
.with_title("Test Window")
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App {
|
||||
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
let (window, gl_config) = match &self.gl_display {
|
||||
GlDisplayCreationState::Builder(builder) => {
|
||||
let (window, gl_config) = match builder.clone().build(
|
||||
event_loop,
|
||||
self.template.clone(),
|
||||
gl_config_picker
|
||||
) {
|
||||
Ok((window, gl_config)) => (window.unwrap(), gl_config),
|
||||
Err(e) => {
|
||||
panic!("Encountered Error {:#?}", e);
|
||||
}
|
||||
};
|
||||
|
||||
self.gl_display = GlDisplayCreationState::Init;
|
||||
self.gl_context = Some(gl_create_context(&window, &gl_config).treat_as_possibly_current());
|
||||
|
||||
(window, gl_config)
|
||||
},
|
||||
GlDisplayCreationState::Init => {
|
||||
let gl_config = self.gl_context.as_ref().unwrap().config();
|
||||
match glutin_winit::finalize_window(event_loop, window_attributes(), &gl_config) {
|
||||
Ok(window) => (window, gl_config),
|
||||
Err(e) => {
|
||||
panic!("Todo: Handle error for {:#?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let attrs = window
|
||||
.build_surface_attributes(Default::default())
|
||||
.expect("Failed to build surface attributes");
|
||||
|
||||
let gl_surface = unsafe {
|
||||
gl_config.display().create_window_surface(&gl_config, &attrs).unwrap()
|
||||
};
|
||||
|
||||
let gl_context = self.gl_context.as_ref().unwrap();
|
||||
gl_context.make_current(&gl_surface).unwrap();
|
||||
|
||||
if self.renderer.is_none() {
|
||||
let mut renderer = Renderer::new(&gl_context.display());
|
||||
|
||||
renderer.upload_scene_data(&self.scene_data);
|
||||
|
||||
println!("Built Renderer");
|
||||
|
||||
self.renderer.get_or_insert_with(|| renderer);
|
||||
}
|
||||
|
||||
if let Err(res) = gl_surface.set_swap_interval(
|
||||
gl_context,
|
||||
SwapInterval::Wait(NonZero::new(1).unwrap())
|
||||
) {
|
||||
eprintln!("Error setting vsync: {:?}", res)
|
||||
}
|
||||
|
||||
assert!(self.state.replace(AppState { gl_surface, window }).is_none());
|
||||
}
|
||||
|
||||
fn suspended(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
println!("Android window removed");
|
||||
self.state = None;
|
||||
self.gl_context = Some(
|
||||
self.gl_context.take().unwrap().make_not_current().unwrap().treat_as_possibly_current()
|
||||
);
|
||||
}
|
||||
|
||||
fn window_event(
|
||||
&mut self,
|
||||
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||
_window_id: window::WindowId,
|
||||
event: event::WindowEvent,
|
||||
) {
|
||||
match event {
|
||||
event::WindowEvent::Resized(size) if size.width != 0 && size.height != 0 => {
|
||||
if let Some(AppState { gl_surface, window: _ }) = &self.state {
|
||||
let gl_context = self.gl_context.as_ref().unwrap();
|
||||
|
||||
gl_surface.resize(
|
||||
gl_context,
|
||||
NonZero::new(size.width).unwrap(),
|
||||
NonZero::new(size.height).unwrap()
|
||||
);
|
||||
|
||||
let renderer = self.renderer.as_ref().unwrap();
|
||||
renderer.resize(size.width as i32, size.height as i32);
|
||||
}
|
||||
},
|
||||
event::WindowEvent::CloseRequested
|
||||
| event::WindowEvent::KeyboardInput { event: KeyEvent { logical_key: Key::Named(NamedKey::Escape), .. }, .. } => {
|
||||
event_loop.exit();
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
fn exiting(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
let _gl_display = self.gl_context.take().unwrap().display();
|
||||
|
||||
self.state = None;
|
||||
|
||||
#[cfg(egl_backend)]
|
||||
#[allow(irrefutable_let_patterns)]
|
||||
if let glutin::display::Display::Egl(display) = _gl_display {
|
||||
unsafe {
|
||||
display.terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn about_to_wait(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||
if let Some(AppState { gl_surface, window }) = self.state.as_ref() {
|
||||
let gl_context = self.gl_context.as_ref().unwrap();
|
||||
let renderer = self.renderer.as_ref().unwrap();
|
||||
|
||||
if let Some(current_scene) = &self.current_scene {
|
||||
renderer.render(current_scene);
|
||||
}
|
||||
|
||||
window.request_redraw();
|
||||
gl_surface.swap_buffers(gl_context).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
#![allow(clippy::all)]
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
include!(concat!(env!("OUT_DIR"), "/gl_bindings.rs"));
|
||||
|
||||
pub use Gles2 as Gl;
|
||||
|
||||
use glutin::config::{Config, GlConfig};
|
||||
use glutin::context::{ContextApi, ContextAttributesBuilder, NotCurrentContext, Version};
|
||||
use glutin::display::GetGlDisplay;
|
||||
use glutin::prelude::GlDisplay;
|
||||
use raw_window_handle::HasWindowHandle;
|
||||
use winit::window::Window;
|
||||
|
||||
pub fn gl_config_picker(configs: Box<dyn Iterator<Item = Config> + '_>) -> Config {
|
||||
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()
|
||||
}
|
||||
|
||||
pub fn gl_create_context(window: &Window, gl_config: &Config) -> NotCurrentContext {
|
||||
let raw_window_handle = window.window_handle().ok().map(|wh| wh.as_raw());
|
||||
let context_attributes = ContextAttributesBuilder::new().build(raw_window_handle);
|
||||
|
||||
let fallback_context_attributes = ContextAttributesBuilder::new()
|
||||
.with_context_api(ContextApi::Gles(None))
|
||||
.build(raw_window_handle);
|
||||
|
||||
let legacy_context_attributes = ContextAttributesBuilder::new()
|
||||
.with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1))))
|
||||
.build(raw_window_handle);
|
||||
|
||||
let gl_display = gl_config.display();
|
||||
|
||||
unsafe {
|
||||
gl_display.create_context(gl_config, &context_attributes).unwrap_or_else(|_| {
|
||||
gl_display.create_context(gl_config, &fallback_context_attributes).unwrap_or_else(|_| {
|
||||
gl_display
|
||||
.create_context(gl_config, &legacy_context_attributes)
|
||||
.expect("Failed to create context")
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,208 +0,0 @@
|
||||
use glutin::prelude::GlDisplay;
|
||||
use crate::app::gl;
|
||||
use crate::models::{self, Model, ModelData, RenderObject, Scene, ShaderSource};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::ffi::{ CStr, CString };
|
||||
|
||||
fn get_gl_string(gl: &gl::Gl, variant: gl::types::GLenum) -> Option<&'static CStr>{
|
||||
unsafe {
|
||||
let s = gl.GetString(variant);
|
||||
(!s.is_null()).then(|| CStr::from_ptr(s.cast()))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Renderer {
|
||||
gl: gl::Gl,
|
||||
shaders: HashMap<String, gl::types::GLuint>,
|
||||
scenes: HashMap<String, Scene>
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
pub fn new<D: GlDisplay>(gl_display: &D) -> Self {
|
||||
let gl = gl::Gl::load_with(|symbol| {
|
||||
let symbol = CString::new(symbol).unwrap();
|
||||
gl_display.get_proc_address(symbol.as_c_str()).cast()
|
||||
});
|
||||
|
||||
if let Some(renderer) = get_gl_string(&gl, gl::RENDERER) {
|
||||
println!("Running on {}", renderer.to_string_lossy());
|
||||
}
|
||||
|
||||
if let Some(version) = get_gl_string(&gl, gl::VERSION) {
|
||||
println!("OpenGL version {}", version.to_string_lossy());
|
||||
}
|
||||
|
||||
if let Some(shaders_version) = get_gl_string(&gl, gl::SHADING_LANGUAGE_VERSION) {
|
||||
println!("Shaders version on {}", shaders_version.to_string_lossy());
|
||||
}
|
||||
|
||||
Self {
|
||||
gl,
|
||||
shaders: HashMap::new(),
|
||||
scenes: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn upload_scene_data(&mut self, scene_data: &ModelData) {
|
||||
let objects = scene_data.objects_data
|
||||
.iter()
|
||||
.map(|(mesh, shader_src)| {
|
||||
let shader = self.create_shader(shader_src);
|
||||
let render_object = self.upload_mesh(mesh);
|
||||
(render_object, shader)
|
||||
})
|
||||
.collect::<Vec<(RenderObject, u32)>>();
|
||||
println!("Uploading Scene {}", scene_data.name);
|
||||
self.scenes.insert(scene_data.name.clone(), Model { objects });
|
||||
}
|
||||
|
||||
pub fn upload_mesh(&self, mesh: &models::Mesh) -> RenderObject {
|
||||
unsafe {
|
||||
let gl = &self.gl;
|
||||
|
||||
let mut vao = std::mem::zeroed();
|
||||
gl.GenVertexArrays(1, &mut vao);
|
||||
gl.BindVertexArray(vao);
|
||||
|
||||
let mut vbo = std::mem::zeroed();
|
||||
gl.GenBuffers(1, &mut vbo);
|
||||
gl.BindBuffer(gl::ARRAY_BUFFER, vbo);
|
||||
let vertex_data = mesh.vertices
|
||||
.iter()
|
||||
.map(|v| {
|
||||
[v.x, v.y, v.z, 1.0, 0.1, 0.1]
|
||||
})
|
||||
.collect::<Vec<[f32; 6]>>();
|
||||
|
||||
gl.BufferData(
|
||||
gl::ARRAY_BUFFER,
|
||||
(vertex_data.len() * std::mem::size_of::<[f32; 6]>()) as gl::types::GLsizeiptr,
|
||||
vertex_data.as_ptr() as *const _,
|
||||
gl::STATIC_DRAW,
|
||||
);
|
||||
|
||||
let pos_attrib = 0;
|
||||
let color_attrib = 1;
|
||||
|
||||
gl.VertexAttribPointer(
|
||||
pos_attrib as gl::types::GLuint,
|
||||
3,
|
||||
gl::FLOAT,
|
||||
0,
|
||||
6 * std::mem::size_of::<f32>() as gl::types::GLsizei,
|
||||
std::ptr::null()
|
||||
);
|
||||
|
||||
gl.VertexAttribPointer(
|
||||
color_attrib as gl::types::GLuint,
|
||||
3,
|
||||
gl::FLOAT,
|
||||
0,
|
||||
6 * std::mem::size_of::<f32>() as gl::types::GLsizei,
|
||||
(3 * std::mem::size_of::<f32>()) as *const _,
|
||||
);
|
||||
|
||||
gl.EnableVertexAttribArray(pos_attrib as gl::types::GLuint);
|
||||
gl.EnableVertexAttribArray(color_attrib as gl::types::GLuint);
|
||||
|
||||
RenderObject {
|
||||
vao,
|
||||
vbo,
|
||||
_ebo: None,
|
||||
vertex_count: mesh.vertices.len() as i32,
|
||||
_index_count: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_shader(gl: &gl::Gl, shader: gl::types::GLenum, source: &[u8]) -> gl::types::GLuint {
|
||||
unsafe {
|
||||
let shader = gl.CreateShader(shader);
|
||||
gl.ShaderSource(shader, 1, [source.as_ptr().cast()].as_ptr(), std::ptr::null());
|
||||
gl.CompileShader(shader);
|
||||
shader
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_shader(&self, shader_src: &ShaderSource) -> gl::types::GLuint {
|
||||
unsafe {
|
||||
let vertex_shader = Renderer::compile_shader(&self.gl, gl::VERTEX_SHADER, shader_src.vertex_src);
|
||||
let fragment_shader = Renderer::compile_shader(&self.gl, gl::FRAGMENT_SHADER, shader_src.fragment_src);
|
||||
|
||||
let program = self.gl.CreateProgram();
|
||||
|
||||
self.gl.AttachShader(program, vertex_shader);
|
||||
self.gl.AttachShader(program, fragment_shader);
|
||||
|
||||
self.gl.LinkProgram(program);
|
||||
|
||||
self.gl.DeleteShader(vertex_shader);
|
||||
self.gl.DeleteShader(fragment_shader);
|
||||
|
||||
program
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_shader(&mut self, name: &str, shader: gl::types::GLuint) {
|
||||
if let None = self.shaders.get(name) {
|
||||
self.shaders.insert(name.to_string(), shader);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_shader(&self, name: &str) -> Option<&gl::types::GLuint> {
|
||||
self.shaders.get(name)
|
||||
}
|
||||
|
||||
pub fn remove_shader(&mut self, name: &str) {
|
||||
self.shaders.remove(name);
|
||||
}
|
||||
|
||||
pub fn resize(&self, width: i32, height: i32) {
|
||||
unsafe {
|
||||
self.gl.Viewport(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_object(&self, obj: &RenderObject, shader: gl::types::GLuint) {
|
||||
unsafe {
|
||||
self.UseProgram(shader);
|
||||
|
||||
self.BindBuffer(gl::ARRAY_BUFFER, obj.vbo);
|
||||
self.BindVertexArray(obj.vao);
|
||||
|
||||
self.DrawArrays(gl::TRIANGLES, 0, obj.vertex_count);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(&self, current_scene: &String) {
|
||||
unsafe {
|
||||
self.ClearColor(1.0, 1.0, 1.0, 0.9);
|
||||
self.Clear(gl::COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
if let Some(scene) = self.scenes.get(current_scene) {
|
||||
for model in scene.models {
|
||||
self.draw_object(obj, *shader);
|
||||
}
|
||||
} else {
|
||||
eprintln!("Unknown Scene Requested: {}", current_scene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Renderer {
|
||||
type Target = gl::Gl;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.gl
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Renderer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
self.shaders.values().for_each(|shader| self.gl.DeleteProgram(*shader));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user