summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-19 13:24:31 +1100
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-19 13:24:31 +1100
commit6182860f1b1aba4128b4f66eda7977600e60d1a0 (patch)
tree388d9aff8ca19ef324633ac1bea43f1548675150
parent5d1750d9adfc45b53c75310c58e31dfdbd8a6e15 (diff)
parentd6d742f8a24490f885e4a1ae3fea7ec46b01f58c (diff)
fix merge
-rw-r--r--.clang-format2
-rw-r--r--.github/workflows/continuous-workflow.yml9
-rw-r--r--Makefile60
-rw-r--r--README.md11
-rw-r--r--TODO.md6
-rw-r--r--archive/src/render/archive/backends/metal/backend_metal.m2
-rw-r--r--archive/xmake.lua (renamed from xmake.lua)0
-rw-r--r--assets/shaders/blinn_phong.frag97
-rw-r--r--assets/shaders/blinn_phong.vert37
-rw-r--r--assets/shaders/cube.frag13
-rw-r--r--assets/shaders/cube.metal29
-rw-r--r--assets/shaders/cube.vert21
-rw-r--r--assets/shaders/debug_quad.frag13
-rw-r--r--assets/shaders/debug_quad.vert13
-rw-r--r--assets/shaders/grid.frag60
-rw-r--r--assets/shaders/grid.vert42
-rw-r--r--assets/shaders/immdraw.frag9
-rw-r--r--assets/shaders/immdraw.vert23
-rw-r--r--assets/shaders/object.frag15
-rw-r--r--assets/shaders/object.vert29
-rw-r--r--assets/shaders/pbr_params.frag126
-rw-r--r--assets/shaders/pbr_params.vert27
-rw-r--r--assets/shaders/pbr_textured.frag159
-rw-r--r--assets/shaders/shadows.frag5
-rw-r--r--assets/shaders/shadows.vert16
-rw-r--r--assets/shaders/skinned.vert59
-rw-r--r--assets/shaders/skinned_geometry.vert52
-rw-r--r--assets/shaders/skybox.frag12
-rw-r--r--assets/shaders/skybox.vert19
-rw-r--r--assets/shaders/static_geometry.vert33
-rw-r--r--assets/shaders/terrain.frag13
-rw-r--r--assets/shaders/terrain.vert22
-rw-r--r--assets/shaders/triangle.frag6
-rw-r--r--assets/shaders/triangle.metal51
-rw-r--r--assets/shaders/triangle.vert11
-rw-r--r--assets/shaders/ui_rect.frag9
-rw-r--r--assets/shaders/ui_rect.vert13
-rw-r--r--assets/textures/mc_grass.jpegbin0 -> 20480 bytes
-rw-r--r--bindgen/BINDGEN.md1
-rw-r--r--bindgen/odin/README.md1
-rw-r--r--bindgen/rust/celeritas-sys/src/lib.rs53
-rw-r--r--bindgen/rust/src/prelude.rs30
-rw-r--r--docs/getting-started.md7
-rw-r--r--docs/index.md2
-rw-r--r--docs/project-layout.md32
-rw-r--r--examples/cube.c70
-rw-r--r--examples/triangle.c71
-rw-r--r--include/celeritas.h482
-rw-r--r--src/backend_mtl.m263
-rw-r--r--src/camera.c13
-rw-r--r--src/core.c51
-rw-r--r--src/debug_strings.c5
-rw-r--r--src/geometry.c85
-rw-r--r--src/impl.c4
-rw-r--r--src/log.c6
-rw-r--r--src/maths.c42
-rw-r--r--src/mem.c88
-rw-r--r--src/scene.c26
58 files changed, 1245 insertions, 1211 deletions
diff --git a/.clang-format b/.clang-format
index 059381e..404bcb1 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,7 +1,7 @@
---
Language: Cpp
BasedOnStyle: Google
-ColumnLimit: 100
+ColumnLimit: 120
Cpp11BracedListStyle: false # {.x = 1.0, .y = 2.0} -> { .x = 1.0, .y = 2.0 }
IncludeBlocks: Preserve # sort each block of include statements instead of all
DerivePointerAlignment: false
diff --git a/.github/workflows/continuous-workflow.yml b/.github/workflows/continuous-workflow.yml
index f9a3f53..b6c381b 100644
--- a/.github/workflows/continuous-workflow.yml
+++ b/.github/workflows/continuous-workflow.yml
@@ -5,17 +5,16 @@ jobs:
Compile-and-Test:
runs-on: ubuntu-latest
steps:
- - name: Install system dependencies, xmake, etc
+ - name: Install system dependencies, make, etc
run: |
- sudo add-apt-repository ppa:xmake-io/xmake
sudo apt update
- sudo apt install -y xmake xorg-dev libglu1-mesa-dev clang-format
+ sudo apt install -y xorg-dev libglfw3-dev libglu1-mesa-dev clang-format make
- name: Check out repository code
uses: actions/checkout@v4
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- name: Check formatting
- run: find src/ -iname *.h -o -iname *.c | xargs clang-format --style=file --dry-run --Werror
+ run: make format-check
- name: Compile C code
- run: xmake build -y
+ run: make
diff --git a/Makefile b/Makefile
index 7c50323..597ecdc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
CC := clang
-INCLUDES := -I./include -Ideps/glfw-3.3.8/include/GLFW
-CFLAGS := -Wall -Wextra -O2 $(INCLUDES)
+INCLUDES := -I./include -Ideps/glfw-3.3.8/include/GLFW -Ideps/stb_image
+CFLAGS := -Wall -Wextra -O2 -fPIC $(INCLUDES)
+# TODO(low prio): split static object files and shared object files so we can remove -fPIC from static lib builds
LDFLAGS := -lglfw
# Detect OS
@@ -18,12 +19,23 @@ EXAMPLES_DIR := examples
SRCS := $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/**/*.c)
OBJS := $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(SRCS))
+# Format-able files
+FORMAT_FILES := include/celeritas.h $(SRC_DIR)/*.c $(EXAMPLES_DIR)/*.c
+
+# Shader files
+METAL_SHADERS := $(wildcard $(SHADER_DIR)/*.metal)
+METAL_AIR_FILES := $(patsubst $(SHADER_DIR)/%.metal,$(SHADER_OUT_DIR)/%.air,$(METAL_SHADERS))
+METAL_LIB := $(SHADER_OUT_DIR)/default.metallib
+
# Library outputs
STATIC_LIB := $(BUILD_DIR)/libceleritas.a
+SHARED_FLAGS := -fPIC
ifeq ($(UNAME_S),Darwin)
SHARED_LIB := $(BUILD_DIR)/libceleritas.dylib
SHARED_FLAGS := -dynamiclib
- LDFLAGS += -framework Foundation -framework CoreFoundation -framework CoreGraphics -framework AppKit
+ LDFLAGS += -framework Foundation -framework CoreFoundation -framework CoreGraphics -framework AppKit -framework QuartzCore -framework Metal -framework MetalKit
+ SRCS += $(SRC_DIR)/backend_mtl.m
+ OBJS += $(OBJ_DIR)/backend_mtl.o
else
SHARED_LIB := $(BUILD_DIR)/libceleritas.so
SHARED_FLAGS := -shared
@@ -34,7 +46,12 @@ endif
# $^ - prerequisites of current rule separated by spaces
# $< - first prerequisite file only
-$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c include/celeritas.h
+ @mkdir -p $(OBJ_DIR)
+ $(CC) $(CFLAGS) -c $< -o $@
+
+# Objective C
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.m
@mkdir -p $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $@
@@ -50,15 +67,44 @@ shared: $(SHARED_LIB)
static: $(STATIC_LIB)
+# Shaders
+$(SHADER_OUT_DIR)/%.air: $(SHADER_DIR)/%.metal
+ @mkdir -p $(SHADER_OUT_DIR)
+ xcrun -sdk macosx metal -c $< -o $@
+
+$(METAL_LIB): $(METAL_AIR_FILES)
+ xcrun -sdk macosx metallib $^ -o $(SHADER_OUT_DIR)/default.metallib
+
.PHONY: all
all: shared static
.PHONY: triangle
-triangle: build/triangle.bin
+triangle: $(EXAMPLES_DIR)/triangle.c $(SHARED_LIB) $(SHADER_OUT_DIR)/triangle.air $(METAL_LIB)
+ @mkdir -p $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(EXAMPLES_DIR)/triangle.c -L$(BUILD_DIR) -lceleritas $(LDFLAGS) -o $(BUILD_DIR)/triangle.bin
+ MTL_DEBUG_LAYER=1 build/triangle.bin
-build/triangle.bin: $(EXAMPLES_DIR)/triangle.c $(STATIC_LIB)
+.PHONY: cube
+cube: $(EXAMPLES_DIR)/cube.c $(SHARED_LIB) $(SHADER_OUT_DIR)/cube.air $(METAL_LIB)
@mkdir -p $(BUILD_DIR)
- $(CC) $(CFLAGS) $< -o $@ -L$(BUILD_DIR) -lceleritas $(LDFLAGS)
+ $(CC) $(CFLAGS) $(EXAMPLES_DIR)/cube.c -L$(BUILD_DIR) -lceleritas $(LDFLAGS) -o $(BUILD_DIR)/cube.bin
+ MTL_DEBUG_LAYER=1 build/cube.bin
+
+.PHONY: format
+format:
+ clang-format -i $(FORMAT_FILES)
+
+.PHONY: format-check
+format-check:
+ clang-format --dry-run -Werror $(FORMAT_FILES)
+
+.PHONY: tidy-fix
+tidy:
+ clang-tidy -fix $(SRCS) $(EXAMPLES_DIR)/*.c -- $(CFLAGS)
+
+.PHONY: tidy-check
+tidy-check:
+ clang-tidy $(SRCS) $(EXAMPLES_DIR)/*.c -- $(CFLAGS)
.PHONY: clean
clean:
diff --git a/README.md b/README.md
index 9a11669..60d59a6 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,8 @@ All third-party dependencies are licensed under their own license.
- Bindgen
- Targets Vulkan 1.3 for simpler code
- Plugin system (?)
+- We can build tools on top of this layer while maintaining high performance. The C side retains
+ all rendering data.
Renderer Goals:
@@ -32,8 +34,7 @@ Renderer Goals:
#### Handy commands
-* Check symbols in an 'archive' (static library)
- * `nm -C build/libcore.a`
-* Generate compiler_commands.json
- * `xmake project -k compile_commands`
-
+- Check symbols in an 'archive' (static library)
+ - `nm -C build/libcore.a`
+- Generate compiler_commands.json
+ - `bear -- make`
diff --git a/TODO.md b/TODO.md
index a374d06..c4aac15 100644
--- a/TODO.md
+++ b/TODO.md
@@ -4,7 +4,9 @@
- ~~compile shared lib~~
- compile and run tests
- compile example
-- [ ] Consolidate down to a handful of examples
+- [x] Consolidate down to a handful of examples
- [x] Get rid of doxygen
+- [x] make format
- [ ] Move to Vulkan-first rendering
-- [ ] Build in pipeline (needs vulkan) \ No newline at end of file
+- [ ] Build in CI pipeline (needs vulkan)
+- [ ] Incorporate vma \ No newline at end of file
diff --git a/archive/src/render/archive/backends/metal/backend_metal.m b/archive/src/render/archive/backends/metal/backend_metal.m
index 4787755..0e9399e 100644
--- a/archive/src/render/archive/backends/metal/backend_metal.m
+++ b/archive/src/render/archive/backends/metal/backend_metal.m
@@ -1,5 +1,5 @@
#include <assert.h>
-// #define CEL_REND_BACKEND_METAL
+#define CEL_REND_BACKEND_METAL
#if defined(CEL_REND_BACKEND_METAL)
#include <stddef.h>
#include "ral_types.h"
diff --git a/xmake.lua b/archive/xmake.lua
index 3c05a70..3c05a70 100644
--- a/xmake.lua
+++ b/archive/xmake.lua
diff --git a/assets/shaders/blinn_phong.frag b/assets/shaders/blinn_phong.frag
deleted file mode 100644
index 267c71b..0000000
--- a/assets/shaders/blinn_phong.frag
+++ /dev/null
@@ -1,97 +0,0 @@
-#version 430 core
-out vec4 FragColor;
-
-// A Blinn-Phong material with textures for diffuse and specular
-// lighting maps and a numeric shininess factor.
-struct Material {
- sampler2D diffuse;
- sampler2D specular;
- float shininess;
-};
-
-struct DirLight {
- vec3 direction;
- vec3 ambient;
- vec3 diffuse;
- vec3 specular;
-};
-
-struct PointLight {
- vec3 position;
- // fall off properties
- float constant;
- float linear;
- float quadratic;
-
- vec3 ambient;
- vec3 diffuse;
- vec3 specular;
-};
-
-in VS_OUT {
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- // vec4 FragPosLightSpace;
- vec4 Color;
-} fs_in;
-
-// --- Uniforms
-#define NUM_POINT_LIGHTS 4
-uniform vec3 viewPos;
-uniform Material material;
-uniform DirLight dirLight;
-uniform PointLight pointLights[NUM_POINT_LIGHTS];
-
-// --- Function prototypes
-vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
-vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
-
-void main() {
- vec3 norm = normalize(fs_in.Normal);
- vec3 viewDir = normalize(viewPos - fs_in.FragPos);
-
- vec3 result = CalcDirLight(dirLight, norm, viewDir);
- for (int i = 0; i < 4; i++) {
- result += CalcPointLight(pointLights[i], norm, fs_in.FragPos, viewDir);
- }
-
-// FragColor = vec4(result, 1.0);
- FragColor = fs_in.Color + 0.5;
-}
-
-vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
-{
- vec3 lightDir = normalize(-light.direction);
- // diffuse shading
- float diff = max(dot(normal, lightDir), 0.0);
- // specular shading
- vec3 reflectDir = reflect(-lightDir, normal);
- float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
- // combine result
- vec3 ambient = light.ambient * vec3(texture(material.diffuse, fs_in.TexCoords));
- vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, fs_in.TexCoords));
- vec3 specular = light.specular * spec * vec3(texture(material.specular, fs_in.TexCoords));
- return (ambient + diffuse + specular);
-}
-
-vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
-{
- vec3 lightDir = normalize(light.position - fragPos);
- // diffuse
- float diff = max(dot(normal, lightDir), 0.0);
- // specular
- vec3 reflectDir = reflect(-lightDir, normal);
- float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
- // attentuation
- float distance = length(light.position - fragPos);
- float attentuation = 1.0 / (light.constant + light.linear * distance * light.quadratic * (distance * distance));
- // result
- vec3 ambient = light.ambient * vec3(texture(material.diffuse, fs_in.TexCoords));
- vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, fs_in.TexCoords));
- vec3 specular = light.specular * spec * vec3(texture(material.specular, fs_in.TexCoords));
- ambient *= attentuation;
- diffuse *= attentuation;
- specular *= attentuation;
- return (ambient + diffuse + specular);
-}
diff --git a/assets/shaders/blinn_phong.vert b/assets/shaders/blinn_phong.vert
deleted file mode 100644
index 18609b7..0000000
--- a/assets/shaders/blinn_phong.vert
+++ /dev/null
@@ -1,37 +0,0 @@
-#version 410 core
-
-struct Uniforms {
- mat4 model;
- mat4 view;
- mat4 projection;
-};
-
-uniform Uniforms ubo;
-
-// Inputs
-layout (location = 0) in vec3 inPos;
-layout (location = 1) in vec3 inNormal;
-layout (location = 2) in vec2 inTexCoords;
-
-// uniform mat4 model;
-// uniform mat4 view;
-// uniform mat4 projection;
-// uniform mat4 lightSpaceMatrix;
-
-// Output
-out VS_OUT {
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- // vec4 FragPosLightSpace;
- vec4 Color;
-} vs_out;
-
-void main() {
- vs_out.FragPos = vec3(ubo.model * vec4(inPos, 1.0));
- vs_out.Normal = inNormal;
- vs_out.TexCoords = inTexCoords;
- // vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
- vs_out.Color = vec4(1.0);
- gl_Position = ubo.projection * ubo.view * ubo.model * vec4(inPos, 1.0);
-}
diff --git a/assets/shaders/cube.frag b/assets/shaders/cube.frag
deleted file mode 100644
index a405e6a..0000000
--- a/assets/shaders/cube.frag
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 410
-
-layout(location = 0) in vec3 fragColor;
-layout(location = 1) in vec2 fragTexCoord;
-
- uniform sampler2D texSampler;
-
-layout(location = 0) out vec4 outColor;
-
-void main() {
- outColor = texture(texSampler, fragTexCoord); // vec4(fragTexCoord, 0.0);
- // outColor = vec4(1.0);
-}
diff --git a/assets/shaders/cube.metal b/assets/shaders/cube.metal
new file mode 100644
index 0000000..dc7ace1
--- /dev/null
+++ b/assets/shaders/cube.metal
@@ -0,0 +1,29 @@
+#include <metal_stdlib>
+using namespace metal;
+
+struct VertexData {
+ float4 position;
+ float4 normal;
+ float2 texCoords;
+};
+
+struct VertexOut {
+ float4 position [[position]];
+ float2 textureCoordinate;
+};
+
+struct TransformationData {
+ float4x4 modelMatrix;
+ float4x4 viewMatrix;
+ float4x4 perspectiveMatrix;
+};
+
+vertex VertexOut cubeVertexShader(uint vertexID [[vertex_id]],
+ constant VertexData* vertexData,
+ constant TransformationData* transformationData)
+{
+ VertexOut out;
+ out.position = transformationData->perspectiveMatrix * transformationData->viewMatrix * transformationData->modelMatrix * vertexData[vertexID].position;
+ out.textureCoordinate = vertexData[vertexID].texCoords;
+ return out;
+} \ No newline at end of file
diff --git a/assets/shaders/cube.vert b/assets/shaders/cube.vert
deleted file mode 100644
index cd345f6..0000000
--- a/assets/shaders/cube.vert
+++ /dev/null
@@ -1,21 +0,0 @@
-#version 410 core
-
-uniform Matrices {
- mat4 model;
- mat4 view;
- mat4 proj;
-} ubo;
-
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-
-layout(location = 0) out vec3 fragColor;
-layout(location = 1) out vec2 fragTexCoord;
-
-void main() {
- gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
- // gl_Position = vec4(inPosition, 1.0);
- fragColor = abs(inNormal);
- fragTexCoord = inTexCoords;
-}
diff --git a/assets/shaders/debug_quad.frag b/assets/shaders/debug_quad.frag
deleted file mode 100644
index 877b26a..0000000
--- a/assets/shaders/debug_quad.frag
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 410 core
-out vec4 FragColor;
-
-in vec2 TexCoords;
-
-uniform sampler2D depthMap;
-
-void main()
-{
- float depthValue = texture(depthMap, TexCoords).r;
- FragColor = vec4(vec3(depthValue), 1.0); // orthographic
- //FragColor = vec4(1.0);
-}
diff --git a/assets/shaders/debug_quad.vert b/assets/shaders/debug_quad.vert
deleted file mode 100644
index 8b8201c..0000000
--- a/assets/shaders/debug_quad.vert
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 410 core
-layout (location = 0) in vec3 inPosition;
-layout (location = 1) in vec3 inNormal;
-layout (location = 2) in vec2 inTexCoords;
-
-out vec2 TexCoords;
-
-void main()
-{
- TexCoords = inTexCoords;
- vec2 xy = inPosition.xz;
- gl_Position = vec4(xy, 0.0, 1.0);
-}
diff --git a/assets/shaders/grid.frag b/assets/shaders/grid.frag
deleted file mode 100644
index 6cf8a7c..0000000
--- a/assets/shaders/grid.frag
+++ /dev/null
@@ -1,60 +0,0 @@
-#version 410 core
-
-out vec4 FragColor;
-
-in float near; //0.01
-in float far; //100
-in vec3 nearPoint;
-in vec3 farPoint;
-in mat4 fragView;
-in mat4 fragProj;
-
-// void main() {
-// // FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-// float t = -nearPoint.y / (farPoint.y - nearPoint.y);
-// if (t > 0) {
-// FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-// } else {
-// FragColor = vec4(0.0);
-// }
-// // FragColor = vec4(1.0, 0.0, 0.0, 1.0 * float(t > 0)); // opacity = 1 when t > 0, opacity = 0 otherwise
-// }
-
-vec4 grid(vec3 fragPos3D, float scale, bool drawAxis) {
- vec2 coord = fragPos3D.xz * scale;
- vec2 derivative = fwidth(coord);
- vec2 grid = abs(fract(coord - 0.5) - 0.5) / derivative;
- float line = min(grid.x, grid.y);
- float minimumz = min(derivative.y, 1);
- float minimumx = min(derivative.x, 1);
- vec4 color = vec4(0.2, 0.2, 0.2, 1.0 - min(line, 1.0));
- // z axis
- if(fragPos3D.x > -0.1 * minimumx && fragPos3D.x < 0.1 * minimumx)
- color.z = 1.0;
- // x axis
- if(fragPos3D.z > -0.1 * minimumz && fragPos3D.z < 0.1 * minimumz)
- color.x = 1.0;
- return color;
-}
-float computeDepth(vec3 pos) {
- vec4 clip_space_pos = fragProj * fragView * vec4(pos.xyz, 1.0);
- return (clip_space_pos.z / clip_space_pos.w);
-}
-float computeLinearDepth(vec3 pos) {
- vec4 clip_space_pos = fragProj * fragView * vec4(pos.xyz, 1.0);
- float clip_space_depth = (clip_space_pos.z / clip_space_pos.w) * 2.0 - 1.0; // put back between -1 and 1
- float linearDepth = (2.0 * near * far) / (far + near - clip_space_depth * (far - near)); // get linear value between 0.01 and 100
- return linearDepth / far; // normalize
-}
-void main() {
- float t = -nearPoint.y / (farPoint.y - nearPoint.y);
- vec3 fragPos3D = nearPoint + t * (farPoint - nearPoint);
-
- gl_FragDepth = computeDepth(fragPos3D);
-
- float linearDepth = computeLinearDepth(fragPos3D);
- float fading = max(0, (0.5 - linearDepth));
-
- FragColor = (grid(fragPos3D, 10, true) + grid(fragPos3D, 1, true))* float(t > 0); // adding multiple resolution for the grid
- FragColor.a *= fading;
-} \ No newline at end of file
diff --git a/assets/shaders/grid.vert b/assets/shaders/grid.vert
deleted file mode 100644
index 592cbfc..0000000
--- a/assets/shaders/grid.vert
+++ /dev/null
@@ -1,42 +0,0 @@
-#version 410 core
-
-uniform Camera {
- mat4 view;
- mat4 proj;
- vec4 viewPos;
-} cam;
-
-out vec3 nearPoint;
-out vec3 farPoint;
-out float near;
-out float far;
-out mat4 fragView;
-out mat4 fragProj;
-
-// Grid position are in xy clipped space
-vec3 gridPlane[6] = vec3[](
- vec3(1, 1, 0), vec3(-1, -1, 0), vec3(-1, 1, 0),
- vec3(-1, -1, 0), vec3(1, 1, 0), vec3(1, -1, 0)
-);
-
-vec3 UnprojectPoint(float x, float y, float z, mat4 view, mat4 projection) {
- mat4 viewInv = inverse(view);
- mat4 projInv = inverse(projection);
- vec4 unprojectedPoint = viewInv * projInv * vec4(x, y, z, 1.0);
- return unprojectedPoint.xyz / unprojectedPoint.w;
-}
-
-// normal vertex projection
-void main() {
- // gl_Position = cam.proj * cam.view * vec4(gridPlane[gl_VertexID].xyz, 1.0);
- vec3 p = gridPlane[gl_VertexID].xyz;
- nearPoint = UnprojectPoint(p.x, p.y, -1.0, cam.view, cam.proj).xyz; // unprojecting on the near plane
- farPoint = UnprojectPoint(p.x, p.y, 1.0, cam.view, cam.proj).xyz; // unprojecting on the far plane
-
- fragView = cam.view;
- fragProj = cam.proj;
- near = 0.01;
- far = 100.0;
-
- gl_Position = vec4(p, 1.0); // using directly the clipped coordinates
-} \ No newline at end of file
diff --git a/assets/shaders/immdraw.frag b/assets/shaders/immdraw.frag
deleted file mode 100644
index 9cb214f..0000000
--- a/assets/shaders/immdraw.frag
+++ /dev/null
@@ -1,9 +0,0 @@
-#version 410 core
-
-out vec4 FragColor;
-
-in vec4 aColour;
-
-void main() {
- FragColor = aColour;
-}
diff --git a/assets/shaders/immdraw.vert b/assets/shaders/immdraw.vert
deleted file mode 100644
index ee9e7ca..0000000
--- a/assets/shaders/immdraw.vert
+++ /dev/null
@@ -1,23 +0,0 @@
-#version 410 core
-
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-
-uniform Camera {
- mat4 view;
- mat4 proj;
- vec4 viewPos;
-} cam;
-
-uniform ImmUniforms {
- mat4 model;
- vec4 colour;
-} imm;
-
-out vec4 aColour;
-
-void main() {
- aColour = imm.colour;
- gl_Position = cam.proj * cam.view * imm.model * vec4(inPosition, 1.0);
-}
diff --git a/assets/shaders/object.frag b/assets/shaders/object.frag
deleted file mode 100644
index fa50fcf..0000000
--- a/assets/shaders/object.frag
+++ /dev/null
@@ -1,15 +0,0 @@
-#version 450
-#extension GL_ARB_separate_shader_objects : enable
-
-layout(location = 0) in vec3 in_position;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec2 in_tex_coord;
-
-layout(set = 0, binding = 1) uniform sampler2D texSampler;
-
-layout(location = 0) out vec4 out_color;
-
-void main() {
- // out_color = vec4(1.0);
- out_color = texture(texSampler, in_tex_coord);
-} \ No newline at end of file
diff --git a/assets/shaders/object.vert b/assets/shaders/object.vert
deleted file mode 100644
index 23c0ffb..0000000
--- a/assets/shaders/object.vert
+++ /dev/null
@@ -1,29 +0,0 @@
-#version 450
-#extension GL_ARB_separate_shader_objects : enable
-
-layout(location = 0) in vec3 in_position;
-layout(location = 1) in vec3 in_normal;
-layout(location = 2) in vec2 in_tex_coord;
-
-layout(location = 0) out vec3 out_position;
-layout(location = 1) out vec3 out_normal;
-layout(location = 2) out vec2 out_tex_coord;
-
-layout(set = 0, binding = 0) uniform global_object_uniform {
- mat4 projection;
- mat4 view;
-}
-global_ubo;
-
-layout(push_constant) uniform push_constants {
- mat4 model; // 64 bytes
-}
-u_push_constants;
-
-void main() {
- gl_Position = global_ubo.projection * global_ubo.view * u_push_constants.model *
- vec4(in_position.x, in_position.y, in_position.z, 1.0);
- out_position = in_position;
- out_normal = in_normal;
- out_tex_coord = in_tex_coord;
-} \ No newline at end of file
diff --git a/assets/shaders/pbr_params.frag b/assets/shaders/pbr_params.frag
deleted file mode 100644
index 7dbdc9d..0000000
--- a/assets/shaders/pbr_params.frag
+++ /dev/null
@@ -1,126 +0,0 @@
-#version 410 core
-
-out vec4 FragColor;
-
-layout(location = 0) in vec3 fragWorldPos;
-layout(location = 1) in vec3 fragNormal;
-layout(location = 2) in vec2 fragTexCoords;
-
-struct PointLight {
- vec4 position;
- vec4 color;
-};
-
-// --- Uniforms
-// Material properties
-uniform PBR_Params {
- uniform vec3 albedo;
- uniform float metallic;
- uniform float roughness;
- uniform float ao;
-} pbr;
-// Lights data
-#define NUM_POINT_LIGHTS 4
-uniform Scene_Lights {
- PointLight pointLights[NUM_POINT_LIGHTS];
- vec4 viewPos;
-} scene;
-
-const float PI = 3.14;
-
-// Forward declarations
-vec3 fresnelSchlick(float cosTheta, vec3 F0);
-float DistributionGGX(vec3 N, vec3 H, float roughness);
-float GeometrySchlickGGX(float NdotV, float roughness);
-float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness);
-
-void main() {
- vec3 norm = normalize(fragNormal); // N
- vec3 N = norm;
- vec3 viewDir = normalize(vec3(scene.viewPos) - fragWorldPos); // V
- vec3 V = viewDir;
-
- vec3 F0 = vec3(0.04);
- F0 = mix(F0, pbr.albedo, pbr.metallic);
-
- vec3 Lo = vec3(0.0);
- for (int i = 0; i < 4; ++i) {
- vec3 lightVec = normalize(vec3(scene.pointLights[i].position) - fragWorldPos); // L
- vec3 L = lightVec;
- vec3 halfway = normalize(viewDir + lightVec); // H
- vec3 H = halfway;
- float distance = length(vec3(scene.pointLights[i].position) - fragWorldPos);
- float attenuation = 1.0 / (distance * distance);
- vec3 radiance = vec3(scene.pointLights[i].color) * attenuation;
-
- // cook-torrance brdf
- float NDF = DistributionGGX(norm, halfway, pbr.roughness);
- float G = GeometrySmith(norm, viewDir, lightVec, pbr.roughness);
- // vec3 F = fresnelSchlick(max(dot(halfway, viewDir), 0.0), F0);
- vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
-
- vec3 numerator = NDF * G * F;
- float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
- vec3 specular = numerator / denominator;
-
- vec3 kS = F;
-
- vec3 kD = vec3(1.0) - kS;
- kD *= 1.0 - pbr.metallic;
-
- // add to outgoing radiance Lo
- float NdotL = max(dot(N, L), 0.0);
- Lo += (kD * pbr.albedo / PI + specular) * radiance * NdotL;
- // Lo += radiance;
- }
-
- vec3 ambient = vec3(0.03) * pbr.albedo * pbr.ao;
- vec3 color = ambient + Lo; //ambient + Lo;
-
- color = color / (color + vec3(1.0));
- color = pow(color, vec3(1.0/2.2));
-
- FragColor = vec4(color, 1.0);
- // FragColor = vec4(scene.pointLights[0].position);
- //FragColor = vec4(fragNormal, 1.0);
- // FragColor = vec4(pbr.metallic, pbr.roughness, pbr.ao, 1.0);
- // FragColor = scene.viewPos;
-}
-
-/* The below are from https://learnopengl.com/PBR/Lighting */
-
-vec3 fresnelSchlick(float cosTheta, vec3 F0) {
- return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
-}
-float DistributionGGX(vec3 N, vec3 H, float roughness) {
- float a = roughness*roughness;
- float a2 = a*a;
- float NdotH = max(dot(N, H), 0.0);
- float NdotH2 = NdotH*NdotH;
-
- float num = a2;
- float denom = (NdotH2 * (a2 - 1.0) + 1.0);
- denom = PI * denom * denom;
-
- return num / denom;
-}
-
-float GeometrySchlickGGX(float NdotV, float roughness)
-{
- float r = (roughness + 1.0);
- float k = (r*r) / 8.0;
-
- float num = NdotV;
- float denom = NdotV * (1.0 - k) + k;
-
- return num / denom;
-}
-float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
-{
- float NdotV = max(dot(N, V), 0.0);
- float NdotL = max(dot(N, L), 0.0);
- float ggx2 = GeometrySchlickGGX(NdotV, roughness);
- float ggx1 = GeometrySchlickGGX(NdotL, roughness);
-
- return ggx1 * ggx2;
-}
diff --git a/assets/shaders/pbr_params.vert b/assets/shaders/pbr_params.vert
deleted file mode 100644
index 01d0cfe..0000000
--- a/assets/shaders/pbr_params.vert
+++ /dev/null
@@ -1,27 +0,0 @@
-#version 410 core
-
-// Vertex attributes
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-
-// Uniforms
-uniform MVP_Matrices {
- mat4 model; // TODO: make model a push constant/raw uniform
- mat4 view;
- mat4 proj;
-} mvp;
-
-// Outputs
-layout(location = 0) out vec3 fragWorldPos;
-layout(location = 1) out vec3 fragNormal;
-layout(location = 2) out vec2 fragTexCoords;
-
-void main() {
- fragWorldPos = vec3(mvp.model * vec4(inPosition, 1.0));
- fragNormal = mat3(transpose(inverse(mvp.model))) * inNormal;
-
- fragTexCoords = inTexCoords;
-
- gl_Position = mvp.proj * mvp.view * mvp.model * vec4(inPosition, 1.0);
-}
diff --git a/assets/shaders/pbr_textured.frag b/assets/shaders/pbr_textured.frag
deleted file mode 100644
index 0c801f8..0000000
--- a/assets/shaders/pbr_textured.frag
+++ /dev/null
@@ -1,159 +0,0 @@
-#version 410 core
-
-out vec4 FragColor;
-
-in vec3 fragWorldPos;
-in vec3 fragNormal;
-in vec2 fragTexCoords;
-
-in vec4 viewPos;
-
-struct PointLight {
- vec4 position;
- vec4 color;
-};
-
-// --- Uniforms
-
-// Lights data
-#define NUM_POINT_LIGHTS 4
-uniform Lights {
- PointLight pointLights[NUM_POINT_LIGHTS];
-} scene;
-
-uniform PBR_Params {
- vec3 albedo;
- float metallic;
- float roughness;
- float ao;
-} params;
-
-// Material Textures
-uniform sampler2D albedoMap;
-uniform sampler2D metallicRoughnessMap;
-uniform sampler2D aoMap;
-uniform sampler2D normalMap;
-
-const float PI = 3.14;
-
-// Forward declarations
-vec3 fresnelSchlick(float cosTheta, vec3 F0);
-float DistributionGGX(vec3 N, vec3 H, float roughness);
-float GeometrySchlickGGX(float NdotV, float roughness);
-float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness);
-
-vec3 getNormalFromMap()
-{
- vec3 tangentNormal = texture(normalMap, fragTexCoords).xyz * 2.0 - 1.0;
-
- vec3 Q1 = dFdx(fragWorldPos);
- vec3 Q2 = dFdy(fragWorldPos);
- vec2 st1 = dFdx(fragTexCoords);
- vec2 st2 = dFdy(fragTexCoords);
-
- vec3 N = normalize(fragNormal);
- vec3 T = normalize(Q1 * st2.t - Q2 * st1.t);
- vec3 B = -normalize(cross(N, T));
- mat3 TBN = mat3(T, B, N);
-
- return normalize(TBN * tangentNormal);
-}
-
-void main() {
- // vec3 albedo = pow(texture(albedoMap, fragTexCoords).rgb, vec3(2.2));
- vec3 albedo = params.albedo * texture(albedoMap, fragTexCoords).rgb;
- float metallic = params.metallic * texture(metallicRoughnessMap, fragTexCoords).b;
- float roughness = params.roughness * texture(metallicRoughnessMap, fragTexCoords).g;
- float ao = texture(aoMap, fragTexCoords).r;
-
- // vec3 norm = normalize(fragNormal); // N
- vec3 norm = getNormalFromMap();
- vec3 N = norm;
- vec3 viewDir = normalize(vec3(viewPos) - fragWorldPos); // V
- vec3 V = viewDir;
-
- vec3 F0 = vec3(0.04);
- F0 = mix(F0, albedo, metallic);
-
- vec3 Lo = vec3(0.0);
- for (int i = 0; i < 4; ++i) {
- vec3 lightVec = normalize(vec3(scene.pointLights[i].position) - fragWorldPos); // L
- vec3 L = lightVec;
- vec3 halfway = normalize(viewDir + lightVec); // H
- vec3 H = halfway;
- float distance = length(vec3(scene.pointLights[i].position) - fragWorldPos);
- float attenuation = 1.0 / (distance * distance);
- vec3 radiance = vec3(scene.pointLights[i].color) * attenuation;
-
- // cook-torrance brdf
- float NDF = DistributionGGX(norm, halfway, roughness);
- float G = GeometrySmith(norm, viewDir, lightVec, roughness);
- // vec3 F = fresnelSchlick(max(dot(halfway, viewDir), 0.0), F0);
- vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0);
-
- vec3 numerator = NDF * G * F;
- float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
- vec3 specular = numerator / denominator;
-
- vec3 kS = F;
-
- vec3 kD = vec3(1.0) - kS;
- kD *= 1.0 - metallic;
-
- // add to outgoing radiance Lo
- float NdotL = max(dot(N, L), 0.0);
- Lo += (kD * albedo / PI + specular) * radiance * NdotL;
- // Lo += radiance;
- }
-
- vec3 ambient = vec3(0.03) * albedo * ao;
- vec3 color = ambient + Lo; //ambient + Lo;
-
- color = color / (color + vec3(1.0));
- color = pow(color, vec3(1.0 / 2.2));
-
- FragColor = vec4(color, 1.0);
- FragColor = vec4(1.0);
- // FragColor = vec4(scene.pointLights[0].position);
- // FragColor = vec4(albedo, 1.0);
- // FragColor = vec4(pbr.metallic, pbr.roughness, pbr.ao, 1.0);
- // FragColor = vec4(fragTexCoords, 0.0, 1.0);
-}
-
-/* The below are from https://learnopengl.com/PBR/Lighting */
-
-vec3 fresnelSchlick(float cosTheta, vec3 F0) {
- return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
-}
-float DistributionGGX(vec3 N, vec3 H, float roughness) {
- float a = roughness * roughness;
- float a2 = a * a;
- float NdotH = max(dot(N, H), 0.0);
- float NdotH2 = NdotH * NdotH;
-
- float num = a2;
- float denom = (NdotH2 * (a2 - 1.0) + 1.0);
- denom = PI * denom * denom;
-
- return num / denom;
-}
-
-float GeometrySchlickGGX(float NdotV, float roughness)
-{
- float r = (roughness + 1.0);
- float k = (r * r) / 8.0;
-
- float num = NdotV;
- float denom = NdotV * (1.0 - k) + k;
-
- return num / denom;
-}
-float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
-{
- float NdotV = max(dot(N, V), 0.0);
- float NdotL = max(dot(N, L), 0.0);
- float ggx2 = GeometrySchlickGGX(NdotV, roughness);
- float ggx1 = GeometrySchlickGGX(NdotL, roughness);
-
- return ggx1 * ggx2;
-}
diff --git a/assets/shaders/shadows.frag b/assets/shaders/shadows.frag
deleted file mode 100644
index 0876b66..0000000
--- a/assets/shaders/shadows.frag
+++ /dev/null
@@ -1,5 +0,0 @@
-#version 410 core
-
-void main() {
- gl_FragDepth = gl_FragCoord.z;
-} \ No newline at end of file
diff --git a/assets/shaders/shadows.vert b/assets/shaders/shadows.vert
deleted file mode 100644
index 65ff169..0000000
--- a/assets/shaders/shadows.vert
+++ /dev/null
@@ -1,16 +0,0 @@
-#version 410 core
-
-// Vertex attributes
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-
-// Uniforms
-uniform ShadowUniforms {
- mat4 model;
- mat4 lightSpace;
-} uniforms;
-
-void main() {
- gl_Position = uniforms.lightSpace * uniforms.model * vec4(inPosition, 1.0);
-}
diff --git a/assets/shaders/skinned.vert b/assets/shaders/skinned.vert
deleted file mode 100644
index cb2ca85..0000000
--- a/assets/shaders/skinned.vert
+++ /dev/null
@@ -1,59 +0,0 @@
-#version 410 core
-// Inputs
-layout (location = 0) in vec3 inPos;
-layout (location = 1) in vec3 inNormal;
-layout (location = 2) in vec2 inTexCoords;
-layout (location = 3) in ivec4 inBoneIndices;
-layout (location = 4) in vec4 inWeights;
-
-uniform mat4 model;
-uniform mat4 view;
-uniform mat4 projection;
-uniform mat4 lightSpaceMatrix;
-
-const int MAX_BONES = 100;
-const int MAX_BONE_INFLUENCES = 4;
-uniform mat4 boneMatrices[MAX_BONES]; // TODO!
-
-// Output
-out VS_OUT {
- vec3 FragPos;
- vec3 Normal;
- vec2 TexCoords;
- vec4 FragPosLightSpace;
- vec4 Color;
-} vs_out;
-
-void main() {
- // vec4 totalPosition = vec4(0.0f);
- // for(int i = 0 ; i < MAX_BONE_INFLUENCES ; i++) {
- // if(inBoneIndices[i] == 0)
- // continue;
- // if(inBoneIndices[i] >=MAX_BONES)
- // {
- // totalPosition = vec4(inPos,1.0f);
- // break;
- // }
- // vec4 localPosition = finalBoneMatrices[inBoneIndices[i]] * vec4(inPos,1.0f);
- // totalPosition += localPosition * inWeights[i];
- // vec3 localNormal = mat3(finalBoneMatrices[inBoneIndices[i]]) * inNormal;
- // vs_out.Normal = localNormal;
- // }
-
-
- mat4 skinMatrix = // mat4(1.0)
- // boneMatrices[int(inBoneIndices.z)]; // should just be the identtiy
- inWeights.x * boneMatrices[int(inBoneIndices.x)] +
- inWeights.y * boneMatrices[int(inBoneIndices.y)] +
- inWeights.z * boneMatrices[int(inBoneIndices.z)] +
- inWeights.w * boneMatrices[int(inBoneIndices.w)];
-
- vec4 totalPosition = skinMatrix * vec4(inPos, 1.0);
-
- vs_out.FragPos = vec3(model * totalPosition);
- // vs_out.Normal = inNormal;
- vs_out.TexCoords = inTexCoords;
- vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0);
- vs_out.Color = inWeights;
- gl_Position = projection * view * model * totalPosition;
-} \ No newline at end of file
diff --git a/assets/shaders/skinned_geometry.vert b/assets/shaders/skinned_geometry.vert
deleted file mode 100644
index a610442..0000000
--- a/assets/shaders/skinned_geometry.vert
+++ /dev/null
@@ -1,52 +0,0 @@
-#version 410 core
-
-// Vertex attributes
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-layout(location = 3) in ivec4 inBoneIndices;
-layout(location = 4) in vec4 inWeights;
-
-const int MAX_BONES = 100;
-const int MAX_BONE_INFLUENCES = 4;
-
-uniform AnimData {
- mat4 boneMatrices[MAX_BONES];
-} anim;
-
-uniform Camera {
- mat4 view;
- mat4 proj;
- vec4 viewPos;
-} cam;
-
-uniform Model {
- mat4 inner;
-} model;
-
-// Outputs
-layout(location = 0) out vec3 fragWorldPos;
-layout(location = 1) out vec3 fragNormal;
-layout(location = 2) out vec2 fragTexCoords;
-
-out vec4 viewPos;
-// out vec4 dbgcolor;
-
-void main() {
- mat4 skinMatrix =
- inWeights.x * anim.boneMatrices[int(inBoneIndices.x)] +
- inWeights.y * anim.boneMatrices[int(inBoneIndices.y)] +
- inWeights.z * anim.boneMatrices[int(inBoneIndices.z)] +
- inWeights.w * anim.boneMatrices[int(inBoneIndices.w)];
-
- vec4 totalPosition = skinMatrix * vec4(inPosition, 1.0);
-
- fragWorldPos = vec3(model.inner * totalPosition);
- fragNormal = mat3(transpose(inverse(model.inner))) * inNormal; // world-space normal
- fragTexCoords = inTexCoords;
-
- viewPos = cam.viewPos;
-
- gl_Position = cam.proj * cam.view * model.inner * vec4(inPosition, 1.0);
- // gl_Position = cam.proj * cam.view * model.inner * totalPosition;
-}
diff --git a/assets/shaders/skybox.frag b/assets/shaders/skybox.frag
deleted file mode 100644
index d2f3844..0000000
--- a/assets/shaders/skybox.frag
+++ /dev/null
@@ -1,12 +0,0 @@
-#version 410 core
-
-out vec4 FragColor;
-
-in vec3 TexCoords;
-
-uniform samplerCube cubeMap;
-
-void main() {
- FragColor = texture(cubeMap, TexCoords);
- // FragColor = vec4(1.0, 0.0, 0.0, 1.0);
-}
diff --git a/assets/shaders/skybox.vert b/assets/shaders/skybox.vert
deleted file mode 100644
index 6b56527..0000000
--- a/assets/shaders/skybox.vert
+++ /dev/null
@@ -1,19 +0,0 @@
-#version 410 core
-
-layout(location = 0) in vec3 inPosition;
-// layout(location = 1) in vec3 inNormal;
-// layout(location = 2) in vec2 inTexCoords;
-
-uniform Camera {
- mat4 view;
- mat4 proj;
- vec4 viewPos;
-} cam;
-
-out vec3 TexCoords;
-
-void main() {
- TexCoords = inPosition;
- vec4 pos = cam.proj * cam.view * vec4(inPosition, 1.0);
- gl_Position = pos.xyww;
-}
diff --git a/assets/shaders/static_geometry.vert b/assets/shaders/static_geometry.vert
deleted file mode 100644
index 2021691..0000000
--- a/assets/shaders/static_geometry.vert
+++ /dev/null
@@ -1,33 +0,0 @@
-#version 410 core
-
-// Vertex attributes
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-
-uniform Camera {
- mat4 view;
- mat4 proj;
- vec4 viewPos;
-} cam;
-
-uniform Model {
- mat4 inner;
-} model;
-
-// Outputs
-layout(location = 0) out vec3 fragWorldPos;
-layout(location = 1) out vec3 fragNormal;
-layout(location = 2) out vec2 fragTexCoords;
-
-out vec4 viewPos;
-
-void main() {
- fragWorldPos = vec3(model.inner * vec4(inPosition, 1.0));
- fragNormal = mat3(transpose(inverse(model.inner))) * inNormal; // world-space normal
- fragTexCoords = inTexCoords;
-
- viewPos = cam.viewPos;
-
- gl_Position = cam.proj * cam.view * model.inner * vec4(inPosition, 1.0);
-}
diff --git a/assets/shaders/terrain.frag b/assets/shaders/terrain.frag
deleted file mode 100644
index 0cc76c8..0000000
--- a/assets/shaders/terrain.frag
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 410 core
-
-out vec4 FragColor;
-
-in vec4 Color;
-in vec2 TexCoord;
-
-uniform sampler2D TextureSlot1;
-
-void main() {
- vec4 tex_color = texture(TextureSlot1, TexCoord);
- FragColor = Color * tex_color;
-} \ No newline at end of file
diff --git a/assets/shaders/terrain.vert b/assets/shaders/terrain.vert
deleted file mode 100644
index 40f2b3e..0000000
--- a/assets/shaders/terrain.vert
+++ /dev/null
@@ -1,22 +0,0 @@
-#version 410 core
-
-layout(location = 0) in vec3 inPosition;
-layout(location = 1) in vec3 inNormal;
-layout(location = 2) in vec2 inTexCoords;
-
-uniform Camera {
- mat4 view;
- mat4 proj;
- vec4 viewPos;
-} cam;
-
-out vec4 Color;
-out vec2 TexCoord;
-
-void main() {
- vec3 position = vec3(inPosition.x, inPosition.y / 2.0, inPosition.z);
- gl_Position = cam.proj * cam.view * vec4(position, 1.0);
-
- Color = vec4(inPosition.y / 100.0);
- TexCoord = inTexCoords;
-} \ No newline at end of file
diff --git a/assets/shaders/triangle.frag b/assets/shaders/triangle.frag
deleted file mode 100644
index 3ae1fc4..0000000
--- a/assets/shaders/triangle.frag
+++ /dev/null
@@ -1,6 +0,0 @@
-#version 410
-
-layout(location = 0) in vec3 fragColor;
-layout(location = 0) out vec4 outColor;
-
-void main() { outColor = vec4(fragColor, 0.0); }
diff --git a/assets/shaders/triangle.metal b/assets/shaders/triangle.metal
index 6055705..ccb7ca7 100644
--- a/assets/shaders/triangle.metal
+++ b/assets/shaders/triangle.metal
@@ -1,33 +1,40 @@
#include <metal_stdlib>
-
using namespace metal;
-struct VertexIn {
- float2 position;
- float3 color;
+struct VertexData {
+ float4 position;
+ float2 texCoords;
};
struct VertexOut {
- float4 computedPosition [[position]];
- float3 fragColor;
-};
+ // The [[position]] attribute of this member indicates that this value
+ // is the clip space position of the vertex when this structure is
+ // returned from the vertex function.
+ float4 position [[position]];
-// Vertex shader
-vertex VertexOut basic_vertex(
- const device VertexIn* vertex_array [[ buffer(0) ]],
- unsigned int vid [[ vertex_id ]]
- ) {
- VertexIn v = vertex_array[vid];
+ // Since this member does not have a special attribute, the rasterizer
+ // interpolates its value with the values of the other triangle vertices
+ // and then passes the interpolated value to the fragment shader for each
+ // fragment in the triangle.
+ float2 textureCoordinate;
+};
- VertexOut outVertex = VertexOut();
- outVertex.computedPosition = float4(v.position.xy, 0.0, 1.0);
- outVertex.fragColor = v.color;
- return outVertex;
+vertex VertexOut
+vertexShader(uint vertexID [[vertex_id]],
+ constant VertexData* vertexData)
+{
+ VertexOut out;
+ out.position = vertexData[vertexID].position;
+ out.textureCoordinate = vertexData[vertexID].texCoords;
+ return out;
}
-// Fragment shader
-fragment float4 basic_fragment(
- VertexOut interpolated [[stage_in]]
-) {
- return float4(interpolated.fragColor, 1.0);
+fragment float4 fragmentShader(VertexOut in [[stage_in]],
+ texture2d<float> colorTexture [[texture(0)]]) {
+
+ constexpr sampler textureSampler (mag_filter::linear,
+ min_filter::linear);
+ // Sample the texture to obtain a color
+ const float4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);
+ return colorSample;
} \ No newline at end of file
diff --git a/assets/shaders/triangle.vert b/assets/shaders/triangle.vert
deleted file mode 100644
index 45b4907..0000000
--- a/assets/shaders/triangle.vert
+++ /dev/null
@@ -1,11 +0,0 @@
-#version 410
-
-layout(location = 0) in vec2 inPos;
-layout(location = 1) in vec3 inColor;
-
-layout(location = 0) out vec3 fragColor;
-
-void main() {
- gl_Position = vec4(inPos, 0.0, 1.0);
- fragColor = inColor;
-}
diff --git a/assets/shaders/ui_rect.frag b/assets/shaders/ui_rect.frag
deleted file mode 100644
index fce0a2e..0000000
--- a/assets/shaders/ui_rect.frag
+++ /dev/null
@@ -1,9 +0,0 @@
-#version 410 core
-out vec4 FragColor;
-
-in vec3 outColor;
-
-void main()
-{
- FragColor = vec4(outColor, 1.0f);
-}
diff --git a/assets/shaders/ui_rect.vert b/assets/shaders/ui_rect.vert
deleted file mode 100644
index 060fdcb..0000000
--- a/assets/shaders/ui_rect.vert
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 410 core
-layout (location = 0) in vec2 aPos;
-layout (location = 1) in vec3 color;
-
-out vec3 outColor;
-
-// uniform mat4 projection;
-
-void main()
-{
- gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
- outColor = color;
-}
diff --git a/assets/textures/mc_grass.jpeg b/assets/textures/mc_grass.jpeg
new file mode 100644
index 0000000..4f87254
--- /dev/null
+++ b/assets/textures/mc_grass.jpeg
Binary files differ
diff --git a/bindgen/BINDGEN.md b/bindgen/BINDGEN.md
index da7c785..6d32cdf 100644
--- a/bindgen/BINDGEN.md
+++ b/bindgen/BINDGEN.md
@@ -3,5 +3,4 @@ This is where we host code generation tools for generating bindings to `celerita
Planned languages are:
- OCaml (due to fairly different semantics we may have an extra high-level wrapper around the C bindings for convenience)
-- Odin
- Rust
diff --git a/bindgen/odin/README.md b/bindgen/odin/README.md
deleted file mode 100644
index f87f5c1..0000000
--- a/bindgen/odin/README.md
+++ /dev/null
@@ -1 +0,0 @@
-# TODO \ No newline at end of file
diff --git a/bindgen/rust/celeritas-sys/src/lib.rs b/bindgen/rust/celeritas-sys/src/lib.rs
index 9ea3e47..5b65f5e 100644
--- a/bindgen/rust/celeritas-sys/src/lib.rs
+++ b/bindgen/rust/celeritas-sys/src/lib.rs
@@ -6,28 +6,29 @@ use serde::{Deserialize, Serialize};
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
-// // --- Conversions
-// pub mod conversions {
-// use crate::{Mat4, Vec3, Vec4};
+// --- Conversions
+pub mod conversions {
+ use crate::{mat4, vec3, vec4};
-// impl From<Vec3> for glam::Vec3 {
-// fn from(v: Vec3) -> Self {
-// Self {
-// x: v.x,
-// y: v.y,
-// z: v.z,
-// }
-// }
-// }
-// impl From<glam::Vec3> for Vec3 {
-// fn from(v: glam::Vec3) -> Self {
-// Self {
-// x: v.x,
-// y: v.y,
-// z: v.z,
-// }
-// }
-// }
+ impl From<vec3> for glam::Vec3 {
+ fn from(v: vec3) -> Self {
+ Self {
+ x: v.x,
+ y: v.y,
+ z: v.z,
+ }
+ }
+ }
+ impl From<glam::Vec3> for vec3 {
+ fn from(v: glam::Vec3) -> Self {
+ Self {
+ x: v.x,
+ y: v.y,
+ z: v.z,
+ }
+ }
+ }
+}
// impl From<Vec4> for glam::Vec4 {
// fn from(v: Vec4) -> Self {
@@ -102,14 +103,14 @@ include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
// };
// }
-impl Default for ShaderBinding {
+impl Default for shader_binding {
fn default() -> Self {
Self {
label: "static".as_ptr() as *const _,
- kind: ShaderBindingKind_BINDING_COUNT,
- vis: ShaderVisibility_VISIBILITY_VERTEX,
- data: ShaderBinding__bindgen_ty_1 {
- bytes: ShaderBinding__bindgen_ty_1__bindgen_ty_1 {
+ binding_type: shader_binding_type_BINDING_BUFFER,
+ visibility: shader_stage_STAGE_VERTEX,
+ data: shader_binding__bindgen_ty_1 {
+ bytes: shader_binding__bindgen_ty_1__bindgen_ty_1 {
size: 0,
data: std::ptr::null_mut(),
},
diff --git a/bindgen/rust/src/prelude.rs b/bindgen/rust/src/prelude.rs
index 7adf11b..240b13a 100644
--- a/bindgen/rust/src/prelude.rs
+++ b/bindgen/rust/src/prelude.rs
@@ -1,20 +1,20 @@
-pub use celeritas_sys::Mat4;
-pub use celeritas_sys::Quat;
-pub use celeritas_sys::Transform;
-/// --- maths types
-pub use celeritas_sys::Vec2;
-pub use celeritas_sys::Vec3;
-pub use celeritas_sys::Vec4;
+// --- maths types
+pub use celeritas_sys::mat4;
+pub use celeritas_sys::quat;
+pub use celeritas_sys::transform;
+pub use celeritas_sys::vec2;
+pub use celeritas_sys::vec3;
+pub use celeritas_sys::vec4;
// --- handles
-pub use celeritas_sys::BufHandle;
-pub use celeritas_sys::MaterialHandle;
-pub use celeritas_sys::MeshHandle;
-pub use celeritas_sys::ModelHandle;
-pub use celeritas_sys::PipelineHandle;
-pub use celeritas_sys::TexHandle;
-// pub use celeritas_sys::PipelineLayoutHandle;
-// pub use celeritas_sys::RenderpassHandle;
+pub type BufHandle = celeritas_sys::buf_handle;
+pub type TexHandle = celeritas_sys::tex_handle;
+// pub type MaterialHandle = celeritas_sys::material_handle;
+// pub type MeshHandle = celeritas_sys::mesh_handle;
+pub type ModelHandle = celeritas_sys::model_handle;
+pub type PipelineHandle = celeritas_sys::pipeline_handle;
+// pub type PipelineLayoutHandle = celeritas_sys::pipeline_layout_handle;
+// pub type RenderpassHandle = celeritas_sys::renderpass_handle;
// // --- conversions
// pub use celeritas_sys::conversions;
diff --git a/docs/getting-started.md b/docs/getting-started.md
deleted file mode 100644
index 0baf21c..0000000
--- a/docs/getting-started.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: Getting up and running
----
-
-The main build tool we use is [xmake](https://xmake.io/#/getting_started) so installing that is the main prerequisite.
-
-Once that is installed you *should* be able to simply run `xmake build` in the top-level directory. \ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
index fd5b8f6..fb3b6e2 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -20,7 +20,7 @@ Celeritas is the original Latin word for celerity that the English is derived fr
## Feature Set
-[See here (README)](https://github.com/omnisci3nce/celeritas-core/blob/winter-cleaning/README.md#todo)
+[See here (README)](https://github.com/omnisci3nce/celeritas-core/blob/masterREADME.md#goals)
## Getting started
diff --git a/docs/project-layout.md b/docs/project-layout.md
deleted file mode 100644
index 9a33e8f..0000000
--- a/docs/project-layout.md
+++ /dev/null
@@ -1,32 +0,0 @@
----
-title: Project Structure
----
-
-```
-assets/ - shaders and bundled assets for examples (must be licensed open)
-bindgen/ - bindings generation
-deps/ - third-party dependencies
-docs/ - these docs you're reading now that get built with mkdocs
-src/
- core/ - core game engine facilities
- logos/ -
- maths/
- platform/
- ral/
- render/
- resources/
- std/
- systems/
- ui/
-```
-
-
-#### Core
-
-Core holds specifically functionality vital to making games or 3D applications. Contrast this with `std` which contains
-code that could form the base layer of almost any software out there.
-
-#### Std
-
-Data structures, algorithms, memory management, etc - all code here forms a foundation for everything above it and can conceivably
-be reused in non-game applications. \ No newline at end of file
diff --git a/examples/cube.c b/examples/cube.c
index e69de29..629a570 100644
--- a/examples/cube.c
+++ b/examples/cube.c
@@ -0,0 +1,70 @@
+#include <celeritas.h>
+#include "glfw3.h"
+
+pipeline_handle draw_pipeline;
+buf_handle cube_vbuf;
+tex_handle texture;
+
+// transformation data
+typedef struct MVPData {
+ mat4 model;
+ mat4 view;
+ mat4 projection;
+} MVPData;
+
+void draw() {
+ // prepare data
+ mat4 translation_matrix = mat4_translation(vec3(0, 0, -1));
+
+ f32 angle_degrees = glfwGetTime() / 2.0 * 45.0;
+ f32 angle = angle_degrees * PI / 180.0;
+ mat4 rotation_matrix = mat4_rotation(quat_from_axis_angle(VEC3_Y, angle, true));
+
+ render_pass_desc d = {};
+ gpu_encoder* enc = ral_render_encoder(d);
+ ral_encode_bind_pipeline(enc, draw_pipeline);
+ ral_encode_set_vertex_buf(enc, cube_vbuf);
+ ral_encode_set_texture(enc, texture, 0);
+ ral_encode_draw_tris(enc, 0, 36);
+ ral_encoder_finish_and_submit(enc);
+}
+
+int main() {
+ core_bringup("Celeritas Example: Triangle", NULL);
+
+ // create rendering pipeline
+ gfx_pipeline_desc pipeline_desc = {
+ .label = "Textured cube pipeline",
+ .vertex_desc = static_3d_vertex_format(),
+ .vertex = {
+ .source = NULL,
+ .is_spirv = false,
+ .entry_point = "cubeVertexShader",
+ .stage = STAGE_VERTEX,
+ },
+ .fragment = {
+ .source = NULL,
+ .is_spirv = false,
+ .entry_point = "fragmentShader",
+ .stage = STAGE_FRAGMENT,
+ },
+ };
+
+ draw_pipeline = ral_gfx_pipeline_create(pipeline_desc);
+
+ // create the cube geometry
+ geometry cube = geo_cuboid(1.0, 1.0, 1.0);
+
+ // upload vertex data to the gpu
+ cube_vbuf = ral_buffer_create(64 * 36, cube.vertex_data);
+
+ while (!app_should_exit()) {
+ glfwPollEvents();
+
+ ral_frame_start();
+ ral_frame_draw(&draw);
+ ral_frame_end();
+ }
+
+ return 0;
+}
diff --git a/examples/triangle.c b/examples/triangle.c
index 1c81d38..7770fd1 100644
--- a/examples/triangle.c
+++ b/examples/triangle.c
@@ -2,8 +2,77 @@
#include <celeritas.h>
+// static vec4 vertices[] = {
+// {-0.5f, -0.5f, 0.0f, 1.0},
+// { 0.5f, -0.5f, 0.0f, 1.0},
+// { 0.0f, 0.5f, 0.0f, 1.0}
+// };
+
+typedef struct VertexData {
+ vec4 position;
+ vec2 texCoords;
+ f32 pad1;
+ f32 pad2;
+} VertexData;
+
+VertexData squareVertices[] = {
+ { { -0.5, -0.5, 0.5, 1.0f }, { 0.0f, 0.0f }, 0.0, 0.0 }, { { -0.5, 0.5, 0.5, 1.0f }, { 0.0f, 1.0f }, 0.0, 0.0 },
+ { { 0.5, 0.5, 0.5, 1.0f }, { 1.0f, 1.0f }, 0.0, 0.0 }, { { -0.5, -0.5, 0.5, 1.0f }, { 0.0f, 0.0f }, 0.0, 0.0 },
+ { { 0.5, 0.5, 0.5, 1.0f }, { 1.0f, 1.0f }, 0.0, 0.0 }, { { 0.5, -0.5, 0.5, 1.0f }, { 1.0f, 0.0f }, 0.0, 0.0 }
+};
+
+pipeline_handle draw_pipeline;
+buf_handle tri_vert_buffer;
+tex_handle texture;
+
+void draw() {
+ render_pass_desc d = {};
+ gpu_encoder* enc = ral_render_encoder(d);
+ ral_encode_bind_pipeline(enc, draw_pipeline);
+ ral_encode_set_vertex_buf(enc, tri_vert_buffer);
+ ral_encode_set_texture(enc, texture, 0);
+ ral_encode_draw_tris(enc, 0, 6);
+ ral_encoder_finish_and_submit(enc);
+}
+
int main() {
- Core_Bringup("Celeritas Example: Triangle", NULL);
+ core_bringup("Celeritas Example: Triangle", NULL);
+
+ // create rendering pipeline
+ gfx_pipeline_desc pipeline_desc = {
+ .label = "Triangle drawing pipeline",
+ .vertex_desc = NULL, // TODO
+ .vertex = {
+ .source = NULL,
+ .is_spirv = false,
+ .entry_point = "vertexShader",
+ .stage = STAGE_VERTEX,
+ },
+ .fragment = {
+ .source = NULL,
+ .is_spirv = false,
+ .entry_point = "fragmentShader",
+ .stage = STAGE_FRAGMENT,
+ },
+ };
+
+ draw_pipeline = ral_gfx_pipeline_create(pipeline_desc);
+
+ // load texture from file
+ texture = ral_texture_load_from_file("assets/textures/mc_grass.jpeg");
+
+ // create our buffer to hold vertices
+ size_t buffer_size = sizeof(VertexData) * 6;
+ printf("size of vertices %ld\n", buffer_size);
+ tri_vert_buffer = ral_buffer_create(buffer_size, &squareVertices);
+
+ while (!app_should_exit()) {
+ glfwPollEvents();
+
+ ral_frame_start();
+ ral_frame_draw(&draw);
+ ral_frame_end();
+ }
return 0;
}
diff --git a/include/celeritas.h b/include/celeritas.h
index 2e0bd28..0b56bf5 100644
--- a/include/celeritas.h
+++ b/include/celeritas.h
@@ -1,11 +1,23 @@
#pragma once
+/*
+ Common abbreviations:
+ buf = buffer
+ tex = texture
+ desc = description
+ idx = index
+*/
+
// Standard library includes
+#include <assert.h>
+#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
// Third party dependency includes
#include <glfw3.h>
@@ -59,55 +71,112 @@ _Static_assert(sizeof(ptrdiff_t) == 8, "type ptrdiff_t should be 8 bytes");
// Platform informs renderer backend (unless user overrides)
#if defined(CEL_PLATFORM_LINUX) || defined(CEL_PLATFORM_WINDOWS)
-#define CEL_REND_BACKEND_VULKAN 1
-#elif defined(CEL_PLATFORM_MAC)
-#define CEL_REND_BACKEND_METAL 1
+#define GPU_VULKAN 1
+#else
+#define GPU_METAL 1
#endif
// --- Forward declare vital structures
-typedef struct Core Core;
-typedef struct Renderer Renderer;
-typedef struct InputState InputState;
+typedef struct core core;
+typedef struct renderer renderer;
+typedef struct input_state input_state;
struct GLFWwindow;
// Global getters
-Core* GetGlobalCore();
-Renderer* GetRenderer();
-struct GLFWwindow* GetWindow();
+core* get_g_core();
+renderer* get_g_renderer();
+struct GLFWwindow* get_window();
-struct Core {
+struct core {
const char* app_name;
struct GLFWwindow* window;
- Renderer* renderer;
- InputState* input;
+ bool should_exit;
+ renderer* renderer;
+ input_state* input;
};
-extern Core g_core; /** @brief global `Core` that other files can use */
+extern core g_core; /** @brief global `Core` that other files can use */
+
+void core_bringup(const char* window_name, struct GLFWwindow* optional_window);
+void core_shutdown();
+void core_resize_viewport(int width, int height);
+bool app_should_exit();
+
+// --- Error handling
-void Core_Bringup(const char* window_name, struct GLFWwindow* optional_window);
-void Core_Shutdown();
-void Core_ResizeViewport(int width, int height);
-bool AppShouldExit();
+// global error handling
+#define CEL_OK 0
+extern int g_last_error;
+
+/** @brief get last global status value */
+int cel_check_status();
+void _cel_push_error(int error_code);
// --- Memory facilities: Allocators, helpers
// TODO: Arenas
-// TODO: Pool allocator
+
+// Pool
+typedef struct void_pool_header void_pool_header; // TODO: change name of this
+struct void_pool_header {
+ void_pool_header* next;
+};
+
+typedef struct void_pool {
+ u64 capacity;
+ u64 entry_size;
+ u64 count;
+ void* backing_buffer;
+ void_pool_header* free_list_head;
+ const char* debug_label;
+} void_pool;
+
+void_pool void_pool_create(void* storage, const char* debug_label, u64 capacity, u64 entry_size);
+void void_pool_free_all(void_pool* pool);
+bool void_pool_is_empty(void_pool* pool);
+bool void_pool_is_full(void_pool* pool);
+void* void_pool_get(void_pool* pool, u32 raw_handle);
+void* void_pool_alloc(void_pool* pool, u32* out_raw_handle);
+void void_pool_dealloc(void_pool* pool, u32 raw_handle);
+u32 void_pool_insert(void_pool* pool, void* item);
+
+#define TYPED_POOL(T, Name) \
+ typedef struct Name##_pool { \
+ void_pool inner; \
+ } Name##_pool; \
+ \
+ static Name##_pool Name##_pool_create(void* storage, u64 cap, u64 entry_size) { \
+ void_pool p = void_pool_create(storage, "\"" #Name "\"", cap, entry_size); \
+ return (Name##_pool){ .inner = p }; \
+ } \
+ static inline T* Name##_pool_get(Name##_pool* pool, Name##_handle handle) { \
+ return (T*)void_pool_get(&pool->inner, handle.raw); \
+ } \
+ static inline T* Name##_pool_alloc(Name##_pool* pool, Name##_handle* out_handle) { \
+ return (T*)void_pool_alloc(&pool->inner, &out_handle->raw); \
+ } \
+ static inline void Name##_pool_dealloc(Name##_pool* pool, Name##_handle handle) { \
+ void_pool_dealloc(&pool->inner, handle.raw); \
+ } \
+ static Name##_handle Name##_pool_insert(Name##_pool* pool, T* item) { \
+ u32 raw_handle = void_pool_insert(pool, item); \
+ return (Name##_handle){ .raw = raw_handle }; \
+ }
// --- Strings
// --- Logging
// Log levels
-typedef enum LogLevel {
+typedef enum loglevel {
LOG_LEVEL_FATAL = 0,
LOG_LEVEL_ERROR = 1,
LOG_LEVEL_WARN = 2,
LOG_LEVEL_INFO = 3,
LOG_LEVEL_DEBUG = 4,
LOG_LEVEL_TRACE = 5,
-} LogLevel;
+} loglevel;
-void log_output(char* module, LogLevel level, const char* msg, ...);
+void log_output(char* module, loglevel level, const char* msg, ...);
#define NAMESPACED_LOGGER(module) \
static inline void FATAL(const char* msg, ...) { \
@@ -119,31 +188,31 @@ void log_output(char* module, LogLevel level, const char* msg, ...);
static inline void ERROR(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_FATAL, msg, args); \
+ log_output(#module, LOG_LEVEL_ERROR, msg, args); \
va_end(args); \
} \
static inline void WARN(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_FATAL, msg, args); \
+ log_output(#module, LOG_LEVEL_WARN, msg, args); \
va_end(args); \
} \
static inline void INFO(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_FATAL, msg, args); \
+ log_output(#module, LOG_LEVEL_INFO, msg, args); \
va_end(args); \
} \
static inline void DEBUG(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_FATAL, msg, args); \
+ log_output(#module, LOG_LEVEL_DEBUG, msg, args); \
va_end(args); \
} \
static inline void TRACE(const char* msg, ...) { \
va_list args; \
va_start(args, msg); \
- log_output(#module, LOG_LEVEL_FATAL, msg, args); \
+ log_output(#module, LOG_LEVEL_TRACE, msg, args); \
va_end(args); \
}
@@ -155,77 +224,127 @@ void log_output(char* module, LogLevel level, const char* msg, ...);
#define TAU (2.0 * PI)
/** @brief 2D Vector */
-typedef struct Vec2 {
+typedef struct vec2 {
f32 x, y;
-} Vec2;
+} vec2;
/** @brief 3D Vector */
-typedef struct Vec3 {
+typedef struct vec3 {
f32 x, y, z;
-} Vec3;
+} vec3;
/** @brief 4D Vector */
-typedef struct Vec4 {
+typedef struct vec4 {
f32 x, y, z, w;
-} Vec4;
+} vec4;
/** @brief Quaternion */
-typedef Vec4 Quat;
+typedef vec4 quat;
/** @brief 4x4 Matrix */
-typedef struct Mat4 {
+typedef struct mat4 {
// TODO: use this format for more readable code: vec4 x_axis, y_axis, z_axis, w_axis;
f32 data[16];
-} Mat4;
+} mat4;
/** @brief 3D affine transformation */
-typedef struct Transform {
- Vec3 position;
- Quat rotation;
- Vec3 scale;
+typedef struct transform {
+ vec3 position;
+ quat rotation;
+ vec3 scale;
bool is_dirty;
-} Transform;
-
-inlined Vec3 Vec3_Create(f32 x, f32 y, f32 z);
-inlined Vec3 Vec3_Add(Vec3 u, Vec3 v);
-inlined Vec3 Vec3_Sub(Vec3 u, Vec3 v);
-inlined Vec3 Vec3_Mult(Vec3 u, f32 s);
-inlined Vec3 Vec3_Div(Vec3 u, f32 s);
+} transform;
+
+_Static_assert(alignof(vec3) == 4, "vec3 is 4 byte aligned");
+_Static_assert(sizeof(vec3) == 12, "vec3 is 12 bytes so has no padding");
+_Static_assert(alignof(vec4) == 4, "vec4 is 4 byte aligned");
+
+inlined vec3 vec3_create(f32 x, f32 y, f32 z);
+inlined vec3 vec3_add(vec3 u, vec3 v);
+inlined vec3 vec3_sub(vec3 u, vec3 v);
+inlined vec3 vec3_mult(vec3 u, f32 s);
+inlined vec3 vec3_div(vec3 u, f32 s);
+inlined vec3 vec3_len_squared(vec3 a);
+inlined f32 vec3_len(vec3 a);
+inlined vec3 vec3_negate(vec3 a);
+inlined vec3 vec3_normalise(vec3 a);
+inlined f32 vec3_dot(vec3 a, vec3 b);
+inlined vec3 vec3_cross(vec3 a, vec3 b);
+
+inlined vec4 vec4_create(f32 x, f32 y, f32 z, f32 w);
+
+// quaternion functions
+inlined quat quat_ident();
+quat quat_from_axis_angle(vec3 axis, f32 angle, bool normalise);
+quat quat_slerp(quat a, quat b, f32 percentage);
+
+// matrix functions
+inlined mat4 mat4_ident();
+mat4 mat4_translation(vec3 position);
+mat4 mat4_scale(vec3 scale);
+mat4 mat4_rotation(quat rotation);
+mat4 mat4_mult(mat4 lhs, mat4 rhs);
+mat4 mat4_transposed(mat4 m);
+mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_clip, f32 far_clip);
+mat4 mat4_orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 near_clip, f32 far_clip);
+mat4 mat4_look_at(vec3 position, vec3 target, vec3 up);
+
+// transform functions
+inlined transform transform_create(vec3 pos, quat rot, vec3 scale);
+mat4 transform_to_mat(transform* tf);
+
+// helpers
+
+#define vec3(x, y, z) ((vec3){ x, y, z })
+#define vec4(x, y, z, w) ((vec4){ x, y, z, w })
+inlined vec4 v3tov4(vec3 v3) { return vec4_create(v3.x, v3.y, v3.z, 1.0); }
+
+static const vec3 VEC3_X = vec3(1.0, 0.0, 0.0);
+static const vec3 VEC3_NEG_X = vec3(-1.0, 0.0, 0.0);
+static const vec3 VEC3_Y = vec3(0.0, 1.0, 0.0);
+static const vec3 VEC3_NEG_Y = vec3(0.0, -1.0, 0.0);
+static const vec3 VEC3_Z = vec3(0.0, 0.0, 1.0);
+static const vec3 VEC3_NEG_Z = vec3(0.0, 0.0, -1.0);
+static const vec3 VEC3_ZERO = vec3(0.0, 0.0, 0.0);
+static const vec3 VEC3_ONES = vec3(1.0, 1.0, 1.0);
// --- RAL
-DEFINE_HANDLE(BufHandle);
-DEFINE_HANDLE(TexHandle);
-DEFINE_HANDLE(PipelineHandle);
+DEFINE_HANDLE(buf_handle);
+DEFINE_HANDLE(tex_handle);
+DEFINE_HANDLE(pipeline_handle);
+DEFINE_HANDLE(compute_pipeline_handle);
#define MAX_VERTEX_ATTRIBUTES 16
#define MAX_SHADER_BINDINGS 16
// Backend-specific structs
-typedef struct GPU_Swapchain GPU_Swapchain;
-typedef struct GPU_Pipeline GPU_Pipeline;
-typedef struct GPU_CmdEncoder GPU_CmdEncoder;
+typedef struct gpu_swapchain gpu_swapchain;
+typedef struct gpu_encoder gpu_encoder; // Render command encoder
+typedef struct gpu_compute_encoder gpu_compute_encoder;
+typedef struct gpu_buffer gpu_buffer;
+typedef struct gpu_texture gpu_texture;
// NOTE: Can we just use Storage buffer for everything?
-// typedef enum GPU_BufferType {} GPU_BufferType;
+// typedef enum gpu_buf_type {} gpu_buf_type;
-typedef enum GPU_TextureType {
+typedef enum gpu_tex_type {
TEXTURE_TYPE_2D,
TEXTURE_TYPE_3D,
TEXTURE_TYPE_2D_ARRAY,
TEXTURE_TYPE_CUBE_MAP,
TEXTURE_TYPE_COUNT
-} GPU_TextureType;
+} gpu_tex_type;
/** @brief Texture Description - used by texture creation functions */
-typedef struct TextureDesc {
- GPU_TextureType tex_type;
+typedef struct texture_desc {
+ gpu_tex_type tex_type;
// GPU_TextureFormat format;
int width, height, num_channels;
-} TextureDesc;
+} texture_desc;
/// @strip_prefix(ATTR_)
-typedef enum VertexAttribType {
+typedef enum vertex_attrib_type {
ATTR_F32,
ATTR_F32x2,
ATTR_F32x3,
@@ -238,18 +357,19 @@ typedef enum VertexAttribType {
ATTR_I32x2,
ATTR_I32x3,
ATTR_I32x4,
-} VertexAttribType;
+} vertex_attrib_type;
-typedef struct VertexDesc {
+typedef struct vertex_desc {
const char* label;
- VertexAttribType attributes[MAX_VERTEX_ATTRIBUTES];
+ vertex_attrib_type attributes[MAX_VERTEX_ATTRIBUTES];
u32 attribute_count;
-} VertexDesc;
+ u32 padding;
+} vertex_desc;
-typedef struct ShaderDesc {
-} ShaderDesc;
+// Some default formats
+vertex_desc static_3d_vertex_format();
-typedef enum ShaderBindingKind {
+typedef enum shader_binding_type {
BINDING_BYTES,
BINDING_BUFFER,
BINDING_BUFFER_ARRAY,
@@ -257,105 +377,221 @@ typedef enum ShaderBindingKind {
BINDING_TEXTURE_ARRAY,
BINDING_SAMPLER,
BINDING_COUNT
-} ShaderBindingKind;
+} shader_binding_type;
-typedef enum ShaderVisibility {
- VISIBILITY_VERTEX = 1 << 0,
- VISIBILITY_FRAGMENT = 1 << 1,
- VISIBILITY_COMPUTE = 1 << 2,
-} ShaderVisibility;
+typedef enum shader_stage {
+ STAGE_VERTEX = 1 << 0,
+ STAGE_FRAGMENT = 1 << 1,
+ STAGE_COMPUTE = 1 << 2,
+} shader_stage;
-typedef struct ShaderBinding {
+typedef struct shader_binding {
const char* label;
- ShaderBindingKind kind;
- ShaderVisibility vis;
+ shader_binding_type binding_type;
+ shader_stage visibility;
union {
struct {
u32 size;
void* data;
} bytes;
struct {
- BufHandle handle;
+ buf_handle handle;
} buffer;
struct {
- TexHandle handle;
+ tex_handle handle;
} texture;
} data;
-} ShaderBinding;
+} shader_binding;
-typedef struct ShaderDataLayout {
- ShaderBinding bindings[MAX_SHADER_BINDINGS];
+typedef struct shader_data_layout {
+ shader_binding bindings[MAX_SHADER_BINDINGS];
size_t binding_count;
-} ShaderDataLayout;
+} shader_data_layout;
-typedef enum CullMode { CULL_BACK_FACE, CULL_FRONT_FACE } CullMode;
+typedef struct shader_function {
+ const char* source;
+ bool is_spirv;
+ const char* entry_point;
+ shader_stage stage;
+} shader_function;
-typedef struct GraphicsPipelineDesc {
+typedef enum cull_mode { Cull_BackFace, Cull_FrontFace } cull_mode;
+
+typedef struct gfx_pipeline_desc {
const char* label;
- VertexDesc vertex_desc;
- ShaderDesc vs;
- ShaderDesc fs;
+ vertex_desc vertex_desc;
+ shader_function vertex;
+ shader_function fragment;
// ShaderDataLayout data_layouts[MAX_SHADER_DATA_LAYOUTS];
// u32 data_layouts_count;
-} GraphicsPipelineDesc;
+} gfx_pipeline_desc;
+
+typedef struct compute_pipeline_desc { /* TODO */
+} compute_pipeline_desc;
+
+typedef struct render_pass_desc {
+} render_pass_desc;
// --- RAL Functions
-BufHandle GPU_BufferCreate(u64 size, const void* data);
-void GPU_BufferDestroy(BufHandle handle);
-TexHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data);
-void GPU_TextureDestroy(TexHandle handle);
+
+// Resources
+buf_handle ral_buffer_create(u64 size, const void* data);
+void ral_buffer_destroy(buf_handle handle);
+
+tex_handle ral_texture_create(texture_desc desc, bool create_view, const void* data);
+tex_handle ral_texture_load_from_file(const char* filepath);
+void ral_texture_destroy(tex_handle handle);
+
+// Encoders / cmd buffers
+/** @brief grabs a new command encoder from the pool of available ones and begins recording */
+gpu_encoder* ral_render_encoder(render_pass_desc rpass_desc);
+
+gpu_compute_encoder ral_compute_encoder();
+
+void ral_encoder_finish(gpu_encoder* enc);
+void ral_encoder_submit(gpu_encoder* enc);
+void ral_encoder_finish_and_submit(gpu_encoder* enc);
+
+pipeline_handle ral_gfx_pipeline_create(gfx_pipeline_desc desc);
+void ral_gfx_pipeline_destroy(pipeline_handle handle);
+
+compute_pipeline_handle ral_compute_pipeline_create(compute_pipeline_desc);
+void ral_compute_pipeline_destroy(compute_pipeline_handle handle);
+
+// Encoding
+void ral_encode_bind_pipeline(gpu_encoder* enc, pipeline_handle pipeline);
+void ral_encode_set_vertex_buf(gpu_encoder* enc, buf_handle vbuf);
+void ral_encode_set_index_buf(gpu_encoder* enc, buf_handle ibuf);
+void ral_encode_set_texture(gpu_encoder* enc, tex_handle texture, u32 slot);
+void ral_encode_draw_tris(gpu_encoder* enc, size_t start, size_t count);
+
+// Backend lifecycle
+void ral_backend_init(const char* window_name, struct GLFWwindow* window);
+void ral_backend_shutdown();
+void ral_backend_resize_framebuffer(int width, int height);
+
+// Frame lifecycle
+
+typedef void (*scoped_draw_commands)(); // callback that we run our draw commands within.
+// allows us to wrap some api-specific behaviour
+
+void ral_frame_start();
+void ral_frame_draw(scoped_draw_commands draw_fn);
+void ral_frame_end();
// --- Containers (Forward declared as internals are unnecessary for external header)
typedef struct u32_darray u32_darray;
// --- Base Renderer types
-DEFINE_HANDLE(MeshHandle);
-DEFINE_HANDLE(MaterialHandle);
-DEFINE_HANDLE(ModelHandle);
+DEFINE_HANDLE(mesh_handle);
+DEFINE_HANDLE(material_handle);
+DEFINE_HANDLE(model_handle);
-typedef struct Geometry {
- VertexDesc vertex_format;
+typedef struct geometry {
+ vertex_desc vertex_format;
void* vertex_data;
bool has_indices; // When this is false indexed drawing is not used
u32_darray* indices;
-} Geometry;
-
-typedef struct Mesh {
- BufHandle vertex_buffer;
- BufHandle index_buffer;
- MaterialHandle material;
- Geometry geometry;
- // bool is_skinned; // false = its static
- // Armature armature;
- // bool is_uploaded; // has the data been uploaded to the GPU
-} Mesh;
-
-// --- Render primitives
-
-Geometry Geo_CreatePlane(f32 x_scale, f32 z_scale, u32 tiling_u, u32 tiling_v);
-Geometry Geo_CreateCuboid(f32 x_scale, f32 y_scale, f32 z_scale);
-Geometry Geo_CreateCylinder(f32 radius, f32 height, u32 resolution);
-Geometry Geo_CreateCone(f32 radius, f32 height, u32 resolution);
-Geometry Geo_CreateUVsphere(f32 radius, u32 north_south_lines, u32 east_west_lines);
-Geometry Geo_CreateIcosphere(f32 radius, f32 n_subdivisions);
+} geometry;
+
+typedef u32 joint_idx;
+typedef struct armature {
+} armature;
+
+/** @brief Mesh data that has been uploaded to GPU and is ready to be rendered each frame
+ Gets stored in a pool */
+typedef struct mesh {
+ buf_handle vertex_buffer;
+ buf_handle index_buffer;
+ // todo: material?
+ geometry geo; // the originating mesh data
+ const armature* skinning_data;
+} mesh;
+
+typedef struct draw_mesh_cmd {
+ mesh_handle mesh;
+ mat4 transform;
+ vec3 bounding_sphere_center;
+ f32 bounding_sphere_radius;
+ const armature* skinning_data; // NULL = static mesh
+ bool cast_shadows;
+} draw_mesh_cmd;
+
+// --- Geometry/Mesh primitives
+
+geometry geo_plane(f32 x_scale, f32 z_scale, u32 tiling_u, u32 tiling_v);
+geometry geo_cuboid(f32 x_scale, f32 y_scale, f32 z_scale);
+geometry geo_cylinder(f32 radius, f32 height, u32 resolution);
+geometry geo_cone(f32 radius, f32 height, u32 resolution);
+geometry geo_uv_sphere(f32 radius, u32 north_south_lines, u32 east_west_lines);
+geometry geo_ico_sphere(f32 radius, f32 n_subdivisions);
+void geo_scale_uniform(geometry* geo, f32 scale);
+void geo_scale_xyz(geometry* geo, vec3 scale_xyz);
+
+// --- Renderer
+
+// void renderer_init(renderer* rend);
+// void renderer_shutdown(renderer* rend);
+
+typedef struct camera {
+ vec3 position;
+ // TODO: move to using a quaternion for the camera's orientation - need to update
+ // how the view transformation matrix is calculated
+ vec3 forwards;
+ vec3 up;
+ f32 fov;
+} camera;
+
+/** @brief calculates the view and projection matrices for a camera */
+mat4 camera_view_proj(camera camera, f32 lens_height, f32 lens_width, mat4* out_view, mat4* out_proj);
+
+// TODO: Filament PBR model
// --- Scene / Transform Hierarchy
// --- Gameplay
-typedef struct Camera {
- Vec3 position;
- Quat orientation;
- f32 fov;
-} Camera;
+// --- Game and model data
-// --- Reference Renderer
+typedef struct model {
+} model;
-// TODO: Filament PBR model
+model_handle model_load_from_gltf(const char* path);
// --- Animation
+typedef enum keyframe_kind { Keyframe_Rotation, Keyframe_Translation, Keyframe_Scale, Keyframe_Weights } keyframe_kind;
+
+extern const char* keyframe_kind_strings[4];
+
+typedef union keyframe {
+ quat rotation;
+ vec3 translation;
+ vec3 scale;
+ f32 weights[4];
+} keyframe;
+
+typedef struct keyframes {
+ keyframe_kind kind;
+ keyframe* values;
+ size_t n_frames;
+} keyframes;
+
+typedef enum interpolation { Interpolation_Step, Interpolation_Linear, Interpolation_Cubic } interpolation;
+
+extern const char* interpolation_strings[3];
+
+typedef struct animation_spline {
+ f32* timestamps;
+ size_t n_timestamps;
+ keyframes frames;
+} animation_spline;
+
+// Compute shader approach so we only need one kind of vertex format
+
+// --- Input
+
// --- Collisions
// --- Physics
diff --git a/src/backend_mtl.m b/src/backend_mtl.m
new file mode 100644
index 0000000..48e0ab0
--- /dev/null
+++ b/src/backend_mtl.m
@@ -0,0 +1,263 @@
+#include <celeritas.h>
+
+#ifdef GPU_METAL
+
+#define MTL_DEBUG_LAYER 1 // enable all metal validation layers
+
+// Obj-C imports
+#import <Foundation/Foundation.h>
+#import <Metal/Metal.h>
+#import <MetalKit/MetalKit.h>
+#import <QuartzCore/CAMetalLayer.h>
+#include <CoreGraphics/CGGeometry.h>
+
+#define GLFW_INCLUDE_NONE
+#import <GLFW/glfw3.h>
+#define GLFW_EXPOSE_NATIVE_COCOA
+#import <GLFW/glfw3native.h>
+#include "stb_image.h"
+
+NAMESPACED_LOGGER(metal);
+
+// --- RAL types
+
+struct gpu_swapchain {
+ int width, height;
+ CAMetalLayer* swapchain;
+};
+
+struct gpu_encoder {
+ id<MTLCommandBuffer> cmd_buffer;
+ id<MTLRenderCommandEncoder> cmd_encoder;
+};
+
+typedef struct metal_pipeline {
+ id<MTLRenderPipelineState> pso;
+} metal_pipeline;
+
+typedef struct metal_buffer {
+ id<MTLBuffer> id;
+} metal_buffer;
+
+typedef struct metal_texture {
+ id<MTLTexture> id;
+} metal_texture;
+
+TYPED_POOL(metal_buffer, buf);
+TYPED_POOL(metal_texture, tex);
+TYPED_POOL(metal_pipeline, pipeline);
+
+typedef struct metal_context {
+ GLFWwindow* window;
+ NSWindow* metal_window;
+
+ id<MTLDevice> device;
+ id<CAMetalDrawable> surface;
+ gpu_swapchain default_swapchain;
+ id<MTLLibrary> default_library;
+
+ id<MTLCommandQueue> command_queue;
+
+ /* pools */
+ buf_pool bufpool;
+ tex_pool texpool;
+ pipeline_pool psopool; // pso = pipeline state object
+} metal_context;
+
+static metal_context ctx;
+
+void ral_backend_init(const char* window_name, struct GLFWwindow* window) {
+ TRACE("loading Metal backend");
+
+ TRACE("gpu device creation");
+ const id<MTLDevice> gpu = MTLCreateSystemDefaultDevice();
+ ctx.device = gpu;
+
+ TRACE("window init");
+ glfwMakeContextCurrent(window);
+ NSWindow* nswindow = glfwGetCocoaWindow(window);
+ ctx.metal_window = nswindow;
+
+ int width, height;
+ glfwGetFramebufferSize(window, &width, &height);
+
+ // effectively the "framebuffer"
+ CAMetalLayer* metal_layer = [CAMetalLayer layer];
+ metal_layer.device = gpu;
+ metal_layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
+ metal_layer.drawableSize = CGSizeMake(width, height);
+ ctx.metal_window.contentView.layer = metal_layer;
+ ctx.metal_window.contentView.wantsLayer = true;
+ ctx.default_swapchain.swapchain = metal_layer;
+
+ TRACE("command queue creation");
+ const id<MTLCommandQueue> queue = [ctx.device newCommandQueue];
+ ctx.command_queue = queue;
+
+ TRACE("resource pool init");
+ metal_buffer* buffer_storage = malloc(sizeof(metal_buffer) * 100);
+ ctx.bufpool = buf_pool_create(buffer_storage, 100, sizeof(metal_buffer));
+
+ metal_texture* texture_storage = malloc(sizeof(metal_texture) * 100);
+ ctx.texpool = tex_pool_create(texture_storage, 100, sizeof(metal_texture));
+
+ metal_pipeline* pipeline_storage = malloc(sizeof(metal_pipeline) * 100);
+ ctx.psopool = pipeline_pool_create(pipeline_storage, 100, sizeof(metal_pipeline));
+
+ TRACE("create default metal lib");
+ NSError* nserr = 0x0;
+ id<MTLLibrary> default_library = [ctx.device newLibraryWithFile:@"build/shaders/default.metallib" error:&nserr];
+ if (!default_library) {
+ ERROR("Error loading metal lib\n");
+ exit(1);
+ }
+ ctx.default_library = default_library;
+
+ INFO("Successfully initialised Metal RAL backend");
+}
+
+void ral_backend_shutdown() {
+ // no-op
+}
+
+buf_handle ral_buffer_create(u64 size, const void *data) {
+ buf_handle handle;
+ metal_buffer* buffer = buf_pool_alloc(&ctx.bufpool, &handle);
+ buffer->id = [ctx.device newBufferWithBytes:data length:size options:MTLResourceStorageModeShared];
+
+ return handle;
+}
+
+tex_handle ral_texture_create(texture_desc desc, bool create_view, const void *data) {
+ tex_handle handle;
+ metal_texture* texture = tex_pool_alloc(&ctx.texpool, &handle);
+
+ MTLTextureDescriptor* texture_descriptor = [[MTLTextureDescriptor alloc] init];
+ [texture_descriptor setPixelFormat:MTLPixelFormatRGBA8Unorm];
+ [texture_descriptor setWidth:desc.width];
+ [texture_descriptor setHeight:desc.height];
+
+ texture->id = [ctx.device newTextureWithDescriptor:texture_descriptor];
+
+ MTLRegion region = MTLRegionMake2D(0, 0, desc.width, desc.height);
+ u32 bytes_per_row = 4 * desc.width;
+
+ [texture->id replaceRegion:region mipmapLevel:0 withBytes:data bytesPerRow:bytes_per_row];
+
+ [texture_descriptor release];
+
+ return handle;
+}
+
+tex_handle ral_texture_load_from_file(const char* filepath) {
+ texture_desc desc;
+
+ stbi_set_flip_vertically_on_load(true);
+ unsigned char* image = stbi_load(filepath, &desc.width, &desc.height, &desc.num_channels, STBI_rgb_alpha);
+ assert(image != NULL);
+
+ tex_handle handle = ral_texture_create(desc, false, image);
+ stbi_image_free(image);
+ return handle;
+}
+
+pipeline_handle ral_gfx_pipeline_create(gfx_pipeline_desc desc) {
+ TRACE("creating graphics pipeline");
+
+ pipeline_handle handle;
+ metal_pipeline* p = pipeline_pool_alloc(&ctx.psopool, &handle);
+
+ @autoreleasepool {
+ // setup vertex and fragment shaders
+ NSString* vertex_entry_point = [NSString stringWithUTF8String:desc.vertex.entry_point];
+ id<MTLFunction> vertex_func = [ctx.default_library newFunctionWithName:vertex_entry_point];
+ assert(vertex_func);
+
+ NSString* fragment_entry_point = [NSString stringWithUTF8String:desc.fragment.entry_point];
+ id<MTLFunction> fragment_func = [ctx.default_library newFunctionWithName:fragment_entry_point];
+ assert(fragment_func);
+
+ NSError* err = 0x0;
+ MTLRenderPipelineDescriptor* pld = [[MTLRenderPipelineDescriptor alloc] init];
+ // in auto release pool so dont need to call release()
+
+ [pld setLabel:@"Pipeline"];
+ [pld setVertexFunction:vertex_func];
+ [pld setFragmentFunction:fragment_func];
+ pld.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
+ pld.colorAttachments[0].blendingEnabled = YES;
+ assert(pld);
+
+ id<MTLRenderPipelineState> pso = [ctx.device newRenderPipelineStateWithDescriptor:pld error:&err];
+ assert(pso);
+ p->pso = pso;
+ }
+
+ return handle;
+}
+
+gpu_encoder* ral_render_encoder(render_pass_desc rpass_desc) {
+ id<MTLCommandBuffer> buffer = [ctx.command_queue commandBuffer];
+
+ // create renderpass descriptor
+ MTLRenderPassDescriptor* rpd = [[MTLRenderPassDescriptor alloc] init];
+ MTLRenderPassColorAttachmentDescriptor* cd = rpd.colorAttachments[0];
+ [cd setTexture:ctx.surface.texture];
+ [cd setLoadAction:MTLLoadActionClear];
+ MTLClearColor clearColor = MTLClearColorMake(41.0f/255.0f, 42.0f/255.0f, 48.0f/255.0f, 1.0);
+ [cd setClearColor:clearColor];
+ [cd setStoreAction:MTLStoreActionStore];
+
+ id<MTLRenderCommandEncoder> encoder = [buffer renderCommandEncoderWithDescriptor:rpd];
+
+ gpu_encoder* enc = malloc(sizeof(gpu_encoder));
+ enc->cmd_buffer = buffer;
+ enc->cmd_encoder = encoder;
+
+ return enc;
+}
+
+void ral_encoder_finish_and_submit(gpu_encoder* enc) {
+ [enc->cmd_encoder endEncoding];
+ [enc->cmd_buffer presentDrawable:ctx.surface];
+ [enc->cmd_buffer commit];
+ [enc->cmd_buffer waitUntilCompleted];
+}
+
+void ral_encode_bind_pipeline(gpu_encoder *enc, pipeline_handle pipeline) {
+ metal_pipeline* p = pipeline_pool_get(&ctx.psopool, pipeline);
+ [enc->cmd_encoder setRenderPipelineState:p->pso];
+}
+
+void ral_encode_set_vertex_buf(gpu_encoder *enc, buf_handle vbuf) {
+ metal_buffer* b = buf_pool_get(&ctx.bufpool, vbuf);
+ [enc->cmd_encoder setVertexBuffer:b->id offset:0 atIndex:0 ];
+}
+
+void ral_encode_set_texture(gpu_encoder* enc, tex_handle texture, u32 slot) {
+ metal_texture* t = tex_pool_get(&ctx.texpool, texture);
+ [enc->cmd_encoder setFragmentTexture:t->id atIndex:slot];
+}
+
+void ral_encode_draw_tris(gpu_encoder* enc, size_t start, size_t count) {
+ MTLPrimitiveType tri_primitive = MTLPrimitiveTypeTriangle;
+ [enc->cmd_encoder drawPrimitives:tri_primitive vertexStart:start vertexCount:count];
+}
+
+void ral_frame_start() {}
+
+void ral_frame_draw(scoped_draw_commands draw_fn) {
+ @autoreleasepool {
+ ctx.surface = [ctx.default_swapchain.swapchain nextDrawable];
+ draw_fn();
+ }
+}
+
+void ral_frame_end() {}
+
+void ral_backend_resize_framebuffer(int width, int height) {
+ TRACE("resizing framebuffer");
+ ctx.default_swapchain.swapchain.drawableSize = CGSizeMake((float)width, (float)height);
+}
+
+#endif \ No newline at end of file
diff --git a/src/camera.c b/src/camera.c
new file mode 100644
index 0000000..eb8fc7d
--- /dev/null
+++ b/src/camera.c
@@ -0,0 +1,13 @@
+#include <celeritas.h>
+
+mat4 camera_view_proj(camera camera, f32 lens_height, f32 lens_width, mat4* out_view, mat4* out_proj) {
+ mat4 projection_matrix = mat4_perspective(camera.fov, lens_width / lens_height, 0.1, 1000.0);
+ // TODO: store near/far on camera rather than hard-coding here.
+
+ vec3 camera_direction = vec3_add(camera.position, camera.forwards);
+ mat4 view_matrix = mat4_look_at(camera.position, camera_direction, camera.up);
+ if (out_view) *out_view = view_matrix;
+ if (out_proj) *out_proj = projection_matrix;
+
+ return mat4_mult(view_matrix, projection_matrix);
+} \ No newline at end of file
diff --git a/src/core.c b/src/core.c
index 158615c..ed09597 100644
--- a/src/core.c
+++ b/src/core.c
@@ -1,15 +1,58 @@
// The engine "core"
#include <celeritas.h>
+#include <stdlib.h>
+#include "glfw3.h"
NAMESPACED_LOGGER(core);
-void Core_Bringup(const char* window_name, struct GLFWwindow* optional_window) {
- // INFO("Initiate Core bringup");
+core g_core = { 0 };
+
+#ifdef GPU_METAL
+static const char* gapi = "Metal";
+#else
+static const char* gapi = "Vulkan";
+#endif
+
+// forward declares
+void key_callback(GLFWwindow* win, int key, int scancode, int action, int mods);
+void resize_callback(GLFWwindow* win, int width, int height);
+
+void core_bringup(const char* window_name, struct GLFWwindow* optional_window) {
INFO("Initiate Core bringup");
INFO("Create GLFW window");
+ glfwInit();
+
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+
+ char* full_window_name = malloc(sizeof(char) * 100);
+ sprintf(full_window_name, "%s (%s)", window_name, gapi);
+
+ if (optional_window) {
+ g_core.window = optional_window;
+ } else {
+ GLFWwindow* glfw_window = glfwCreateWindow(800, 600, full_window_name, NULL, NULL);
+ g_core.window = glfw_window;
+ }
+
+ // This may move into a renderer struct
+ ral_backend_init(window_name, g_core.window);
+
+ glfwSetKeyCallback(g_core.window, key_callback);
+ glfwSetFramebufferSizeCallback(g_core.window, resize_callback);
+}
+void core_shutdown() {
+ ral_backend_shutdown();
+ glfwTerminate();
+}
+
+bool app_should_exit() { return glfwWindowShouldClose(g_core.window) || g_core.should_exit; }
+
+void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
+ if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
+ g_core.should_exit = true;
+ }
}
-void Core_Shutdown() {}
-bool AppShouldExit() { return false; }
+void resize_callback(GLFWwindow* window, int width, int height) { ral_backend_resize_framebuffer(width, height); } \ No newline at end of file
diff --git a/src/debug_strings.c b/src/debug_strings.c
new file mode 100644
index 0000000..b1e09aa
--- /dev/null
+++ b/src/debug_strings.c
@@ -0,0 +1,5 @@
+#include <celeritas.h>
+
+const char* keyframe_kind_strings[4] = { "ROTATION", "TRANSLATION", "SCALE", "WEIGHTS" };
+
+const char* interpolation_strings[3] = { "Step", "Linear", "Cubic" }; \ No newline at end of file
diff --git a/src/geometry.c b/src/geometry.c
new file mode 100644
index 0000000..05414d3
--- /dev/null
+++ b/src/geometry.c
@@ -0,0 +1,85 @@
+#include <celeritas.h>
+
+typedef struct static_3d_vert {
+ vec4 pos;
+ vec4 norm;
+ vec2 uv;
+ vec2 pad;
+} static_3d_vert;
+
+vertex_desc static_3d_vertex_format() {
+ vertex_desc desc;
+ desc.label = "Static 3D Vertex";
+ desc.attributes[0] = ATTR_F32x4; // position
+ desc.attributes[1] = ATTR_F32x4; // normal
+ desc.attributes[2] = ATTR_F32x2; // tex coord
+ desc.attribute_count = 3;
+ desc.padding = 16; // 16 bytes padding
+
+ return desc;
+}
+
+geometry geo_cuboid(f32 x_scale, f32 y_scale, f32 z_scale) {
+ vec4 BACK_BOT_LEFT = (vec4){ 0, 0, 0, 0 };
+ vec4 BACK_BOT_RIGHT = (vec4){ 1, 0, 0, 0 };
+ vec4 BACK_TOP_LEFT = (vec4){ 0, 1, 0, 0 };
+ vec4 BACK_TOP_RIGHT = (vec4){ 1, 1, 0, 0 };
+ vec4 FRONT_BOT_LEFT = (vec4){ 0, 0, 1, 0 };
+ vec4 FRONT_BOT_RIGHT = (vec4){ 1, 0, 1, 0 };
+ vec4 FRONT_TOP_LEFT = (vec4){ 0, 1, 1, 0 };
+ vec4 FRONT_TOP_RIGHT = (vec4){ 1, 1, 1, 0 };
+
+ // allocate the data
+ static_3d_vert* vertices = malloc(36 * 64);
+
+ vertices[0] = (static_3d_vert){ .pos = BACK_TOP_RIGHT, .norm = (v3tov4(VEC3_NEG_Z)), .uv = { 0, 0 } };
+ vertices[1] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_Z), .uv = { 0, 1 } };
+ vertices[2] = (static_3d_vert){ .pos = BACK_TOP_LEFT, .norm = v3tov4(VEC3_NEG_Z), .uv = { 0, 0 } };
+ vertices[3] = (static_3d_vert){ .pos = BACK_TOP_RIGHT, .norm = v3tov4(VEC3_NEG_Z), .uv = { 1, 0 } };
+ vertices[4] = (static_3d_vert){ .pos = BACK_BOT_RIGHT, .norm = v3tov4(VEC3_NEG_Z), .uv = { 1, 1 } };
+ vertices[5] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_Z), .uv = { 0, 1 } };
+
+ // front faces
+ vertices[6] = (static_3d_vert){ .pos = FRONT_BOT_LEFT, .norm = v3tov4(VEC3_Z), .uv = { 0, 1 } };
+ vertices[7] = (static_3d_vert){ .pos = FRONT_TOP_RIGHT, .norm = v3tov4(VEC3_Z), .uv = { 1, 0 } };
+ vertices[8] = (static_3d_vert){ .pos = FRONT_TOP_LEFT, .norm = v3tov4(VEC3_Z), .uv = { 0, 0 } };
+ vertices[9] = (static_3d_vert){ .pos = FRONT_BOT_LEFT, .norm = v3tov4(VEC3_Z), .uv = { 0, 1 } };
+ vertices[10] = (static_3d_vert){ .pos = FRONT_BOT_RIGHT, .norm = v3tov4(VEC3_Z), .uv = { 1, 1 } };
+ vertices[11] = (static_3d_vert){ .pos = FRONT_TOP_RIGHT, .norm = v3tov4(VEC3_Z), .uv = { 1, 0 } };
+
+ // top faces
+ vertices[12] = (static_3d_vert){ .pos = BACK_TOP_LEFT, .norm = v3tov4(VEC3_Y), .uv = { 0, 0 } };
+ vertices[13] = (static_3d_vert){ .pos = FRONT_TOP_LEFT, .norm = v3tov4(VEC3_Y), .uv = { 0, 1 } };
+ vertices[14] = (static_3d_vert){ .pos = FRONT_TOP_RIGHT, .norm = v3tov4(VEC3_Y), .uv = { 1, 1 } };
+ vertices[15] = (static_3d_vert){ .pos = BACK_TOP_LEFT, .norm = v3tov4(VEC3_Y), .uv = { 0, 0 } };
+ vertices[16] = (static_3d_vert){ .pos = FRONT_TOP_RIGHT, .norm = v3tov4(VEC3_Y), .uv = { 1, 1 } };
+ vertices[17] = (static_3d_vert){ .pos = BACK_TOP_RIGHT, .norm = v3tov4(VEC3_Y), .uv = { 1, 0 } };
+
+ // bottom faces
+ vertices[18] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_Y), .uv = { 0, 1 } };
+ vertices[19] = (static_3d_vert){ .pos = FRONT_BOT_RIGHT, .norm = v3tov4(VEC3_NEG_Y), .uv = { 1, 1 } };
+ vertices[20] = (static_3d_vert){ .pos = FRONT_BOT_LEFT, .norm = v3tov4(VEC3_NEG_Y), .uv = { 0, 1 } };
+ vertices[21] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_Y), .uv = { 0, 1 } };
+ vertices[22] = (static_3d_vert){ .pos = BACK_BOT_RIGHT, .norm = v3tov4(VEC3_NEG_Y), .uv = { 1, 1 } };
+ vertices[23] = (static_3d_vert){ .pos = FRONT_BOT_RIGHT, .norm = v3tov4(VEC3_NEG_Y), .uv = { 0, 1 } };
+
+ // right faces
+ vertices[24] = (static_3d_vert){ .pos = FRONT_TOP_RIGHT, .norm = v3tov4(VEC3_X), .uv = { 0, 0 } };
+ vertices[25] = (static_3d_vert){ .pos = BACK_BOT_RIGHT, .norm = v3tov4(VEC3_X), .uv = { 1, 1 } };
+ vertices[26] = (static_3d_vert){ .pos = BACK_TOP_RIGHT, .norm = v3tov4(VEC3_X), .uv = { 1, 0 } };
+ vertices[27] = (static_3d_vert){ .pos = BACK_BOT_RIGHT, .norm = v3tov4(VEC3_X), .uv = { 1, 1 } };
+ vertices[28] = (static_3d_vert){ .pos = FRONT_TOP_RIGHT, .norm = v3tov4(VEC3_X), .uv = { 0, 0 } };
+ vertices[29] = (static_3d_vert){ .pos = FRONT_BOT_RIGHT, .norm = v3tov4(VEC3_X), .uv = { 0, 1 } };
+
+ // left faces
+ vertices[30] = (static_3d_vert){ .pos = FRONT_TOP_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
+ vertices[31] = (static_3d_vert){ .pos = BACK_TOP_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
+ vertices[32] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
+ vertices[33] = (static_3d_vert){ .pos = BACK_BOT_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
+ vertices[34] = (static_3d_vert){ .pos = FRONT_BOT_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
+ vertices[35] = (static_3d_vert){ .pos = FRONT_TOP_LEFT, .norm = v3tov4(VEC3_NEG_X), .uv = { 0, 0 } };
+
+ return (geometry){
+ .vertex_format = static_3d_vertex_format(), .vertex_data = vertices, .has_indices = false, .indices = NULL
+ };
+} \ No newline at end of file
diff --git a/src/impl.c b/src/impl.c
new file mode 100644
index 0000000..18f2549
--- /dev/null
+++ b/src/impl.c
@@ -0,0 +1,4 @@
+// For pulling in implementation files of single-header libraries
+
+#define STB_IMAGE_IMPLEMENTATION
+#include "stb_image.h" \ No newline at end of file
diff --git a/src/log.c b/src/log.c
index f0dfd87..66ffe2d 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,7 +1,9 @@
#include <celeritas.h>
-void log_output(char* module, LogLevel level, const char* message, ...) {
+static const char* log_level_strings[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" };
+
+void log_output(char* module, loglevel level, const char* message, ...) {
char out_msg[4096];
- printf("Msg: %s\n", message);
+ printf("[%s] %s - %s\n", module, log_level_strings[level], message);
}
diff --git a/src/maths.c b/src/maths.c
index 3ad1e2e..c1fab2a 100644
--- a/src/maths.c
+++ b/src/maths.c
@@ -1,3 +1,43 @@
#include <celeritas.h>
-Vec3 Vec3_Create(f32 x, f32 y, f32 z) { return (Vec3){ x, y, z }; }
+vec3 vec3_create(f32 x, f32 y, f32 z) { return (vec3){ x, y, z }; }
+
+vec3 vec3_add(vec3 u, vec3 v) { return (vec3){ .x = u.x + v.x, .y = u.y + v.y, .z = u.z + v.z }; }
+
+vec4 vec4_create(f32 x, f32 y, f32 z, f32 w) { return (vec4){ x, y, z, w }; }
+
+mat4 mat4_ident() { return (mat4){ .data = { 1.0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.0 } }; }
+
+mat4 mat4_mult(mat4 lhs, mat4 rhs) {
+ mat4 out_matrix = mat4_ident();
+
+ const f32* m1_ptr = lhs.data;
+ const f32* m2_ptr = rhs.data;
+ f32* dst_ptr = out_matrix.data;
+
+ for (i32 i = 0; i < 4; ++i) {
+ for (i32 j = 0; j < 4; ++j) {
+ *dst_ptr = m1_ptr[0] * m2_ptr[0 + j] + m1_ptr[1] * m2_ptr[4 + j] + m1_ptr[2] * m2_ptr[8 + j] +
+ m1_ptr[3] * m2_ptr[12 + j];
+ dst_ptr++;
+ }
+ m1_ptr += 4;
+ }
+
+ return out_matrix;
+}
+
+mat4 mat4_perspective(f32 fov_radians, f32 aspect_ratio, f32 near_z, f32 far_z) {
+ f32 half_tan_fov = tanf(fov_radians * 0.5f);
+ mat4 out_matrix = { .data = { 0 } };
+ out_matrix.data[0] = 1.0f / (aspect_ratio * half_tan_fov);
+ out_matrix.data[5] = 1.0f / half_tan_fov;
+ out_matrix.data[10] = -((far_z + near_z) / (far_z - near_z));
+ out_matrix.data[11] = -1.0f;
+ out_matrix.data[14] = -((2.0f * far_z * near_z) / (far_z - near_z));
+ return out_matrix;
+}
+
+mat4 mat4_look_at(vec3 position, vec3 target, vec3 up) {
+ // TODO
+} \ No newline at end of file
diff --git a/src/mem.c b/src/mem.c
index e69de29..2649db5 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -0,0 +1,88 @@
+#include <celeritas.h>
+
+void_pool void_pool_create(void* storage, const char* debug_label, u64 capacity, u64 entry_size) {
+ size_t _memory_requirements = capacity * entry_size;
+ // void* backing_buf = arena_alloc(a, memory_requirements);
+
+ assert(entry_size >= sizeof(void_pool_header)); // TODO: create my own assert with error message
+
+ void_pool pool = { .capacity = capacity,
+ .entry_size = entry_size,
+ .count = 0,
+ .backing_buffer = storage,
+ .free_list_head = NULL,
+ .debug_label = debug_label };
+
+ void_pool_free_all(&pool);
+
+ return pool;
+}
+
+void void_pool_free_all(void_pool* pool) {
+ // set all entries to be free
+ for (u64 i = 0; i < pool->capacity; i++) {
+ void* ptr = &pool->backing_buffer[i * pool->entry_size];
+ void_pool_header* free_node = (void_pool_header*)ptr; // we reuse the actual entry itself to hold the header
+ if (i == (pool->capacity - 1)) {
+ // if the last one we make its next pointer NULL indicating its full
+ free_node->next = NULL;
+ }
+ free_node->next = pool->free_list_head;
+ // now the head points to this entry
+ pool->free_list_head = free_node;
+ }
+}
+
+void* void_pool_get(void_pool* pool, u32 raw_handle) {
+ // An handle is an index into the array essentially
+ void* ptr = pool->backing_buffer + (raw_handle * pool->entry_size);
+ return ptr;
+}
+
+void* void_pool_alloc(void_pool* pool, u32* out_raw_handle) {
+ // get the next free node
+ if (pool->count == pool->capacity) {
+ // WARN("Pool is full!");
+ return NULL;
+ }
+ if (pool->free_list_head == NULL) {
+ // ERROR("%s Pool is full (head = null)", pool->debug_label);
+ return NULL;
+ }
+ void_pool_header* free_node = pool->free_list_head;
+
+ // What index does this become?
+ uintptr_t start = (uintptr_t)pool->backing_buffer;
+ uintptr_t cur = (uintptr_t)free_node;
+ // TRACE("%ld %ld ", start, cur);
+ assert(cur > start);
+ u32 index = (u32)((cur - start) / pool->entry_size);
+ /* printf("Index %d\n", index); */
+ if (out_raw_handle != NULL) {
+ *out_raw_handle = index;
+ }
+
+ pool->free_list_head = free_node->next;
+
+ memset(free_node, 0, pool->entry_size);
+ pool->count++;
+ return (void*)free_node;
+}
+
+void void_pool_dealloc(void_pool* pool, u32 raw_handle) {
+ // push free node back onto the free list
+ void* ptr = void_pool_get(pool, raw_handle);
+ void_pool_header* freed_node = (void_pool_header*)ptr;
+
+ freed_node->next = pool->free_list_head;
+ pool->free_list_head = freed_node;
+
+ pool->count--;
+}
+
+u32 void_pool_insert(void_pool* pool, void* item) {
+ u32 raw_handle;
+ void* item_dest = void_pool_alloc(pool, &raw_handle);
+ memcpy(item_dest, item, pool->entry_size);
+ return raw_handle;
+}
diff --git a/src/scene.c b/src/scene.c
new file mode 100644
index 0000000..26e19dc
--- /dev/null
+++ b/src/scene.c
@@ -0,0 +1,26 @@
+/**
+ * @file scene.c
+ * @author your name (you@domain.com)
+ * @brief
+ * @version 0.1
+ * @date 2024-10-18
+ *
+ * @copyright Copyright (c) 2024
+ *
+ */
+#include <celeritas.h>
+
+// Retained mode scene tree that handles performant transform propagation, and allows systems, or other languages via
+// bindings, to manipulate rendering/scene data without *owning* said data.
+
+typedef struct scene_tree_node {
+ const char* label;
+} scene_tree_node;
+
+DEFINE_HANDLE(scene_node_handle);
+TYPED_POOL(scene_tree_node, scene_node);
+
+typedef struct render_scene_tree {
+} render_scene_tree;
+
+// What kind of operations and mutations can we perform on the tree?