initial GL stuff
commit
7146de6c50
|
|
@ -0,0 +1,2 @@
|
||||||
|
zig-out
|
||||||
|
.zig-cache
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
// Although this function looks imperative, note that its job is to
|
||||||
|
// declaratively construct a build graph that will be executed by an external
|
||||||
|
// runner.
|
||||||
|
|
||||||
|
|
||||||
|
// const GL_TYPE = enum([]const u8) {
|
||||||
|
// COMPAT = "compat",
|
||||||
|
// CORE = "core",
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// const GL_VERSION = enum([]const u8) {
|
||||||
|
// GL33 = "3.3",
|
||||||
|
// GL46 = "4.6",
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
const glad_folder = "glad-4.6-compat";
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard optimization options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||||
|
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
// const lib = b.addStaticLibrary(.{
|
||||||
|
// .name = "test-game",
|
||||||
|
// // In this case the main source file is merely a path, however, in more
|
||||||
|
// // complicated build scripts, this could be a generated file.
|
||||||
|
// .root_source_file = b.path("src/root.zig"),
|
||||||
|
// .target = target,
|
||||||
|
// .optimize = optimize,
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// // This declares intent for the library to be installed into the standard
|
||||||
|
// // location when the user invokes the "install" step (the default step when
|
||||||
|
// // running `zig build`).
|
||||||
|
// b.installArtifact(lib);
|
||||||
|
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "test-game",
|
||||||
|
.root_source_file = b.path("src/main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
exe.addCSourceFile(.{
|
||||||
|
.file = b.path(glad_folder ++ "/src/glad.c")
|
||||||
|
});
|
||||||
|
exe.addIncludePath(b.path(glad_folder ++ "/include"));
|
||||||
|
exe.linkLibC();
|
||||||
|
exe.linkSystemLibrary("glfw");
|
||||||
|
exe.linkSystemLibrary("GL");
|
||||||
|
exe.linkSystemLibrary("z");
|
||||||
|
exe.linkSystemLibrary("spng");
|
||||||
|
|
||||||
|
// This declares intent for the executable to be installed into the
|
||||||
|
// standard location when the user invokes the "install" step (the default
|
||||||
|
// step when running `zig build`).
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
// This *creates* a Run step in the build graph, to be executed when another
|
||||||
|
// step is evaluated that depends on it. The next line below will establish
|
||||||
|
// such a dependency.
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
|
||||||
|
// By making the run step depend on the install step, it will be run from the
|
||||||
|
// installation directory rather than directly from within the cache directory.
|
||||||
|
// This is not necessary, however, if the application depends on other installed
|
||||||
|
// files, this ensures they will be present and in the expected location.
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
// This allows the user to pass arguments to the application in the build
|
||||||
|
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||||
|
if (b.args) |args| {
|
||||||
|
run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||||
|
// and can be selected like this: `zig build run`
|
||||||
|
// This will evaluate the `run` step rather than the default, which is "install".
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
|
||||||
|
// // Creates a step for unit testing. This only builds the test executable
|
||||||
|
// // but does not run it.
|
||||||
|
// const lib_unit_tests = b.addTest(.{
|
||||||
|
// .root_source_file = b.path("src/root.zig"),
|
||||||
|
// .target = target,
|
||||||
|
// .optimize = optimize,
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
||||||
|
|
||||||
|
// const exe_unit_tests = b.addTest(.{
|
||||||
|
// .root_source_file = b.path("src/main.zig"),
|
||||||
|
// .target = target,
|
||||||
|
// .optimize = optimize,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||||
|
|
||||||
|
// Similar to creating the run step earlier, this exposes a `test` step to
|
||||||
|
// the `zig build --help` menu, providing a way for the user to request
|
||||||
|
// running the unit tests.
|
||||||
|
// const test_step = b.step("test", "Run unit tests");
|
||||||
|
// test_step.dependOn(&run_lib_unit_tests.step);
|
||||||
|
// test_step.dependOn(&run_exe_unit_tests.step);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
.{
|
||||||
|
// This is the default name used by packages depending on this one. For
|
||||||
|
// example, when a user runs `zig fetch --save <url>`, this field is used
|
||||||
|
// as the key in the `dependencies` table. Although the user can choose a
|
||||||
|
// different name, most users will stick with this provided value.
|
||||||
|
//
|
||||||
|
// It is redundant to include "zig" in this name because it is already
|
||||||
|
// within the Zig package namespace.
|
||||||
|
.name = "test-game",
|
||||||
|
|
||||||
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
|
.version = "0.0.0",
|
||||||
|
|
||||||
|
// This field is optional.
|
||||||
|
// This is currently advisory only; Zig does not yet do anything
|
||||||
|
// with this value.
|
||||||
|
//.minimum_zig_version = "0.11.0",
|
||||||
|
|
||||||
|
// This field is optional.
|
||||||
|
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
||||||
|
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
||||||
|
// Once all dependencies are fetched, `zig build` no longer requires
|
||||||
|
// internet connectivity.
|
||||||
|
.dependencies = .{
|
||||||
|
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
|
||||||
|
//.example = .{
|
||||||
|
// // When updating this field to a new URL, be sure to delete the corresponding
|
||||||
|
// // `hash`, otherwise you are communicating that you expect to find the old hash at
|
||||||
|
// // the new URL.
|
||||||
|
// .url = "https://example.com/foo.tar.gz",
|
||||||
|
//
|
||||||
|
// // This is computed from the file contents of the directory of files that is
|
||||||
|
// // obtained after fetching `url` and applying the inclusion rules given by
|
||||||
|
// // `paths`.
|
||||||
|
// //
|
||||||
|
// // This field is the source of truth; packages do not come from a `url`; they
|
||||||
|
// // come from a `hash`. `url` is just one of many possible mirrors for how to
|
||||||
|
// // obtain a package matching this `hash`.
|
||||||
|
// //
|
||||||
|
// // Uses the [multihash](https://multiformats.io/multihash/) format.
|
||||||
|
// .hash = "...",
|
||||||
|
//
|
||||||
|
// // When this is provided, the package is found in a directory relative to the
|
||||||
|
// // build root. In this case the package's hash is irrelevant and therefore not
|
||||||
|
// // computed. This field and `url` are mutually exclusive.
|
||||||
|
// .path = "foo",
|
||||||
|
|
||||||
|
// // When this is set to `true`, a package is declared to be lazily
|
||||||
|
// // fetched. This makes the dependency only get fetched if it is
|
||||||
|
// // actually used.
|
||||||
|
// .lazy = false,
|
||||||
|
//},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Specifies the set of files and directories that are included in this package.
|
||||||
|
// Only files and directories listed here are included in the `hash` that
|
||||||
|
// is computed for this package. Only files listed here will remain on disk
|
||||||
|
// when using the zig package manager. As a rule of thumb, one should list
|
||||||
|
// files required for compilation plus any license(s).
|
||||||
|
// Paths are relative to the build root. Use the empty string (`""`) to refer to
|
||||||
|
// the build root itself.
|
||||||
|
// A directory listed here means that all files within, recursively, are included.
|
||||||
|
.paths = .{
|
||||||
|
"build.zig",
|
||||||
|
"build.zig.zon",
|
||||||
|
"src",
|
||||||
|
// For example...
|
||||||
|
//"LICENSE",
|
||||||
|
//"README.md",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,311 @@
|
||||||
|
#ifndef __khrplatform_h_
|
||||||
|
#define __khrplatform_h_
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
||||||
|
**
|
||||||
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
** copy of this software and/or associated documentation files (the
|
||||||
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
|
** the following conditions:
|
||||||
|
**
|
||||||
|
** The above copyright notice and this permission notice shall be included
|
||||||
|
** in all copies or substantial portions of the Materials.
|
||||||
|
**
|
||||||
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Khronos platform-specific types and definitions.
|
||||||
|
*
|
||||||
|
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
||||||
|
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
||||||
|
* The last semantic modification to khrplatform.h was at commit ID:
|
||||||
|
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
||||||
|
*
|
||||||
|
* Adopters may modify this file to suit their platform. Adopters are
|
||||||
|
* encouraged to submit platform specific modifications to the Khronos
|
||||||
|
* group so that they can be included in future versions of this file.
|
||||||
|
* Please submit changes by filing pull requests or issues on
|
||||||
|
* the EGL Registry repository linked above.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* See the Implementer's Guidelines for information about where this file
|
||||||
|
* should be located on your system and for more details of its use:
|
||||||
|
* http://www.khronos.org/registry/implementers_guide.pdf
|
||||||
|
*
|
||||||
|
* This file should be included as
|
||||||
|
* #include <KHR/khrplatform.h>
|
||||||
|
* by Khronos client API header files that use its types and defines.
|
||||||
|
*
|
||||||
|
* The types in khrplatform.h should only be used to define API-specific types.
|
||||||
|
*
|
||||||
|
* Types defined in khrplatform.h:
|
||||||
|
* khronos_int8_t signed 8 bit
|
||||||
|
* khronos_uint8_t unsigned 8 bit
|
||||||
|
* khronos_int16_t signed 16 bit
|
||||||
|
* khronos_uint16_t unsigned 16 bit
|
||||||
|
* khronos_int32_t signed 32 bit
|
||||||
|
* khronos_uint32_t unsigned 32 bit
|
||||||
|
* khronos_int64_t signed 64 bit
|
||||||
|
* khronos_uint64_t unsigned 64 bit
|
||||||
|
* khronos_intptr_t signed same number of bits as a pointer
|
||||||
|
* khronos_uintptr_t unsigned same number of bits as a pointer
|
||||||
|
* khronos_ssize_t signed size
|
||||||
|
* khronos_usize_t unsigned size
|
||||||
|
* khronos_float_t signed 32 bit floating point
|
||||||
|
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
||||||
|
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
||||||
|
* nanoseconds
|
||||||
|
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
||||||
|
* khronos_boolean_enum_t enumerated boolean type. This should
|
||||||
|
* only be used as a base type when a client API's boolean type is
|
||||||
|
* an enum. Client APIs which use an integer or other type for
|
||||||
|
* booleans cannot use this as the base type for their boolean.
|
||||||
|
*
|
||||||
|
* Tokens defined in khrplatform.h:
|
||||||
|
*
|
||||||
|
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
||||||
|
*
|
||||||
|
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
||||||
|
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
||||||
|
*
|
||||||
|
* Calling convention macros defined in this file:
|
||||||
|
* KHRONOS_APICALL
|
||||||
|
* KHRONOS_APIENTRY
|
||||||
|
* KHRONOS_APIATTRIBUTES
|
||||||
|
*
|
||||||
|
* These may be used in function prototypes as:
|
||||||
|
*
|
||||||
|
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
||||||
|
* int arg1,
|
||||||
|
* int arg2) KHRONOS_APIATTRIBUTES;
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
||||||
|
# define KHRONOS_STATIC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APICALL
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This precedes the return type of the function in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(KHRONOS_STATIC)
|
||||||
|
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
||||||
|
* header compatible with static linking. */
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
# define KHRONOS_APICALL __declspec(dllimport)
|
||||||
|
#elif defined (__SYMBIAN32__)
|
||||||
|
# define KHRONOS_APICALL IMPORT_C
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APICALL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIENTRY
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the return type of the function and precedes the function
|
||||||
|
* name in the function prototype.
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
||||||
|
/* Win32 but not WinCE */
|
||||||
|
# define KHRONOS_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
# define KHRONOS_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* Definition of KHRONOS_APIATTRIBUTES
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
* This follows the closing parenthesis of the function prototype arguments.
|
||||||
|
*/
|
||||||
|
#if defined (__ARMCC_2__)
|
||||||
|
#define KHRONOS_APIATTRIBUTES __softfp
|
||||||
|
#else
|
||||||
|
#define KHRONOS_APIATTRIBUTES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------
|
||||||
|
* basic type definitions
|
||||||
|
*-----------------------------------------------------------------------*/
|
||||||
|
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <stdint.h>
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
/*
|
||||||
|
* To support platform where unsigned long cannot be used interchangeably with
|
||||||
|
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
||||||
|
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
||||||
|
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
||||||
|
* unsigned long long or similar (this results in different C++ name mangling).
|
||||||
|
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
||||||
|
* platforms where the size of a pointer is larger than the size of long.
|
||||||
|
*/
|
||||||
|
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
||||||
|
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
||||||
|
#define KHRONOS_USE_INTPTR_T
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__VMS ) || defined(__sgi)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Using <inttypes.h>
|
||||||
|
*/
|
||||||
|
#include <inttypes.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Win32
|
||||||
|
*/
|
||||||
|
typedef __int32 khronos_int32_t;
|
||||||
|
typedef unsigned __int32 khronos_uint32_t;
|
||||||
|
typedef __int64 khronos_int64_t;
|
||||||
|
typedef unsigned __int64 khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif defined(__sun__) || defined(__digital__)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sun or Digital
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#if defined(__arch64__) || defined(_LP64)
|
||||||
|
typedef long int khronos_int64_t;
|
||||||
|
typedef unsigned long int khronos_uint64_t;
|
||||||
|
#else
|
||||||
|
typedef long long int khronos_int64_t;
|
||||||
|
typedef unsigned long long int khronos_uint64_t;
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hypothetical platform with no float or int64 support
|
||||||
|
*/
|
||||||
|
typedef int khronos_int32_t;
|
||||||
|
typedef unsigned int khronos_uint32_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 0
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 0
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic fallback
|
||||||
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef int32_t khronos_int32_t;
|
||||||
|
typedef uint32_t khronos_uint32_t;
|
||||||
|
typedef int64_t khronos_int64_t;
|
||||||
|
typedef uint64_t khronos_uint64_t;
|
||||||
|
#define KHRONOS_SUPPORT_INT64 1
|
||||||
|
#define KHRONOS_SUPPORT_FLOAT 1
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that are (so far) the same on all platforms
|
||||||
|
*/
|
||||||
|
typedef signed char khronos_int8_t;
|
||||||
|
typedef unsigned char khronos_uint8_t;
|
||||||
|
typedef signed short int khronos_int16_t;
|
||||||
|
typedef unsigned short int khronos_uint16_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
||||||
|
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
||||||
|
* to be the only LLP64 architecture in current use.
|
||||||
|
*/
|
||||||
|
#ifdef KHRONOS_USE_INTPTR_T
|
||||||
|
typedef intptr_t khronos_intptr_t;
|
||||||
|
typedef uintptr_t khronos_uintptr_t;
|
||||||
|
#elif defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_intptr_t;
|
||||||
|
typedef unsigned long long int khronos_uintptr_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_intptr_t;
|
||||||
|
typedef unsigned long int khronos_uintptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN64)
|
||||||
|
typedef signed long long int khronos_ssize_t;
|
||||||
|
typedef unsigned long long int khronos_usize_t;
|
||||||
|
#else
|
||||||
|
typedef signed long int khronos_ssize_t;
|
||||||
|
typedef unsigned long int khronos_usize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_FLOAT
|
||||||
|
/*
|
||||||
|
* Float type
|
||||||
|
*/
|
||||||
|
typedef float khronos_float_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if KHRONOS_SUPPORT_INT64
|
||||||
|
/* Time types
|
||||||
|
*
|
||||||
|
* These types can be used to represent a time interval in nanoseconds or
|
||||||
|
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
||||||
|
* of nanoseconds since some arbitrary system event (e.g. since the last
|
||||||
|
* time the system booted). The Unadjusted System Time is an unsigned
|
||||||
|
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
||||||
|
* may be either signed or unsigned.
|
||||||
|
*/
|
||||||
|
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
||||||
|
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy value used to pad enum types to 32 bits.
|
||||||
|
*/
|
||||||
|
#ifndef KHRONOS_MAX_ENUM
|
||||||
|
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerated boolean type
|
||||||
|
*
|
||||||
|
* Values other than zero should be considered to be true. Therefore
|
||||||
|
* comparisons should not be made against KHRONOS_TRUE.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
KHRONOS_FALSE = 0,
|
||||||
|
KHRONOS_TRUE = 1,
|
||||||
|
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
||||||
|
} khronos_boolean_enum_t;
|
||||||
|
|
||||||
|
#endif /* __khrplatform_h_ */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,12 @@
|
||||||
|
const Layer = @This();
|
||||||
|
|
||||||
|
z_index: i32,
|
||||||
|
|
||||||
|
fn layer(z_index: i32) Layer {
|
||||||
|
return .{
|
||||||
|
.z_index = z_index
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const FLOOR = layer(0);
|
||||||
|
pub const ENTITIES = layer(1);
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
const Rectf = @import("geometry/Rectf.zig");
|
||||||
|
const Recti = @import("geometry/Recti.zig");
|
||||||
|
const Vec2f = @import("geometry/Vec2f.zig");
|
||||||
|
const Texture = @import("Texture.zig");
|
||||||
|
const Layer = @import("Layer.zig");
|
||||||
|
const shaders = @import("shaders.zig");
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("glad/glad.h");
|
||||||
|
@cInclude("GLFW/glfw3.h");
|
||||||
|
});
|
||||||
|
const Sprite = @This();
|
||||||
|
|
||||||
|
texture_area: Rectf = undefined,
|
||||||
|
texture: *const Texture = undefined,
|
||||||
|
|
||||||
|
pub fn create(tex: *const Texture, rect: Recti) Sprite {
|
||||||
|
return .{
|
||||||
|
.texture_area = rect.scalef(Vec2f.new(
|
||||||
|
@floatFromInt(tex.width),
|
||||||
|
@floatFromInt(tex.height)
|
||||||
|
)),
|
||||||
|
.texture = tex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(self: *const Sprite, screen_pos: *const Recti, layer: Layer) void {
|
||||||
|
self.texture.bind(c.GL_TEXTURE0);
|
||||||
|
c.glBegin(c.GL_QUADS);
|
||||||
|
{
|
||||||
|
c.glVertexAttrib2f(shaders.TEXCOORD_ATTRIBUTE_ID, self.texture_area.a.x, self.texture_area.a.y);
|
||||||
|
c.glVertexAttrib4f(shaders.COLOR_ATTRIBUTE_ID, 1, 1, 1, 1);
|
||||||
|
c.glVertex3i(screen_pos.a.x, screen_pos.a.y, layer.z_index);
|
||||||
|
c.glVertexAttrib2f(shaders.TEXCOORD_ATTRIBUTE_ID, self.texture_area.b.x, self.texture_area.a.y);
|
||||||
|
c.glVertexAttrib4f(shaders.COLOR_ATTRIBUTE_ID, 1, 1, 1, 1);
|
||||||
|
c.glVertex3i(screen_pos.b.x, screen_pos.a.y, layer.z_index);
|
||||||
|
c.glVertexAttrib2f(shaders.TEXCOORD_ATTRIBUTE_ID, self.texture_area.b.x, self.texture_area.b.y);
|
||||||
|
c.glVertexAttrib4f(shaders.COLOR_ATTRIBUTE_ID, 1, 1, 1, 1);
|
||||||
|
c.glVertex3i(screen_pos.b.x, screen_pos.b.y, layer.z_index);
|
||||||
|
c.glVertexAttrib2f(shaders.TEXCOORD_ATTRIBUTE_ID, self.texture_area.a.x, self.texture_area.b.y);
|
||||||
|
c.glVertexAttrib4f(shaders.COLOR_ATTRIBUTE_ID, 1, 1, 1, 1);
|
||||||
|
c.glVertex3i(screen_pos.a.x, screen_pos.b.y, layer.z_index);
|
||||||
|
}
|
||||||
|
c.glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
const c = @cImport({
|
||||||
|
// @cInclude("png.h");
|
||||||
|
@cInclude("spng.h");
|
||||||
|
// @cInclude("zlib.h");
|
||||||
|
// @cInclude("stdio.h");
|
||||||
|
|
||||||
|
@cInclude("glad/glad.h");
|
||||||
|
@cInclude("GLFW/glfw3.h");
|
||||||
|
});
|
||||||
|
const std = @import("std");
|
||||||
|
const File = std.fs.File;
|
||||||
|
const Dir = std.fs.Dir;
|
||||||
|
const heap = std.heap.page_allocator;
|
||||||
|
|
||||||
|
const Texture = @This();
|
||||||
|
|
||||||
|
const Error = error {
|
||||||
|
Fuck
|
||||||
|
};
|
||||||
|
|
||||||
|
handle: u32,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
|
||||||
|
pub fn bind(self: *const Texture, unit: u32) void {
|
||||||
|
c.glActiveTexture(unit);
|
||||||
|
c.glBindTexture(c.GL_TEXTURE_2D, self.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(path: []const u8) !Texture {
|
||||||
|
|
||||||
|
var file = try std.fs.cwd().openFile(path, .{});
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
|
const file_size = (try file.stat()).size;
|
||||||
|
const buffer: []u8 = try heap.alloc(u8, file_size);
|
||||||
|
defer heap.free(buffer);
|
||||||
|
const reader = file.reader();
|
||||||
|
_ = try reader.readAll(buffer);
|
||||||
|
|
||||||
|
const context = c.spng_ctx_new(0);
|
||||||
|
defer c.spng_ctx_free(context);
|
||||||
|
_ = c.spng_set_png_buffer(context, @ptrCast(buffer), buffer.len);
|
||||||
|
|
||||||
|
var out_size: usize = undefined;
|
||||||
|
_ = c.spng_decoded_image_size(context, c.SPNG_FMT_RGBA8, &out_size);
|
||||||
|
const out_buf: []u8 = try heap.alloc(u8, out_size);
|
||||||
|
defer heap.free(out_buf);
|
||||||
|
_ = c.spng_decode_image(context, @ptrCast(out_buf), out_size, c.SPNG_FMT_RGBA8, 0);
|
||||||
|
var ihdr = c.struct_spng_ihdr {};
|
||||||
|
_ = c.spng_get_ihdr(context, &ihdr);
|
||||||
|
|
||||||
|
var tex_id: u32 = undefined;
|
||||||
|
c.glGenTextures(1, &tex_id);
|
||||||
|
c.glBindTexture(c.GL_TEXTURE_2D, tex_id);
|
||||||
|
c.glActiveTexture(c.GL_TEXTURE0);
|
||||||
|
c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_NEAREST);
|
||||||
|
c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_NEAREST);
|
||||||
|
c.glTexImage2D(c.GL_TEXTURE_2D, 0, c.GL_RGBA, @intCast(ihdr.width), @intCast(ihdr.height), 0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, @ptrCast(out_buf));
|
||||||
|
c.glBindTexture(c.GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
|
std.debug.print("texture generated: ID={} Path={s}\n", .{ tex_id, path });
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.handle = @intCast(tex_id),
|
||||||
|
.width = ihdr.width,
|
||||||
|
.height = ihdr.height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Recti = @import("geometry/Recti.zig");
|
||||||
|
const Matrix4f = @import("geometry/Matrix4f.zig");
|
||||||
|
const shaders = @import("shaders.zig");
|
||||||
|
const Texture = @import("Texture.zig");
|
||||||
|
const Sprite = @import("Sprite.zig");
|
||||||
|
const Layer = @import("Layer.zig");
|
||||||
|
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("glad/glad.h");
|
||||||
|
@cInclude("GLFW/glfw3.h");
|
||||||
|
});
|
||||||
|
const HashMap = std.HashMap;
|
||||||
|
|
||||||
|
|
||||||
|
// export const IGame = struct {
|
||||||
|
// render: fn () void,
|
||||||
|
// update: fn (f32) void,
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
|
fn errorCallback(err: c_int, desc_c: [*c]const u8) callconv(.C) void {
|
||||||
|
const desc: *const u8 = @ptrCast(desc_c);
|
||||||
|
std.log.err("glfw error {x:0>8}: {s}", .{ err, desc });
|
||||||
|
}
|
||||||
|
|
||||||
|
// export fn run(game: *const IGame) !void {
|
||||||
|
pub fn run() !void {
|
||||||
|
|
||||||
|
// in case of errors, set callback early!
|
||||||
|
// for some reason this returns an error function as well??
|
||||||
|
_ = c.glfwSetErrorCallback(errorCallback);
|
||||||
|
|
||||||
|
// initialize glfw capabilities & cleanup
|
||||||
|
if (c.glfwInit() != 1) {
|
||||||
|
std.log.err("Failed to init glfw", .{});
|
||||||
|
return error.Initialization;
|
||||||
|
}
|
||||||
|
defer c.glfwTerminate();
|
||||||
|
|
||||||
|
// ensure glfw knows what we're about
|
||||||
|
// c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
|
c.glfwDefaultWindowHints();
|
||||||
|
c.glfwWindowHint(c.GLFW_SAMPLES, 4);
|
||||||
|
// c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
|
// c.glfwWindowHint(c.GLFW_OPENGL_PROFILE, c.GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
|
// create the window & cleanup
|
||||||
|
const window = c.glfwCreateWindow(640, 480, "My Title", null, null) orelse {
|
||||||
|
std.log.err("Failed to open window", .{});
|
||||||
|
return error.Initialization;
|
||||||
|
};
|
||||||
|
defer c.glfwDestroyWindow(window);
|
||||||
|
|
||||||
|
// load opengl into the window
|
||||||
|
c.glfwMakeContextCurrent(window);
|
||||||
|
if (c.gladLoadGL() != 1) {
|
||||||
|
std.log.err("Failed to load GL context", .{});
|
||||||
|
return error.Initialization;
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure the context!
|
||||||
|
c.glfwSwapInterval(1);
|
||||||
|
|
||||||
|
// compile shaders...
|
||||||
|
try shaders.load();
|
||||||
|
|
||||||
|
const texture = try Texture.create("textures.png");
|
||||||
|
// texture.bind(c.GL_TEXTURE0);
|
||||||
|
const sprite = Sprite.create(&texture, Recti.from_xywh(8*27, 8*4, 8, 16));
|
||||||
|
|
||||||
|
const clearBrightness: f32 = 0.09;
|
||||||
|
c.glClearColor(clearBrightness, clearBrightness, clearBrightness, 1.0);
|
||||||
|
// c.glEnable(c.GL_MULTISAMPLE);
|
||||||
|
c.glDisable(c.GL_MULTISAMPLE);
|
||||||
|
// c.glEnable(c.GL_BLEND);
|
||||||
|
// c.glBlendFunc(c.GL_SRC_ALPHA, c.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
// c.glEnable(c.GL_DEPTH_TEST);
|
||||||
|
// c.glDepthFunc(c.GL_LEQUAL);
|
||||||
|
// c.glDepthMask(c.GL_TRUE);
|
||||||
|
|
||||||
|
var width: c_int = undefined;
|
||||||
|
var height: c_int = undefined;
|
||||||
|
c.glfwGetFramebufferSize(window, @ptrCast(&width), @ptrCast(&height));
|
||||||
|
|
||||||
|
const projection = Matrix4f.orthographic(0, @floatFromInt(width), @floatFromInt(height), 0, 0, 100);
|
||||||
|
|
||||||
|
// run the main loop
|
||||||
|
while (c.glfwWindowShouldClose(window) == 0) {
|
||||||
|
shaders.set_projection_matrix(&projection);
|
||||||
|
|
||||||
|
// std.debug.print("size: {d} x {d}\n", .{width, height});
|
||||||
|
// c.glViewport(0, 0, width, height);
|
||||||
|
c.glClear(c.GL_COLOR_BUFFER_BIT | c.GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// c.glBegin(c.GL_TRIANGLES);
|
||||||
|
//
|
||||||
|
// c.glVertex2f(0, 1);
|
||||||
|
// // c.glVertexAttrib4f(1, 1, 0, 0, 1);
|
||||||
|
// c.glVertex2f(-1, -1);
|
||||||
|
// // c.glVertexAttrib4f(1, 0, 1, 0, 1);
|
||||||
|
// c.glVertex2f(1, -1);
|
||||||
|
// // c.glVertexAttrib4f(1, 0, 0, 1, 1);
|
||||||
|
//
|
||||||
|
// c.glEnd();
|
||||||
|
sprite.draw(&Recti.from_xywh(100, 100, 32, 64), Layer.FLOOR);
|
||||||
|
// draw.rect(&geometry.Rect.from_xywh(100, 100, 256, 256), draw.Layer.FLOOR);
|
||||||
|
|
||||||
|
// game.render();
|
||||||
|
// game.update(1.0);
|
||||||
|
c.glfwSwapBuffers(window);
|
||||||
|
c.glfwPollEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
const Vec2i = @import("geometry/Vec2i.zig");
|
||||||
|
|
||||||
|
pub const Recti = struct {
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
w: i32,
|
||||||
|
h: i32,
|
||||||
|
a: Vec2i,
|
||||||
|
b: Vec2i,
|
||||||
|
|
||||||
|
pub fn from_xywh(x: i32, y: i32, w: i32, h: i32) Recti {
|
||||||
|
return .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
.w = w,
|
||||||
|
.h = h,
|
||||||
|
.a = Vec2i.new(x, y),
|
||||||
|
.b = Vec2i.new(x + w, y + h),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Matrix4f = struct {
|
||||||
|
values: [16]f32 = identity,
|
||||||
|
|
||||||
|
const SIZE: i8 = 4 * 4;
|
||||||
|
const identity = from_values([16]f32 {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn from_values(values: [16]f32) Matrix4f {
|
||||||
|
return .{ .values = values };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) Matrix4f {
|
||||||
|
var ortho = Matrix4f.identity;
|
||||||
|
ortho.values[0 + 0 * 4] = 2.0 / (right - left);
|
||||||
|
ortho.values[1 + 1 * 4] = 2.0 / (top - bottom);
|
||||||
|
ortho.values[2 + 2 * 4] = 2.0 / (near - far);
|
||||||
|
|
||||||
|
ortho.values[0 + 3 * 4] = (left + right) / (left - right);
|
||||||
|
ortho.values[1 + 3 * 4] = (bottom + top) / (bottom - top);
|
||||||
|
ortho.values[2 + 3 * 4] = (far + near) / (far - near);
|
||||||
|
return ortho;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
const Matrix4f = @This();
|
||||||
|
|
||||||
|
values: [16]f32 = identity,
|
||||||
|
|
||||||
|
const SIZE: i8 = 4 * 4;
|
||||||
|
const identity = from_values([16]f32 {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn from_values(values: [16]f32) Matrix4f {
|
||||||
|
return .{ .values = values };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn orthographic(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32) Matrix4f {
|
||||||
|
var ortho = Matrix4f.identity;
|
||||||
|
ortho.values[0 + 0 * 4] = 2.0 / (right - left);
|
||||||
|
ortho.values[1 + 1 * 4] = 2.0 / (top - bottom);
|
||||||
|
ortho.values[2 + 2 * 4] = 2.0 / (near - far);
|
||||||
|
|
||||||
|
ortho.values[0 + 3 * 4] = (left + right) / (left - right);
|
||||||
|
ortho.values[1 + 3 * 4] = (bottom + top) / (bottom - top);
|
||||||
|
ortho.values[2 + 3 * 4] = (far + near) / (far - near);
|
||||||
|
return ortho;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
const Vec2f = @import("./Vec2f.zig");
|
||||||
|
const Recti = @import("./Recti.zig");
|
||||||
|
|
||||||
|
const Rectf = @This();
|
||||||
|
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
w: f32,
|
||||||
|
h: f32,
|
||||||
|
a: Vec2f,
|
||||||
|
b: Vec2f,
|
||||||
|
|
||||||
|
pub fn from_xywh(x: f32, y: f32, w: f32, h: f32) Rectf {
|
||||||
|
return .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
.w = w,
|
||||||
|
.h = h,
|
||||||
|
.a = Vec2f.new(x, y),
|
||||||
|
.b = Vec2f.new(x + w, y + h),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_recti(self: *const Rectf) Recti {
|
||||||
|
return Recti.from_xywh(
|
||||||
|
@intCast(self.x),
|
||||||
|
@intCast(self.y),
|
||||||
|
@intCast(self.w),
|
||||||
|
@intCast(self.h),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
const Vec2i = @import("./Vec2i.zig");
|
||||||
|
const Vec2f = @import("./Vec2f.zig");
|
||||||
|
const Rectf = @import("./Rectf.zig");
|
||||||
|
|
||||||
|
const Recti = @This();
|
||||||
|
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
w: i32,
|
||||||
|
h: i32,
|
||||||
|
a: Vec2i,
|
||||||
|
b: Vec2i,
|
||||||
|
|
||||||
|
pub fn from_xywh(x: i32, y: i32, w: i32, h: i32) Recti {
|
||||||
|
return .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
.w = w,
|
||||||
|
.h = h,
|
||||||
|
.a = Vec2i.new(x, y),
|
||||||
|
.b = Vec2i.new(x + w, y + h),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_rectf(self: *const Recti) Rectf {
|
||||||
|
return Rectf.from_xywh(
|
||||||
|
@intCast(self.x),
|
||||||
|
@intCast(self.y),
|
||||||
|
@intCast(self.w),
|
||||||
|
@intCast(self.h),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scalef(self: *const Recti, scale: Vec2f) Rectf {
|
||||||
|
return Rectf.from_xywh(
|
||||||
|
@as(f32, @floatFromInt(self.x)) / scale.x,
|
||||||
|
@as(f32, @floatFromInt(self.y)) / scale.y,
|
||||||
|
@as(f32, @floatFromInt(self.w)) / scale.x,
|
||||||
|
@as(f32, @floatFromInt(self.h)) / scale.y,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
const Vec2f = @This();
|
||||||
|
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
|
|
||||||
|
pub fn new(x: f32, y: f32) Vec2f {
|
||||||
|
return .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ZERO = new(0, 0);
|
||||||
|
pub const ONE = new(1, 1);
|
||||||
|
pub const NORTH = new(0, -1);
|
||||||
|
pub const SOUTH = new(0, 1);
|
||||||
|
pub const EAST = new(1, 0);
|
||||||
|
pub const WEST = new(-1, 0);
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
const Vec2i = @This();
|
||||||
|
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
|
||||||
|
pub fn new(x: i32, y: i32) Vec2i {
|
||||||
|
return .{
|
||||||
|
.x = x,
|
||||||
|
.y = y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const ZERO = new(0, 0);
|
||||||
|
pub const ONE = new(1, 1);
|
||||||
|
pub const NORTH = new(0, -1);
|
||||||
|
pub const SOUTH = new(0, 1);
|
||||||
|
pub const EAST = new(1, 0);
|
||||||
|
pub const WEST = new(-1, 0);
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
const std = @import("std");
|
||||||
|
const engine = @import("engine.zig");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
try engine.run();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
export fn add(a: i32, b: i32) i32 {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const heap = std.heap.page_allocator;
|
||||||
|
const Matrix4f = @import("geometry/Matrix4f.zig");
|
||||||
|
const Textures = @import("Texture.zig");
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("glad/glad.h");
|
||||||
|
@cInclude("GLFW/glfw3.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
const Error = error {
|
||||||
|
NotInitialized,
|
||||||
|
AlreadyInitialized,
|
||||||
|
};
|
||||||
|
|
||||||
|
const VERT_SHADER_TEXT =
|
||||||
|
\\ #version 330
|
||||||
|
\\ uniform mat4 uProjection;
|
||||||
|
\\
|
||||||
|
\\ in vec3 Position;
|
||||||
|
\\ in vec4 Color;
|
||||||
|
\\ in vec2 TexCoord;
|
||||||
|
\\
|
||||||
|
\\ out vec4 vColor;
|
||||||
|
\\ out vec2 vTexCoord;
|
||||||
|
\\
|
||||||
|
\\ void main() {
|
||||||
|
\\ gl_Position = uProjection * vec4(Position, 1.0);
|
||||||
|
\\ vColor = Color;
|
||||||
|
\\ vTexCoord = TexCoord;
|
||||||
|
\\ }
|
||||||
|
;
|
||||||
|
|
||||||
|
const FRAG_SHADER_TEXT =
|
||||||
|
\\ #version 330
|
||||||
|
\\ uniform sampler2D uTexture0;
|
||||||
|
\\
|
||||||
|
\\ in vec4 vColor;
|
||||||
|
\\ in vec2 vTexCoord;
|
||||||
|
\\
|
||||||
|
\\ out vec4 color;
|
||||||
|
\\
|
||||||
|
\\ void main() {
|
||||||
|
\\ vec4 texColor = color = texture(uTexture0, vTexCoord);
|
||||||
|
\\ if(texColor == vec4(1, 0, 1, 1) || texColor == vec4(1, 0, 0, 1) || texColor.w == 0.0) {
|
||||||
|
\\ discard;
|
||||||
|
\\ return;
|
||||||
|
\\ }
|
||||||
|
\\ color = texColor * vColor;
|
||||||
|
\\ // color = vColor;
|
||||||
|
\\ // color = vec4(vTexCoord.x, vTexCoord.y, 0, 1);
|
||||||
|
\\ }
|
||||||
|
;
|
||||||
|
|
||||||
|
pub const POSITION_ATTRIBUTE_ID = 0;
|
||||||
|
pub const COLOR_ATTRIBUTE_ID = 1;
|
||||||
|
pub const TEXCOORD_ATTRIBUTE_ID = 2;
|
||||||
|
|
||||||
|
|
||||||
|
var flat: Shader = undefined;
|
||||||
|
var active_shader: *const Shader = undefined;
|
||||||
|
|
||||||
|
pub fn load() !void {
|
||||||
|
// if (active_shader != undefined) return Error.AlreadyInitialized;
|
||||||
|
flat = try Shader.compile(VERT_SHADER_TEXT, FRAG_SHADER_TEXT);
|
||||||
|
flat.enable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_projection_matrix(matrix: *const Matrix4f) void {
|
||||||
|
active_shader.set_projection_matrix(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Shader = struct {
|
||||||
|
vertex_shader: c.GLuint,
|
||||||
|
fragment_shader: c.GLuint,
|
||||||
|
program_handle: c.GLuint,
|
||||||
|
|
||||||
|
const Error = error {
|
||||||
|
CompilationFailed
|
||||||
|
};
|
||||||
|
// cache: HashMap<*const u8, i32> = undefined,
|
||||||
|
|
||||||
|
fn enable(self: *const Shader) void {
|
||||||
|
c.glUseProgram(self.program_handle);
|
||||||
|
active_shader = self;
|
||||||
|
|
||||||
|
c.glUniform1i(c.glGetUniformLocation(self.program_handle, "uTexture0"), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile(vert_shader_text: []const u8, frag_shader_text: []const u8) !Shader {
|
||||||
|
const vertex_shader: c.GLuint= c.glCreateShader(c.GL_VERTEX_SHADER);
|
||||||
|
{
|
||||||
|
c.glShaderSource(vertex_shader, 1, @ptrCast(&vert_shader_text), null);
|
||||||
|
c.glCompileShader(vertex_shader);
|
||||||
|
var compile_status: c.GLint = undefined;
|
||||||
|
c.glGetShaderiv(vertex_shader, c.GL_COMPILE_STATUS, &compile_status);
|
||||||
|
if (compile_status != c.GL_TRUE) {
|
||||||
|
std.log.err("Vertex shader compilation failed!", .{});
|
||||||
|
var error_text: [1000]u8 = undefined;
|
||||||
|
var len: i32 = undefined;
|
||||||
|
c.glGetShaderInfoLog(vertex_shader, 1000, &len, &error_text);
|
||||||
|
std.debug.print("{s}\n", .{ error_text[0..@intCast(len)] });
|
||||||
|
return Shader.Error.CompilationFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fragment_shader: c.GLuint = c.glCreateShader(c.GL_FRAGMENT_SHADER);
|
||||||
|
{
|
||||||
|
c.glShaderSource(fragment_shader, 1, @ptrCast(&frag_shader_text), null);
|
||||||
|
c.glCompileShader(fragment_shader);
|
||||||
|
var compile_status: c.GLint = undefined;
|
||||||
|
c.glGetShaderiv(fragment_shader, c.GL_COMPILE_STATUS, &compile_status);
|
||||||
|
if (compile_status != c.GL_TRUE) {
|
||||||
|
std.log.err("Fragment shader compilation failed!", .{});
|
||||||
|
var error_text: [1000]u8 = undefined;
|
||||||
|
var len: i32 = undefined;
|
||||||
|
c.glGetShaderInfoLog(fragment_shader, 1000, &len, &error_text);
|
||||||
|
std.debug.print("{s}\n", .{ error_text[0..@intCast(len)] });
|
||||||
|
return Shader.Error.CompilationFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO add logging for errors in compilation...
|
||||||
|
|
||||||
|
const program_handle: c.GLuint = c.glCreateProgram();
|
||||||
|
c.glAttachShader(program_handle, vertex_shader);
|
||||||
|
c.glAttachShader(program_handle, fragment_shader);
|
||||||
|
c.glLinkProgram(program_handle);
|
||||||
|
c.glValidateProgram(program_handle);
|
||||||
|
|
||||||
|
c.glBindAttribLocation(program_handle, POSITION_ATTRIBUTE_ID, "Position");
|
||||||
|
c.glBindAttribLocation(program_handle, COLOR_ATTRIBUTE_ID, "Color");
|
||||||
|
c.glBindAttribLocation(program_handle, TEXCOORD_ATTRIBUTE_ID, "TexCoord");
|
||||||
|
|
||||||
|
c.glDeleteShader(vertex_shader);
|
||||||
|
c.glDeleteShader(fragment_shader);
|
||||||
|
|
||||||
|
return Shader {
|
||||||
|
.vertex_shader = vertex_shader,
|
||||||
|
.fragment_shader = fragment_shader,
|
||||||
|
.program_handle = program_handle,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_uniform_id(self: Shader, name: [*c]const u8) c.GLint {
|
||||||
|
return c.glGetUniformLocation(self.program_handle, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_projection_matrix(self: Shader, matrix: *const Matrix4f) void {
|
||||||
|
const attribute_id: c.GLint = self.get_uniform_id("uProjection");
|
||||||
|
c.glUniformMatrix4fv(attribute_id, 1, c.GL_FALSE, @ptrCast(&matrix.values));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
Loading…
Reference in New Issue