diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-10-19 13:24:31 +1100 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-10-19 13:24:31 +1100 |
commit | 6182860f1b1aba4128b4f66eda7977600e60d1a0 (patch) | |
tree | 388d9aff8ca19ef324633ac1bea43f1548675150 | |
parent | 5d1750d9adfc45b53c75310c58e31dfdbd8a6e15 (diff) | |
parent | d6d742f8a24490f885e4a1ae3fea7ec46b01f58c (diff) |
fix merge
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 @@ -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: @@ -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` @@ -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 Binary files differnew file mode 100644 index 0000000..4f87254 --- /dev/null +++ b/assets/textures/mc_grass.jpeg 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 @@ -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 @@ -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 @@ -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? |