This commit is contained in:
Tuomas Katajisto 2025-04-26 10:51:41 +03:00
commit b5523acad0
99 changed files with 80582 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store
.build/

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# JAI Sokol WASM example
This is a small project to demo how to use Jai + Sokol and output to WASM.
Notes:
- Jai only supports WASM64 at the moment, so we need the [Memory64](https://github.com/WebAssembly/memory64/blob/main/proposals/memory64/Overview.md) extension for now. It's available as a feature flag in [some browsers](https://webassembly.org/features/#table-row-memory64).
- I'm (unfortunately) using [emscripten](https://emscripten.org) to compile the final wasm file so everything is still clunky.
- Sokol-jai: https://github.com/colinbellino/sokol-jai
## How to build?
- Run `jai first.jai`, which should output in the `dist/` folder.
- Serve the `dist/` folder with any server you want (any tool that can app serve static assets should work).
- Open in a browser. (http://127.0.0.1:8080 for example)

79
dist/index.html vendored Normal file
View File

@ -0,0 +1,79 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="UTF-8"/>
<title>${name}</title>
<style type="text/css">
body {
margin: 0;
background-color: black;
}
.game-title {
pointer-events: none;
position: absolute;
bottom: 10px;
margin-top: 0px;
padding-left: 10px;
color: white;
text-decoration: none;
z-index: 1;
text-align: left;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 30px;
}
.game-menu-item {
pointer-events: auto;
font-size: 18px;
padding-left: 10px;
font-family: Arial, Helvetica, sans-serif;
}
.game-menu-link {
text-decoration: none;
color: white;
}
.game {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body style="background:black">
<div class="game-title">${name}
<span class="game-menu-item"><a class="game-menu-link" href="index.html">home</a></span>
</div>
<canvas class="game" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type="text/javascript">
var Module = {
onRuntimeInitialized: function () {
const originalSet = HEAPU8.set.bind(HEAPU8);
HEAPU8.set = function(array, offset) {
if (typeof offset === 'bigint') {
offset = Number(offset);
}
return originalSet(array, offset);
};
},
preRun: [],
print: (...args) => console.log('[stdout]: ' + args.join(' ')),
printErr: (...args) => console.log('[stderr]: ' + args.join(' ')),
};
window.onerror = (event) => console.log('[onerror]: ' + event.message);
</script>
<script async type="text/javascript" src="index.js"></script>
</body>
</html>

4927
dist/index.js vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
dist/index.wasm vendored Executable file

Binary file not shown.

BIN
dist/main.o vendored Normal file

Binary file not shown.

BIN
dist/resources/DroidSerif-Regular.ttf vendored Normal file

Binary file not shown.

BIN
first Executable file

Binary file not shown.

113
first.jai Normal file
View File

@ -0,0 +1,113 @@
#run {
{
process_result, output, error := run_command("bash", "./compile_shaders.sh", working_directory=tprint("%/src/shaders", #filepath));
if process_result.exit_code != 0 {
log_error("Shader compilation failed.");
if output {
log_error(output,, logger = runtime_support_default_logger);
}
exit(1);
}
}
opt := get_build_options();
args := opt.compile_time_command_line;
doWasmBuild := false;
for arg : args {
if arg == "wasm" then doWasmBuild = true;
}
if doWasmBuild {
set_build_options_dc(.{do_output = false});
make_directory_if_it_does_not_exist("dist", recursive = true);
{
process_result, output, error := run_command("cp", "-r", "./resources", "./dist/", working_directory=tprint("%", #filepath));
w := compiler_create_workspace("Wasm");
options := get_build_options(w);
copy_commonly_propagated_fields(get_build_options(), *options);
options.output_type = .OBJECT_FILE;
options.backend = .LLVM; // WASM only works with the LLVM backend, obviously.
options.os_target = .WASM;
options.cpu_target = .CUSTOM;
options.emit_debug_info = .DWARF;
options.backtrace_on_crash = .OFF; // Runtime_Support_Crash_Handler doesnt support WASM (yet?)
options.output_path = "dist/";
options.output_executable_name = "main";
options.llvm_options.target_system_features = "+bulk-memory"; // "This options is needed so that "memcpy" and "memset" are mapped to "memory.copy" and "memory.fill" instructions in WASM.
options.llvm_options.enable_split_modules = false;
options.llvm_options.function_sections = true; // To get around "LLVM ERROR: section already has a defining function: .text"
import_paths: [..]string;
// Add our own modules folder first so that we can override modules with our own version, if necessary.
for options.import_path array_add(*import_paths, it);
options.import_path = import_paths;
// This was compiled from https://github.com/wingo/walloc via "clang -Oz --target=wasm64 -nostdlib -c -o walloc.o walloc.c".
// We should probably port this allocator to Jai instead…
// -rluba, 2023-11-15
walloc_object_file_path := "walloc.o";
STACK_SIZE :: 24 * 1024;
options.additional_linker_arguments = .["--stack-first", "-z", tprint("stack-size=%", STACK_SIZE), walloc_object_file_path];
set_build_options(options, w);
// Replace the default allocator with Walloc (https://github.com/wingo/walloc).
remap_import(w, "*", "Default_Allocator", "Walloc");
compiler_begin_intercept(w);
add_build_file("src/platform_specific/main_web.jai", w);
while true {
message := compiler_wait_for_message();
if message.kind == {
case .TYPECHECKED;
typechecked := cast(*Message_Typechecked) message;
for body: typechecked.procedure_bodies {
header := body.expression.header;
// You could replace individual procedure bodies here, if you needed to.
}
case .COMPLETE;
break;
}
}
compiler_end_intercept(w);
}
{
args := string.[
"emcc",
"src/platform_specific/main.c", "dist/main.o", "modules/sokol-jai/sokol/gfx/sokol_gfx_wasm_gl_debug.a", "modules/sokol-jai/sokol/log/sokol_log_wasm_gl_debug.a", "modules/sokol-jai/sokol/time/sokol_time_wasm_gl_debug.a", "modules/sokol-jai/sokol/app/sokol_app_wasm_gl_debug.a", "modules/sokol-jai/sokol/glue/sokol_glue_wasm_gl_debug.a", "modules/sokol-jai/sokol/fetch/sokol_fetch_wasm_gl_debug.a", "modules/sokol-jai/sokol/gl/sokol_gl_wasm_gl_debug.a", "modules/sokol-jai/sokol/fontstash/sokol_fontstash_wasm_gl_debug.a",
"-o", "dist/index.html",
"-sERROR_ON_UNDEFINED_SYMBOLS=1", "-sMEMORY64", "-sMAX_WEBGL_VERSION=2",
"--js-library=src/platform_specific/runtime.js",
"--shell-file=src/platform_specific/shell.html",
];
process_result, output, error := run_command(..args, capture_and_return_output = true);
if process_result.exit_code != 0 {
log_error("EMCC compilation failed.");
if error {
log_error(error,, logger = runtime_support_default_logger);
}
exit(1);
}
}
} else {
#load "src/platform_specific/main_native.jai";
}
}
#import "Basic";
#import "Compiler";
#import "Process";
#import "File";

63
modules/Walloc.jai Executable file
View File

@ -0,0 +1,63 @@
#scope_module
walloc_malloc :: (size: s64) -> *void #foreign "malloc"; // Will be provided by WASM
walloc_free :: (p: *void) #foreign "free"; // Will be provided by WASM
#scope_export
walloc_allocator :: Allocator.{allocator_proc, null};
allocator_proc :: (mode: Allocator_Mode, requested_size: s64, old_size: s64, old_memory: *void, allocator_data: *void) -> *void {
if #complete mode == {
case .STARTUP; #through;
case .SHUTDOWN; #through;
case .THREAD_START; #through;
case .THREAD_STOP;
return null;
case .ALLOCATE; #through;
case .RESIZE;
// @TODO: Can we support proper realloc?
result := walloc_malloc(requested_size);
if mode == .RESIZE {
size_to_copy := min(old_size, requested_size);
if result && size_to_copy memcpy(result, old_memory, size_to_copy);
}
return result;
case .FREE;
log("[Walloc]: FREE");
walloc_free(old_memory);
return null;
case .CREATE_HEAP; #through;
case .DESTROY_HEAP;
context.handling_assertion_failure = true;
context.assertion_failed(#location(), "This allocator does not support multiple heaps.\n");
context.handling_assertion_failure = false;
return null;
case .IS_THIS_YOURS;
context.handling_assertion_failure = true;
context.assertion_failed(#location(), "This allocator does not support IS_THIS_YOURS.\n");
context.handling_assertion_failure = false;
return null;
case .CAPS;
if old_memory { <<cast(*string)old_memory = CAPS_VERSION_STRING; }
return cast(*void) (Allocator_Caps.HINT_I_AM_A_GENERAL_HEAP_ALLOCATOR|.MULTIPLE_THREADS|.FREE|.ACTUALLY_RESIZE);
case;
context.handling_assertion_failure = true;
context.assertion_failed(#location(), "Invalid or corrupt mode passed to Walloc.allocator_proc().\n");
context.handling_assertion_failure = false;
return null;
}
}
#scope_file
CAPS_VERSION_STRING :: "Walloc";
#import "Basic";

View File

@ -0,0 +1,3 @@
// This is a window type replacement to fix using get_rect without simp...
Window_Type :: s32;
INVALID_WINDOW : Window_Type : -1;

3
modules/Window_Type.jai Normal file
View File

@ -0,0 +1,3 @@
// This is a window type replacement to fix using get_rect without simp...
Window_Type :: s32;
INVALID_WINDOW : Window_Type : 0;

16
modules/sokol-jai/.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.vscode/
build/
*.a
*.o
*.lib
*.obj
*.pdb
*.bin
*.exp
*.ilk
*.dll
*.dylib
*.exe
*.dSYM/
!libclang_rt.osx.a
.DS_Store

View File

@ -0,0 +1,2 @@
## CHANGELOG

View File

@ -0,0 +1,62 @@
<!-- [![Jai](https://github.com/colinbellino/sokol-jai/actions/workflows/main.yml/badge.svg)](https://github.com/colinbellino/sokol-jai/actions/workflows/main.yml) -->
Auto-generated Jai bindings for the [sokol headers](https://github.com/floooh/sokol).
To include sokol in your project you can copy the [sokol](sokol/) directory.
## BUILD
Supported platforms are: Windows, macOS, Linux (with X11)
On Linux install the following packages: libglu1-mesa-dev, mesa-common-dev, xorg-dev, libasound-dev
(or generally: the dev packages required for X11, GL and ALSA development)
1. First build the required static link libraries:
```bash
cd sokol
# on macOS:
./build_clibs_macos.sh
# on Linux:
./build_clibs_linux.sh
# on Windows with MSVC (from a 'Visual Studio Developer Command Prompt')
build_clibs_windows.cmd
cd ..
```
2. Create a build directory and cd into it:
```bash
mkdir build
cd build
```
3. Build and run the samples:
```bash
jai ../examples/first.jai - clear
jai ../examples/first.jai - triangle
jai ../examples/first.jai - offscreen
jai ../examples/first.jai - blend
jai ../examples/first.jai - debugtext-print
jai ../examples/first.jai - saudio
jai ../examples/first.jai - fontstash-sapp
jai ../examples/first.jai - sgl-context-sapp
```
By default, the backend 3D API will be selected based on the target platform:
- macOS: Metal
- Windows: D3D11
- Linux: GL
To force the GL backend on macOS or Windows, build with ```-GL```:
```
jai ../examples/first.jai - clear -GL
```
The ```clear``` sample prints the selected backend to the terminal:
```
jai ../examples/first.jai - clear -GL
>> using GL backend
```

21
modules/sokol-jai/examples/.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
.build
clear/clear
triangle/triangle
quad/quad
bufferoffsets/bufferoffsets
cube/cube
noninterleaved/noninterleaved
texcube/texcube
shapes/shapes
offscreen/offscreen
instancing/instancing
mrt/mrt
blend/blend
debugtext/debugtext
debugtext-print/debugtext-print
debugtext-userfont/debugtext-userfont
saudio/saudio
sgl/sgl
sgl-points/sgl-points
sgl-context/sgl-context
vertexpull/vertexpull

View File

@ -0,0 +1,138 @@
//------------------------------------------------------------------------------
// blend/module.jai
//
// Test/demonstrate blend modes.
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#load "../math.jai";
#load "./shader.jai";
NUM_BLEND_FACTORS :: 15;
state: struct {
pass_action: sg_pass_action;
bind: sg_bindings;
pips: [NUM_BLEND_FACTORS][NUM_BLEND_FACTORS]sg_pipeline;
bg_pip: sg_pipeline;
r: float;
quad_vs_params: Quad_Vs_Params;
bg_fs_params: Bg_Fs_Params;
}
init :: () #c_call {
push_context,defer_pop;
sg_setup(*(sg_desc.{
pipeline_pool_size = NUM_BLEND_FACTORS * NUM_BLEND_FACTORS + 1,
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
// a quad vertex buffer
vertices := float.[
// pos color
-1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.5,
+1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.5,
-1.0, +1.0, 0.0, 0.0, 0.0, 1.0, 0.5,
+1.0, +1.0, 0.0, 1.0, 1.0, 0.0, 0.5,
];
buffer := sg_buffer_desc.{ data = .{ ptr = *vertices, size = size_of(type_of(vertices)) } };
state.bind.vertex_buffers[0] = sg_make_buffer(*buffer);
// shader and pipeline object for rendering the background quad
bg_pip_desc: sg_pipeline_desc;
bg_pip_desc.shader = sg_make_shader(*bg_shader_desc(sg_query_backend()));
// we use the same vertex buffer as for the colored 3D quads,
// but only the first two floats from the position, need to
// provide a stride to skip the gap to the next vertex
bg_pip_desc.layout.buffers[0] = .{ stride = 28 };
bg_pip_desc.layout.attrs[ATTR_bg_position] = .{ format = .FLOAT2 };
bg_pip_desc.primitive_type = .TRIANGLE_STRIP;
state.bg_pip = sg_make_pipeline(*bg_pip_desc);
// a shader for the blended quads
quad_shd := sg_make_shader(*quad_shader_desc(sg_query_backend()));
// one pipeline object per blend-factor combination
pip_desc := sg_pipeline_desc.{
shader = quad_shd,
primitive_type = .TRIANGLE_STRIP,
blend_color = .{ 1.0, 0.0, 0.0, 1.0 },
};
pip_desc.layout.attrs[ATTR_quad_position] = .{ format = .FLOAT3 };
pip_desc.layout.attrs[ATTR_quad_color0] = .{ format = .FLOAT4 };
for src : 0 .. NUM_BLEND_FACTORS-1 {
for dst : 0 .. NUM_BLEND_FACTORS-1 {
pip_desc.colors[0].blend = .{
enabled = true,
src_factor_rgb = cast(sg_blend_factor) (src + 1),
dst_factor_rgb = cast(sg_blend_factor) (dst + 1),
src_factor_alpha = .ONE,
dst_factor_alpha = .ZERO,
};
state.pips[src][dst] = sg_make_pipeline(*pip_desc);
}
}
}
frame :: () #c_call {
push_context,defer_pop;
t := cast(float) (sapp_frame_duration() * 60.0);
state.r += 0.6 * t;
state.bg_fs_params.tick += 1.0 * t;
// view-projection matrix
proj := persp_mat4(fov = 90.0, aspect = sapp_widthf() / sapp_heightf(), near = 0.01, far = 100.0);
view := lookat_mat4(eye = .{ 0.0, 0.0, 25.0 }, center = .{}, up = .{ 0.0, 1.0, 0.0 });
view_proj := multiply_mat4(proj, view);
// start rendering
sg_begin_pass(*(sg_pass.{ action = state.pass_action, swapchain = xx,force sglue_swapchain() }));
// draw a background quad
sg_apply_pipeline(state.bg_pip);
sg_apply_bindings(*state.bind);
sg_apply_uniforms(UB_bg_fs_params, *(sg_range.{ ptr = *state.bg_fs_params, size = size_of(Bg_Fs_Params) }));
sg_draw(0, 4, 1);
// draw the blended quads
r0 := state.r;
for src : 0 .. NUM_BLEND_FACTORS - 1 {
for dst : 0 .. NUM_BLEND_FACTORS - 1 {
// compute model-view-proj matrix
rm := rotate_mat4(r0, .{ 0.0, 1.0, 0.0 });
x := cast(float) (dst - NUM_BLEND_FACTORS/2) * 3.0;
y := cast(float) (src - NUM_BLEND_FACTORS/2) * 2.2;
model := multiply_mat4(translate_mat4(.{ x, y, 0.0 }), rm);
state.quad_vs_params.mvp = multiply_mat4(view_proj, model);
sg_apply_pipeline(state.pips[src][dst]);
sg_apply_bindings(*state.bind);
sg_apply_uniforms(UB_quad_vs_params, *(sg_range.{ ptr = *state.quad_vs_params, size = size_of(Quad_Vs_Params) }));
sg_draw(0, 4, 1);
}
}
sg_end_pass();
sg_commit();
}
cleanup :: () #c_call {
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 800,
height = 600,
sample_count = 4,
window_title = "blend",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,52 @@
//------------------------------------------------------------------------------
// shaders for blend-sapp sample
//------------------------------------------------------------------------------
@ctype mat4 Matrix4
@vs vs_bg
in vec2 position;
void main() {
gl_Position = vec4(position, 0.5, 1.0);
}
@end
@fs fs_bg
layout(binding=0) uniform bg_fs_params {
float tick;
};
out vec4 frag_color;
void main() {
vec2 xy = fract((gl_FragCoord.xy-vec2(tick)) / 50.0);
frag_color = vec4(vec3(xy.x*xy.y), 1.0);
}
@end
@program bg vs_bg fs_bg
@vs vs_quad
layout(binding=0) uniform quad_vs_params {
mat4 mvp;
};
in vec4 position;
in vec4 color0;
out vec4 color;
void main() {
gl_Position = mvp * position;
color = color0;
}
@end
@fs fs_quad
in vec4 color;
out vec4 frag_color;
void main() {
frag_color = color;
}
@end
@program quad vs_quad fs_quad

View File

@ -0,0 +1,758 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader.glsl -o shader.jai -l glsl410:metal_macos:hlsl5 -f sokol_jai
Overview:
=========
Shader program: 'bg':
Get shader desc: bg_shader_desc(sg_query_backend())
Vertex Shader: vs_bg
Fragment Shader: fs_bg
Attributes:
ATTR_bg_position => 0
Shader program: 'quad':
Get shader desc: quad_shader_desc(sg_query_backend())
Vertex Shader: vs_quad
Fragment Shader: fs_quad
Attributes:
ATTR_quad_position => 0
ATTR_quad_color0 => 1
Bindings:
Uniform block 'bg_fs_params':
Jai struct: Bg_Fs_Params
Bind slot: UB_bg_fs_params => 0
Uniform block 'quad_vs_params':
Jai struct: Quad_Vs_Params
Bind slot: UB_quad_vs_params => 0
*/
ATTR_bg_position :: 0;
ATTR_quad_position :: 0;
ATTR_quad_color0 :: 1;
UB_bg_fs_params :: 0;
UB_quad_vs_params :: 0;
Bg_Fs_Params :: struct {
tick: float;
_: [12]u8;
};
Quad_Vs_Params :: struct {
mvp: Matrix4;
};
/*
#version 410
layout(location = 0) in vec2 position;
void main()
{
gl_Position = vec4(position, 0.5, 1.0);
}
*/
vs_bg_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,
0x7d,0x0a,0x0a,0x00,
];
/*
#version 410
uniform vec4 bg_fs_params[1];
layout(location = 0) out vec4 frag_color;
void main()
{
vec2 _28 = fract((gl_FragCoord.xy - vec2(bg_fs_params[0].x)) * vec2(0.0199999995529651641845703125));
float _39 = _28.x * _28.y;
frag_color = vec4(_39, _39, _39, 1.0);
}
*/
fs_bg_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x62,0x67,0x5f,0x66,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,
0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,
0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,
0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,
0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x63,0x32,0x20,0x5f,0x32,
0x38,0x20,0x3d,0x20,0x66,0x72,0x61,0x63,0x74,0x28,0x28,0x67,0x6c,0x5f,0x46,0x72,
0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x2e,0x78,0x79,0x20,0x2d,0x20,0x76,0x65,0x63,
0x32,0x28,0x62,0x67,0x5f,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,
0x5d,0x2e,0x78,0x29,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x30,0x2e,0x30,
0x31,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x35,0x32,0x39,0x36,0x35,0x31,0x36,
0x34,0x31,0x38,0x34,0x35,0x37,0x30,0x33,0x31,0x32,0x35,0x29,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x39,0x20,0x3d,0x20,0x5f,
0x32,0x38,0x2e,0x78,0x20,0x2a,0x20,0x5f,0x32,0x38,0x2e,0x79,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,
0x65,0x63,0x34,0x28,0x5f,0x33,0x39,0x2c,0x20,0x5f,0x33,0x39,0x2c,0x20,0x5f,0x33,
0x39,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 410
uniform vec4 quad_vs_params[4];
layout(location = 0) in vec4 position;
layout(location = 0) out vec4 color;
layout(location = 1) in vec4 color0;
void main()
{
gl_Position = mat4(quad_vs_params[0], quad_vs_params[1], quad_vs_params[2], quad_vs_params[3]) * position;
color = color0;
}
*/
vs_quad_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x71,0x75,0x61,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,
0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,
0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a,
0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x6d,0x61,0x74,0x34,0x28,0x71,0x75,0x61,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,
0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x71,0x75,0x61,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x71,0x75,0x61,0x64,0x5f,
0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x71,0x75,
0x61,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,
0x20,0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,
0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 410
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec4 color;
void main()
{
frag_color = color;
}
*/
fs_quad_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,
0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,
0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
static float4 gl_Position;
static float2 position;
struct SPIRV_Cross_Input
{
float2 position : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = float4(position, 0.5f, 1.0f);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
position = stage_input.position;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
return stage_output;
}
*/
vs_bg_source_hlsl5 := u8.[
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,
0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,
0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,
0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,
0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x53,0x56,0x5f,0x50,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x76,
0x65,0x72,0x74,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,
0x30,0x2e,0x35,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,
0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,
0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,
0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,
0x70,0x75,0x74,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x76,0x65,0x72,0x74,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,
0x75,0x74,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,
0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,
0x74,0x70,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x20,0x3d,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x61,0x67,0x65,
0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x00,
];
/*
cbuffer bg_fs_params : register(b0)
{
float _17_tick : packoffset(c0);
};
static float4 gl_FragCoord;
static float4 frag_color;
struct SPIRV_Cross_Input
{
float4 gl_FragCoord : SV_Position;
};
struct SPIRV_Cross_Output
{
float4 frag_color : SV_Target0;
};
void frag_main()
{
float2 _28 = frac((gl_FragCoord.xy - _17_tick.xx) * 0.0199999995529651641845703125f.xx);
float _39 = _28.x * _28.y;
frag_color = float4(_39, _39, _39, 1.0f);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
gl_FragCoord = stage_input.gl_FragCoord;
gl_FragCoord.w = 1.0 / gl_FragCoord.w;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.frag_color = frag_color;
return stage_output;
}
*/
fs_bg_source_hlsl5 := u8.[
0x63,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x62,0x67,0x5f,0x66,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x20,0x3a,0x20,0x72,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x28,
0x62,0x30,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,
0x5f,0x31,0x37,0x5f,0x74,0x69,0x63,0x6b,0x20,0x3a,0x20,0x70,0x61,0x63,0x6b,0x6f,
0x66,0x66,0x73,0x65,0x74,0x28,0x63,0x30,0x29,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x0a,
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,
0x5f,0x46,0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x3b,0x0a,0x73,0x74,0x61,0x74,
0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,
0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,
0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,
0x46,0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x20,0x3a,0x20,0x53,0x56,0x5f,0x50,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,
0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,
0x20,0x53,0x56,0x5f,0x54,0x61,0x72,0x67,0x65,0x74,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,
0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,
0x32,0x38,0x20,0x3d,0x20,0x66,0x72,0x61,0x63,0x28,0x28,0x67,0x6c,0x5f,0x46,0x72,
0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x2e,0x78,0x79,0x20,0x2d,0x20,0x5f,0x31,0x37,
0x5f,0x74,0x69,0x63,0x6b,0x2e,0x78,0x78,0x29,0x20,0x2a,0x20,0x30,0x2e,0x30,0x31,
0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x35,0x32,0x39,0x36,0x35,0x31,0x36,0x34,
0x31,0x38,0x34,0x35,0x37,0x30,0x33,0x31,0x32,0x35,0x66,0x2e,0x78,0x78,0x29,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x39,0x20,0x3d,
0x20,0x5f,0x32,0x38,0x2e,0x78,0x20,0x2a,0x20,0x5f,0x32,0x38,0x2e,0x79,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x5f,0x33,0x39,0x2c,0x20,0x5f,0x33,0x39,
0x2c,0x20,0x5f,0x33,0x39,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x7d,0x0a,
0x0a,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,
0x70,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,
0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,
0x5f,0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,
0x5f,0x46,0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x46,0x72,0x61,0x67,
0x43,0x6f,0x6f,0x72,0x64,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x46,0x72,
0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x2e,0x77,0x20,0x3d,0x20,0x31,0x2e,0x30,0x20,
0x2f,0x20,0x67,0x6c,0x5f,0x46,0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,0x2e,0x77,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,
0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,
0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,0x67,
0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,
0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x00,
];
/*
cbuffer quad_vs_params : register(b0)
{
row_major float4x4 _19_mvp : packoffset(c0);
};
static float4 gl_Position;
static float4 position;
static float4 color;
static float4 color0;
struct SPIRV_Cross_Input
{
float4 position : TEXCOORD0;
float4 color0 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 color : TEXCOORD0;
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = mul(position, _19_mvp);
color = color0;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
position = stage_input.position;
color0 = stage_input.color0;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
stage_output.color = color;
return stage_output;
}
*/
vs_quad_source_hlsl5 := u8.[
0x63,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x71,0x75,0x61,0x64,0x5f,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x3a,0x20,0x72,0x65,0x67,0x69,0x73,0x74,0x65,
0x72,0x28,0x62,0x30,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x5f,
0x6d,0x61,0x6a,0x6f,0x72,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x5f,
0x31,0x39,0x5f,0x6d,0x76,0x70,0x20,0x3a,0x20,0x70,0x61,0x63,0x6b,0x6f,0x66,0x66,
0x73,0x65,0x74,0x28,0x63,0x30,0x29,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x0a,0x73,0x74,
0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,
0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,
0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a,0x73,0x74,0x72,
0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x54,0x45,
0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x54,0x45,0x58,
0x43,0x4f,0x4f,0x52,0x44,0x31,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,
0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,
0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,
0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x53,
0x56,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,
0x76,0x6f,0x69,0x64,0x20,0x76,0x65,0x72,0x74,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x75,0x6c,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x2c,0x20,0x5f,0x31,0x39,0x5f,0x6d,0x76,0x70,0x29,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,
0x0a,0x7d,0x0a,0x0a,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,
0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,
0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,
0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3d,0x20,0x73,
0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,
0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x72,0x74,0x5f,0x6d,0x61,0x69,0x6e,
0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,
0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,
0x75,0x74,0x70,0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,
0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
0x00,
];
/*
static float4 frag_color;
static float4 color;
struct SPIRV_Cross_Input
{
float4 color : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 frag_color : SV_Target0;
};
void frag_main()
{
frag_color = color;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
color = stage_input.color;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.frag_color = frag_color;
return stage_output;
}
*/
fs_quad_source_hlsl5 := u8.[
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,
0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,
0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x54,0x45,
0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,
0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,
0x20,0x53,0x56,0x5f,0x54,0x61,0x72,0x67,0x65,0x74,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,
0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,
0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,
0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,
0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,
0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,
0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,
0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,
0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,
0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x72,0x61,0x67,0x5f,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
0x6e,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,
0x7d,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 gl_Position [[position]];
};
struct main0_in
{
float2 position [[attribute(0)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = float4(in.position, 0.5, 1.0);
return out;
}
*/
vs_bg_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,
0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,
0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,
0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,
0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,
0x76,0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,
0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,
0x69,0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,
0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,
0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x2c,0x20,0x30,0x2e,0x35,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,
0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct bg_fs_params
{
float tick;
};
struct main0_out
{
float4 frag_color [[color(0)]];
};
fragment main0_out main0(constant bg_fs_params& _17 [[buffer(0)]], float4 gl_FragCoord [[position]])
{
main0_out out = {};
float2 _28 = fract((gl_FragCoord.xy - float2(_17.tick)) * float2(0.0199999995529651641845703125));
float _39 = _28.x * _28.y;
out.frag_color = float4(_39, _39, _39, 1.0);
return out;
}
*/
fs_bg_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x62,
0x67,0x5f,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x74,0x69,0x63,0x6b,0x3b,0x0a,0x7d,0x3b,
0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,
0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x63,0x6f,0x6c,
0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,
0x67,0x6d,0x65,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,
0x6d,0x61,0x69,0x6e,0x30,0x28,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x62,
0x67,0x5f,0x66,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,0x37,
0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x46,0x72,0x61,0x67,0x43,0x6f,
0x6f,0x72,0x64,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,
0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x5f,0x32,0x38,0x20,0x3d,0x20,0x66,0x72,0x61,
0x63,0x74,0x28,0x28,0x67,0x6c,0x5f,0x46,0x72,0x61,0x67,0x43,0x6f,0x6f,0x72,0x64,
0x2e,0x78,0x79,0x20,0x2d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x5f,0x31,0x37,
0x2e,0x74,0x69,0x63,0x6b,0x29,0x29,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,
0x28,0x30,0x2e,0x30,0x31,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x35,0x35,0x32,0x39,
0x36,0x35,0x31,0x36,0x34,0x31,0x38,0x34,0x35,0x37,0x30,0x33,0x31,0x32,0x35,0x29,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x5f,0x33,0x39,
0x20,0x3d,0x20,0x5f,0x32,0x38,0x2e,0x78,0x20,0x2a,0x20,0x5f,0x32,0x38,0x2e,0x79,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x66,0x72,0x61,0x67,0x5f,0x63,
0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x5f,0x33,
0x39,0x2c,0x20,0x5f,0x33,0x39,0x2c,0x20,0x5f,0x33,0x39,0x2c,0x20,0x31,0x2e,0x30,
0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,
0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct quad_vs_params
{
float4x4 mvp;
};
struct main0_out
{
float4 color [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 position [[attribute(0)]];
float4 color0 [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant quad_vs_params& _19 [[buffer(0)]])
{
main0_out out = {};
out.gl_Position = _19.mvp * in.position;
out.color = in.color0;
return out;
}
*/
vs_quad_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x71,
0x75,0x61,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,
0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,
0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,
0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,
0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,
0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,
0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x5b,0x5b,
0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,0x0a,
0x7d,0x3b,0x0a,0x0a,0x76,0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,
0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,
0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,
0x6e,0x5d,0x5d,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x71,0x75,
0x61,0x64,0x5f,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,
0x39,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,
0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,
0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,0x20,0x2a,0x20,0x69,0x6e,0x2e,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,
0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,0x72,
0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,
0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float4 color [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.frag_color = in.color;
return out;
}
*/
fs_quad_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,
0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,
0x65,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,
0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,
0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,
0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
bg_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "bg_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_bg_source_glsl410;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bg_source_glsl410;
desc.fragment_func.entry = "main";
desc.attrs[0].glsl_name = "position";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 1;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "bg_fs_params";
case .D3D11;
desc.vertex_func.source = xx *vs_bg_source_hlsl5;
desc.vertex_func.d3d11_target = "vs_5_0";
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_bg_source_hlsl5;
desc.fragment_func.d3d11_target = "ps_5_0";
desc.fragment_func.entry = "main";
desc.attrs[0].hlsl_sem_name = "TEXCOORD";
desc.attrs[0].hlsl_sem_index = 0;
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].hlsl_register_b_n = 0;
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_bg_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_bg_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.uniform_blocks[0].stage = .FRAGMENT;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 16;
desc.uniform_blocks[0].msl_buffer_n = 0;
}
return desc;
}
quad_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "quad_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_quad_source_glsl410;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_quad_source_glsl410;
desc.fragment_func.entry = "main";
desc.attrs[0].glsl_name = "position";
desc.attrs[1].glsl_name = "color0";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "quad_vs_params";
case .D3D11;
desc.vertex_func.source = xx *vs_quad_source_hlsl5;
desc.vertex_func.d3d11_target = "vs_5_0";
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_quad_source_hlsl5;
desc.fragment_func.d3d11_target = "ps_5_0";
desc.fragment_func.entry = "main";
desc.attrs[0].hlsl_sem_name = "TEXCOORD";
desc.attrs[0].hlsl_sem_index = 0;
desc.attrs[1].hlsl_sem_name = "TEXCOORD";
desc.attrs[1].hlsl_sem_index = 1;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].hlsl_register_b_n = 0;
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_quad_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_quad_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].msl_buffer_n = 0;
}
return desc;
}

View File

@ -0,0 +1,59 @@
//------------------------------------------------------------------------------
// clear/module.jai
//
// Minimal sample which just clears the default framebuffer
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
pass_action: sg_pass_action;
init :: () #c_call {
push_context,defer_pop;
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
pass_action.colors[0] = .{ load_action = .CLEAR, clear_value = .{ 1.0, 0.0, 0.0, 1.0 } };
// just some debug output what backend we're running on
if sg_query_backend() == {
case .D3D11; print(">> using D3D11 backend");
case .GLCORE; #through;
case .GLES3; print(">> using GL backend");
case .METAL_MACOS; #through;
case .METAL_IOS; #through;
case .METAL_SIMULATOR; print(">> using Metal backend");
case .WGPU; print(">> using WebGPU backend");
case .DUMMY; print(">> using dummy backend");
}
}
frame :: () #c_call {
g := pass_action.colors[0].clear_value.g + 0.01;
pass_action.colors[0].clear_value.g = ifx(g > 1.0) then 0.0 else g;
sg_begin_pass(*(sg_pass.{ action = pass_action, swapchain = xx,force sglue_swapchain() }));
sg_end_pass();
sg_commit();
}
cleanup :: () #c_call {
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 400,
height = 300,
window_title = "clear",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,92 @@
//------------------------------------------------------------------------------
// debugtext-print/module.jai
//
// Simple text rendering with sokol/debugtext, formatting, tabs, etc...
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#import,dir "../../sokol/debugtext"(USE_GL=USE_GL);
NUM_FONTS :: 3;
Color :: struct {
r, g, b: u8;
}
state: struct {
pass_action: sg_pass_action;
palette: [3]Color;
} = .{
pass_action = .{
colors = .[
.{ load_action = .CLEAR, clear_value = .{ 0.0, 0.125, 0.25, 1.0 } },
.{}, .{}, .{},
],
},
palette = .[
.{ 0xf4, 0x43, 0x36 },
.{ 0x21, 0x96, 0xf3 },
.{ 0x4c, 0xaf, 0x50 },
],
};
init :: () #c_call {
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
sdtx_setup(*(sdtx_desc_t.{
fonts[0] = sdtx_font_kc854(),
fonts[1] = sdtx_font_c64(),
fonts[2] = sdtx_font_oric(),
logger = .{ func = slog_func },
}));
}
frame :: () #c_call {
push_context,defer_pop;
frame_count := cast(u32) sapp_frame_count();
frame_time := sapp_frame_duration() * 1000.0;
sdtx_canvas(sapp_widthf() * 0.5, sapp_heightf() * 0.5);
sdtx_origin(3.0, 3.0);
for i : 0 .. NUM_FONTS-1 {
color := state.palette[i];
sdtx_font(cast(s32) i);
sdtx_color3b(color.r, color.g, color.b);
sdtx_printf("Hello '%'!\n", ifx((frame_count & (1<<7)) == 0) then "Welt" else "World");
sdtx_printf("\tFrame Time:\t\t%.3f\n", frame_time);
sdtx_printf("\tFrame Count:\t%d\t0x%04X\n", frame_count, frame_count);
sdtx_putr("Range Test 1(xyzbla)", 12);
sdtx_putr("\nRange Test 2\n", 32);
sdtx_move_y(2);
}
sg_begin_pass(*(sg_pass.{ action = state.pass_action, swapchain = xx,force sglue_swapchain() }));
sdtx_draw();
sg_end_pass();
sg_commit();
}
cleanup :: () #c_call {
sdtx_shutdown();
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 640,
height = 480,
window_title = "debugtext-printf",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,33 @@
#import "Compiler";
#import "Basic";
#import "Process";
#run {
options := get_build_options();
assert(options.compile_time_command_line.count >= 1, "Missing args, did you forget to pass the name of the example? (ie: jai first.jai - clear)");
example_name := options.compile_time_command_line[0];
use_gl := array_find(options.compile_time_command_line, "-GL");
workspace := compiler_create_workspace(tprint("Building example: %", example_name));
output_path := "../build/";
options.output_path = output_path;
options.output_executable_name = example_name;
set_build_options(options, workspace);
compiler_begin_intercept(workspace);
add_build_string(tprint("USE_GL :: %;", use_gl), workspace);
add_build_file(tprint("%/module.jai", example_name), workspace);
while true {
message := compiler_wait_for_message();
if message.kind == {
case .ERROR; { exit(1); }
case .COMPLETE; { break; }
}
}
compiler_end_intercept(workspace);
run_command(tprint("%/%", output_path, example_name));
set_build_options_dc(.{ do_output = false });
}

View File

@ -0,0 +1,255 @@
//------------------------------------------------------------------------------
// fontstash-sapp/module.jai
//
// Text rendering via fontstash, stb_truetype and sokol_fontstash.h
//------------------------------------------------------------------------------
#import "Basic";
#import "File";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#import,dir "../../sokol/gl"(USE_GL=USE_GL);
#import,dir "../../sokol/fontstash"(USE_GL=USE_GL);
state: struct {
fons: *FONScontext;
dpi_scale: float;
font_normal: s32;
font_italic: s32;
font_bold: s32;
font_japanese: s32;
font_normal_data: [256 * 1024]u8;
font_italic_data: [256 * 1024]u8;
font_bold_data: [256 * 1024]u8;
font_japanese_data: [2 * 1024 * 1024]u8;
}
// round to next power of 2 (see bit-twiddling-hacks)
round_pow2 :: (v: float) -> s32 {
vi := (cast(u32) v) - 1;
for i : 0..4 {
vi |= (vi >> (1<<i));
}
return cast(s32) (vi + 1);
}
line :: (sx: float, sy: float, ex: float, ey: float) #c_call {
sgl_begin_lines();
sgl_c4b(255, 255, 0, 128);
sgl_v2f(sx, sy);
sgl_v2f(ex, ey);
sgl_end();
}
init :: () #c_call {
push_context,defer_pop;
state.dpi_scale = sapp_dpi_scale();
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
sgl_setup(*(sgl_desc_t.{
logger = .{ func = slog_func },
}));
atlas_dim := round_pow2(512.0 * state.dpi_scale);
fons_context := sfons_create(*(sfons_desc_t.{
width = atlas_dim,
height = atlas_dim,
}));
state.fons = fons_context;
state.font_normal = FONS_INVALID;
state.font_italic = FONS_INVALID;
state.font_bold = FONS_INVALID;
state.font_japanese = FONS_INVALID;
{
file_data := read_entire_file("../examples/fontstash-sapp/DroidSerif-Regular.ttf");
state.font_normal = fonsAddFontMem(state.fons, "sans", *file_data[0], xx file_data.count, 0);
}
{
file_data := read_entire_file("../examples/fontstash-sapp/DroidSerif-Italic.ttf");
state.font_italic = fonsAddFontMem(state.fons, "sans-italic", *file_data[0], xx file_data.count, 0);
}
{
file_data := read_entire_file("../examples/fontstash-sapp/DroidSerif-Bold.ttf");
state.font_bold = fonsAddFontMem(state.fons, "sans-bold", *file_data[0], xx file_data.count, 0);
}
{
file_data := read_entire_file("../examples/fontstash-sapp/DroidSansJapanese.ttf");
state.font_japanese = fonsAddFontMem(state.fons, "sans-japanese", *file_data[0], xx file_data.count, 0);
}
}
frame :: () #c_call {
dpis := state.dpi_scale;
white := sfons_rgba(255, 255, 255, 255);
black := sfons_rgba(0, 0, 0, 255);
brown := sfons_rgba(192, 128, 0, 128);
blue := sfons_rgba(0, 192, 255, 255);
fonsClearState(state.fons);
sgl_defaults();
sgl_matrix_mode_projection();
sgl_ortho(0.0, sapp_widthf(), sapp_heightf(), 0.0, -1.0, +1.0);
sx := 50*dpis;
sy := 50*dpis;
dx := sx;
dy := sy;
lh : float = 0.0;
fs := state.fons;
if (state.font_normal != FONS_INVALID) {
fonsSetFont(fs, state.font_normal);
fonsSetSize(fs, 124.0*dpis);
fonsVertMetrics(fs, null, null, *lh);
dx = sx;
dy += lh;
fonsSetColor(fs, white);
dx = fonsDrawText(fs, dx, dy, "The quick ", null);
}
if (state.font_italic != FONS_INVALID) {
fonsSetFont(fs, state.font_italic);
fonsSetSize(fs, 48.0*dpis);
fonsSetColor(fs, brown);
dx = fonsDrawText(fs, dx, dy, "brown ", null);
}
if (state.font_normal != FONS_INVALID) {
fonsSetFont(fs, state.font_normal);
fonsSetSize(fs, 24.0*dpis);
fonsSetColor(fs, white);
dx = fonsDrawText(fs, dx, dy,"fox ", null);
}
if ((state.font_normal != FONS_INVALID) && (state.font_italic != FONS_INVALID) && (state.font_bold != FONS_INVALID)) {
fonsVertMetrics(fs, null, null, *lh);
dx = sx;
dy += lh*1.2;
fonsSetFont(fs, state.font_italic);
dx = fonsDrawText(fs, dx, dy, "jumps over ",null);
fonsSetFont(fs, state.font_bold);
dx = fonsDrawText(fs, dx, dy, "the lazy ",null);
fonsSetFont(fs, state.font_normal);
dx = fonsDrawText(fs, dx, dy, "dog.",null);
}
if (state.font_normal != FONS_INVALID) {
dx = sx;
dy += lh*1.2;
fonsSetSize(fs, 12.0*dpis);
fonsSetFont(fs, state.font_normal);
fonsSetColor(fs, blue);
fonsDrawText(fs, dx,dy,"Now is the time for all good men to come to the aid of the party.",null);
}
if (state.font_italic != FONS_INVALID) {
fonsVertMetrics(fs, null, null, *lh);
dx = sx;
dy += lh*1.2*2;
fonsSetSize(fs, 18.0*dpis);
fonsSetFont(fs, state.font_italic);
fonsSetColor(fs, white);
fonsDrawText(fs, dx, dy, "Ég get etið gler án þess að meiða mig.", null);
}
if (state.font_japanese != FONS_INVALID) {
fonsVertMetrics(fs, null,null,*lh);
dx = sx;
dy += lh*1.2;
fonsSetFont(fs, state.font_japanese);
fonsDrawText(fs, dx,dy,"私はガラスを食べられます。それは私を傷つけません。",null);
}
// Font alignment
if (state.font_normal != FONS_INVALID) {
fonsSetSize(fs, 18.0*dpis);
fonsSetFont(fs, state.font_normal);
fonsSetColor(fs, white);
dx = 50*dpis; dy = 350*dpis;
line(dx-10*dpis,dy,dx+250*dpis,dy);
fonsSetAlign(fs, xx FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
dx = fonsDrawText(fs, dx,dy,"Top",null);
dx += 10*dpis;
fonsSetAlign(fs, xx FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE);
dx = fonsDrawText(fs, dx,dy,"Middle",null);
dx += 10*dpis;
fonsSetAlign(fs, xx FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE);
dx = fonsDrawText(fs, dx,dy,"Baseline",null);
dx += 10*dpis;
fonsSetAlign(fs, xx FONS_ALIGN_LEFT | FONS_ALIGN_BOTTOM);
fonsDrawText(fs, dx,dy,"Bottom",null);
dx = 150*dpis; dy = 400*dpis;
line(dx,dy-30*dpis,dx,dy+80.0*dpis);
fonsSetAlign(fs, xx FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE);
fonsDrawText(fs, dx,dy,"Left",null);
dy += 30*dpis;
fonsSetAlign(fs, xx FONS_ALIGN_CENTER | FONS_ALIGN_BASELINE);
fonsDrawText(fs, dx,dy,"Center",null);
dy += 30*dpis;
fonsSetAlign(fs, xx FONS_ALIGN_RIGHT | FONS_ALIGN_BASELINE);
fonsDrawText(fs, dx,dy,"Right",null);
}
// Blur
if (state.font_italic != FONS_INVALID) {
dx = 500*dpis; dy = 350*dpis;
fonsSetAlign(fs, xx FONS_ALIGN_LEFT | FONS_ALIGN_BASELINE);
fonsSetSize(fs, 60.0*dpis);
fonsSetFont(fs, state.font_italic);
fonsSetColor(fs, white);
fonsSetSpacing(fs, 5.0*dpis);
fonsSetBlur(fs, 10.0);
fonsDrawText(fs, dx,dy,"Blurry...",null);
}
if (state.font_bold != FONS_INVALID) {
dy += 50.0*dpis;
fonsSetSize(fs, 18.0*dpis);
fonsSetFont(fs, state.font_bold);
fonsSetColor(fs, black);
fonsSetSpacing(fs, 0.0);
fonsSetBlur(fs, 3.0);
fonsDrawText(fs, dx,dy+2,"DROP THAT SHADOW",null);
fonsSetColor(fs, white);
fonsSetBlur(fs, 0);
fonsDrawText(fs, dx,dy,"DROP THAT SHADOW",null);
}
// flush fontstash's font atlas to sokol-gfx texture
sfons_flush(fs);
// render pass
pass := sg_pass.{
action = .{
colors[0] = .{
load_action = .CLEAR,
clear_value = .{ 0.3, 0.3, 0.32, 1.0 },
},
},
swapchain = xx,force sglue_swapchain(),
};
sg_begin_pass(*pass);
sgl_draw();
// __dbgui_draw();
sg_end_pass();
sg_commit();
}
cleanup :: () #c_call {
sfons_destroy(state.fons);
sgl_shutdown();
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 800,
height = 600,
window_title = "fontstash",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,80 @@
// Note: some of those procedures are already implemented in the language's Math module, but for the sake of keeping the examples close to the C version, we'll be using the ones below.
// Ported from "HandmadeMath.h", available at https://github.com/floooh/sokol-samples/blob/master/sapp/HandmadeMath.h).
#import "Math";
persp_mat4 :: (fov: float, aspect: float, near: float, far: float) -> Matrix4 {
m := Matrix4_Identity;
t := tan(fov * (PI / 360));
m.coef[0][0] = 1.0 / t;
m.coef[1][1] = aspect / t;
m.coef[2][3] = -1.0;
m.coef[2][2] = (near + far) / (near - far);
m.coef[3][2] = (2.0 * near * far) / (near - far);
m.coef[3][3] = 0;
return m;
}
lookat_mat4 :: (eye: Vector3, center: Vector3, up: Vector3) -> Matrix4 {
m: Matrix4;
f := normalize(center - eye);
s := normalize(cross(f, up));
u := cross(s, f);
m.coef[0][0] = s.x;
m.coef[0][1] = u.x;
m.coef[0][2] = -f.x;
m.coef[1][0] = s.y;
m.coef[1][1] = u.y;
m.coef[1][2] = -f.y;
m.coef[2][0] = s.z;
m.coef[2][1] = u.z;
m.coef[2][2] = -f.z;
m.coef[3][0] = -dot(s, eye);
m.coef[3][1] = -dot(u, eye);
m.coef[3][2] = dot(f, eye);
m.coef[3][3] = 1.0;
return m;
}
multiply_mat4 :: (left: Matrix4, right: Matrix4) -> Matrix4 {
m: Matrix4;
for col : 0 .. 3 {
for row : 0 .. 3 {
m.coef[col][row] = left.coef[0][row] * right.coef[col][0] +
left.coef[1][row] * right.coef[col][1] +
left.coef[2][row] * right.coef[col][2] +
left.coef[3][row] * right.coef[col][3];
}
}
return m;
}
rotate_mat4 :: (angle: float, axis_unorm: Vector3) -> Matrix4 {
m := Matrix4_Identity;
axis := normalize(axis_unorm);
sin_theta := sin(radians(angle));
cos_theta := cos(radians(angle));
cos_value := 1.0 - cos_theta;
m.coef[0][0] = (axis.x * axis.x * cos_value) + cos_theta;
m.coef[0][1] = (axis.x * axis.y * cos_value) + (axis.z * sin_theta);
m.coef[0][2] = (axis.x * axis.z * cos_value) - (axis.y * sin_theta);
m.coef[1][0] = (axis.y * axis.x * cos_value) - (axis.z * sin_theta);
m.coef[1][1] = (axis.y * axis.y * cos_value) + cos_theta;
m.coef[1][2] = (axis.y * axis.z * cos_value) + (axis.x * sin_theta);
m.coef[2][0] = (axis.z * axis.x * cos_value) + (axis.y * sin_theta);
m.coef[2][1] = (axis.z * axis.y * cos_value) - (axis.x * sin_theta);
m.coef[2][2] = (axis.z * axis.z * cos_value) + cos_theta;
return m;
}
translate_mat4 :: (translation: Vector3) -> Matrix4 {
m := Matrix4_Identity;
m.coef[3][0] = translation.x;
m.coef[3][1] = translation.y;
m.coef[3][2] = translation.z;
return m;
}
radians :: (degrees: float) -> float { return degrees * TAU / 360.0; }

View File

@ -0,0 +1,220 @@
//------------------------------------------------------------------------------
// offscreen/main.jai
//
// Render to an offscreen rendertarget texture, and use this texture
// for rendering to the display.
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#import,dir "../../sokol/shape"(USE_GL=USE_GL);
#load "../math.jai";
#load "./shader.jai";
OFFSCREEN_SAMPLE_COUNT :: 1;
state: struct {
offscreen: struct {
pass_action: sg_pass_action;
attachments: sg_attachments;
pip: sg_pipeline;
bind: sg_bindings;
};
default: struct {
pass_action: sg_pass_action;
pip: sg_pipeline;
bind: sg_bindings;
};
donut: sshape_element_range_t;
sphere: sshape_element_range_t;
rx, ry: float;
vertices: [4000]sshape_vertex_t;
indices: [24000]u16;
}
init :: () #c_call {
push_context,defer_pop;
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
// default pass action: clear to blue-ish
state.default.pass_action = .{
colors[0] = .{ load_action = .CLEAR, clear_value = .{ 0.25, 0.45, 0.65, 1.0 } },
};
// offscreen pass action: clear to grey
state.offscreen.pass_action = .{
colors[0] = .{ load_action = .CLEAR, clear_value = .{ 0.25, 0.25, 0.25, 1.0 } },
};
// a render pass with one color- and one depth-attachment image
img_desc := sg_image_desc.{
render_target = true,
width = 256,
height = 256,
pixel_format = .RGBA8,
sample_count = OFFSCREEN_SAMPLE_COUNT,
};
color_img := sg_make_image(*img_desc);
img_desc.pixel_format = .DEPTH;
depth_img := sg_make_image(*img_desc);
state.offscreen.attachments = sg_make_attachments(*(sg_attachments_desc.{
colors[0] = .{ image = color_img },
depth_stencil = .{
image = depth_img,
},
}));
// a donut shape which is rendered into the offscreen render target, and
// a sphere shape which is rendered into the default framebuffer
buf := sshape_buffer_t.{
vertices = .{ buffer = .{ ptr = *state.vertices, size = size_of(type_of(state.vertices)) } },
indices = .{ buffer = .{ ptr = *state.indices, size = size_of(type_of(state.indices)) } },
};
buf = sshape_build_torus(*buf, *(sshape_torus_t.{
radius = 0.5,
ring_radius = 0.3,
sides = 20,
rings = 30,
}));
state.donut = sshape_element_range(*buf);
buf = sshape_build_sphere(*buf, *(sshape_sphere_t.{
radius = 0.5,
slices = 72,
stacks = 40,
}));
state.sphere = sshape_element_range(*buf);
vbuf := sg_make_buffer(xx,force *sshape_vertex_buffer_desc(*buf));
ibuf := sg_make_buffer(xx,force *sshape_index_buffer_desc(*buf));
// pipeline-state-object for offscreen-rendered donut, don't need texture coord here
offscreen_pip_desc := sg_pipeline_desc.{
shader = sg_make_shader(*offscreen_shader_desc(sg_query_backend())),
index_type = .UINT16,
cull_mode = .BACK,
sample_count = OFFSCREEN_SAMPLE_COUNT,
depth = .{
pixel_format = .DEPTH,
compare = .LESS_EQUAL,
write_enabled = true,
},
colors[0] = .{ pixel_format = .RGBA8 },
};
offscreen_pip_desc.layout.buffers[0] = xx,force sshape_vertex_buffer_layout_state();
offscreen_pip_desc.layout.attrs[ATTR_offscreen_position] = xx,force sshape_position_vertex_attr_state();
offscreen_pip_desc.layout.attrs[ATTR_offscreen_normal] = xx,force sshape_normal_vertex_attr_state();
state.offscreen.pip = sg_make_pipeline(*offscreen_pip_desc);
// and another pipeline-state-object for the default pass
default_pip_desc := sg_pipeline_desc.{
shader = sg_make_shader(*default_shader_desc(sg_query_backend())),
index_type = .UINT16,
cull_mode = .BACK,
depth = .{
compare = .LESS_EQUAL,
write_enabled = true,
},
};
default_pip_desc.layout.buffers[0] = xx,force sshape_vertex_buffer_layout_state();
default_pip_desc.layout.attrs[ATTR_default_position] = xx,force sshape_position_vertex_attr_state();
default_pip_desc.layout.attrs[ATTR_default_normal] = xx,force sshape_normal_vertex_attr_state();
default_pip_desc.layout.attrs[ATTR_default_texcoord0] = xx,force sshape_texcoord_vertex_attr_state();
state.default.pip = sg_make_pipeline(*default_pip_desc);
// a sampler object for sampling the render target as texture
smp := sg_make_sampler(*(sg_sampler_desc.{
min_filter = .LINEAR,
mag_filter = .LINEAR,
wrap_u = .REPEAT,
wrap_v = .REPEAT,
}));
// the resource bindings for rendering a non-textured cube into offscreen render target
state.offscreen.bind = .{
vertex_buffers[0] = vbuf,
index_buffer = ibuf,
};
// resource bindings to render a textured shape, using the offscreen render target as texture
state.default.bind = .{
vertex_buffers[0] = vbuf,
index_buffer = ibuf,
};
state.default.bind.images[IMG_tex] = color_img;
state.default.bind.samplers[SMP_smp] = smp;
}
frame :: () #c_call {
push_context,defer_pop;
t := cast(float) (sapp_frame_duration() * 60.0);
state.rx += 1.0 * t;
state.ry += 2.0 * t;
// the offscreen pass, rendering an rotating, untextured donut into a render target image
vs_params := Vs_Params.{
mvp = compute_mvp(rx = state.rx, ry = state.ry, aspect = 1.0, eye_dist = 2.5),
};
sg_begin_pass(*(sg_pass.{ action = state.offscreen.pass_action, attachments = state.offscreen.attachments }));
sg_apply_pipeline(state.offscreen.pip);
sg_apply_bindings(*state.offscreen.bind);
sg_apply_uniforms(UB_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_draw(state.donut.base_element, state.donut.num_elements, 1);
sg_end_pass();
// and the default-pass, rendering a rotating textured sphere which uses the
// previously rendered offscreen render-target as texture
vs_params = Vs_Params.{
mvp = compute_mvp(
rx = -state.rx * 0.25,
ry = state.ry * 0.25,
aspect = sapp_widthf() / sapp_heightf(),
eye_dist = 2.0,
),
};
sg_begin_pass(*(sg_pass.{ action = state.default.pass_action, swapchain = xx,force sglue_swapchain() }));
sg_apply_pipeline(state.default.pip);
sg_apply_bindings(*state.default.bind);
sg_apply_uniforms(UB_vs_params, *(sg_range.{ ptr = *vs_params, size = size_of(type_of(vs_params)) }));
sg_draw(state.sphere.base_element, state.sphere.num_elements, 1);
sg_end_pass();
sg_commit();
}
compute_mvp :: (rx: float, ry: float, aspect: float, eye_dist: float) -> Matrix4 {
proj := persp_mat4(fov = 45.0, aspect = aspect, near = 0.01, far = 10.0);
view := lookat_mat4(eye = .{ 0.0, 0.0, eye_dist }, center = .{}, up = .{ 0.0, 1.0, 0.0 });
view_proj := multiply_mat4(proj, view);
rxm := rotate_mat4(rx, .{ 1.0, 0.0, 0.0 });
rym := rotate_mat4(ry, .{ 0.0, 1.0, 0.0 });
model := multiply_mat4(rym, rxm);
mvp := multiply_mat4(view_proj, model);
return mvp;
}
cleanup :: () #c_call {
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 800,
height = 600,
sample_count = 4,
window_title = "offscreen",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// shaders for offscreen-sapp sample
//------------------------------------------------------------------------------
@ctype mat4 Matrix4
// shared code for all shaders
@block uniforms
layout(binding=0) uniform vs_params {
mat4 mvp;
};
@end
// offscreen rendering shaders
@vs vs_offscreen
@include_block uniforms
in vec4 position;
in vec4 normal;
out vec4 nrm;
void main() {
gl_Position = mvp * position;
nrm = normal;
}
@end
@fs fs_offscreen
in vec4 nrm;
out vec4 frag_color;
void main() {
frag_color = vec4(nrm.xyz * 0.5 + 0.5, 1.0);
}
@end
@program offscreen vs_offscreen fs_offscreen
// default-pass shaders
@vs vs_default
@include_block uniforms
in vec4 position;
in vec4 normal;
in vec2 texcoord0;
out vec4 nrm;
out vec2 uv;
void main() {
gl_Position = mvp * position;
uv = texcoord0;
nrm = mvp * normal;
}
@end
@fs fs_default
layout(binding=0) uniform texture2D tex;
layout(binding=0) uniform sampler smp;
in vec4 nrm;
in vec2 uv;
out vec4 frag_color;
void main() {
vec4 c = texture(sampler2D(tex, smp), uv * vec2(20.0, 10.0));
float l = clamp(dot(nrm.xyz, normalize(vec3(1.0, 1.0, -1.0))), 0.0, 1.0) * 2.0;
frag_color = vec4(c.xyz * (l + 0.25), 1.0);
}
@end
@program default vs_default fs_default

View File

@ -0,0 +1,922 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader.glsl -o shader.jai -l glsl410:metal_macos:hlsl5 -f sokol_jai
Overview:
=========
Shader program: 'default':
Get shader desc: default_shader_desc(sg_query_backend())
Vertex Shader: vs_default
Fragment Shader: fs_default
Attributes:
ATTR_default_position => 0
ATTR_default_normal => 1
ATTR_default_texcoord0 => 2
Shader program: 'offscreen':
Get shader desc: offscreen_shader_desc(sg_query_backend())
Vertex Shader: vs_offscreen
Fragment Shader: fs_offscreen
Attributes:
ATTR_offscreen_position => 0
ATTR_offscreen_normal => 1
Bindings:
Uniform block 'vs_params':
Jai struct: Vs_Params
Bind slot: UB_vs_params => 0
Image 'tex':
Image type: ._2D
Sample type: .FLOAT
Multisampled: false
Bind slot: IMG_tex => 0
Sampler 'smp':
Type: .FILTERING
Bind slot: SMP_smp => 0
Image Sampler Pair 'tex_smp':
Image: tex
Sampler: smp
*/
ATTR_default_position :: 0;
ATTR_default_normal :: 1;
ATTR_default_texcoord0 :: 2;
ATTR_offscreen_position :: 0;
ATTR_offscreen_normal :: 1;
UB_vs_params :: 0;
IMG_tex :: 0;
SMP_smp :: 0;
Vs_Params :: struct {
mvp: Matrix4;
};
/*
#version 410
uniform vec4 vs_params[4];
layout(location = 0) in vec4 position;
layout(location = 0) out vec4 nrm;
layout(location = 1) in vec4 normal;
void main()
{
gl_Position = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]) * position;
nrm = normal;
}
*/
vs_offscreen_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,
0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,
0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,
0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,
0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x72,
0x6d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,
0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,
0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,0x73,
0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,
0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,
0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x6e,0x6f,0x72,0x6d,
0x61,0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 410
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec4 nrm;
void main()
{
frag_color = vec4((nrm.xyz * 0.5) + vec3(0.5), 1.0);
}
*/
fs_offscreen_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,
0x76,0x65,0x63,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,
0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,
0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x28,
0x6e,0x72,0x6d,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x30,0x2e,0x35,0x29,0x20,0x2b,
0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x35,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,
0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 410
uniform vec4 vs_params[4];
layout(location = 0) in vec4 position;
layout(location = 1) out vec2 uv;
layout(location = 2) in vec2 texcoord0;
layout(location = 0) out vec4 nrm;
layout(location = 1) in vec4 normal;
void main()
{
mat4 _22 = mat4(vs_params[0], vs_params[1], vs_params[2], vs_params[3]);
gl_Position = _22 * position;
uv = texcoord0;
nrm = _22 * normal;
}
*/
vs_default_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61,
0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,
0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,
0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,
0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,
0x3d,0x20,0x31,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,
0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,
0x6e,0x20,0x3d,0x20,0x32,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x74,
0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,
0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x6c,0x61,0x79,
0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,
0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,
0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x74,0x34,0x20,0x5f,0x32,0x32,0x20,0x3d,0x20,
0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,
0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,
0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x76,
0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x5f,0x32,0x32,0x20,0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,
0x64,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x5f,0x32,
0x32,0x20,0x2a,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 410
uniform sampler2D tex_smp;
layout(location = 1) in vec2 uv;
layout(location = 0) in vec4 nrm;
layout(location = 0) out vec4 frag_color;
void main()
{
frag_color = vec4(texture(tex_smp, uv * vec2(20.0, 10.0)).xyz * fma(clamp(dot(nrm.xyz, vec3(0.57735025882720947265625, 0.57735025882720947265625, -0.57735025882720947265625)), 0.0, 1.0), 2.0, 0.25), 1.0);
}
*/
fs_default_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x75,0x6e,
0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,
0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,
0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,
0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,
0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x6c,0x61,0x79,
0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,
0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,
0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,
0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x76,0x65,0x63,0x34,0x28,0x74,0x65,0x78,0x74,
0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x75,0x76,0x20,
0x2a,0x20,0x76,0x65,0x63,0x32,0x28,0x32,0x30,0x2e,0x30,0x2c,0x20,0x31,0x30,0x2e,
0x30,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x66,0x6d,0x61,0x28,0x63,0x6c,
0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x6e,0x72,0x6d,0x2e,0x78,0x79,0x7a,0x2c,
0x20,0x76,0x65,0x63,0x33,0x28,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x32,0x35,
0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,0x35,0x2c,
0x20,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,
0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x2d,0x30,0x2e,0x35,
0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,
0x32,0x36,0x35,0x36,0x32,0x35,0x29,0x29,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,
0x2e,0x30,0x29,0x2c,0x20,0x32,0x2e,0x30,0x2c,0x20,0x30,0x2e,0x32,0x35,0x29,0x2c,
0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
cbuffer vs_params : register(b0)
{
row_major float4x4 _19_mvp : packoffset(c0);
};
static float4 gl_Position;
static float4 position;
static float4 nrm;
static float4 normal;
struct SPIRV_Cross_Input
{
float4 position : TEXCOORD0;
float4 normal : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 nrm : TEXCOORD0;
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = mul(position, _19_mvp);
nrm = normal;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
position = stage_input.position;
normal = stage_input.normal;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
stage_output.nrm = nrm;
return stage_output;
}
*/
vs_offscreen_source_hlsl5 := u8.[
0x63,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x20,0x3a,0x20,0x72,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x28,0x62,0x30,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x5f,0x6d,0x61,0x6a,0x6f,0x72,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x5f,0x31,0x39,0x5f,0x6d,0x76,
0x70,0x20,0x3a,0x20,0x70,0x61,0x63,0x6b,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x63,
0x30,0x29,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,
0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x73,
0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x6f,0x72,
0x6d,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,
0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x6f,0x72,
0x6d,0x61,0x6c,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x31,0x3b,
0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,
0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x20,
0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x3a,0x20,0x53,0x56,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x76,0x65,0x72,0x74,
0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x6d,0x75,0x6c,0x28,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x5f,0x31,0x39,0x5f,0x6d,0x76,
0x70,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x6e,0x6f,
0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,
0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,
0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,
0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x72,0x6d,0x61,
0x6c,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x72,0x74,
0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,
0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,
0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x67,0x6c,0x5f,
0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,
0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x6e,0x72,0x6d,0x20,0x3d,
0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,
0x0a,0x00,
];
/*
static float4 frag_color;
static float4 nrm;
struct SPIRV_Cross_Input
{
float4 nrm : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 frag_color : SV_Target0;
};
void frag_main()
{
frag_color = float4((nrm.xyz * 0.5f) + 0.5f.xxx, 1.0f);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
nrm = stage_input.nrm;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.frag_color = frag_color;
return stage_output;
}
*/
fs_offscreen_source_hlsl5 := u8.[
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x0a,0x73,0x74,
0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,
0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,
0x52,0x44,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,
0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,
0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x53,0x56,0x5f,
0x54,0x61,0x72,0x67,0x65,0x74,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x28,0x6e,0x72,0x6d,0x2e,0x78,0x79,0x7a,
0x20,0x2a,0x20,0x30,0x2e,0x35,0x66,0x29,0x20,0x2b,0x20,0x30,0x2e,0x35,0x66,0x2e,
0x78,0x78,0x78,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,
0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,
0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,
0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,
0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,
0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x6e,0x72,
0x6d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,
0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,
0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x66,0x72,0x61,0x67,0x5f,0x63,
0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,
0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,
0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x00,
];
/*
cbuffer vs_params : register(b0)
{
row_major float4x4 _19_mvp : packoffset(c0);
};
static float4 gl_Position;
static float4 position;
static float2 uv;
static float2 texcoord0;
static float4 nrm;
static float4 normal;
struct SPIRV_Cross_Input
{
float4 position : TEXCOORD0;
float4 normal : TEXCOORD1;
float2 texcoord0 : TEXCOORD2;
};
struct SPIRV_Cross_Output
{
float4 nrm : TEXCOORD0;
float2 uv : TEXCOORD1;
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = mul(position, _19_mvp);
uv = texcoord0;
nrm = mul(normal, _19_mvp);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
position = stage_input.position;
texcoord0 = stage_input.texcoord0;
normal = stage_input.normal;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
stage_output.uv = uv;
stage_output.nrm = nrm;
return stage_output;
}
*/
vs_default_source_hlsl5 := u8.[
0x63,0x62,0x75,0x66,0x66,0x65,0x72,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
0x73,0x20,0x3a,0x20,0x72,0x65,0x67,0x69,0x73,0x74,0x65,0x72,0x28,0x62,0x30,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x5f,0x6d,0x61,0x6a,0x6f,0x72,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x5f,0x31,0x39,0x5f,0x6d,0x76,
0x70,0x20,0x3a,0x20,0x70,0x61,0x63,0x6b,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x63,
0x30,0x29,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,
0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x3b,0x0a,0x73,0x74,
0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x74,0x65,0x78,0x63,
0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,
0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,
0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x3a,
0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x31,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,
0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x32,0x3b,0x0a,0x7d,0x3b,
0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,
0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x20,0x3a,0x20,0x54,
0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,
0x52,0x44,0x31,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x53,0x56,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x76,0x65,0x72,0x74,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,
0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x3d,0x20,0x6d,0x75,0x6c,0x28,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x2c,0x20,0x5f,0x31,0x39,0x5f,0x6d,0x76,0x70,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x75,0x76,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x6d,0x75,0x6c,0x28,0x6e,0x6f,
0x72,0x6d,0x61,0x6c,0x2c,0x20,0x5f,0x31,0x39,0x5f,0x6d,0x76,0x70,0x29,0x3b,0x0a,
0x7d,0x0a,0x0a,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,
0x75,0x74,0x70,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,
0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,
0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3d,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x74,0x65,0x78,
0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x72,0x6d,
0x61,0x6c,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,
0x2e,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x72,
0x74,0x5f,0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,
0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,
0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x67,0x6c,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,
0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x75,0x76,0x20,0x3d,
0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,
0x75,0x74,0x70,0x75,0x74,0x2e,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x6e,0x72,0x6d,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x61,0x67,
0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x00,
];
/*
Texture2D<float4> tex : register(t0);
SamplerState smp : register(s0);
static float2 uv;
static float4 nrm;
static float4 frag_color;
struct SPIRV_Cross_Input
{
float4 nrm : TEXCOORD0;
float2 uv : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 frag_color : SV_Target0;
};
void frag_main()
{
frag_color = float4(tex.Sample(smp, uv * float2(20.0f, 10.0f)).xyz * mad(clamp(dot(nrm.xyz, float3(0.57735025882720947265625f, 0.57735025882720947265625f, -0.57735025882720947265625f)), 0.0f, 1.0f), 2.0f, 0.25f), 1.0f);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
uv = stage_input.uv;
nrm = stage_input.nrm;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.frag_color = frag_color;
return stage_output;
}
*/
fs_default_source_hlsl5 := u8.[
0x54,0x65,0x78,0x74,0x75,0x72,0x65,0x32,0x44,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x3e,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x72,0x65,0x67,0x69,0x73,0x74,0x65,0x72,
0x28,0x74,0x30,0x29,0x3b,0x0a,0x53,0x61,0x6d,0x70,0x6c,0x65,0x72,0x53,0x74,0x61,
0x74,0x65,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x72,0x65,0x67,0x69,0x73,0x74,0x65,
0x72,0x28,0x73,0x30,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,0x6d,0x3b,0x0a,0x73,0x74,0x61,
0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,
0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,0x72,
0x6d,0x20,0x3a,0x20,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,0x76,0x20,0x3a,0x20,0x54,
0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x31,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,
0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,
0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,
0x3a,0x20,0x53,0x56,0x5f,0x54,0x61,0x72,0x67,0x65,0x74,0x30,0x3b,0x0a,0x7d,0x3b,
0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,
0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,
0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x74,0x65,0x78,
0x2e,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x73,0x6d,0x70,0x2c,0x20,0x75,0x76,0x20,
0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x28,0x32,0x30,0x2e,0x30,0x66,0x2c,0x20,
0x31,0x30,0x2e,0x30,0x66,0x29,0x29,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,0x6d,0x61,
0x64,0x28,0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x6e,0x72,0x6d,0x2e,
0x78,0x79,0x7a,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x35,0x37,
0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,
0x36,0x35,0x36,0x32,0x35,0x66,0x2c,0x20,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,
0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,
0x35,0x66,0x2c,0x20,0x2d,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,
0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,0x35,0x66,0x29,
0x29,0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,0x66,0x29,0x2c,0x20,
0x32,0x2e,0x30,0x66,0x2c,0x20,0x30,0x2e,0x32,0x35,0x66,0x29,0x2c,0x20,0x31,0x2e,
0x30,0x66,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,
0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,
0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,
0x69,0x6e,0x70,0x75,0x74,0x2e,0x75,0x76,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6e,0x72,
0x6d,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,
0x6e,0x72,0x6d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,
0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,
0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,
0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x66,0x72,0x61,0x67,
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,
0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct vs_params
{
float4x4 mvp;
};
struct main0_out
{
float4 nrm [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 position [[attribute(0)]];
float4 normal [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant vs_params& _19 [[buffer(0)]])
{
main0_out out = {};
out.gl_Position = _19.mvp * in.position;
out.nrm = in.normal;
return out;
}
*/
vs_offscreen_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x76,
0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,0x3b,0x0a,0x7d,0x3b,0x0a,
0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,
0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,
0x72,0x6d,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,
0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,
0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,
0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,
0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,
0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,
0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x65,0x72,
0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,
0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,
0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x63,0x6f,
0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,
0x26,0x20,0x5f,0x31,0x39,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,
0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,
0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,0x20,0x2a,0x20,0x69,
0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,
0x6f,0x75,0x74,0x2e,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x6e,0x6f,0x72,
0x6d,0x61,0x6c,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float4 nrm [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.frag_color = float4((in.nrm.xyz * 0.5) + float3(0.5), 1.0);
return out;
}
*/
fs_offscreen_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x6e,0x72,0x6d,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,
0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,
0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,
0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,
0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,
0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x28,0x28,0x69,0x6e,0x2e,0x6e,0x72,0x6d,0x2e,0x78,0x79,0x7a,0x20,0x2a,0x20,
0x30,0x2e,0x35,0x29,0x20,0x2b,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,
0x35,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct vs_params
{
float4x4 mvp;
};
struct main0_out
{
float4 nrm [[user(locn0)]];
float2 uv [[user(locn1)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 position [[attribute(0)]];
float4 normal [[attribute(1)]];
float2 texcoord0 [[attribute(2)]];
};
vertex main0_out main0(main0_in in [[stage_in]], constant vs_params& _19 [[buffer(0)]])
{
main0_out out = {};
out.gl_Position = _19.mvp * in.position;
out.uv = in.texcoord0;
out.nrm = _19.mvp * in.normal;
return out;
}
*/
vs_default_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x76,
0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,0x3b,0x0a,0x7d,0x3b,0x0a,
0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,
0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,
0x72,0x6d,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,
0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x75,
0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x31,0x29,0x5d,
0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,
0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,
0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x6e,
0x6f,0x72,0x6d,0x61,0x6c,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,
0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x5b,0x5b,0x61,
0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x32,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x76,0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,
0x5d,0x5d,0x2c,0x20,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x76,0x73,0x5f,
0x70,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f,0x31,0x39,0x20,0x5b,0x5b,0x62,0x75,
0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,
0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,
0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,
0x76,0x70,0x20,0x2a,0x20,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x75,0x76,0x20,0x3d,0x20,0x69,
0x6e,0x2e,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x6f,0x75,0x74,0x2e,0x6e,0x72,0x6d,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,
0x76,0x70,0x20,0x2a,0x20,0x69,0x6e,0x2e,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x3b,0x0a,
0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,
0x7d,0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float4 nrm [[user(locn0)]];
float2 uv [[user(locn1)]];
};
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]])
{
main0_out out = {};
out.frag_color = float4(tex.sample(smp, (in.uv * float2(20.0, 10.0))).xyz * fma(fast::clamp(dot(in.nrm.xyz, float3(0.57735025882720947265625, 0.57735025882720947265625, -0.57735025882720947265625)), 0.0, 1.0), 2.0, 0.25), 1.0);
return out;
}
*/
fs_default_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x6e,0x72,0x6d,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,
0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,
0x75,0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x31,0x29,
0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,
0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,
0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73,
0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,0x74,0x75,
0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x74,0x65,0x78,0x20,
0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,
0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x73,0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,
0x6d,0x70,0x6c,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,
0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x34,0x28,0x74,0x65,0x78,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x73,0x6d,0x70,
0x2c,0x20,0x28,0x69,0x6e,0x2e,0x75,0x76,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,
0x32,0x28,0x32,0x30,0x2e,0x30,0x2c,0x20,0x31,0x30,0x2e,0x30,0x29,0x29,0x29,0x2e,
0x78,0x79,0x7a,0x20,0x2a,0x20,0x66,0x6d,0x61,0x28,0x66,0x61,0x73,0x74,0x3a,0x3a,
0x63,0x6c,0x61,0x6d,0x70,0x28,0x64,0x6f,0x74,0x28,0x69,0x6e,0x2e,0x6e,0x72,0x6d,
0x2e,0x78,0x79,0x7a,0x2c,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33,0x28,0x30,0x2e,0x35,
0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,
0x32,0x36,0x35,0x36,0x32,0x35,0x2c,0x20,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,
0x32,0x35,0x38,0x38,0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,
0x35,0x2c,0x20,0x2d,0x30,0x2e,0x35,0x37,0x37,0x33,0x35,0x30,0x32,0x35,0x38,0x38,
0x32,0x37,0x32,0x30,0x39,0x34,0x37,0x32,0x36,0x35,0x36,0x32,0x35,0x29,0x29,0x2c,
0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x2c,0x20,0x32,0x2e,0x30,0x2c,
0x20,0x30,0x2e,0x32,0x35,0x29,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
0x0a,0x00,
];
default_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "default_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_default_source_glsl410;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_default_source_glsl410;
desc.fragment_func.entry = "main";
desc.attrs[0].glsl_name = "position";
desc.attrs[1].glsl_name = "normal";
desc.attrs[2].glsl_name = "texcoord0";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "vs_params";
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
desc.image_sampler_pairs[0].glsl_name = "tex_smp";
case .D3D11;
desc.vertex_func.source = xx *vs_default_source_hlsl5;
desc.vertex_func.d3d11_target = "vs_5_0";
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_default_source_hlsl5;
desc.fragment_func.d3d11_target = "ps_5_0";
desc.fragment_func.entry = "main";
desc.attrs[0].hlsl_sem_name = "TEXCOORD";
desc.attrs[0].hlsl_sem_index = 0;
desc.attrs[1].hlsl_sem_name = "TEXCOORD";
desc.attrs[1].hlsl_sem_index = 1;
desc.attrs[2].hlsl_sem_name = "TEXCOORD";
desc.attrs[2].hlsl_sem_index = 2;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].hlsl_register_b_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].hlsl_register_t_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].hlsl_register_s_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_default_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_default_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].msl_buffer_n = 0;
desc.images[0].stage = .FRAGMENT;
desc.images[0].multisampled = false;
desc.images[0].image_type = ._2D;
desc.images[0].sample_type = .FLOAT;
desc.images[0].msl_texture_n = 0;
desc.samplers[0].stage = .FRAGMENT;
desc.samplers[0].sampler_type = .FILTERING;
desc.samplers[0].msl_sampler_n = 0;
desc.image_sampler_pairs[0].stage = .FRAGMENT;
desc.image_sampler_pairs[0].image_slot = 0;
desc.image_sampler_pairs[0].sampler_slot = 0;
}
return desc;
}
offscreen_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "offscreen_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_offscreen_source_glsl410;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_offscreen_source_glsl410;
desc.fragment_func.entry = "main";
desc.attrs[0].glsl_name = "position";
desc.attrs[1].glsl_name = "normal";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].glsl_uniforms[0].type = .FLOAT4;
desc.uniform_blocks[0].glsl_uniforms[0].array_count = 4;
desc.uniform_blocks[0].glsl_uniforms[0].glsl_name = "vs_params";
case .D3D11;
desc.vertex_func.source = xx *vs_offscreen_source_hlsl5;
desc.vertex_func.d3d11_target = "vs_5_0";
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_offscreen_source_hlsl5;
desc.fragment_func.d3d11_target = "ps_5_0";
desc.fragment_func.entry = "main";
desc.attrs[0].hlsl_sem_name = "TEXCOORD";
desc.attrs[0].hlsl_sem_index = 0;
desc.attrs[1].hlsl_sem_name = "TEXCOORD";
desc.attrs[1].hlsl_sem_index = 1;
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].hlsl_register_b_n = 0;
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_offscreen_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_offscreen_source_metal_macos;
desc.fragment_func.entry = "main0";
desc.uniform_blocks[0].stage = .VERTEX;
desc.uniform_blocks[0].layout = .STD140;
desc.uniform_blocks[0].size = 64;
desc.uniform_blocks[0].msl_buffer_n = 0;
}
return desc;
}

View File

@ -0,0 +1,69 @@
//------------------------------------------------------------------------------
// saudio/module.jai
// Test sokol-audio.
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#import,dir "../../sokol/debugtext"(USE_GL=USE_GL);
#import,dir "../../sokol/audio";
NUM_SAMPLES :: 32;
state: struct {
pass_action: sg_pass_action;
even_odd: u32;
sample_pos: int;
samples: [NUM_SAMPLES]float;
} = .{
pass_action = .{
colors = .[ .{ load_action = .CLEAR, clear_value = .{ 1.0, 0.5, 0.0, 1.0 }, }, .{}, .{}, .{}, ],
},
};
init :: () #c_call {
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
saudio_setup(*(saudio_desc.{
logger = .{ func = slog_func },
}));
}
frame :: () #c_call {
num_frames := saudio_expect();
for i : 0 .. num_frames - 1 {
state.even_odd += 1;
state.samples[state.sample_pos] = ifx((state.even_odd & (1<<5)) == 0) then 0.05 else -0.05;
state.sample_pos += 1;
if state.sample_pos == NUM_SAMPLES {
state.sample_pos = 0;
saudio_push(*state.samples[0], NUM_SAMPLES);
}
}
sg_begin_pass(*(sg_pass.{ action = state.pass_action, swapchain = xx,force sglue_swapchain() }));
sg_end_pass();
sg_commit();
}
cleanup :: () #c_call {
saudio_shutdown();
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 400,
height = 300,
window_title = "saudio",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,198 @@
//------------------------------------------------------------------------------
// sgl-context-sapp/module.jai
//
// Demonstrates how to render in different render passes with sokol_gl.h
// using sokol-gl contexts.
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#import,dir "../../sokol/shape"(USE_GL=USE_GL);
#import,dir "../../sokol/gl"(USE_GL=USE_GL);
#load "../math.jai";
SGL_DEFAULT_CONTEXT :: sgl_context.{ 0x00010001 };
OFFSCREEN_PIXELFORMAT :: sg_pixel_format.RGBA8;
OFFSCREEN_SAMPLECOUNT :: 1;
OFFSCREEN_WIDTH :: 32;
OFFSCREEN_HEIGHT :: 32;
state: struct {
angle_deg: float64;
offscreen: struct {
pass_action: sg_pass_action;
attachments: sg_attachments;
img: sg_image;
sgl_ctx: sgl_context;
};
display: struct {
pass_action: sg_pass_action;
smp: sg_sampler;
sgl_pip: sgl_pipeline;
};
}
init :: () #c_call {
push_context,defer_pop;
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger.func = slog_func,
}));
// setup sokol-gl with the default context compatible with the default render pass
sgl_setup(*(sgl_desc_t.{
max_vertices = 64,
max_commands = 16,
logger.func = slog_func,
}));
// pass action and pipeline for the default render pass
state.display.pass_action = .{
colors[0] = .{
load_action = .CLEAR,
clear_value = .{ 0.5, 0.7, 1.0, 1.0 },
},
};
state.display.sgl_pip = sgl_context_make_pipeline(sgl_default_context(), xx *(sg_pipeline_desc.{
cull_mode = .BACK,
depth = .{
write_enabled = true,
compare = .LESS_EQUAL,
},
}));
// create a sokol-gl context compatible with the offscreen render pass
// (specific color pixel format, no depth-stencil-surface, no MSAA)
state.offscreen.sgl_ctx = sgl_make_context(*(sgl_context_desc_t.{
max_vertices = 8,
max_commands = 4,
color_format = xx OFFSCREEN_PIXELFORMAT,
depth_format = .NONE,
sample_count = OFFSCREEN_SAMPLECOUNT,
}));
// create an offscreen render target texture, pass, and pass_action
state.offscreen.img = sg_make_image(*(sg_image_desc.{
render_target = true,
width = OFFSCREEN_WIDTH,
height = OFFSCREEN_HEIGHT,
pixel_format = xx OFFSCREEN_PIXELFORMAT,
sample_count = xx OFFSCREEN_SAMPLECOUNT,
}));
state.offscreen.attachments = sg_make_attachments(*(sg_attachments_desc.{
colors[0].image = state.offscreen.img,
}));
state.offscreen.pass_action = .{
colors[0] = .{
load_action = .CLEAR,
clear_value = .{ 0.0, 0.0, 0.0, 1.0 },
},
};
// a sampler for sampling the offscreen render target
state.display.smp = sg_make_sampler(*(sg_sampler_desc.{
wrap_u = .CLAMP_TO_EDGE,
wrap_v = .CLAMP_TO_EDGE,
min_filter = .NEAREST,
mag_filter = .NEAREST,
}));
}
frame :: () #c_call {
push_context,defer_pop;
state.angle_deg += sapp_frame_duration() * 60.0;
a := sgl_rad(cast(float) state.angle_deg);
// draw a rotating quad into the offscreen render target texture
sgl_set_context(state.offscreen.sgl_ctx);
sgl_defaults();
sgl_matrix_mode_modelview();
sgl_rotate(a, 0.0, 0.0, 1.0);
draw_quad();
// draw a rotating 3D cube, using the offscreen render target as texture
sgl_set_context(SGL_DEFAULT_CONTEXT);
sgl_defaults();
sgl_enable_texture();
sgl_texture(xx,force state.offscreen.img, xx,force state.display.smp);
sgl_load_pipeline(state.display.sgl_pip);
sgl_matrix_mode_projection();
sgl_perspective(sgl_rad(45.0), sapp_widthf()/sapp_heightf(), 0.1, 100.0);
eye := float.[ sin(a) * 6.0, sin(a) * 3.0, cos(a) * 6.0 ];
sgl_matrix_mode_modelview();
sgl_lookat(eye[0], eye[1], eye[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
draw_cube();
// do the actual offscreen and display rendering in sokol-gfx passes
sg_begin_pass(*(sg_pass.{ action = state.offscreen.pass_action, attachments = state.offscreen.attachments }));
sgl_context_draw(state.offscreen.sgl_ctx);
sg_end_pass();
sg_begin_pass(*(sg_pass.{ action = state.display.pass_action, swapchain = xx,force sglue_swapchain() }));
sgl_context_draw(SGL_DEFAULT_CONTEXT);
sg_end_pass();
sg_commit();
}
// helper function to draw a colored quad with sokol-gl
draw_quad :: () {
sgl_begin_quads();
sgl_v2f_c3b( 0.0, -1.0, 255, 0, 0);
sgl_v2f_c3b( 1.0, 0.0, 0, 0, 255);
sgl_v2f_c3b( 0.0, 1.0, 0, 255, 255);
sgl_v2f_c3b(-1.0, 0.0, 0, 255, 0);
sgl_end();
}
// helper function to draw a textured cube with sokol-gl
draw_cube :: () {
sgl_begin_quads();
sgl_v3f_t2f(-1.0, 1.0, -1.0, 0.0, 1.0);
sgl_v3f_t2f( 1.0, 1.0, -1.0, 1.0, 1.0);
sgl_v3f_t2f( 1.0, -1.0, -1.0, 1.0, 0.0);
sgl_v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0);
sgl_v3f_t2f(-1.0, -1.0, 1.0, 0.0, 1.0);
sgl_v3f_t2f( 1.0, -1.0, 1.0, 1.0, 1.0);
sgl_v3f_t2f( 1.0, 1.0, 1.0, 1.0, 0.0);
sgl_v3f_t2f(-1.0, 1.0, 1.0, 0.0, 0.0);
sgl_v3f_t2f(-1.0, -1.0, 1.0, 0.0, 1.0);
sgl_v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0);
sgl_v3f_t2f(-1.0, 1.0, -1.0, 1.0, 0.0);
sgl_v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0);
sgl_v3f_t2f( 1.0, -1.0, 1.0, 0.0, 1.0);
sgl_v3f_t2f( 1.0, -1.0, -1.0, 1.0, 1.0);
sgl_v3f_t2f( 1.0, 1.0, -1.0, 1.0, 0.0);
sgl_v3f_t2f( 1.0, 1.0, 1.0, 0.0, 0.0);
sgl_v3f_t2f( 1.0, -1.0, -1.0, 0.0, 1.0);
sgl_v3f_t2f( 1.0, -1.0, 1.0, 1.0, 1.0);
sgl_v3f_t2f(-1.0, -1.0, 1.0, 1.0, 0.0);
sgl_v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0);
sgl_v3f_t2f(-1.0, 1.0, -1.0, 0.0, 1.0);
sgl_v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0);
sgl_v3f_t2f( 1.0, 1.0, 1.0, 1.0, 0.0);
sgl_v3f_t2f( 1.0, 1.0, -1.0, 0.0, 0.0);
sgl_end();
}
cleanup :: () #c_call {
sgl_shutdown();
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 800,
height = 600,
sample_count = 4,
window_title = "sokol-gl contexts (sapp)",
icon.sokol_default = true,
logger.func = slog_func,
}));
}

View File

@ -0,0 +1,75 @@
//------------------------------------------------------------------------------
// triangle/module.jai
//
// Hello Triangle sample.
//------------------------------------------------------------------------------
#import "Basic";
#import,dir "../../sokol/log"(USE_GL=USE_GL);
#import,dir "../../sokol/gfx"(USE_GL=USE_GL);
#import,dir "../../sokol/app"(USE_GL=USE_GL);
#import,dir "../../sokol/glue"(USE_GL=USE_GL);
#load "./shader.jai";
state: struct {
pip: sg_pipeline;
bind: sg_bindings;
pass_action: sg_pass_action;
}
init :: () #c_call {
push_context,defer_pop;
sg_setup(*(sg_desc.{
environment = xx,force sglue_environment(),
logger = .{ func = slog_func },
}));
// a vertex buffer with 3 vertices
vertices := float.[
// positions // colors
0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0,
0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0,
-0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0,
];
buffer := sg_buffer_desc.{ data = .{ ptr = *vertices, size = size_of(type_of(vertices)) } };
state.bind.vertex_buffers[0] = sg_make_buffer(*buffer);
// create shader from code-generated sg_shader_desc
shd := sg_make_shader(*triangle_shader_desc(sg_query_backend()));
// create a shader and pipeline object (default render states are fine for triangle)
pipeline: sg_pipeline_desc;
pipeline.shader = shd;
pipeline.layout.attrs[ATTR_triangle_position] = .{ format = .FLOAT3 };
pipeline.layout.attrs[ATTR_triangle_color0] = .{ format = .FLOAT4 };
state.pip = sg_make_pipeline(*pipeline);
// a pass action to clear framebuffer to black
state.pass_action.colors[0] = .{ load_action = .CLEAR, clear_value = .{ 0, 0, 0,1 } };
}
frame :: () #c_call {
sg_begin_pass(*(sg_pass.{ action = state.pass_action, swapchain = xx,force sglue_swapchain() }));
sg_apply_pipeline(state.pip);
sg_apply_bindings(*state.bind);
sg_draw(0, 3, 1);
sg_end_pass();
sg_commit();
}
cleanup :: () #c_call {
sg_shutdown();
}
main :: () {
sapp_run(*(sapp_desc.{
init_cb = init,
frame_cb = frame,
cleanup_cb = cleanup,
width = 640,
height = 480,
window_title = "triangle",
icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}

View File

@ -0,0 +1,22 @@
@vs vs
in vec4 position;
in vec4 color0;
out vec4 color;
void main() {
gl_Position = position;
color = color0;
}
@end
@fs fs
in vec4 color;
out vec4 frag_color;
void main() {
frag_color = color;
}
@end
@program triangle vs fs

View File

@ -0,0 +1,341 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader.glsl -o shader.jai -l glsl410:metal_macos:hlsl5 -f sokol_jai
Overview:
=========
Shader program: 'triangle':
Get shader desc: triangle_shader_desc(sg_query_backend())
Vertex Shader: vs
Fragment Shader: fs
Attributes:
ATTR_triangle_position => 0
ATTR_triangle_color0 => 1
Bindings:
*/
ATTR_triangle_position :: 0;
ATTR_triangle_color0 :: 1;
/*
#version 410
layout(location = 0) in vec4 position;
layout(location = 0) out vec4 color;
layout(location = 1) in vec4 color0;
void main()
{
gl_Position = position;
color = color0;
}
*/
vs_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,
0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,
0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a,
0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,
0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x7d,0x0a,
0x0a,0x00,
];
/*
#version 410
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec4 color;
void main()
{
frag_color = color;
}
*/
fs_source_glsl410 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x31,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,
0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,
0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
static float4 gl_Position;
static float4 position;
static float4 color;
static float4 color0;
struct SPIRV_Cross_Input
{
float4 position : TEXCOORD0;
float4 color0 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float4 color : TEXCOORD0;
float4 gl_Position : SV_Position;
};
void vert_main()
{
gl_Position = position;
color = color0;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
position = stage_input.position;
color0 = stage_input.color0;
vert_main();
SPIRV_Cross_Output stage_output;
stage_output.gl_Position = gl_Position;
stage_output.color = color;
return stage_output;
}
*/
vs_source_hlsl5 := u8.[
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,
0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
0x6e,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a,0x73,
0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,
0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,
0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x54,
0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x31,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,
0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,
0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,
0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x54,0x45,0x58,
0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,
0x20,0x53,0x56,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x7d,0x3b,
0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x76,0x65,0x72,0x74,0x5f,0x6d,0x61,0x69,0x6e,
0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,
0x6f,0x72,0x30,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,
0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,
0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,
0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,
0x0a,0x20,0x20,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x70,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,
0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,0x63,
0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x65,0x72,0x74,0x5f,
0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,
0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,
0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x67,0x6c,
0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x67,0x6c,0x5f,0x50,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x73,0x74,0x61,
0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20,
0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,
0x75,0x72,0x6e,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,
0x3b,0x0a,0x7d,0x0a,0x00,
];
/*
static float4 frag_color;
static float4 color;
struct SPIRV_Cross_Input
{
float4 color : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float4 frag_color : SV_Target0;
};
void frag_main()
{
frag_color = color;
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
color = stage_input.color;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.frag_color = frag_color;
return stage_output;
}
*/
fs_source_hlsl5 := u8.[
0x73,0x74,0x61,0x74,0x69,0x63,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x73,0x74,0x61,0x74,0x69,0x63,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,
0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,
0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x54,0x45,
0x58,0x43,0x4f,0x4f,0x52,0x44,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,
0x75,0x63,0x74,0x20,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,
0x4f,0x75,0x74,0x70,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,
0x20,0x53,0x56,0x5f,0x54,0x61,0x72,0x67,0x65,0x74,0x30,0x3b,0x0a,0x7d,0x3b,0x0a,
0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x72,0x61,0x67,0x5f,0x6d,0x61,0x69,0x6e,0x28,
0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,
0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x53,
0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,
0x74,0x20,0x6d,0x61,0x69,0x6e,0x28,0x53,0x50,0x49,0x52,0x56,0x5f,0x43,0x72,0x6f,
0x73,0x73,0x5f,0x49,0x6e,0x70,0x75,0x74,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,
0x6e,0x70,0x75,0x74,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x2e,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,
0x6d,0x61,0x69,0x6e,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x53,0x50,0x49,0x52,
0x56,0x5f,0x43,0x72,0x6f,0x73,0x73,0x5f,0x4f,0x75,0x74,0x70,0x75,0x74,0x20,0x73,
0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x66,0x72,
0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x66,0x72,0x61,0x67,0x5f,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
0x6e,0x20,0x73,0x74,0x61,0x67,0x65,0x5f,0x6f,0x75,0x74,0x70,0x75,0x74,0x3b,0x0a,
0x7d,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 color [[user(locn0)]];
float4 gl_Position [[position]];
};
struct main0_in
{
float4 position [[attribute(0)]];
float4 color0 [[attribute(1)]];
};
vertex main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.gl_Position = in.position;
out.color = in.color0;
return out;
}
*/
vs_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,
0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,
0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,
0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,
0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,
0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,
0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,0x29,0x5d,0x5d,
0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,
0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,
0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,
0x5f,0x69,0x6e,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,
0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,
0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,
0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,
0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,
0x0a,0x0a,0x00,
];
/*
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float4 frag_color [[color(0)]];
};
struct main0_in
{
float4 color [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]])
{
main0_out out = {};
out.frag_color = in.color;
return out;
}
*/
fs_source_metal_macos := u8.[
0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,
0x6e,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,
0x65,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,
0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,
0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,
0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,
0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
triangle_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "triangle_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_source_glsl410;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_source_glsl410;
desc.fragment_func.entry = "main";
desc.attrs[0].glsl_name = "position";
desc.attrs[1].glsl_name = "color0";
case .D3D11;
desc.vertex_func.source = xx *vs_source_hlsl5;
desc.vertex_func.d3d11_target = "vs_5_0";
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_source_hlsl5;
desc.fragment_func.d3d11_target = "ps_5_0";
desc.fragment_func.entry = "main";
desc.attrs[0].hlsl_sem_name = "TEXCOORD";
desc.attrs[0].hlsl_sem_index = 0;
desc.attrs[1].hlsl_sem_name = "TEXCOORD";
desc.attrs[1].hlsl_sem_index = 1;
case .METAL_MACOS;
desc.vertex_func.source = xx *vs_source_metal_macos;
desc.vertex_func.entry = "main0";
desc.fragment_func.source = xx *fs_source_metal_macos;
desc.fragment_func.entry = "main0";
}
return desc;
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,627 @@
// machine generated, do not edit
/*
sokol_audio.h -- cross-platform audio-streaming API
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_AUDIO_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Optionally provide the following defines with your own implementations:
SOKOL_DUMMY_BACKEND - use a dummy backend
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_AUDIO_API_DECL- public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_AUDIO_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
SAUDIO_RING_MAX_SLOTS - max number of slots in the push-audio ring buffer (default 1024)
SAUDIO_OSX_USE_SYSTEM_HEADERS - define this to force inclusion of system headers on
macOS instead of using embedded CoreAudio declarations
If sokol_audio.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_AUDIO_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
Link with the following libraries:
- on macOS: AudioToolbox
- on iOS: AudioToolbox, AVFoundation
- on FreeBSD: asound
- on Linux: asound
- on Android: aaudio
- on Windows with MSVC or Clang toolchain: no action needed, libs are defined in-source via pragma-comment-lib
- on Windows with MINGW/MSYS2 gcc: compile with '-mwin32' and link with -lole32
FEATURE OVERVIEW
================
You provide a mono- or stereo-stream of 32-bit float samples, which
Sokol Audio feeds into platform-specific audio backends:
- Windows: WASAPI
- Linux: ALSA
- FreeBSD: ALSA
- macOS: CoreAudio
- iOS: CoreAudio+AVAudioSession
- emscripten: WebAudio with ScriptProcessorNode
- Android: AAudio
Sokol Audio will not do any buffer mixing or volume control, if you have
multiple independent input streams of sample data you need to perform the
mixing yourself before forwarding the data to Sokol Audio.
There are two mutually exclusive ways to provide the sample data:
1. Callback model: You provide a callback function, which will be called
when Sokol Audio needs new samples. On all platforms except emscripten,
this function is called from a separate thread.
2. Push model: Your code pushes small blocks of sample data from your
main loop or a thread you created. The pushed data is stored in
a ring buffer where it is pulled by the backend code when
needed.
The callback model is preferred because it is the most direct way to
feed sample data into the audio backends and also has less moving parts
(there is no ring buffer between your code and the audio backend).
Sometimes it is not possible to generate the audio stream directly in a
callback function running in a separate thread, for such cases Sokol Audio
provides the push-model as a convenience.
SOKOL AUDIO, SOLOUD AND MINIAUDIO
=================================
The WASAPI, ALSA and CoreAudio backend code has been taken from the
SoLoud library (with some modifications, so any bugs in there are most
likely my fault). If you need a more fully-featured audio solution, check
out SoLoud, it's excellent:
https://github.com/jarikomppa/soloud
Another alternative which feature-wise is somewhere inbetween SoLoud and
sokol-audio might be MiniAudio:
https://github.com/mackron/miniaudio
GLOSSARY
========
- stream buffer:
The internal audio data buffer, usually provided by the backend API. The
size of the stream buffer defines the base latency, smaller buffers have
lower latency but may cause audio glitches. Bigger buffers reduce or
eliminate glitches, but have a higher base latency.
- stream callback:
Optional callback function which is called by Sokol Audio when it
needs new samples. On Windows, macOS/iOS and Linux, this is called in
a separate thread, on WebAudio, this is called per-frame in the
browser thread.
- channel:
A discrete track of audio data, currently 1-channel (mono) and
2-channel (stereo) is supported and tested.
- sample:
The magnitude of an audio signal on one channel at a given time. In
Sokol Audio, samples are 32-bit float numbers in the range -1.0 to
+1.0.
- frame:
The tightly packed set of samples for all channels at a given time.
For mono 1 frame is 1 sample. For stereo, 1 frame is 2 samples.
- packet:
In Sokol Audio, a small chunk of audio data that is moved from the
main thread to the audio streaming thread in order to decouple the
rate at which the main thread provides new audio data, and the
streaming thread consuming audio data.
WORKING WITH SOKOL AUDIO
========================
First call saudio_setup() with your preferred audio playback options.
In most cases you can stick with the default values, these provide
a good balance between low-latency and glitch-free playback
on all audio backends.
You should always provide a logging callback to be aware of any
warnings and errors. The easiest way is to use sokol_log.h for this:
#include "sokol_log.h"
// ...
saudio_setup(&(saudio_desc){
.logger = {
.func = slog_func,
}
});
If you want to use the callback-model, you need to provide a stream
callback function either in saudio_desc.stream_cb or saudio_desc.stream_userdata_cb,
otherwise keep both function pointers zero-initialized.
Use push model and default playback parameters:
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
Use stream callback model and default playback parameters:
saudio_setup(&(saudio_desc){
.stream_cb = my_stream_callback
.logger.func = slog_func,
});
The standard stream callback doesn't have a user data argument, if you want
that, use the alternative stream_userdata_cb and also set the user_data pointer:
saudio_setup(&(saudio_desc){
.stream_userdata_cb = my_stream_callback,
.user_data = &my_data
.logger.func = slog_func,
});
The following playback parameters can be provided through the
saudio_desc struct:
General parameters (both for stream-callback and push-model):
int sample_rate -- the sample rate in Hz, default: 44100
int num_channels -- number of channels, default: 1 (mono)
int buffer_frames -- number of frames in streaming buffer, default: 2048
The stream callback prototype (either with or without userdata):
void (*stream_cb)(float* buffer, int num_frames, int num_channels)
void (*stream_userdata_cb)(float* buffer, int num_frames, int num_channels, void* user_data)
Function pointer to the user-provide stream callback.
Push-model parameters:
int packet_frames -- number of frames in a packet, default: 128
int num_packets -- number of packets in ring buffer, default: 64
The sample_rate and num_channels parameters are only hints for the audio
backend, it isn't guaranteed that those are the values used for actual
playback.
To get the actual parameters, call the following functions after
saudio_setup():
int saudio_sample_rate(void)
int saudio_channels(void);
It's unlikely that the number of channels will be different than requested,
but a different sample rate isn't uncommon.
(NOTE: there's an yet unsolved issue when an audio backend might switch
to a different sample rate when switching output devices, for instance
plugging in a bluetooth headset, this case is currently not handled in
Sokol Audio).
You can check if audio initialization was successful with
saudio_isvalid(). If backend initialization failed for some reason
(for instance when there's no audio device in the machine), this
will return false. Not checking for success won't do any harm, all
Sokol Audio function will silently fail when called after initialization
has failed, so apart from missing audio output, nothing bad will happen.
Before your application exits, you should call
saudio_shutdown();
This stops the audio thread (on Linux, Windows and macOS/iOS) and
properly shuts down the audio backend.
THE STREAM CALLBACK MODEL
=========================
To use Sokol Audio in stream-callback-mode, provide a callback function
like this in the saudio_desc struct when calling saudio_setup():
void stream_cb(float* buffer, int num_frames, int num_channels) {
...
}
Or the alternative version with a user-data argument:
void stream_userdata_cb(float* buffer, int num_frames, int num_channels, void* user_data) {
my_data_t* my_data = (my_data_t*) user_data;
...
}
The job of the callback function is to fill the *buffer* with 32-bit
float sample values.
To output silence, fill the buffer with zeros:
void stream_cb(float* buffer, int num_frames, int num_channels) {
const int num_samples = num_frames * num_channels;
for (int i = 0; i < num_samples; i++) {
buffer[i] = 0.0f;
}
}
For stereo output (num_channels == 2), the samples for the left
and right channel are interleaved:
void stream_cb(float* buffer, int num_frames, int num_channels) {
assert(2 == num_channels);
for (int i = 0; i < num_frames; i++) {
buffer[2*i + 0] = ...; // left channel
buffer[2*i + 1] = ...; // right channel
}
}
Please keep in mind that the stream callback function is running in a
separate thread, if you need to share data with the main thread you need
to take care yourself to make the access to the shared data thread-safe!
THE PUSH MODEL
==============
To use the push-model for providing audio data, simply don't set (keep
zero-initialized) the stream_cb field in the saudio_desc struct when
calling saudio_setup().
To provide sample data with the push model, call the saudio_push()
function at regular intervals (for instance once per frame). You can
call the saudio_expect() function to ask Sokol Audio how much room is
in the ring buffer, but if you provide a continuous stream of data
at the right sample rate, saudio_expect() isn't required (it's a simple
way to sync/throttle your sample generation code with the playback
rate though).
With saudio_push() you may need to maintain your own intermediate sample
buffer, since pushing individual sample values isn't very efficient.
The following example is from the MOD player sample in
sokol-samples (https://github.com/floooh/sokol-samples):
const int num_frames = saudio_expect();
if (num_frames > 0) {
const int num_samples = num_frames * saudio_channels();
read_samples(flt_buf, num_samples);
saudio_push(flt_buf, num_frames);
}
Another option is to ignore saudio_expect(), and just push samples as they
are generated in small batches. In this case you *need* to generate the
samples at the right sample rate:
The following example is taken from the Tiny Emulators project
(https://github.com/floooh/chips-test), this is for mono playback,
so (num_samples == num_frames):
// tick the sound generator
if (ay38910_tick(&sys->psg)) {
// new sample is ready
sys->sample_buffer[sys->sample_pos++] = sys->psg.sample;
if (sys->sample_pos == sys->num_samples) {
// new sample packet is ready
saudio_push(sys->sample_buffer, sys->num_samples);
sys->sample_pos = 0;
}
}
THE WEBAUDIO BACKEND
====================
The WebAudio backend is currently using a ScriptProcessorNode callback to
feed the sample data into WebAudio. ScriptProcessorNode has been
deprecated for a while because it is running from the main thread, with
the default initialization parameters it works 'pretty well' though.
Ultimately Sokol Audio will use Audio Worklets, but this requires a few
more things to fall into place (Audio Worklets implemented everywhere,
SharedArrayBuffers enabled again, and I need to figure out a 'low-cost'
solution in terms of implementation effort, since Audio Worklets are
a lot more complex than ScriptProcessorNode if the audio data needs to come
from the main thread).
The WebAudio backend is automatically selected when compiling for
emscripten (__EMSCRIPTEN__ define exists).
https://developers.google.com/web/updates/2017/12/audio-worklet
https://developers.google.com/web/updates/2018/06/audio-worklet-design-pattern
"Blob URLs": https://www.html5rocks.com/en/tutorials/workers/basics/
Also see: https://blog.paul.cx/post/a-wait-free-spsc-ringbuffer-for-the-web/
THE COREAUDIO BACKEND
=====================
The CoreAudio backend is selected on macOS and iOS (__APPLE__ is defined).
Since the CoreAudio API is implemented in C (not Objective-C) on macOS the
implementation part of Sokol Audio can be included into a C source file.
However on iOS, Sokol Audio must be compiled as Objective-C due to it's
reliance on the AVAudioSession object. The iOS code path support both
being compiled with or without ARC (Automatic Reference Counting).
For thread synchronisation, the CoreAudio backend will use the
pthread_mutex_* functions.
The incoming floating point samples will be directly forwarded to
CoreAudio without further conversion.
macOS and iOS applications that use Sokol Audio need to link with
the AudioToolbox framework.
THE WASAPI BACKEND
==================
The WASAPI backend is automatically selected when compiling on Windows
(_WIN32 is defined).
For thread synchronisation a Win32 critical section is used.
WASAPI may use a different size for its own streaming buffer then requested,
so the base latency may be slightly bigger. The current backend implementation
converts the incoming floating point sample values to signed 16-bit
integers.
The required Windows system DLLs are linked with #pragma comment(lib, ...),
so you shouldn't need to add additional linker libs in the build process
(otherwise this is a bug which should be fixed in sokol_audio.h).
THE ALSA BACKEND
================
The ALSA backend is automatically selected when compiling on Linux
('linux' is defined).
For thread synchronisation, the pthread_mutex_* functions are used.
Samples are directly forwarded to ALSA in 32-bit float format, no
further conversion is taking place.
You need to link with the 'asound' library, and the <alsa/asoundlib.h>
header must be present (usually both are installed with some sort
of ALSA development package).
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
saudio_setup(&(saudio_desc){
// ...
.allocator = {
.alloc_fn = my_alloc,
.free_fn = my_free,
.user_data = ...,
}
});
...
If no overrides are provided, malloc and free will be used.
This only affects memory allocation calls done by sokol_audio.h
itself though, not any allocations in OS libraries.
Memory allocation will only happen on the same thread where saudio_setup()
was called, so you don't need to worry about thread-safety.
ERROR REPORTING AND LOGGING
===========================
To get any logging information at all you need to provide a logging callback in the setup call
the easiest way is to use sokol_log.h:
#include "sokol_log.h"
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
To override logging with your own callback, first write a logging function like this:
void my_log(const char* tag, // e.g. 'saudio'
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
uint32_t log_item_id, // SAUDIO_LOGITEM_*
const char* message_or_null, // a message string, may be nullptr in release mode
uint32_t line_nr, // line number in sokol_audio.h
const char* filename_or_null, // source filename, may be nullptr in release mode
void* user_data)
{
...
}
...and then setup sokol-audio like this:
saudio_setup(&(saudio_desc){
.logger = {
.func = my_log,
.user_data = my_user_data,
}
});
The provided logging function must be reentrant (e.g. be callable from
different threads).
If you don't want to provide your own custom logger it is highly recommended to use
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
errors.
LICENSE
=======
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#system_library,link_always "ole32";
#if DEBUG { sokol_audio_clib :: #library "sokol_audio_windows_x64_gl_debug"; }
else { sokol_audio_clib :: #library "sokol_audio_windows_x64_gl_release"; }
} else {
#system_library,link_always "ole32";
#if DEBUG { sokol_audio_clib :: #library "sokol_audio_windows_x64_d3d11_debug"; }
else { sokol_audio_clib :: #library "sokol_audio_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#system_library,link_always "ole32";
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_windows_x64_gl_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_windows_x64_gl_release"; }
} else {
#system_library,link_always "ole32";
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_windows_x64_d3d11_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_audio_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#system_library,link_always "AudioToolbox";
#if CPU == .ARM64 {
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_arm64_gl_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_x64_gl_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_x64_gl_release"; }
}
} else {
#system_library,link_always "AudioToolbox";
#if CPU == .ARM64 {
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_arm64_metal_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_x64_metal_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#system_library,link_always "asound"; #system_library,link_always "dl"; #system_library,link_always "pthread";
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_linux_x64_gl_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_audio_clib :: #library,no_dll "sokol_audio_wasm_gl_debug"; }
else { sokol_audio_clib :: #library,no_dll "sokol_audio_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
// setup sokol-audio
saudio_setup :: (desc: *saudio_desc) -> void #foreign sokol_audio_clib;
// shutdown sokol-audio
saudio_shutdown :: () -> void #foreign sokol_audio_clib;
// true after setup if audio backend was successfully initialized
saudio_isvalid :: () -> bool #foreign sokol_audio_clib;
// return the saudio_desc.user_data pointer
saudio_userdata :: () -> *void #foreign sokol_audio_clib;
// return a copy of the original saudio_desc struct
saudio_query_desc :: () -> saudio_desc #foreign sokol_audio_clib;
// actual sample rate
saudio_sample_rate :: () -> s32 #foreign sokol_audio_clib;
// return actual backend buffer size in number of frames
saudio_buffer_frames :: () -> s32 #foreign sokol_audio_clib;
// actual number of channels
saudio_channels :: () -> s32 #foreign sokol_audio_clib;
// return true if audio context is currently suspended (only in WebAudio backend, all other backends return false)
saudio_suspended :: () -> bool #foreign sokol_audio_clib;
// get current number of frames to fill packet queue
saudio_expect :: () -> s32 #foreign sokol_audio_clib;
// push sample frames from main thread, returns number of frames actually pushed
saudio_push :: (frames: *float, num_frames: s32) -> s32 #foreign sokol_audio_clib;
saudio_log_item :: enum u32 {
OK;
MALLOC_FAILED;
ALSA_SND_PCM_OPEN_FAILED;
ALSA_FLOAT_SAMPLES_NOT_SUPPORTED;
ALSA_REQUESTED_BUFFER_SIZE_NOT_SUPPORTED;
ALSA_REQUESTED_CHANNEL_COUNT_NOT_SUPPORTED;
ALSA_SND_PCM_HW_PARAMS_SET_RATE_NEAR_FAILED;
ALSA_SND_PCM_HW_PARAMS_FAILED;
ALSA_PTHREAD_CREATE_FAILED;
WASAPI_CREATE_EVENT_FAILED;
WASAPI_CREATE_DEVICE_ENUMERATOR_FAILED;
WASAPI_GET_DEFAULT_AUDIO_ENDPOINT_FAILED;
WASAPI_DEVICE_ACTIVATE_FAILED;
WASAPI_AUDIO_CLIENT_INITIALIZE_FAILED;
WASAPI_AUDIO_CLIENT_GET_BUFFER_SIZE_FAILED;
WASAPI_AUDIO_CLIENT_GET_SERVICE_FAILED;
WASAPI_AUDIO_CLIENT_SET_EVENT_HANDLE_FAILED;
WASAPI_CREATE_THREAD_FAILED;
AAUDIO_STREAMBUILDER_OPEN_STREAM_FAILED;
AAUDIO_PTHREAD_CREATE_FAILED;
AAUDIO_RESTARTING_STREAM_AFTER_ERROR;
USING_AAUDIO_BACKEND;
AAUDIO_CREATE_STREAMBUILDER_FAILED;
COREAUDIO_NEW_OUTPUT_FAILED;
COREAUDIO_ALLOCATE_BUFFER_FAILED;
COREAUDIO_START_FAILED;
BACKEND_BUFFER_SIZE_ISNT_MULTIPLE_OF_PACKET_SIZE;
}
saudio_logger :: struct {
func : (a0: *u8, a1: u32, a2: u32, a3: *u8, a4: u32, a5: *u8, a6: *void) #c_call;
user_data : *void;
}
saudio_allocator :: struct {
alloc_fn : (a0: u64, a1: *void) -> *void #c_call;
free_fn : (a0: *void, a1: *void) #c_call;
user_data : *void;
}
saudio_desc :: struct {
sample_rate : s32;
num_channels : s32;
buffer_frames : s32;
packet_frames : s32;
num_packets : s32;
stream_cb : (a0: *float, a1: s32, a2: s32) #c_call;
stream_userdata_cb : (a0: *float, a1: s32, a2: s32, a3: *void) #c_call;
user_data : *void;
allocator : saudio_allocator;
logger : saudio_logger;
}

View File

@ -0,0 +1,47 @@
set -e
build_lib_x64_release() {
src=$1
dst=$2
backend=$3
echo $dst
cc -pthread -c -O2 -DNDEBUG -DIMPL -D$backend c/$src.c
ar rcs $dst.a $src.o
}
build_lib_x64_debug() {
src=$1
dst=$2
backend=$3
echo $dst
cc -pthread -c -g -DIMPL -D$backend c/$src.c
ar rcs $dst.a $src.o
}
# x64 + GL + Release
build_lib_x64_release sokol_log log/sokol_log_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_gfx gfx/sokol_gfx_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_app app/sokol_app_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_glue glue/sokol_glue_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_time time/sokol_time_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_audio audio/sokol_audio_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_debugtext debugtext/sokol_debugtext_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_shape shape/sokol_shape_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_gl gl/sokol_gl_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_fontstash fontstash/sokol_fontstash_linux_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_fetch fetch/sokol_fetch_linux_x64_gl_release SOKOL_GLCORE
# x64 + GL + Debug
build_lib_x64_debug sokol_log log/sokol_log_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_gfx gfx/sokol_gfx_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_app app/sokol_app_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_glue glue/sokol_glue_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_time time/sokol_time_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_audio audio/sokol_audio_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_debugtext debugtext/sokol_debugtext_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_shape shape/sokol_shape_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_fontstash fontstash/sokol_fontstash_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_fetch fetch/sokol_fetch_linux_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_gl gl/sokol_gl_linux_x64_gl_debug SOKOL_GLCORE
rm *.o

View File

@ -0,0 +1,140 @@
set -e
architecture=$(uname -m)
build_lib_arm64_release() {
if [[ $architecture == "x86_64" ]]; then
return
fi
src=$1
dst=$2
backend=$3
echo $dst
MACOSX_DEPLOYMENT_TARGET=10.13 cc -c -O2 -x objective-c -arch arm64 -DNDEBUG -DIMPL -D$backend c/$src.c
ar rcs $dst.a $src.o
}
build_lib_arm64_debug() {
if [[ $architecture == "x86_64" ]]; then
return
fi
src=$1
dst=$2
backend=$3
echo $dst
MACOSX_DEPLOYMENT_TARGET=10.13 cc -c -g -x objective-c -arch arm64 -DIMPL -D$backend c/$src.c
ar rcs $dst.a $src.o
}
build_lib_x64_release() {
src=$1
dst=$2
backend=$3
echo $dst
MACOSX_DEPLOYMENT_TARGET=10.13 cc -c -O2 -x objective-c -arch x86_64 -DNDEBUG -DIMPL -D$backend c/$src.c
ar rcs $dst.a $src.o
}
build_lib_x64_debug() {
src=$1
dst=$2
backend=$3
echo $dst
MACOSX_DEPLOYMENT_TARGET=10.13 cc -c -g -x objective-c -arch x86_64 -DIMPL -D$backend c/$src.c
ar rcs $dst.a $src.o
}
# ARM + Metal + Release
build_lib_arm64_release sokol_log log/sokol_log_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_gfx gfx/sokol_gfx_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_app app/sokol_app_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_glue glue/sokol_glue_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_time time/sokol_time_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_audio audio/sokol_audio_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_debugtext debugtext/sokol_debugtext_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_shape shape/sokol_shape_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_gl gl/sokol_gl_macos_arm64_metal_release SOKOL_METAL
build_lib_arm64_release sokol_fontstash fontstash/sokol_fontstash_macos_arm64_metal_release SOKOL_METAL
# ARM + Metal + Debug
build_lib_arm64_debug sokol_log log/sokol_log_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_gfx gfx/sokol_gfx_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_app app/sokol_app_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_glue glue/sokol_glue_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_time time/sokol_time_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_audio audio/sokol_audio_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_debugtext debugtext/sokol_debugtext_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_shape shape/sokol_shape_macos_arm64_metal_debug SOKOL_METAL
build_lib_arm64_debug sokol_gl gl/sokol_gl_macos_arm64_metal_debug SOKOL_METAL
# x64 + Metal + Release
build_lib_x64_release sokol_log log/sokol_log_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_gfx gfx/sokol_gfx_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_app app/sokol_app_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_glue glue/sokol_glue_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_time time/sokol_time_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_audio audio/sokol_audio_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_debugtext debugtext/sokol_debugtext_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_shape shape/sokol_shape_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_gl gl/sokol_gl_macos_x64_metal_release SOKOL_METAL
build_lib_x64_release sokol_fontstash fontstash/sokol_fontstash_macos_x64_metal_release SOKOL_METAL
# x64 + Metal + Debug
build_lib_x64_debug sokol_log log/sokol_log_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_gfx gfx/sokol_gfx_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_app app/sokol_app_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_glue glue/sokol_glue_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_time time/sokol_time_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_audio audio/sokol_audio_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_debugtext debugtext/sokol_debugtext_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_shape shape/sokol_shape_macos_x64_metal_debug SOKOL_METAL
build_lib_x64_debug sokol_gl gl/sokol_gl_macos_x64_metal_debug SOKOL_METAL
# ARM + GL + Release
build_lib_arm64_release sokol_log log/sokol_log_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_gfx gfx/sokol_gfx_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_app app/sokol_app_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_glue glue/sokol_glue_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_time time/sokol_time_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_audio audio/sokol_audio_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_debugtext debugtext/sokol_debugtext_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_shape shape/sokol_shape_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_gl gl/sokol_gl_macos_arm64_gl_release SOKOL_GLCORE
build_lib_arm64_release sokol_fontstash fontstash/sokol_fontstash_macos_arm64_gl_release SOKOL_GLCORE
# ARM + GL + Debug
build_lib_arm64_debug sokol_log log/sokol_log_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_gfx gfx/sokol_gfx_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_app app/sokol_app_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_glue glue/sokol_glue_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_time time/sokol_time_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_audio audio/sokol_audio_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_debugtext debugtext/sokol_debugtext_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_shape shape/sokol_shape_macos_arm64_gl_debug SOKOL_GLCORE
build_lib_arm64_debug sokol_gl gl/sokol_gl_macos_arm64_gl_debug SOKOL_GLCORE
# x64 + GL + Release
build_lib_x64_release sokol_log log/sokol_log_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_gfx gfx/sokol_gfx_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_app app/sokol_app_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_glue glue/sokol_glue_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_time time/sokol_time_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_audio audio/sokol_audio_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_debugtext debugtext/sokol_debugtext_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_shape shape/sokol_shape_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_gl gl/sokol_gl_macos_x64_gl_release SOKOL_GLCORE
build_lib_x64_release sokol_fontstash fontstash/sokol_fontstash_macos_x64_gl_release SOKOL_GLCORE
# x64 + GL + Debug
build_lib_x64_debug sokol_log log/sokol_log_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_gfx gfx/sokol_gfx_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_app app/sokol_app_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_glue glue/sokol_glue_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_time time/sokol_time_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_audio audio/sokol_audio_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_debugtext debugtext/sokol_debugtext_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_shape shape/sokol_shape_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_gl gl/sokol_gl_macos_x64_gl_debug SOKOL_GLCORE
build_lib_x64_debug sokol_fontstash fontstash/sokol_fontstash_macos_x64_gl_debug SOKOL_GLCORE
rm *.o

View File

@ -0,0 +1,50 @@
set -e
FRAMEWORKS_METAL="-framework Metal -framework MetalKit"
FRAMEWORKS_OPENGL="-framework OpenGL"
FRAMEWORKS_CORE="-framework Foundation -framework CoreGraphics -framework Cocoa -framework QuartzCore -framework CoreAudio -framework AudioToolbox"
build_lib_release() {
src=$1
dst=$2
backend=$3
arch=$4
frameworks=""
if [ $backend = "SOKOL_METAL" ]; then
frameworks="${frameworks} ${FRAMEWORKS_METAL}"
else
frameworks="${frameworks} ${FRAMEWORKS_OPENGL}"
fi
echo $dst
MACOSX_DEPLOYMENT_TARGET=10.13 cc -c -O2 -x objective-c -arch $arch -DNDEBUG -DIMPL -D$backend c/$src.c
cc -dynamiclib -arch $arch $FRAMEWORKS_CORE $frameworks -o $dst.dylib $src.o $dep
}
build_lib_debug() {
src=$1
dst=$2
backend=$3
arch=$4
frameworks=""
if [ $backend = "SOKOL_METAL" ]; then
frameworks="${frameworks} ${FRAMEWORKS_METAL}"
else
frameworks="${frameworks} ${FRAMEWORKS_OPENGL}"
fi
echo $dst
MACOSX_DEPLOYMENT_TARGET=10.13 cc -c -g -x objective-c -arch $arch -DIMPL -D$backend c/$src.c
cc -dynamiclib -arch $arch $FRAMEWORKS_CORE $frameworks -o $dst.dylib $src.o $dep
}
mkdir -p dylib
build_lib_release sokol dylib/sokol_dylib_macos_arm64_metal_release SOKOL_METAL arm64
build_lib_debug sokol dylib/sokol_dylib_macos_arm64_metal_debug SOKOL_METAL arm64
build_lib_release sokol dylib/sokol_dylib_macos_x64_metal_release SOKOL_METAL x86_64
build_lib_debug sokol dylib/sokol_dylib_macos_x64_metal_debug SOKOL_METAL x86_64
build_lib_release sokol dylib/sokol_dylib_macos_arm64_gl_release SOKOL_GLCORE33 arm64
build_lib_debug sokol dylib/sokol_dylib_macos_arm64_gl_debug SOKOL_GLCORE33 arm64
build_lib_release sokol dylib/sokol_dylib_macos_x64_gl_release SOKOL_GLCORE33 x86_64
build_lib_debug sokol dylib/sokol_dylib_macos_x64_gl_debug SOKOL_GLCORE33 x86_64
rm *.o

View File

@ -0,0 +1,47 @@
set -e
build_lib_wasm_release() {
src=$1
dst=$2
backend=$3
echo $dst
emcc -c -O2 -DNDEBUG -sMEMORY64 -sSHARED_MEMORY -DIMPL -D$backend c/$src.c
emar rcs $dst.a $src.o
}
build_lib_wasm_debug() {
src=$1
dst=$2
backend=$3
echo $dst
emcc -c -g -DIMPL -sMEMORY64 -sSHARED_MEMORY -D$backend c/$src.c
emar rcs $dst.a $src.o
}
# wasm + GL + Release
build_lib_wasm_release sokol_log log/sokol_log_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_gfx gfx/sokol_gfx_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_app app/sokol_app_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_glue glue/sokol_glue_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_time time/sokol_time_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_audio audio/sokol_audio_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_debugtext debugtext/sokol_debugtext_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_shape shape/sokol_shape_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_fontstash fontstash/sokol_fontstash_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_fetch fetch/sokol_fetch_wasm_gl_release SOKOL_GLES3
build_lib_wasm_release sokol_gl gl/sokol_gl_wasm_gl_release SOKOL_GLES3
# wasm + GL + Debug
build_lib_wasm_debug sokol_log log/sokol_log_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_gfx gfx/sokol_gfx_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_app app/sokol_app_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_glue glue/sokol_glue_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_time time/sokol_time_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_audio audio/sokol_audio_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_debugtext debugtext/sokol_debugtext_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_shape shape/sokol_shape_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_fontstash fontstash/sokol_fontstash_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_fetch fetch/sokol_fetch_wasm_gl_debug SOKOL_GLES3
build_lib_wasm_debug sokol_gl gl/sokol_gl_wasm_gl_debug SOKOL_GLES3
rm *.o

View File

@ -0,0 +1,45 @@
@echo off
set sources=log app gfx glue time audio debugtext shape gl
REM D3D11 Debug
for %%s in (%sources%) do (
cl /c /D_DEBUG /DIMPL /DSOKOL_D3D11 c\sokol_%%s.c /Z7
lib /OUT:%%s\sokol_%%s_windows_x64_d3d11_debug.lib sokol_%%s.obj
del sokol_%%s.obj
)
REM D3D11 Release
for %%s in (%sources%) do (
cl /c /O2 /DNDEBUG /DIMPL /DSOKOL_D3D11 c\sokol_%%s.c
lib /OUT:%%s\sokol_%%s_windows_x64_d3d11_release.lib sokol_%%s.obj
del sokol_%%s.obj
)
REM GL Debug
for %%s in (%sources%) do (
cl /c /D_DEBUG /DIMPL /DSOKOL_GLCORE c\sokol_%%s.c /Z7
lib /OUT:%%s\sokol_%%s_windows_x64_gl_debug.lib sokol_%%s.obj
del sokol_%%s.obj
)
REM GL Release
for %%s in (%sources%) do (
cl /c /O2 /DNDEBUG /DIMPL /DSOKOL_GLCORE c\sokol_%%s.c
lib /OUT:%%s\sokol_%%s_windows_x64_gl_release.lib sokol_%%s.obj
del sokol_%%s.obj
)
REM D3D11 Debug DLL
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_D3D11 c\sokol.c /Z7 /LDd /MDd /DLL /Fe:sokol_dll_windows_x64_d3d11_debug.dll /link /INCREMENTAL:NO
REM D3D11 Release DLL
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_D3D11 c\sokol.c /LD /MD /DLL /Fe:sokol_dll_windows_x64_d3d11_release.dll /link /INCREMENTAL:NO
REM GL Debug DLL
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_GLCORE c\sokol.c /Z7 /LDd /MDd /DLL /Fe:sokol_dll_windows_x64_gl_debug.dll /link /INCREMENTAL:NO
REM GL Release DLL
cl /D_DEBUG /DIMPL /DSOKOL_DLL /DSOKOL_GLCORE c\sokol.c /LD /MD /DLL /Fe:sokol_dll_windows_x64_gl_release.dll /link /INCREMENTAL:NO
del sokol.obj

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
#if defined(IMPL)
#define SOKOL_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_audio.h"
#include "sokol_app.h"
#include "sokol_gfx.h"
#include "sokol_log.h"
#include "sokol_time.h"
#include "sokol_glue.h"
#include "sokol_fetch.h"
#include "sokol_gl.h"
#include "sokol_shape.h"
#include "sokol_debugtext.h"

View File

@ -0,0 +1,5 @@
#if defined(IMPL)
#define SOKOL_APP_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_app.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
#if defined(IMPL)
#define SOKOL_AUDIO_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_audio.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
#if defined(IMPL)
#define SOKOL_DEBUGTEXT_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_gfx.h"
#include "sokol_debugtext.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
#define SOKOL_NO_ENTRY
#if defined(_WIN32)
#define SOKOL_WIN32_FORCE_MAIN
#endif
// FIXME: macOS Zig HACK without this, some C stdlib headers throw errors
#if defined(__APPLE__)
#include <TargetConditionals.h>
#endif

View File

@ -0,0 +1,5 @@
#if defined(IMPL)
#define SOKOL_FETCH_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_fetch.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
#include "sokol_gfx.h"
#include "sokol_gl.h"
#define FONTSTASH_IMPLEMENTATION
#include <stdlib.h>
#include "fontstash.h"
#define SOKOL_IMPL
#include "sokol_fontstash.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
#if defined(IMPL)
#define SOKOL_GFX_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_gfx.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
#if defined(IMPL)
#define SOKOL_GL_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_gfx.h"
#include "sokol_gl.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
#if defined(IMPL)
#define SOKOL_GLUE_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_app.h"
#include "sokol_gfx.h"
#include "sokol_glue.h"

View File

@ -0,0 +1,162 @@
#if defined(SOKOL_IMPL) && !defined(SOKOL_GLUE_IMPL)
#define SOKOL_GLUE_IMPL
#endif
#ifndef SOKOL_GLUE_INCLUDED
/*
sokol_glue.h -- glue helper functions for sokol headers
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_GLUE_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
...optionally provide the following macros to override defaults:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_GLUE_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GLUE_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
If sokol_glue.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_GLUE_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
OVERVIEW
========
sokol_glue.h provides glue helper functions between sokol_gfx.h and sokol_app.h,
so that sokol_gfx.h doesn't need to depend on sokol_app.h but can be
used with different window system glue libraries.
PROVIDED FUNCTIONS
==================
sg_environment sglue_environment(void)
Returns an sg_environment struct initialized by calling sokol_app.h
functions. Use this in the sg_setup() call like this:
sg_setup(&(sg_desc){
.environment = sglue_environment(),
...
});
sg_swapchain sglue_swapchain(void)
Returns an sg_swapchain struct initialized by calling sokol_app.h
functions. Use this in sg_begin_pass() for a 'swapchain pass' like
this:
sg_begin_pass(&(sg_pass){ .swapchain = sglue_swapchain(), ... });
LICENSE
=======
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define SOKOL_GLUE_INCLUDED
#if defined(SOKOL_API_DECL) && !defined(SOKOL_GLUE_API_DECL)
#define SOKOL_GLUE_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_GLUE_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GLUE_IMPL)
#define SOKOL_GLUE_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_GLUE_API_DECL __declspec(dllimport)
#else
#define SOKOL_GLUE_API_DECL extern
#endif
#endif
#ifndef SOKOL_GFX_INCLUDED
#error "Please include sokol_gfx.h before sokol_glue.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
SOKOL_GLUE_API_DECL sg_environment sglue_environment(void);
SOKOL_GLUE_API_DECL sg_swapchain sglue_swapchain(void);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SOKOL_GLUE_INCLUDED */
/*-- IMPLEMENTATION ----------------------------------------------------------*/
#ifdef SOKOL_GLUE_IMPL
#define SOKOL_GLUE_IMPL_INCLUDED (1)
#include <string.h> /* memset */
#ifndef SOKOL_APP_INCLUDED
#error "Please include sokol_app.h before the sokol_glue.h implementation"
#endif
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
SOKOL_API_IMPL sg_environment sglue_environment(void) {
sg_environment env;
memset(&env, 0, sizeof(env));
env.defaults.color_format = (sg_pixel_format) sapp_color_format();
env.defaults.depth_format = (sg_pixel_format) sapp_depth_format();
env.defaults.sample_count = sapp_sample_count();
env.metal.device = sapp_metal_get_device();
env.d3d11.device = sapp_d3d11_get_device();
env.d3d11.device_context = sapp_d3d11_get_device_context();
env.wgpu.device = sapp_wgpu_get_device();
return env;
}
SOKOL_API_IMPL sg_swapchain sglue_swapchain(void) {
sg_swapchain swapchain;
memset(&swapchain, 0, sizeof(swapchain));
swapchain.width = sapp_width();
swapchain.height = sapp_height();
swapchain.sample_count = sapp_sample_count();
swapchain.color_format = (sg_pixel_format)sapp_color_format();
swapchain.depth_format = (sg_pixel_format)sapp_depth_format();
swapchain.metal.current_drawable = sapp_metal_get_current_drawable();
swapchain.metal.depth_stencil_texture = sapp_metal_get_depth_stencil_texture();
swapchain.metal.msaa_color_texture = sapp_metal_get_msaa_color_texture();
swapchain.d3d11.render_view = sapp_d3d11_get_render_view();
swapchain.d3d11.resolve_view = sapp_d3d11_get_resolve_view();
swapchain.d3d11.depth_stencil_view = sapp_d3d11_get_depth_stencil_view();
swapchain.wgpu.render_view = sapp_wgpu_get_render_view();
swapchain.wgpu.resolve_view = sapp_wgpu_get_resolve_view();
swapchain.wgpu.depth_stencil_view = sapp_wgpu_get_depth_stencil_view();
swapchain.gl.framebuffer = sapp_gl_get_framebuffer();
return swapchain;
}
#endif /* SOKOL_GLUE_IMPL */

View File

@ -0,0 +1,5 @@
#if defined(IMPL)
#define SOKOL_LOG_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_log.h"

View File

@ -0,0 +1,334 @@
#if defined(SOKOL_IMPL) && !defined(SOKOL_LOG_IMPL)
#define SOKOL_LOG_IMPL
#endif
#ifndef SOKOL_LOG_INCLUDED
/*
sokol_log.h -- common logging callback for sokol headers
Project URL: https://github.com/floooh/sokol
Example code: https://github.com/floooh/sokol-samples
Do this:
#define SOKOL_IMPL or
#define SOKOL_LOG_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Optionally provide the following defines when building the implementation:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
SOKOL_LOG_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GFX_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
Optionally define the following for verbose output:
SOKOL_DEBUG - by default this is defined if _DEBUG is defined
OVERVIEW
========
sokol_log.h provides a default logging callback for other sokol headers.
To use the default log callback, just include sokol_log.h and provide
a function pointer to the 'slog_func' function when setting up the
sokol library:
For instance with sokol_audio.h:
#include "sokol_log.h"
...
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
Logging output goes to stderr and/or a platform specific logging subsystem
(which means that in some scenarios you might see logging messages duplicated):
- Windows: stderr + OutputDebugStringA()
- macOS/iOS/Linux: stderr + syslog()
- Emscripten: console.info()/warn()/error()
- Android: __android_log_write()
On Windows with sokol_app.h also note the runtime config items to make
stdout/stderr output visible on the console for WinMain() applications
via sapp_desc.win32_console_attach or sapp_desc.win32_console_create,
however when running in a debugger on Windows, the logging output should
show up on the debug output UI panel.
In debug mode, a log message might look like this:
[sspine][error][id:12] /Users/floh/projects/sokol/util/sokol_spine.h:3472:0:
SKELETON_DESC_NO_ATLAS: no atlas object provided in sspine_skeleton_desc.atlas
The source path and line number is formatted like compiler errors, in some IDEs (like VSCode)
such error messages are clickable.
In release mode, logging is less verbose as to not bloat the executable with string data, but you still get
enough information to identify the type and location of an error:
[sspine][error][id:12][line:3472]
RULES FOR WRITING YOUR OWN LOGGING FUNCTION
===========================================
- must be re-entrant because it might be called from different threads
- must treat **all** provided string pointers as optional (can be null)
- don't store the string pointers, copy the string data instead
- must not return for log level panic
LICENSE
=======
zlib/libpng license
Copyright (c) 2023 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define SOKOL_LOG_INCLUDED (1)
#include <stdint.h>
#if defined(SOKOL_API_DECL) && !defined(SOKOL_LOG_API_DECL)
#define SOKOL_LOG_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_LOG_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_LOG_IMPL)
#define SOKOL_LOG_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_LOG_API_DECL __declspec(dllimport)
#else
#define SOKOL_LOG_API_DECL extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
Plug this function into the 'logger.func' struct item when initializing any of the sokol
headers. For instance for sokol_audio.h it would look like this:
saudio_setup(&(saudio_desc){
.logger = {
.func = slog_func
}
});
*/
SOKOL_LOG_API_DECL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // SOKOL_LOG_INCLUDED
// ██ ███ ███ ██████ ██ ███████ ███ ███ ███████ ███ ██ ████████ █████ ████████ ██ ██████ ███ ██
// ██ ████ ████ ██ ██ ██ ██ ████ ████ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██
// ██ ██ ████ ██ ██████ ██ █████ ██ ████ ██ █████ ██ ██ ██ ██ ███████ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
// ██ ██ ██ ██ ███████ ███████ ██ ██ ███████ ██ ████ ██ ██ ██ ██ ██ ██████ ██ ████
//
// >>implementation
#ifdef SOKOL_LOG_IMPL
#define SOKOL_LOG_IMPL_INCLUDED (1)
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
#ifndef SOKOL_DEBUG
#ifndef NDEBUG
#define SOKOL_DEBUG
#endif
#endif
#ifndef SOKOL_ASSERT
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
#define _SOKOL_PRIVATE __attribute__((unused)) static
#else
#define _SOKOL_PRIVATE static
#endif
#endif
#ifndef _SOKOL_UNUSED
#define _SOKOL_UNUSED(x) (void)(x)
#endif
// platform detection
#if defined(__APPLE__)
#define _SLOG_APPLE (1)
#elif defined(__EMSCRIPTEN__)
#define _SLOG_EMSCRIPTEN (1)
#elif defined(_WIN32)
#define _SLOG_WINDOWS (1)
#elif defined(__ANDROID__)
#define _SLOG_ANDROID (1)
#elif defined(__linux__) || defined(__unix__)
#define _SLOG_LINUX (1)
#else
#error "sokol_log.h: unknown platform"
#endif
#include <stdlib.h> // abort
#include <stdio.h> // fputs
#include <stddef.h> // size_t
#if defined(_SLOG_EMSCRIPTEN)
#include <emscripten/emscripten.h>
#elif defined(_SLOG_WINDOWS)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#elif defined(_SLOG_ANDROID)
#include <android/log.h>
#elif defined(_SLOG_LINUX) || defined(_SLOG_APPLE)
#include <syslog.h>
#endif
// size of line buffer (on stack!) in bytes including terminating zero
#define _SLOG_LINE_LENGTH (512)
_SOKOL_PRIVATE char* _slog_append(const char* str, char* dst, char* end) {
if (str) {
char c;
while (((c = *str++) != 0) && (dst < (end - 1))) {
*dst++ = c;
}
}
*dst = 0;
return dst;
}
_SOKOL_PRIVATE char* _slog_itoa(uint32_t x, char* buf, size_t buf_size) {
const size_t max_digits_and_null = 11;
if (buf_size < max_digits_and_null) {
return 0;
}
char* p = buf + max_digits_and_null;
*--p = 0;
do {
*--p = '0' + (x % 10);
x /= 10;
} while (x != 0);
return p;
}
#if defined(_SLOG_EMSCRIPTEN)
EM_JS(void, slog_js_log, (uint32_t level, const char* c_str), {
const str = UTF8ToString(c_str);
switch (level) {
case 0: console.error(str); break;
case 1: console.error(str); break;
case 2: console.warn(str); break;
default: console.info(str); break;
}
})
#endif
SOKOL_API_IMPL void slog_func(const char* tag, uint32_t log_level, uint32_t log_item, const char* message, uint32_t line_nr, const char* filename, void* user_data) {
_SOKOL_UNUSED(user_data);
const char* log_level_str;
switch (log_level) {
case 0: log_level_str = "panic"; break;
case 1: log_level_str = "error"; break;
case 2: log_level_str = "warning"; break;
default: log_level_str = "info"; break;
}
// build log output line
char line_buf[_SLOG_LINE_LENGTH];
char* str = line_buf;
char* end = line_buf + sizeof(line_buf);
char num_buf[32];
if (tag) {
str = _slog_append("[", str, end);
str = _slog_append(tag, str, end);
str = _slog_append("]", str, end);
}
str = _slog_append("[", str, end);
str = _slog_append(log_level_str, str, end);
str = _slog_append("]", str, end);
str = _slog_append("[id:", str, end);
str = _slog_append(_slog_itoa(log_item, num_buf, sizeof(num_buf)), str, end);
str = _slog_append("]", str, end);
// if a filename is provided, build a clickable log message that's compatible with compiler error messages
if (filename) {
str = _slog_append(" ", str, end);
#if defined(_MSC_VER)
// MSVC compiler error format
str = _slog_append(filename, str, end);
str = _slog_append("(", str, end);
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
str = _slog_append("): ", str, end);
#else
// gcc/clang compiler error format
str = _slog_append(filename, str, end);
str = _slog_append(":", str, end);
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
str = _slog_append(":0: ", str, end);
#endif
}
else {
str = _slog_append("[line:", str, end);
str = _slog_append(_slog_itoa(line_nr, num_buf, sizeof(num_buf)), str, end);
str = _slog_append("] ", str, end);
}
if (message) {
str = _slog_append("\n\t", str, end);
str = _slog_append(message, str, end);
}
str = _slog_append("\n\n", str, end);
if (0 == log_level) {
str = _slog_append("ABORTING because of [panic]\n", str, end);
(void)str;
}
// print to stderr?
#if defined(_SLOG_LINUX) || defined(_SLOG_WINDOWS) || defined(_SLOG_APPLE)
fputs(line_buf, stderr);
#endif
// platform specific logging calls
#if defined(_SLOG_WINDOWS)
OutputDebugStringA(line_buf);
#elif defined(_SLOG_ANDROID)
int prio;
switch (log_level) {
case 0: prio = ANDROID_LOG_FATAL; break;
case 1: prio = ANDROID_LOG_ERROR; break;
case 2: prio = ANDROID_LOG_WARN; break;
default: prio = ANDROID_LOG_INFO; break;
}
__android_log_write(prio, "SOKOL", line_buf);
#elif defined(_SLOG_EMSCRIPTEN)
slog_js_log(log_level, line_buf);
#endif
if (0 == log_level) {
abort();
}
}
#endif // SOKOL_LOG_IMPL

View File

@ -0,0 +1,6 @@
#if defined(IMPL)
#define SOKOL_SHAPE_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_gfx.h"
#include "sokol_shape.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
#if defined(IMPL)
#define SOKOL_TIME_IMPL
#endif
#include "sokol_defines.h"
#include "sokol_time.h"

View File

@ -0,0 +1,319 @@
#if defined(SOKOL_IMPL) && !defined(SOKOL_TIME_IMPL)
#define SOKOL_TIME_IMPL
#endif
#ifndef SOKOL_TIME_INCLUDED
/*
sokol_time.h -- simple cross-platform time measurement
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_TIME_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Optionally provide the following defines with your own implementations:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_TIME_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_TIME_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
If sokol_time.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_TIME_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
void stm_setup();
Call once before any other functions to initialize sokol_time
(this calls for instance QueryPerformanceFrequency on Windows)
uint64_t stm_now();
Get current point in time in unspecified 'ticks'. The value that
is returned has no relation to the 'wall-clock' time and is
not in a specific time unit, it is only useful to compute
time differences.
uint64_t stm_diff(uint64_t new, uint64_t old);
Computes the time difference between new and old. This will always
return a positive, non-zero value.
uint64_t stm_since(uint64_t start);
Takes the current time, and returns the elapsed time since start
(this is a shortcut for "stm_diff(stm_now(), start)")
uint64_t stm_laptime(uint64_t* last_time);
This is useful for measuring frame time and other recurring
events. It takes the current time, returns the time difference
to the value in last_time, and stores the current time in
last_time for the next call. If the value in last_time is 0,
the return value will be zero (this usually happens on the
very first call).
uint64_t stm_round_to_common_refresh_rate(uint64_t duration)
This oddly named function takes a measured frame time and
returns the closest "nearby" common display refresh rate frame duration
in ticks. If the input duration isn't close to any common display
refresh rate, the input duration will be returned unchanged as a fallback.
The main purpose of this function is to remove jitter/inaccuracies from
measured frame times, and instead use the display refresh rate as
frame duration.
NOTE: for more robust frame timing, consider using the
sokol_app.h function sapp_frame_duration()
Use the following functions to convert a duration in ticks into
useful time units:
double stm_sec(uint64_t ticks);
double stm_ms(uint64_t ticks);
double stm_us(uint64_t ticks);
double stm_ns(uint64_t ticks);
Converts a tick value into seconds, milliseconds, microseconds
or nanoseconds. Note that not all platforms will have nanosecond
or even microsecond precision.
Uses the following time measurement functions under the hood:
Windows: QueryPerformanceFrequency() / QueryPerformanceCounter()
MacOS/iOS: mach_absolute_time()
emscripten: emscripten_get_now()
Linux+others: clock_gettime(CLOCK_MONOTONIC)
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define SOKOL_TIME_INCLUDED (1)
#include <stdint.h>
#if defined(SOKOL_API_DECL) && !defined(SOKOL_TIME_API_DECL)
#define SOKOL_TIME_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_TIME_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_TIME_IMPL)
#define SOKOL_TIME_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_TIME_API_DECL __declspec(dllimport)
#else
#define SOKOL_TIME_API_DECL extern
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
SOKOL_TIME_API_DECL void stm_setup(void);
SOKOL_TIME_API_DECL uint64_t stm_now(void);
SOKOL_TIME_API_DECL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks);
SOKOL_TIME_API_DECL uint64_t stm_since(uint64_t start_ticks);
SOKOL_TIME_API_DECL uint64_t stm_laptime(uint64_t* last_time);
SOKOL_TIME_API_DECL uint64_t stm_round_to_common_refresh_rate(uint64_t frame_ticks);
SOKOL_TIME_API_DECL double stm_sec(uint64_t ticks);
SOKOL_TIME_API_DECL double stm_ms(uint64_t ticks);
SOKOL_TIME_API_DECL double stm_us(uint64_t ticks);
SOKOL_TIME_API_DECL double stm_ns(uint64_t ticks);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif // SOKOL_TIME_INCLUDED
/*-- IMPLEMENTATION ----------------------------------------------------------*/
#ifdef SOKOL_TIME_IMPL
#define SOKOL_TIME_IMPL_INCLUDED (1)
#include <string.h> /* memset */
#ifndef SOKOL_API_IMPL
#define SOKOL_API_IMPL
#endif
#ifndef SOKOL_ASSERT
#include <assert.h>
#define SOKOL_ASSERT(c) assert(c)
#endif
#ifndef _SOKOL_PRIVATE
#if defined(__GNUC__) || defined(__clang__)
#define _SOKOL_PRIVATE __attribute__((unused)) static
#else
#define _SOKOL_PRIVATE static
#endif
#endif
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
typedef struct {
uint32_t initialized;
LARGE_INTEGER freq;
LARGE_INTEGER start;
} _stm_state_t;
#elif defined(__APPLE__) && defined(__MACH__)
#include <mach/mach_time.h>
typedef struct {
uint32_t initialized;
mach_timebase_info_data_t timebase;
uint64_t start;
} _stm_state_t;
#elif defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>
typedef struct {
uint32_t initialized;
double start;
} _stm_state_t;
#else /* anything else, this will need more care for non-Linux platforms */
#ifdef ESP8266
// On the ESP8266, clock_gettime ignores the first argument and CLOCK_MONOTONIC isn't defined
#define CLOCK_MONOTONIC 0
#endif
#include <time.h>
typedef struct {
uint32_t initialized;
uint64_t start;
} _stm_state_t;
#endif
static _stm_state_t _stm;
/* prevent 64-bit overflow when computing relative timestamp
see https://gist.github.com/jspohr/3dc4f00033d79ec5bdaf67bc46c813e3
*/
#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
_SOKOL_PRIVATE int64_t _stm_int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
int64_t q = value / denom;
int64_t r = value % denom;
return q * numer + r * numer / denom;
}
#endif
SOKOL_API_IMPL void stm_setup(void) {
memset(&_stm, 0, sizeof(_stm));
_stm.initialized = 0xABCDABCD;
#if defined(_WIN32)
QueryPerformanceFrequency(&_stm.freq);
QueryPerformanceCounter(&_stm.start);
#elif defined(__APPLE__) && defined(__MACH__)
mach_timebase_info(&_stm.timebase);
_stm.start = mach_absolute_time();
#elif defined(__EMSCRIPTEN__)
_stm.start = emscripten_get_now();
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
_stm.start = (uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec;
#endif
}
SOKOL_API_IMPL uint64_t stm_now(void) {
SOKOL_ASSERT(_stm.initialized == 0xABCDABCD);
uint64_t now;
#if defined(_WIN32)
LARGE_INTEGER qpc_t;
QueryPerformanceCounter(&qpc_t);
now = (uint64_t) _stm_int64_muldiv(qpc_t.QuadPart - _stm.start.QuadPart, 1000000000, _stm.freq.QuadPart);
#elif defined(__APPLE__) && defined(__MACH__)
const uint64_t mach_now = mach_absolute_time() - _stm.start;
now = (uint64_t) _stm_int64_muldiv((int64_t)mach_now, (int64_t)_stm.timebase.numer, (int64_t)_stm.timebase.denom);
#elif defined(__EMSCRIPTEN__)
double js_now = emscripten_get_now() - _stm.start;
now = (uint64_t) (js_now * 1000000.0);
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
now = ((uint64_t)ts.tv_sec*1000000000 + (uint64_t)ts.tv_nsec) - _stm.start;
#endif
return now;
}
SOKOL_API_IMPL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks) {
if (new_ticks > old_ticks) {
return new_ticks - old_ticks;
}
else {
return 1;
}
}
SOKOL_API_IMPL uint64_t stm_since(uint64_t start_ticks) {
return stm_diff(stm_now(), start_ticks);
}
SOKOL_API_IMPL uint64_t stm_laptime(uint64_t* last_time) {
SOKOL_ASSERT(last_time);
uint64_t dt = 0;
uint64_t now = stm_now();
if (0 != *last_time) {
dt = stm_diff(now, *last_time);
}
*last_time = now;
return dt;
}
// first number is frame duration in ns, second number is tolerance in ns,
// the resulting min/max values must not overlap!
static const uint64_t _stm_refresh_rates[][2] = {
{ 16666667, 1000000 }, // 60 Hz: 16.6667 +- 1ms
{ 13888889, 250000 }, // 72 Hz: 13.8889 +- 0.25ms
{ 13333333, 250000 }, // 75 Hz: 13.3333 +- 0.25ms
{ 11764706, 250000 }, // 85 Hz: 11.7647 +- 0.25
{ 11111111, 250000 }, // 90 Hz: 11.1111 +- 0.25ms
{ 10000000, 500000 }, // 100 Hz: 10.0000 +- 0.5ms
{ 8333333, 500000 }, // 120 Hz: 8.3333 +- 0.5ms
{ 6944445, 500000 }, // 144 Hz: 6.9445 +- 0.5ms
{ 4166667, 1000000 }, // 240 Hz: 4.1666 +- 1ms
{ 0, 0 }, // keep the last element always at zero
};
SOKOL_API_IMPL uint64_t stm_round_to_common_refresh_rate(uint64_t ticks) {
uint64_t ns;
int i = 0;
while (0 != (ns = _stm_refresh_rates[i][0])) {
uint64_t tol = _stm_refresh_rates[i][1];
if ((ticks > (ns - tol)) && (ticks < (ns + tol))) {
return ns;
}
i++;
}
// fallthrough: didn't fit into any buckets
return ticks;
}
SOKOL_API_IMPL double stm_sec(uint64_t ticks) {
return (double)ticks / 1000000000.0;
}
SOKOL_API_IMPL double stm_ms(uint64_t ticks) {
return (double)ticks / 1000000.0;
}
SOKOL_API_IMPL double stm_us(uint64_t ticks) {
return (double)ticks / 1000.0;
}
SOKOL_API_IMPL double stm_ns(uint64_t ticks) {
return (double)ticks;
}
#endif /* SOKOL_TIME_IMPL */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,685 @@
// machine generated, do not edit
/*
sokol_debugtext.h - simple ASCII debug text rendering on top of sokol_gfx.h
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_DEBUGTEXT_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
The following defines are used by the implementation to select the
platform-specific embedded shader code (these are the same defines as
used by sokol_gfx.h and sokol_app.h):
SOKOL_GLCORE
SOKOL_GLES3
SOKOL_D3D11
SOKOL_METAL
SOKOL_WGPU
...optionally provide the following macros to override defaults:
SOKOL_VSNPRINTF - the function name of an alternative vsnprintf() function (default: vsnprintf)
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_DEBUGTEXT_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_DEBUGTEXT_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
If sokol_debugtext.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_DEBUGTEXT_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
Include the following headers before including sokol_debugtext.h:
sokol_gfx.h
FEATURES AND CONCEPTS
=====================
- renders 8-bit ASCII text as fixed-size 8x8 pixel characters
- comes with 6 embedded 8-bit home computer fonts (each taking up 2 KBytes)
- easily plug in your own fonts
- create multiple contexts for rendering text in different layers or render passes
STEP BY STEP
============
--- to initialize sokol-debugtext, call sdtx_setup() *after* initializing
sokol-gfx:
sdtx_setup(&(sdtx_desc_t){ ... });
To see any warnings and errors, you should always install a logging callback.
The easiest way is via sokol_log.h:
#include "sokol_log.h"
sdtx_setup(&(sdtx_desc_t){
.logger.func = slog_func,
});
--- configure sokol-debugtext by populating the sdtx_desc_t struct:
.context_pool_size (default: 8)
The max number of text contexts that can be created.
.printf_buf_size (default: 4096)
The size of the internal text formatting buffer used by
sdtx_printf() and sdtx_vprintf().
.fonts (default: none)
An array of sdtx_font_desc_t structs used to configure the
fonts that can be used for rendering. To use all builtin
fonts call sdtx_setup() like this (in C99):
sdtx_setup(&(sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = sdtx_font_kc854(),
[2] = sdtx_font_z1013(),
[3] = sdtx_font_cpc(),
[4] = sdtx_font_c64(),
[5] = sdtx_font_oric()
}
});
For documentation on how to use you own font data, search
below for "USING YOUR OWN FONT DATA".
.context
The setup parameters for the default text context. This will
be active right after sdtx_setup(), or when calling
sdtx_set_context(SDTX_DEFAULT_CONTEXT):
.max_commands (default: 4096)
The max number of render commands that can be recorded
into the internal command buffer. This directly translates
to the number of render layer changes in a single frame.
.char_buf_size (default: 4096)
The number of characters that can be rendered per frame in this
context, defines the size of an internal fixed-size vertex
buffer. Any additional characters will be silently ignored.
.canvas_width (default: 640)
.canvas_height (default: 480)
The 'virtual canvas size' in pixels. This defines how big
characters will be rendered relative to the default framebuffer
dimensions. Each character occupies a grid of 8x8 'virtual canvas
pixels' (so a virtual canvas size of 640x480 means that 80x60 characters
fit on the screen). For rendering in a resizeable window, you
should dynamically update the canvas size in each frame by
calling sdtx_canvas(w, h).
.tab_width (default: 4)
The width of a tab character in number of character cells.
.color_format (default: 0)
.depth_format (default: 0)
.sample_count (default: 0)
The pixel format description for the default context needed
for creating the context's sg_pipeline object. When
rendering to the default framebuffer you can leave those
zero-initialized, in this case the proper values will be
filled in by sokol-gfx. You only need to provide non-default
values here when rendering to render targets with different
pixel format attributes than the default framebuffer.
--- Before starting to render text, optionally call sdtx_canvas() to
dynamically resize the virtual canvas. This is recommended when
rendering to a resizeable window. The virtual canvas size can
also be used to scale text in relation to the display resolution.
Examples when using sokol-app:
- to render characters at 8x8 'physical pixels':
sdtx_canvas(sapp_width(), sapp_height());
- to render characters at 16x16 physical pixels:
sdtx_canvas(sapp_width()/2.0f, sapp_height()/2.0f);
Do *not* use integer math here, since this will not look nice
when the render target size isn't divisible by 2.
--- Optionally define the origin for the character grid with:
sdtx_origin(x, y);
The provided coordinates are in character grid cells, not in
virtual canvas pixels. E.g. to set the origin to 2 character tiles
from the left and top border:
sdtx_origin(2, 2);
You can define fractions, e.g. to start rendering half
a character tile from the top-left corner:
sdtx_origin(0.5f, 0.5f);
--- Optionally set a different font by calling:
sdtx_font(font_index)
sokol-debugtext provides 8 font slots which can be populated
with the builtin fonts or with user-provided font data, so
'font_index' must be a number from 0 to 7.
--- Position the text cursor with one of the following calls. All arguments
are in character grid cells as floats and relative to the
origin defined with sdtx_origin():
sdtx_pos(x, y) - sets absolute cursor position
sdtx_pos_x(x) - only set absolute x cursor position
sdtx_pos_y(y) - only set absolute y cursor position
sdtx_move(x, y) - move cursor relative in x and y direction
sdtx_move_x(x) - move cursor relative only in x direction
sdtx_move_y(y) - move cursor relative only in y direction
sdtx_crlf() - set cursor to beginning of next line
(same as sdtx_pos_x(0) + sdtx_move_y(1))
sdtx_home() - resets the cursor to the origin
(same as sdtx_pos(0, 0))
--- Set a new text color with any of the following functions:
sdtx_color3b(r, g, b) - RGB 0..255, A=255
sdtx_color3f(r, g, b) - RGB 0.0f..1.0f, A=1.0f
sdtx_color4b(r, g, b, a) - RGBA 0..255
sdtx_color4f(r, g, b, a) - RGBA 0.0f..1.0f
sdtx_color1i(uint32_t rgba) - ABGR (0xAABBGGRR)
--- Output 8-bit ASCII text with the following functions:
sdtx_putc(c) - output a single character
sdtx_puts(str) - output a null-terminated C string, note that
this will *not* append a newline (so it behaves
differently than the CRT's puts() function)
sdtx_putr(str, len) - 'put range' output the first 'len' characters of
a C string or until the zero character is encountered
sdtx_printf(fmt, ...) - output with printf-formatting, note that you
can inject your own printf-compatible function
by overriding the SOKOL_VSNPRINTF define before
including the implementation
sdtx_vprintf(fmt, args) - same as sdtx_printf() but with the arguments
provided in a va_list
- Note that the text will not yet be rendered, only recorded for rendering
at a later time, the actual rendering happens when sdtx_draw() is called
inside a sokol-gfx render pass.
- This means also you can output text anywhere in the frame, it doesn't
have to be inside a render pass.
- Note that character codes <32 are reserved as control characters
and won't render anything. Currently only the following control
characters are implemented:
\r - carriage return (same as sdtx_pos_x(0))
\n - carriage return + line feed (same as stdx_crlf())
\t - a tab character
--- You can 'record' text into render layers, this allows to mix/interleave
sokol-debugtext rendering with other rendering operations inside
sokol-gfx render passes. To start recording text into a different render
layer, call:
sdtx_layer(int layer_id)
...outside a sokol-gfx render pass.
--- finally, from within a sokol-gfx render pass, call:
sdtx_draw()
...for non-layered rendering, or to draw a specific layer:
sdtx_draw_layer(int layer_id)
NOTE that sdtx_draw() is equivalent to:
sdtx_draw_layer(0)
...so sdtx_draw() will *NOT* render all text layers, instead it will
only render the 'default layer' 0.
--- at the end of a frame (defined by the call to sg_commit()), sokol-debugtext
will rewind all contexts:
- the internal vertex index is set to 0
- the internal command index is set to 0
- the current layer id is set to 0
- the current font is set to 0
- the cursor position is reset
RENDERING WITH MULTIPLE CONTEXTS
================================
Use multiple text contexts if you need to render debug text in different
sokol-gfx render passes, or want to render text to different layers
in the same render pass, each with its own set of parameters.
To create a new text context call:
sdtx_context ctx = sdtx_make_context(&(sdtx_context_desc_t){ ... });
The creation parameters in the sdtx_context_desc_t struct are the same
as already described above in the sdtx_setup() function:
.char_buf_size -- max number of characters rendered in one frame, default: 4096
.canvas_width -- the initial virtual canvas width, default: 640
.canvas_height -- the initial virtual canvas height, default: 400
.tab_width -- tab width in number of characters, default: 4
.color_format -- color pixel format of target render pass
.depth_format -- depth pixel format of target render pass
.sample_count -- MSAA sample count of target render pass
To make a new context the active context, call:
sdtx_set_context(ctx)
...and after that call the text output functions as described above, and
finally, inside a sokol-gfx render pass, call sdtx_draw() to actually
render the text for this context.
A context keeps track of the following parameters:
- the active font
- the virtual canvas size
- the origin position
- the current cursor position
- the current tab width
- the current color
- and the current layer-id
You can get the currently active context with:
sdtx_get_context()
To make the default context current, call sdtx_set_context() with the
special SDTX_DEFAULT_CONTEXT handle:
sdtx_set_context(SDTX_DEFAULT_CONTEXT)
Alternatively, use the function sdtx_default_context() to get the default
context handle:
sdtx_set_context(sdtx_default_context());
To destroy a context, call:
sdtx_destroy_context(ctx)
If a context is set as active that no longer exists, all sokol-debugtext
functions that require an active context will silently fail.
You can directly draw the recorded text in a specific context without
setting the active context:
sdtx_context_draw(ctx)
sdtx_context_draw_layer(ctx, layer_id)
USING YOUR OWN FONT DATA
========================
Instead of the built-in fonts you can also plug your own font data
into sokol-debugtext by providing one or several sdtx_font_desc_t
structures in the sdtx_setup call.
For instance to use a built-in font at slot 0, and a user-font at
font slot 1, the sdtx_setup() call might look like this:
sdtx_setup(&sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = {
.data = {
.ptr = my_font_data,
.size = sizeof(my_font_data)
},
.first_char = ...,
.last_char = ...
}
}
});
Where 'my_font_data' is a byte array where every character is described
by 8 bytes arranged like this:
bits
7 6 5 4 3 2 1 0
. . . X X . . . byte 0: 0x18
. . X X X X . . byte 1: 0x3C
. X X . . X X . byte 2: 0x66
. X X . . X X . byte 3: 0x66
. X X X X X X . byte 4: 0x7E
. X X . . X X . byte 5: 0x66
. X X . . X X . byte 6: 0x66
. . . . . . . . byte 7: 0x00
A complete font consists of 256 characters, resulting in 2048 bytes for
the font data array (but note that the character codes 0..31 will never
be rendered).
If you provide such a complete font data array, you can drop the .first_char
and .last_char initialization parameters since those default to 0 and 255,
note that you can also use the SDTX_RANGE() helper macro to build the
.data item:
sdtx_setup(&sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = {
.data = SDTX_RANGE(my_font_data)
}
}
});
If the font doesn't define all 256 character tiles, or you don't need an
entire 256-character font and want to save a couple of bytes, use the
.first_char and .last_char initialization parameters to define a sub-range.
For instance if the font only contains the characters between the Space
(ASCII code 32) and uppercase character 'Z' (ASCII code 90):
sdtx_setup(&sdtx_desc_t){
.fonts = {
[0] = sdtx_font_kc853(),
[1] = {
.data = SDTX_RANGE(my_font_data),
.first_char = 32, // could also write ' '
.last_char = 90 // could also write 'Z'
}
}
});
Character tiles that haven't been defined in the font will be rendered
as a solid 8x8 quad.
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
sdtx_setup(&(sdtx_desc_t){
// ...
.allocator = {
.alloc_fn = my_alloc,
.free_fn = my_free,
.user_data = ...;
}
});
...
If no overrides are provided, malloc and free will be used.
ERROR REPORTING AND LOGGING
===========================
To get any logging information at all you need to provide a logging callback in the setup call,
the easiest way is to use sokol_log.h:
#include "sokol_log.h"
sdtx_setup(&(sdtx_desc_t){
// ...
.logger.func = slog_func
});
To override logging with your own callback, first write a logging function like this:
void my_log(const char* tag, // e.g. 'sdtx'
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
uint32_t log_item_id, // SDTX_LOGITEM_*
const char* message_or_null, // a message string, may be nullptr in release mode
uint32_t line_nr, // line number in sokol_debugtext.h
const char* filename_or_null, // source filename, may be nullptr in release mode
void* user_data)
{
...
}
...and then setup sokol-debugtext like this:
sdtx_setup(&(sdtx_desc_t){
.logger = {
.func = my_log,
.user_data = my_user_data,
}
});
The provided logging function must be reentrant (e.g. be callable from
different threads).
If you don't want to provide your own custom logger it is highly recommended to use
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
errors.
LICENSE
=======
zlib/libpng license
Copyright (c) 2020 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#import,dir "../gfx"(DEBUG = USE_DLL, USE_GL = USE_DLL, USE_DLL = USE_DLL);
sdtx_printf :: (s: string, args: ..Any) {
#import "Basic";
fstr := tprint(s, ..args);
sdtx_putr(to_c_string(fstr), xx fstr.count);
}
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_debugtext_clib :: #library "sokol_debugtext_windows_x64_gl_debug"; }
else { sokol_debugtext_clib :: #library "sokol_debugtext_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_debugtext_clib :: #library "sokol_debugtext_windows_x64_d3d11_debug"; }
else { sokol_debugtext_clib :: #library "sokol_debugtext_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_windows_x64_gl_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_windows_x64_d3d11_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_debugtext_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_arm64_gl_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_x64_gl_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_arm64_metal_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_x64_metal_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_linux_x64_gl_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_wasm_gl_debug"; }
else { sokol_debugtext_clib :: #library,no_dll "sokol_debugtext_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
// initialization/shutdown
sdtx_setup :: (desc: *sdtx_desc_t) -> void #foreign sokol_debugtext_clib;
sdtx_shutdown :: () -> void #foreign sokol_debugtext_clib;
// builtin font data (use to populate sdtx_desc.font[])
sdtx_font_kc853 :: () -> sdtx_font_desc_t #foreign sokol_debugtext_clib;
sdtx_font_kc854 :: () -> sdtx_font_desc_t #foreign sokol_debugtext_clib;
sdtx_font_z1013 :: () -> sdtx_font_desc_t #foreign sokol_debugtext_clib;
sdtx_font_cpc :: () -> sdtx_font_desc_t #foreign sokol_debugtext_clib;
sdtx_font_c64 :: () -> sdtx_font_desc_t #foreign sokol_debugtext_clib;
sdtx_font_oric :: () -> sdtx_font_desc_t #foreign sokol_debugtext_clib;
// context functions
sdtx_make_context :: (desc: *sdtx_context_desc_t) -> sdtx_context #foreign sokol_debugtext_clib;
sdtx_destroy_context :: (ctx: sdtx_context) -> void #foreign sokol_debugtext_clib;
sdtx_set_context :: (ctx: sdtx_context) -> void #foreign sokol_debugtext_clib;
sdtx_get_context :: () -> sdtx_context #foreign sokol_debugtext_clib;
sdtx_default_context :: () -> sdtx_context #foreign sokol_debugtext_clib;
// drawing functions (call inside sokol-gfx render pass)
sdtx_draw :: () -> void #foreign sokol_debugtext_clib;
sdtx_context_draw :: (ctx: sdtx_context) -> void #foreign sokol_debugtext_clib;
sdtx_draw_layer :: (layer_id: s32) -> void #foreign sokol_debugtext_clib;
sdtx_context_draw_layer :: (ctx: sdtx_context, layer_id: s32) -> void #foreign sokol_debugtext_clib;
// switch render layer
sdtx_layer :: (layer_id: s32) -> void #foreign sokol_debugtext_clib;
// switch to a different font
sdtx_font :: (font_index: s32) -> void #foreign sokol_debugtext_clib;
// set a new virtual canvas size in screen pixels
sdtx_canvas :: (w: float, h: float) -> void #foreign sokol_debugtext_clib;
// set a new origin in character grid coordinates
sdtx_origin :: (x: float, y: float) -> void #foreign sokol_debugtext_clib;
// cursor movement functions (relative to origin in character grid coordinates)
sdtx_home :: () -> void #foreign sokol_debugtext_clib;
sdtx_pos :: (x: float, y: float) -> void #foreign sokol_debugtext_clib;
sdtx_pos_x :: (x: float) -> void #foreign sokol_debugtext_clib;
sdtx_pos_y :: (y: float) -> void #foreign sokol_debugtext_clib;
sdtx_move :: (dx: float, dy: float) -> void #foreign sokol_debugtext_clib;
sdtx_move_x :: (dx: float) -> void #foreign sokol_debugtext_clib;
sdtx_move_y :: (dy: float) -> void #foreign sokol_debugtext_clib;
sdtx_crlf :: () -> void #foreign sokol_debugtext_clib;
// set the current text color
sdtx_color3b :: (r: u8, g: u8, b: u8) -> void #foreign sokol_debugtext_clib;
sdtx_color3f :: (r: float, g: float, b: float) -> void #foreign sokol_debugtext_clib;
sdtx_color4b :: (r: u8, g: u8, b: u8, a: u8) -> void #foreign sokol_debugtext_clib;
sdtx_color4f :: (r: float, g: float, b: float, a: float) -> void #foreign sokol_debugtext_clib;
sdtx_color1i :: (rgba: u32) -> void #foreign sokol_debugtext_clib;
// text rendering
sdtx_putc :: (c: u8) -> void #foreign sokol_debugtext_clib;
sdtx_puts :: (str: *u8) -> void #foreign sokol_debugtext_clib;
sdtx_putr :: (str: *u8, len: s32) -> void #foreign sokol_debugtext_clib;
sdtx_log_item_t :: enum u32 {
OK;
MALLOC_FAILED;
ADD_COMMIT_LISTENER_FAILED;
COMMAND_BUFFER_FULL;
CONTEXT_POOL_EXHAUSTED;
CANNOT_DESTROY_DEFAULT_CONTEXT;
}
sdtx_logger_t :: struct {
func : (a0: *u8, a1: u32, a2: u32, a3: *u8, a4: u32, a5: *u8, a6: *void) #c_call;
user_data : *void;
}
sdtx_context :: struct {
id : u32;
}
sdtx_range :: struct {
ptr : *void;
size : u64;
}
sdtx_font_desc_t :: struct {
data : sdtx_range;
first_char : u8;
last_char : u8;
}
sdtx_context_desc_t :: struct {
max_commands : s32;
char_buf_size : s32;
canvas_width : float;
canvas_height : float;
tab_width : s32;
color_format : sg_pixel_format;
depth_format : sg_pixel_format;
sample_count : s32;
}
sdtx_allocator_t :: struct {
alloc_fn : (a0: u64, a1: *void) -> *void #c_call;
free_fn : (a0: *void, a1: *void) #c_call;
user_data : *void;
}
sdtx_desc_t :: struct {
context_pool_size : s32;
printf_buf_size : s32;
fonts : [8]sdtx_font_desc_t;
ctx : sdtx_context_desc_t;
allocator : sdtx_allocator_t;
logger : sdtx_logger_t;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
// TODO: generate this automatically
// ----------------------------------------
STBTT_MACSTYLE_DONTCARE :: 0;
STBTT_MACSTYLE_BOLD :: 1;
STBTT_MACSTYLE_ITALIC :: 2;
STBTT_MACSTYLE_UNDERSCORE :: 4;
STBTT_MACSTYLE_NONE :: 8;
// private structure
stbtt__buf :: struct {
data: *u8;
cursor: s32;
size: s32;
}
//////////////////////////////////////////////////////////////////////////////
//
// TEXTURE BAKING API
//
// If you use this API, you only have to call two functions ever.
//
stbtt_bakedchar :: struct {
x0: u16; // coordinates of bbox in bitmap
y0: u16; // coordinates of bbox in bitmap
x1: u16; // coordinates of bbox in bitmap
y1: u16; // coordinates of bbox in bitmap
xoff: float;
yoff: float;
xadvance: float;
}
// if return is positive, the first unused row of the bitmap
// if return is negative, returns the negative of the number of characters that fit
// if return is 0, no characters fit and no rows were used
// This uses a very crappy packing.
stbtt_aligned_quad :: struct {
x0: float; // top-left
y0: float; // top-left
s0: float; // top-left
t0: float; // top-left
x1: float; // bottom-right
y1: float; // bottom-right
s1: float; // bottom-right
t1: float; // bottom-right
}
//////////////////////////////////////////////////////////////////////////////
//
// NEW TEXTURE BAKING API
//
// This provides options for packing multiple fonts into one atlas, not
// perfectly but better than nothing.
stbtt_packedchar :: struct {
x0: u16; // coordinates of bbox in bitmap
y0: u16; // coordinates of bbox in bitmap
x1: u16; // coordinates of bbox in bitmap
y1: u16; // coordinates of bbox in bitmap
xoff: float;
yoff: float;
xadvance: float;
xoff2: float;
yoff2: float;
}
// stbrp_rect :: struct {}
// Creates character bitmaps from the font_index'th font found in fontdata (use
// font_index=0 if you don't know what that is). It creates num_chars_in_range
// bitmaps for characters with unicode values starting at first_unicode_char_in_range
// and increasing. Data for how to render them is stored in chardata_for_range;
// pass these to stbtt_GetPackedQuad to get back renderable quads.
//
// font_size is the full height of the character from ascender to descender,
// as computed by stbtt_ScaleForPixelHeight. To use a point size as computed
// by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE()
// and pass that result as 'font_size':
// ..., 20 , ... // font max minus min y is 20 pixels tall
// ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall
stbtt_pack_range :: struct {
font_size: float;
first_unicode_codepoint_in_range: s32; // if non-zero, then the chars are continuous, and this is the first codepoint
array_of_unicode_codepoints: *s32; // if non-zero, then this is an array of unicode codepoints
num_chars: s32;
chardata_for_range: *stbtt_packedchar; // output
h_oversample: u8; // don't set these, they're used internally
v_oversample: u8; // don't set these, they're used internally
}
// this is an opaque structure that you shouldn't mess with which holds
// all the context needed from PackBegin to PackEnd.
stbtt_pack_context :: struct {
user_allocator_context: *void;
pack_info: *void;
width: s32;
height: s32;
stride_in_bytes: s32;
padding: s32;
skip_missing: s32;
h_oversample: u32;
v_oversample: u32;
pixels: *u8;
nodes: *void;
}
// The following structure is defined publicly so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque.
stbtt_fontinfo :: struct {
userdata: *void;
data: *u8; // pointer to .ttf file
fontstart: s32; // offset of start of font
numGlyphs: s32; // number of glyphs, needed for range checking
loca: s32; // table locations as offset from start of .ttf
head: s32; // table locations as offset from start of .ttf
glyf: s32; // table locations as offset from start of .ttf
hhea: s32; // table locations as offset from start of .ttf
hmtx: s32; // table locations as offset from start of .ttf
kern: s32; // table locations as offset from start of .ttf
gpos: s32; // table locations as offset from start of .ttf
svg: s32; // table locations as offset from start of .ttf
index_map: s32; // a cmap mapping for our chosen character encoding
indexToLocFormat: s32; // format needed to map from glyph index to glyph
cff: stbtt__buf; // cff font data
charstrings: stbtt__buf; // the charstring index
gsubrs: stbtt__buf; // global charstring subroutines index
subrs: stbtt__buf; // private charstring subroutines index
fontdicts: stbtt__buf; // array of font dicts
fdselect: stbtt__buf; // map from glyph to fontdict
}
// as above, but takes one or more glyph indices for greater efficiency
stbtt_kerningentry :: struct {
glyph1: s32; // use stbtt_FindGlyphIndex
glyph2: s32;
advance: s32;
}
STBTT :: enum u32 {
vmove :: 1;
vline :: 2;
vcurve :: 3;
vcubic :: 4;
STBTT_vmove :: vmove;
STBTT_vline :: vline;
STBTT_vcurve :: vcurve;
STBTT_vcubic :: vcubic;
}
stbtt_vertex :: struct {
x: s16;
y: s16;
cx: s16;
cy: s16;
cx1: s16;
cy1: s16;
type: u8;
padding: u8;
}
// @TODO: don't expose this structure
stbtt__bitmap :: struct {
w: s32;
h: s32;
stride: s32;
pixels: *u8;
}
// returns the string (which may be big-endian double byte, e.g. for unicode)
// and puts the length in bytes in *length.
//
// some of the values for the IDs are below; for more see the truetype spec:
// http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html
// http://www.microsoft.com/typography/otspec/name.htm
STBTT_PLATFORM_ID :: enum u32 {
UNICODE :: 0;
MAC :: 1;
ISO :: 2;
MICROSOFT :: 3;
STBTT_PLATFORM_ID_UNICODE :: UNICODE;
STBTT_PLATFORM_ID_MAC :: MAC;
STBTT_PLATFORM_ID_ISO :: ISO;
STBTT_PLATFORM_ID_MICROSOFT :: MICROSOFT;
}
STBTT_UNICODE_EID :: enum u32 {
UNICODE_1_0 :: 0;
UNICODE_1_1 :: 1;
ISO_10646 :: 2;
UNICODE_2_0_BMP :: 3;
UNICODE_2_0_FULL :: 4;
STBTT_UNICODE_EID_UNICODE_1_0 :: UNICODE_1_0;
STBTT_UNICODE_EID_UNICODE_1_1 :: UNICODE_1_1;
STBTT_UNICODE_EID_ISO_10646 :: ISO_10646;
STBTT_UNICODE_EID_UNICODE_2_0_BMP :: UNICODE_2_0_BMP;
STBTT_UNICODE_EID_UNICODE_2_0_FULL :: UNICODE_2_0_FULL;
}
STBTT_MS_EID :: enum u32 {
SYMBOL :: 0;
UNICODE_BMP :: 1;
SHIFTJIS :: 2;
UNICODE_FULL :: 10;
STBTT_MS_EID_SYMBOL :: SYMBOL;
STBTT_MS_EID_UNICODE_BMP :: UNICODE_BMP;
STBTT_MS_EID_SHIFTJIS :: SHIFTJIS;
STBTT_MS_EID_UNICODE_FULL :: UNICODE_FULL;
}
STBTT_MAC_EID :: enum u32 {
ROMAN :: 0;
ARABIC :: 4;
JAPANESE :: 1;
HEBREW :: 5;
CHINESE_TRAD :: 2;
GREEK :: 6;
KOREAN :: 3;
RUSSIAN :: 7;
STBTT_MAC_EID_ROMAN :: ROMAN;
STBTT_MAC_EID_ARABIC :: ARABIC;
STBTT_MAC_EID_JAPANESE :: JAPANESE;
STBTT_MAC_EID_HEBREW :: HEBREW;
STBTT_MAC_EID_CHINESE_TRAD :: CHINESE_TRAD;
STBTT_MAC_EID_GREEK :: GREEK;
STBTT_MAC_EID_KOREAN :: KOREAN;
STBTT_MAC_EID_RUSSIAN :: RUSSIAN;
}
STBTT_MS_LANG :: enum u32 {
ENGLISH :: 1033;
ITALIAN :: 1040;
CHINESE :: 2052;
JAPANESE :: 1041;
DUTCH :: 1043;
KOREAN :: 1042;
FRENCH :: 1036;
RUSSIAN :: 1049;
GERMAN :: 1031;
SPANISH :: 1033;
HEBREW :: 1037;
SWEDISH :: 1053;
STBTT_MS_LANG_ENGLISH :: ENGLISH;
STBTT_MS_LANG_ITALIAN :: ITALIAN;
STBTT_MS_LANG_CHINESE :: CHINESE;
STBTT_MS_LANG_JAPANESE :: JAPANESE;
STBTT_MS_LANG_DUTCH :: DUTCH;
STBTT_MS_LANG_KOREAN :: KOREAN;
STBTT_MS_LANG_FRENCH :: FRENCH;
STBTT_MS_LANG_RUSSIAN :: RUSSIAN;
STBTT_MS_LANG_GERMAN :: GERMAN;
STBTT_MS_LANG_SPANISH :: SPANISH;
STBTT_MS_LANG_HEBREW :: HEBREW;
STBTT_MS_LANG_SWEDISH :: SWEDISH;
}
STBTT_MAC_LANG :: enum u32 {
ENGLISH :: 0;
JAPANESE :: 11;
ARABIC :: 12;
KOREAN :: 23;
DUTCH :: 4;
RUSSIAN :: 32;
FRENCH :: 1;
SPANISH :: 6;
GERMAN :: 2;
SWEDISH :: 5;
HEBREW :: 10;
CHINESE_SIMPLIFIED :: 33;
ITALIAN :: 3;
CHINESE_TRAD :: 19;
STBTT_MAC_LANG_ENGLISH :: ENGLISH;
STBTT_MAC_LANG_JAPANESE :: JAPANESE;
STBTT_MAC_LANG_ARABIC :: ARABIC;
STBTT_MAC_LANG_KOREAN :: KOREAN;
STBTT_MAC_LANG_DUTCH :: DUTCH;
STBTT_MAC_LANG_RUSSIAN :: RUSSIAN;
STBTT_MAC_LANG_FRENCH :: FRENCH;
STBTT_MAC_LANG_SPANISH :: SPANISH;
STBTT_MAC_LANG_GERMAN :: GERMAN;
STBTT_MAC_LANG_SWEDISH :: SWEDISH;
STBTT_MAC_LANG_HEBREW :: HEBREW;
STBTT_MAC_LANG_CHINESE_SIMPLIFIED :: CHINESE_SIMPLIFIED;
STBTT_MAC_LANG_ITALIAN :: ITALIAN;
STBTT_MAC_LANG_CHINESE_TRAD :: CHINESE_TRAD;
}
// ----------------------------------------
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_fontstash_clib :: #library "sokol_fontstash_windows_x64_gl_debug"; }
else { sokol_fontstash_clib :: #library "sokol_fontstash_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_fontstash_clib :: #library "sokol_fontstash_windows_x64_d3d11_debug"; }
else { sokol_fontstash_clib :: #library "sokol_fontstash_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_windows_x64_gl_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_windows_x64_d3d11_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_fontstash_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_arm64_gl_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_x64_gl_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_arm64_metal_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_x64_metal_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#system_library,link_always "m";
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_linux_x64_gl_debug"; }
sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_linux_x64_gl_release";
} else #if OS == .WASM {
#if DEBUG { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_wasm_gl_debug"; }
else { sokol_fontstash_clib :: #library,no_dll "sokol_fontstash_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
sfons_allocator_t :: struct {
alloc_fn : (a0: u64, a1: *void) -> *void #c_call;
free_fn : (a0: *void, a1: *void) #c_call;
user_data : *void;
}
sfons_desc_t :: struct {
width: s32; // initial width of font atlas texture (default: 512, must be power of 2)
height: s32; // initial height of font atlas texture (default: 512, must be power of 2)
allocator: sfons_allocator_t; // optional memory allocation overrides
}
FONS_VERTEX_COUNT :: 1024;
FONS_MAX_STATES :: 20;
FONS_MAX_FALLBACKS :: 20;
FONS_HASH_LUT_SIZE :: 256;
FONSparams :: struct {
width, height: s32;
flags: u8;
userPtr: *void;
renderCreate: (uptr: *void, width: s32, height: s32) -> s32;
renderResize: (uptr: *void, width: s32, height: s32) -> s32;
renderUpdate: (uptr: *void, rect: *s32, data: *u8) -> void;
renderDraw: (uptr: *void, verts: *float, tcoords: *float, colors: *s32, nverts: s32) -> void;
renderDelete: (uptr: *void) -> void;
}
FONSglyph :: struct {
codepoint: u32;
index: s32;
next: s32;
size, blur: s16;
x0,y0,x1,y1: s16;
xadv,xoff,yoff: s16;
}
FONSttFontImpl :: struct {
font: stbtt_fontinfo;
}
FONSfont :: struct {
font: FONSttFontImpl;
name: [64]u8;
data: *u8;
dataSize: s32;
freeData: u8;
ascender: float;
descender: float;
lineh: float;
glyphs: *FONSglyph;
cglyphs: s32;
nglyphs: s32;
lut: [FONS_HASH_LUT_SIZE]s32;
fallbacks: [FONS_MAX_FALLBACKS]s32;
nfallbacks: s32;
}
FONScontext :: struct {
params: FONSparams;
itw,ith: float;
texData: *u8;
dirtyRect: [4]s32;
fonts: **FONSfont;
atlas: *FONSatlas;
cfonts: s32;
nfonts: s32;
verts: [FONS_VERTEX_COUNT*2]float;
tcoords: [FONS_VERTEX_COUNT*2]float;
colors: [FONS_VERTEX_COUNT]u32;
nverts: s32;
scratch: *u8;
nscratch: s32;
states: [FONS_MAX_STATES]FONSstate;
nstates: s32;
handleError: (uptr: *void, error: s32, val: s32) -> *void;
errorUptr: *void;
}
FONSstate :: struct {
font: s32;
align: s32;
size: float;
color: u32;
blur: float;
spacing: float;
}
FONSatlasNode :: struct {
x, y, width: s16;
}
FONSatlas :: struct
{
width, height: s32;
nodes: *FONSatlasNode;
nnodes: s32;
cnodes: s32;
}
using FONSalign :: enum {
// Horizontal align
FONS_ALIGN_LEFT :: 1<<0; // Default
FONS_ALIGN_CENTER :: 1<<1;
FONS_ALIGN_RIGHT :: 1<<2;
// Vertical align
FONS_ALIGN_TOP :: 1<<3;
FONS_ALIGN_MIDDLE :: 1<<4;
FONS_ALIGN_BOTTOM :: 1<<5;
FONS_ALIGN_BASELINE :: 1<<6; // Default
}
FONS_INVALID :: -1;
sfons_create :: (desc: *sfons_desc_t) -> *FONScontext #foreign sokol_fontstash_clib;
sfons_destroy :: (ctx: *FONScontext) -> void #foreign sokol_fontstash_clib;
sfons_flush :: (ctx: *FONScontext) -> void #foreign sokol_fontstash_clib;
sfons_rgba :: (r: u8, g: u8, b: u8, a: u8) -> u32 #foreign sokol_fontstash_clib;
// Contructor and destructor.
fonsCreateInternal :: (params: *FONSparams) -> *FONScontext #foreign sokol_fontstash_clib;
fonsDeleteInternal :: (s: *FONScontext) -> void #foreign sokol_fontstash_clib;
fonsSetErrorCallback :: (s: *FONScontext, callback: #type (uptr: *void, error: s32, val: s32) -> void #c_call, uptr: *void) -> void #foreign sokol_fontstash_clib;
// Returns current atlas size.
fonsGetAtlasSize :: (s: *FONScontext, width: *s32, height: *s32) -> void #foreign sokol_fontstash_clib;
// Expands the atlas size.
fonsExpandAtlas :: (s: *FONScontext, width: s32, height: s32) -> s32 #foreign sokol_fontstash_clib;
// Resets the whole stash.
fonsResetAtlas :: (stash: *FONScontext, width: s32, height: s32) -> s32 #foreign sokol_fontstash_clib;
// Add fonts
fonsAddFont :: (s: *FONScontext, name: *u8, path: *u8) -> s32 #foreign sokol_fontstash_clib;
fonsAddFontMem :: (s: *FONScontext, name: *u8, data: *u8, ndata: s32, freeData: s32) -> s32 #foreign sokol_fontstash_clib;
fonsGetFontByName :: (s: *FONScontext, name: *u8) -> s32 #foreign sokol_fontstash_clib;
fonsAddFallbackFont :: (stash: *FONScontext, base: s32, fallback: s32) -> s32 #foreign sokol_fontstash_clib;
// State handling
fonsPushState :: (s: *FONScontext) -> void #foreign sokol_fontstash_clib;
fonsPopState :: (s: *FONScontext) -> void #foreign sokol_fontstash_clib;
fonsClearState :: (s: *FONScontext) -> void #foreign sokol_fontstash_clib;
// State setting
fonsSetSize :: (s: *FONScontext, size: float) -> void #foreign sokol_fontstash_clib;
fonsSetColor :: (s: *FONScontext, color: u32) -> void #foreign sokol_fontstash_clib;
fonsSetSpacing :: (s: *FONScontext, spacing: float) -> void #foreign sokol_fontstash_clib;
fonsSetBlur :: (s: *FONScontext, blur: float) -> void #foreign sokol_fontstash_clib;
fonsSetAlign :: (s: *FONScontext, align: s32) -> void #foreign sokol_fontstash_clib;
fonsSetFont :: (s: *FONScontext, font: s32) -> void #foreign sokol_fontstash_clib;
// Draw text
fonsDrawText :: (s: *FONScontext, x: float, y: float, _string: *u8, end: *u8) -> float #foreign sokol_fontstash_clib;
// Measure text
fonsTextBounds :: (s: *FONScontext, x: float, y: float, _string: *u8, end: *u8, bounds: *float) -> float #foreign sokol_fontstash_clib;
fonsLineBounds :: (s: *FONScontext, y: float, miny: *float, maxy: *float) -> void #foreign sokol_fontstash_clib;
fonsVertMetrics :: (s: *FONScontext, ascender: *float, descender: *float, lineh: *float) -> void #foreign sokol_fontstash_clib;
// Text iterator
// fonsTextIterInit :: (stash: *FONScontext, iter: *FONStextIter, x: float, y: float, str: *u8, end: *u8) -> s32 #foreign sokol_fontstash_clib;
// fonsTextIterNext :: (stash: *FONScontext, iter: *FONStextIter, quad: *FONSquad) -> s32 #foreign sokol_fontstash_clib;
// Pull texture changes
fonsGetTextureData :: (stash: *FONScontext, width: *s32, height: *s32) -> *u8 #foreign sokol_fontstash_clib;
fonsValidateTexture :: (s: *FONScontext, dirty: *s32) -> s32 #foreign sokol_fontstash_clib;
// Draws the stash texture for debugging
fonsDrawDebug :: (s: *FONScontext, x: float, y: float) -> void #foreign sokol_fontstash_clib;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,924 @@
// machine generated, do not edit
/*
sokol_gl.h -- OpenGL 1.x style rendering on top of sokol_gfx.h
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_GL_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
The following defines are used by the implementation to select the
platform-specific embedded shader code (these are the same defines as
used by sokol_gfx.h and sokol_app.h):
SOKOL_GLCORE
SOKOL_GLES3
SOKOL_D3D11
SOKOL_METAL
SOKOL_WGPU
...optionally provide the following macros to override defaults:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_GL_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GL_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
If sokol_gl.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_GL_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
Include the following headers before including sokol_gl.h:
sokol_gfx.h
Matrix functions have been taken from MESA and Regal.
FEATURE OVERVIEW:
=================
sokol_gl.h implements a subset of the OpenGLES 1.x feature set useful for
when you just want to quickly render a bunch of triangles or
lines without having to mess with buffers and shaders.
The current feature set is mostly useful for debug visualizations
and simple UI-style 2D rendering:
What's implemented:
- vertex components:
- position (x, y, z)
- 2D texture coords (u, v)
- color (r, g, b, a)
- primitive types:
- triangle list and strip
- line list and strip
- quad list (TODO: quad strips)
- point list
- one texture layer (no multi-texturing)
- viewport and scissor-rect with selectable origin (top-left or bottom-left)
- all GL 1.x matrix stack functions, and additionally equivalent
functions for gluPerspective and gluLookat
Notable GLES 1.x features that are *NOT* implemented:
- vertex lighting (this is the most likely GL feature that might be added later)
- vertex arrays (although providing whole chunks of vertex data at once
might be a useful feature for a later version)
- texture coordinate generation
- line width
- all pixel store functions
- no ALPHA_TEST
- no clear functions (clearing is handled by the sokol-gfx render pass)
- fog
Notable differences to GL:
- No "enum soup" for render states etc, instead there's a
'pipeline stack', this is similar to GL's matrix stack,
but for pipeline-state-objects. The pipeline object at
the top of the pipeline stack defines the active set of render states
- All angles are in radians, not degrees (note the sgl_rad() and
sgl_deg() conversion functions)
- No enable/disable state for scissor test, this is always enabled
STEP BY STEP:
=============
--- To initialize sokol-gl, call:
sgl_setup(const sgl_desc_t* desc)
NOTE that sgl_setup() must be called *after* initializing sokol-gfx
(via sg_setup). This is because sgl_setup() needs to create
sokol-gfx resource objects.
If you're intending to render to the default pass, and also don't
want to tweak memory usage, and don't want any logging output you can
just keep sgl_desc_t zero-initialized:
sgl_setup(&(sgl_desc_t*){ 0 });
In this case, sokol-gl will create internal sg_pipeline objects that
are compatible with the sokol-app default framebuffer.
I would recommend to at least install a logging callback so that
you'll see any warnings and errors. The easiest way is through
sokol_log.h:
#include "sokol_log.h"
sgl_setup(&(sgl_desc_t){
.logger.func = slog_func.
});
If you want to render into a framebuffer with different pixel-format
and MSAA attributes you need to provide the matching attributes in the
sgl_setup() call:
sgl_setup(&(sgl_desc_t*){
.color_format = SG_PIXELFORMAT_...,
.depth_format = SG_PIXELFORMAT_...,
.sample_count = ...,
});
To reduce memory usage, or if you need to create more then the default number of
contexts, pipelines, vertices or draw commands, set the following sgl_desc_t
members:
.context_pool_size (default: 4)
.pipeline_pool_size (default: 64)
.max_vertices (default: 64k)
.max_commands (default: 16k)
Finally you can change the face winding for front-facing triangles
and quads:
.face_winding - default is SG_FACEWINDING_CCW
The default winding for front faces is counter-clock-wise. This is
the same as OpenGL's default, but different from sokol-gfx.
--- Optionally create additional context objects if you want to render into
multiple sokol-gfx render passes (or generally if you want to
use multiple independent sokol-gl "state buckets")
sgl_context ctx = sgl_make_context(const sgl_context_desc_t* desc)
For details on rendering with sokol-gl contexts, search below for
WORKING WITH CONTEXTS.
--- Optionally create pipeline-state-objects if you need render state
that differs from sokol-gl's default state:
sgl_pipeline pip = sgl_make_pipeline(const sg_pipeline_desc* desc)
...this creates a pipeline object that's compatible with the currently
active context, alternatively call:
sgl_pipeline_pip = sgl_context_make_pipeline(sgl_context ctx, const sg_pipeline_desc* desc)
...to create a pipeline object that's compatible with an explicitly
provided context.
The similarity with sokol_gfx.h's sg_pipeline type and sg_make_pipeline()
function is intended. sgl_make_pipeline() also takes a standard
sokol-gfx sg_pipeline_desc object to describe the render state, but
without:
- shader
- vertex layout
- color- and depth-pixel-formats
- primitive type (lines, triangles, ...)
- MSAA sample count
Those will be filled in by sgl_make_pipeline(). Note that each
call to sgl_make_pipeline() needs to create several sokol-gfx
pipeline objects (one for each primitive type).
'depth.write_enabled' will be forced to 'false' if the context this
pipeline object is intended for has its depth pixel format set to
SG_PIXELFORMAT_NONE (which means the framebuffer this context is used
with doesn't have a depth-stencil surface).
--- if you need to destroy sgl_pipeline objects before sgl_shutdown():
sgl_destroy_pipeline(sgl_pipeline pip)
--- After sgl_setup() you can call any of the sokol-gl functions anywhere
in a frame, *except* sgl_draw(). The 'vanilla' functions
will only change internal sokol-gl state, and not call any sokol-gfx
functions.
--- Unlike OpenGL, sokol-gl has a function to reset internal state to
a known default. This is useful at the start of a sequence of
rendering operations:
void sgl_defaults(void)
This will set the following default state:
- current texture coordinate to u=0.0f, v=0.0f
- current color to white (rgba all 1.0f)
- current point size to 1.0f
- unbind the current texture and texturing will be disabled
- *all* matrices will be set to identity (also the projection matrix)
- the default render state will be set by loading the 'default pipeline'
into the top of the pipeline stack
The current matrix- and pipeline-stack-depths will not be changed by
sgl_defaults().
--- change the currently active renderstate through the
pipeline-stack functions, this works similar to the
traditional GL matrix stack:
...load the default pipeline state on the top of the pipeline stack:
sgl_load_default_pipeline()
...load a specific pipeline on the top of the pipeline stack:
sgl_load_pipeline(sgl_pipeline pip)
...push and pop the pipeline stack:
sgl_push_pipeline()
sgl_pop_pipeline()
--- control texturing with:
sgl_enable_texture()
sgl_disable_texture()
sgl_texture(sg_image img, sg_sampler smp)
NOTE: the img and smp handles can be invalid (SG_INVALID_ID), in this
case, sokol-gl will fall back to the internal default (white) texture
and sampler.
--- set the current viewport and scissor rect with:
sgl_viewport(int x, int y, int w, int h, bool origin_top_left)
sgl_scissor_rect(int x, int y, int w, int h, bool origin_top_left)
...or call these alternatives which take float arguments (this might allow
to avoid casting between float and integer in more strongly typed languages
when floating point pixel coordinates are used):
sgl_viewportf(float x, float y, float w, float h, bool origin_top_left)
sgl_scissor_rectf(float x, float y, float w, float h, bool origin_top_left)
...these calls add a new command to the internal command queue, so
that the viewport or scissor rect are set at the right time relative
to other sokol-gl calls.
--- adjust the transform matrices, matrix manipulation works just like
the OpenGL matrix stack:
...set the current matrix mode:
sgl_matrix_mode_modelview()
sgl_matrix_mode_projection()
sgl_matrix_mode_texture()
...load the identity matrix into the current matrix:
sgl_load_identity()
...translate, rotate and scale the current matrix:
sgl_translate(float x, float y, float z)
sgl_rotate(float angle_rad, float x, float y, float z)
sgl_scale(float x, float y, float z)
NOTE that all angles in sokol-gl are in radians, not in degree.
Convert between radians and degree with the helper functions:
float sgl_rad(float deg) - degrees to radians
float sgl_deg(float rad) - radians to degrees
...directly load the current matrix from a float[16] array:
sgl_load_matrix(const float m[16])
sgl_load_transpose_matrix(const float m[16])
...directly multiply the current matrix from a float[16] array:
sgl_mult_matrix(const float m[16])
sgl_mult_transpose_matrix(const float m[16])
The memory layout of those float[16] arrays is the same as in OpenGL.
...more matrix functions:
sgl_frustum(float left, float right, float bottom, float top, float near, float far)
sgl_ortho(float left, float right, float bottom, float top, float near, float far)
sgl_perspective(float fov_y, float aspect, float near, float far)
sgl_lookat(float eye_x, float eye_y, float eye_z, float center_x, float center_y, float center_z, float up_x, float up_y, float up_z)
These functions work the same as glFrustum(), glOrtho(), gluPerspective()
and gluLookAt().
...and finally to push / pop the current matrix stack:
sgl_push_matrix(void)
sgl_pop_matrix(void)
Again, these work the same as glPushMatrix() and glPopMatrix().
--- perform primitive rendering:
...set the current texture coordinate and color 'registers' with or
point size with:
sgl_t2f(float u, float v) - set current texture coordinate
sgl_c*(...) - set current color
sgl_point_size(float size) - set current point size
There are several functions for setting the color (as float values,
unsigned byte values, packed as unsigned 32-bit integer, with
and without alpha).
NOTE that these are the only functions that can be called both inside
sgl_begin_*() / sgl_end() and outside.
Also NOTE that point size is currently hardwired to 1.0f if the D3D11
backend is used.
...start a primitive vertex sequence with:
sgl_begin_points()
sgl_begin_lines()
sgl_begin_line_strip()
sgl_begin_triangles()
sgl_begin_triangle_strip()
sgl_begin_quads()
...after sgl_begin_*() specify vertices:
sgl_v*(...)
sgl_v*_t*(...)
sgl_v*_c*(...)
sgl_v*_t*_c*(...)
These functions write a new vertex to sokol-gl's internal vertex buffer,
optionally with texture-coords and color. If the texture coordinate
and/or color is missing, it will be taken from the current texture-coord
and color 'register'.
...finally, after specifying vertices, call:
sgl_end()
This will record a new draw command in sokol-gl's internal command
list, or it will extend the previous draw command if no relevant
state has changed since the last sgl_begin/end pair.
--- inside a sokol-gfx rendering pass, call the sgl_draw() function
to render the currently active context:
sgl_draw()
...or alternatively call:
sgl_context_draw(ctx)
...to render an explicitly provided context.
This will render everything that has been recorded in the context since
the last call to sgl_draw() through sokol-gfx, and will 'rewind' the internal
vertex-, uniform- and command-buffers.
--- each sokol-gl context tracks internal error states which can
be obtains via:
sgl_error_t sgl_error()
...alternatively with an explicit context argument:
sgl_error_t sgl_context_error(ctx);
...this returns a struct with the following booleans:
.any - true if any of the below errors is true
.vertices_full - internal vertex buffer is full (checked in sgl_end())
.uniforms_full - the internal uniforms buffer is full (checked in sgl_end())
.commands_full - the internal command buffer is full (checked in sgl_end())
.stack_overflow - matrix- or pipeline-stack overflow
.stack_underflow - matrix- or pipeline-stack underflow
.no_context - the active context no longer exists
...depending on the above error state, sgl_draw() may skip rendering
completely, or only draw partial geometry
--- you can get the number of recorded vertices and draw commands in the current
frame and active sokol-gl context via:
int sgl_num_vertices()
int sgl_num_commands()
...this allows you to check whether the vertex or command pools are running
full before the overflow actually happens (in this case you could also
check the error booleans in the result of sgl_error()).
RENDER LAYERS
=============
Render layers allow to split sokol-gl rendering into separate draw-command
groups which can then be rendered separately in a sokol-gfx draw pass. This
allows to mix/interleave sokol-gl rendering with other render operations.
Layered rendering is controlled through two functions:
sgl_layer(int layer_id)
sgl_draw_layer(int layer_id)
(and the context-variant sgl_draw_layer(): sgl_context_draw_layer()
The sgl_layer() function sets the 'current layer', any sokol-gl calls
which internally record draw commands will also store the current layer
in the draw command, and later in a sokol-gfx render pass, a call
to sgl_draw_layer() will only render the draw commands that have
a matching layer.
The default layer is '0', this is active after sokol-gl setup, and
is also restored at the start of a new frame (but *not* by calling
sgl_defaults()).
NOTE that calling sgl_draw() is equivalent with sgl_draw_layer(0)
(in general you should either use either use sgl_draw() or
sgl_draw_layer() in an application, but not both).
WORKING WITH CONTEXTS:
======================
If you want to render to more than one sokol-gfx render pass you need to
work with additional sokol-gl context objects (one context object for
each offscreen rendering pass, in addition to the implicitly created
'default context'.
All sokol-gl state is tracked per context, and there is always a "current
context" (with the notable exception that the currently set context is
destroyed, more on that later).
Using multiple contexts can also be useful if you only render in
a single pass, but want to maintain multiple independent "state buckets".
To create new context object, call:
sgl_context ctx = sgl_make_context(&(sgl_context_desc){
.max_vertices = ..., // default: 64k
.max_commands = ..., // default: 16k
.color_format = ...,
.depth_format = ...,
.sample_count = ...,
});
The color_format, depth_format and sample_count items must be compatible
with the render pass the sgl_draw() or sgL_context_draw() function
will be called in.
Creating a context does *not* make the context current. To do this, call:
sgl_set_context(ctx);
The currently active context will implicitly be used by most sokol-gl functions
which don't take an explicit context handle as argument.
To switch back to the default context, pass the global constant SGL_DEFAULT_CONTEXT:
sgl_set_context(SGL_DEFAULT_CONTEXT);
...or alternatively use the function sgl_default_context() instead of the
global constant:
sgl_set_context(sgl_default_context());
To get the currently active context, call:
sgl_context cur_ctx = sgl_get_context();
The following functions exist in two variants, one which use the currently
active context (set with sgl_set_context()), and another version which
takes an explicit context handle instead:
sgl_make_pipeline() vs sgl_context_make_pipeline()
sgl_error() vs sgl_context_error();
sgl_draw() vs sgl_context_draw();
Except for using the currently active context versus a provided context
handle, the two variants are exactlyidentical, e.g. the following
code sequences do the same thing:
sgl_set_context(ctx);
sgl_pipeline pip = sgl_make_pipeline(...);
sgl_error_t err = sgl_error();
sgl_draw();
vs
sgl_pipeline pip = sgl_context_make_pipeline(ctx, ...);
sgl_error_t err = sgl_context_error(ctx);
sgl_context_draw(ctx);
Destroying the currently active context is a 'soft error'. All following
calls which require a currently active context will silently fail,
and sgl_error() will return SGL_ERROR_NO_CONTEXT.
UNDER THE HOOD:
===============
sokol_gl.h works by recording vertex data and rendering commands into
memory buffers, and then drawing the recorded commands via sokol_gfx.h
The only functions which call into sokol_gfx.h are:
- sgl_setup()
- sgl_shutdown()
- sgl_draw() (and variants)
sgl_setup() must be called after initializing sokol-gfx.
sgl_shutdown() must be called before shutting down sokol-gfx.
sgl_draw() must be called once per frame inside a sokol-gfx render pass.
All other sokol-gl function can be called anywhere in a frame, since
they just record data into memory buffers owned by sokol-gl.
What happens in:
sgl_setup():
Unique resources shared by all contexts are created:
- a shader object (using embedded shader source or byte code)
- an 8x8 white default texture
The default context is created, which involves:
- 3 memory buffers are created, one for vertex data,
one for uniform data, and one for commands
- a dynamic vertex buffer is created
- the default sgl_pipeline object is created, which involves
creating 5 sg_pipeline objects
One vertex is 24 bytes:
- float3 position
- float2 texture coords
- uint32_t color
One uniform block is 128 bytes:
- mat4 model-view-projection matrix
- mat4 texture matrix
One draw command is ca. 24 bytes for the actual
command code plus command arguments.
Each sgl_end() consumes one command, and one uniform block
(only when the matrices have changed).
The required size for one sgl_begin/end pair is (at most):
(152 + 24 * num_verts) bytes
sgl_shutdown():
- all sokol-gfx resources (buffer, shader, default-texture and
all pipeline objects) are destroyed
- the 3 memory buffers are freed
sgl_draw() (and variants)
- copy all recorded vertex data into the dynamic sokol-gfx buffer
via a call to sg_update_buffer()
- for each recorded command:
- if the layer number stored in the command doesn't match
the layer that's to be rendered, skip to the next
command
- if it's a viewport command, call sg_apply_viewport()
- if it's a scissor-rect command, call sg_apply_scissor_rect()
- if it's a draw command:
- depending on what has changed since the last draw command,
call sg_apply_pipeline(), sg_apply_bindings() and
sg_apply_uniforms()
- finally call sg_draw()
All other functions only modify the internally tracked state, add
data to the vertex, uniform and command buffers, or manipulate
the matrix stack.
ON DRAW COMMAND MERGING
=======================
Not every call to sgl_end() will automatically record a new draw command.
If possible, the previous draw command will simply be extended,
resulting in fewer actual draw calls later in sgl_draw().
A draw command will be merged with the previous command if "no relevant
state has changed" since the last sgl_end(), meaning:
- no calls to sgl_viewport() and sgl_scissor_rect()
- the primitive type hasn't changed
- the primitive type isn't a 'strip type' (no line or triangle strip)
- the pipeline state object hasn't changed
- the current layer hasn't changed
- none of the matrices has changed
- none of the texture state has changed
Merging a draw command simply means that the number of vertices
to render in the previous draw command will be incremented by the
number of vertices in the new draw command.
MEMORY ALLOCATION OVERRIDE
==========================
You can override the memory allocation functions at initialization time
like this:
void* my_alloc(size_t size, void* user_data) {
return malloc(size);
}
void my_free(void* ptr, void* user_data) {
free(ptr);
}
...
sgl_setup(&(sgl_desc_t){
// ...
.allocator = {
.alloc_fn = my_alloc,
.free_fn = my_free,
.user_data = ...;
}
});
...
If no overrides are provided, malloc and free will be used.
ERROR REPORTING AND LOGGING
===========================
To get any logging information at all you need to provide a logging callback in the setup call,
the easiest way is to use sokol_log.h:
#include "sokol_log.h"
sgl_setup(&(sgl_desc_t){
// ...
.logger.func = slog_func
});
To override logging with your own callback, first write a logging function like this:
void my_log(const char* tag, // e.g. 'sgl'
uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
uint32_t log_item_id, // SGL_LOGITEM_*
const char* message_or_null, // a message string, may be nullptr in release mode
uint32_t line_nr, // line number in sokol_gl.h
const char* filename_or_null, // source filename, may be nullptr in release mode
void* user_data)
{
...
}
...and then setup sokol-gl like this:
sgl_setup(&(sgl_desc_t){
.logger = {
.func = my_log,
.user_data = my_user_data,
}
});
The provided logging function must be reentrant (e.g. be callable from
different threads).
If you don't want to provide your own custom logger it is highly recommended to use
the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
errors.
LICENSE
=======
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#import,dir "../gfx"(DEBUG = USE_DLL, USE_GL = USE_DLL, USE_DLL = USE_DLL);
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_gl_clib :: #library "sokol_gl_windows_x64_gl_debug"; }
else { sokol_gl_clib :: #library "sokol_gl_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_gl_clib :: #library "sokol_gl_windows_x64_d3d11_debug"; }
else { sokol_gl_clib :: #library "sokol_gl_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_windows_x64_gl_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_windows_x64_d3d11_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_gl_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_arm64_gl_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_x64_gl_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_arm64_metal_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_x64_metal_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_linux_x64_gl_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_gl_clib :: #library,no_dll "sokol_gl_wasm_gl_debug"; }
else { sokol_gl_clib :: #library,no_dll "sokol_gl_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
// setup/shutdown/misc
sgl_setup :: (desc: *sgl_desc_t) -> void #foreign sokol_gl_clib;
sgl_shutdown :: () -> void #foreign sokol_gl_clib;
sgl_rad :: (deg: float) -> float #foreign sokol_gl_clib;
sgl_deg :: (rad: float) -> float #foreign sokol_gl_clib;
sgl_error :: () -> sgl_error_t #foreign sokol_gl_clib;
sgl_context_error :: (ctx: sgl_context) -> sgl_error_t #foreign sokol_gl_clib;
// context functions
sgl_make_context :: (desc: *sgl_context_desc_t) -> sgl_context #foreign sokol_gl_clib;
sgl_destroy_context :: (ctx: sgl_context) -> void #foreign sokol_gl_clib;
sgl_set_context :: (ctx: sgl_context) -> void #foreign sokol_gl_clib;
sgl_get_context :: () -> sgl_context #foreign sokol_gl_clib;
sgl_default_context :: () -> sgl_context #foreign sokol_gl_clib;
// get information about recorded vertices and commands in current context
sgl_num_vertices :: () -> s32 #foreign sokol_gl_clib;
sgl_num_commands :: () -> s32 #foreign sokol_gl_clib;
// draw recorded commands (call inside a sokol-gfx render pass)
sgl_draw :: () -> void #foreign sokol_gl_clib;
sgl_context_draw :: (ctx: sgl_context) -> void #foreign sokol_gl_clib;
sgl_draw_layer :: (layer_id: s32) -> void #foreign sokol_gl_clib;
sgl_context_draw_layer :: (ctx: sgl_context, layer_id: s32) -> void #foreign sokol_gl_clib;
// create and destroy pipeline objects
sgl_make_pipeline :: (desc: *sg_pipeline_desc) -> sgl_pipeline #foreign sokol_gl_clib;
sgl_context_make_pipeline :: (ctx: sgl_context, desc: *sg_pipeline_desc) -> sgl_pipeline #foreign sokol_gl_clib;
sgl_destroy_pipeline :: (pip: sgl_pipeline) -> void #foreign sokol_gl_clib;
// render state functions
sgl_defaults :: () -> void #foreign sokol_gl_clib;
sgl_viewport :: (x: s32, y: s32, w: s32, h: s32, origin_top_left: bool) -> void #foreign sokol_gl_clib;
sgl_viewportf :: (x: float, y: float, w: float, h: float, origin_top_left: bool) -> void #foreign sokol_gl_clib;
sgl_scissor_rect :: (x: s32, y: s32, w: s32, h: s32, origin_top_left: bool) -> void #foreign sokol_gl_clib;
sgl_scissor_rectf :: (x: float, y: float, w: float, h: float, origin_top_left: bool) -> void #foreign sokol_gl_clib;
sgl_enable_texture :: () -> void #foreign sokol_gl_clib;
sgl_disable_texture :: () -> void #foreign sokol_gl_clib;
sgl_texture :: (img: sg_image, smp: sg_sampler) -> void #foreign sokol_gl_clib;
sgl_layer :: (layer_id: s32) -> void #foreign sokol_gl_clib;
// pipeline stack functions
sgl_load_default_pipeline :: () -> void #foreign sokol_gl_clib;
sgl_load_pipeline :: (pip: sgl_pipeline) -> void #foreign sokol_gl_clib;
sgl_push_pipeline :: () -> void #foreign sokol_gl_clib;
sgl_pop_pipeline :: () -> void #foreign sokol_gl_clib;
// matrix stack functions
sgl_matrix_mode_modelview :: () -> void #foreign sokol_gl_clib;
sgl_matrix_mode_projection :: () -> void #foreign sokol_gl_clib;
sgl_matrix_mode_texture :: () -> void #foreign sokol_gl_clib;
sgl_load_identity :: () -> void #foreign sokol_gl_clib;
sgl_load_matrix :: (m: *float) -> void #foreign sokol_gl_clib;
sgl_load_transpose_matrix :: (m: *float) -> void #foreign sokol_gl_clib;
sgl_mult_matrix :: (m: *float) -> void #foreign sokol_gl_clib;
sgl_mult_transpose_matrix :: (m: *float) -> void #foreign sokol_gl_clib;
sgl_rotate :: (angle_rad: float, x: float, y: float, z: float) -> void #foreign sokol_gl_clib;
sgl_scale :: (x: float, y: float, z: float) -> void #foreign sokol_gl_clib;
sgl_translate :: (x: float, y: float, z: float) -> void #foreign sokol_gl_clib;
sgl_frustum :: (l: float, r: float, b: float, t: float, n: float, f: float) -> void #foreign sokol_gl_clib;
sgl_ortho :: (l: float, r: float, b: float, t: float, n: float, f: float) -> void #foreign sokol_gl_clib;
sgl_perspective :: (fov_y: float, aspect: float, z_near: float, z_far: float) -> void #foreign sokol_gl_clib;
sgl_lookat :: (eye_x: float, eye_y: float, eye_z: float, center_x: float, center_y: float, center_z: float, up_x: float, up_y: float, up_z: float) -> void #foreign sokol_gl_clib;
sgl_push_matrix :: () -> void #foreign sokol_gl_clib;
sgl_pop_matrix :: () -> void #foreign sokol_gl_clib;
// these functions only set the internal 'current texcoord / color / point size' (valid inside or outside begin/end)
sgl_t2f :: (u: float, v: float) -> void #foreign sokol_gl_clib;
sgl_c3f :: (r: float, g: float, b: float) -> void #foreign sokol_gl_clib;
sgl_c4f :: (r: float, g: float, b: float, a: float) -> void #foreign sokol_gl_clib;
sgl_c3b :: (r: u8, g: u8, b: u8) -> void #foreign sokol_gl_clib;
sgl_c4b :: (r: u8, g: u8, b: u8, a: u8) -> void #foreign sokol_gl_clib;
sgl_c1i :: (rgba: u32) -> void #foreign sokol_gl_clib;
sgl_point_size :: (s: float) -> void #foreign sokol_gl_clib;
// define primitives, each begin/end is one draw command
sgl_begin_points :: () -> void #foreign sokol_gl_clib;
sgl_begin_lines :: () -> void #foreign sokol_gl_clib;
sgl_begin_line_strip :: () -> void #foreign sokol_gl_clib;
sgl_begin_triangles :: () -> void #foreign sokol_gl_clib;
sgl_begin_triangle_strip :: () -> void #foreign sokol_gl_clib;
sgl_begin_quads :: () -> void #foreign sokol_gl_clib;
sgl_v2f :: (x: float, y: float) -> void #foreign sokol_gl_clib;
sgl_v3f :: (x: float, y: float, z: float) -> void #foreign sokol_gl_clib;
sgl_v2f_t2f :: (x: float, y: float, u: float, v: float) -> void #foreign sokol_gl_clib;
sgl_v3f_t2f :: (x: float, y: float, z: float, u: float, v: float) -> void #foreign sokol_gl_clib;
sgl_v2f_c3f :: (x: float, y: float, r: float, g: float, b: float) -> void #foreign sokol_gl_clib;
sgl_v2f_c3b :: (x: float, y: float, r: u8, g: u8, b: u8) -> void #foreign sokol_gl_clib;
sgl_v2f_c4f :: (x: float, y: float, r: float, g: float, b: float, a: float) -> void #foreign sokol_gl_clib;
sgl_v2f_c4b :: (x: float, y: float, r: u8, g: u8, b: u8, a: u8) -> void #foreign sokol_gl_clib;
sgl_v2f_c1i :: (x: float, y: float, rgba: u32) -> void #foreign sokol_gl_clib;
sgl_v3f_c3f :: (x: float, y: float, z: float, r: float, g: float, b: float) -> void #foreign sokol_gl_clib;
sgl_v3f_c3b :: (x: float, y: float, z: float, r: u8, g: u8, b: u8) -> void #foreign sokol_gl_clib;
sgl_v3f_c4f :: (x: float, y: float, z: float, r: float, g: float, b: float, a: float) -> void #foreign sokol_gl_clib;
sgl_v3f_c4b :: (x: float, y: float, z: float, r: u8, g: u8, b: u8, a: u8) -> void #foreign sokol_gl_clib;
sgl_v3f_c1i :: (x: float, y: float, z: float, rgba: u32) -> void #foreign sokol_gl_clib;
sgl_v2f_t2f_c3f :: (x: float, y: float, u: float, v: float, r: float, g: float, b: float) -> void #foreign sokol_gl_clib;
sgl_v2f_t2f_c3b :: (x: float, y: float, u: float, v: float, r: u8, g: u8, b: u8) -> void #foreign sokol_gl_clib;
sgl_v2f_t2f_c4f :: (x: float, y: float, u: float, v: float, r: float, g: float, b: float, a: float) -> void #foreign sokol_gl_clib;
sgl_v2f_t2f_c4b :: (x: float, y: float, u: float, v: float, r: u8, g: u8, b: u8, a: u8) -> void #foreign sokol_gl_clib;
sgl_v2f_t2f_c1i :: (x: float, y: float, u: float, v: float, rgba: u32) -> void #foreign sokol_gl_clib;
sgl_v3f_t2f_c3f :: (x: float, y: float, z: float, u: float, v: float, r: float, g: float, b: float) -> void #foreign sokol_gl_clib;
sgl_v3f_t2f_c3b :: (x: float, y: float, z: float, u: float, v: float, r: u8, g: u8, b: u8) -> void #foreign sokol_gl_clib;
sgl_v3f_t2f_c4f :: (x: float, y: float, z: float, u: float, v: float, r: float, g: float, b: float, a: float) -> void #foreign sokol_gl_clib;
sgl_v3f_t2f_c4b :: (x: float, y: float, z: float, u: float, v: float, r: u8, g: u8, b: u8, a: u8) -> void #foreign sokol_gl_clib;
sgl_v3f_t2f_c1i :: (x: float, y: float, z: float, u: float, v: float, rgba: u32) -> void #foreign sokol_gl_clib;
sgl_end :: () -> void #foreign sokol_gl_clib;
sgl_log_item_t :: enum u32 {
OK;
MALLOC_FAILED;
MAKE_PIPELINE_FAILED;
PIPELINE_POOL_EXHAUSTED;
ADD_COMMIT_LISTENER_FAILED;
CONTEXT_POOL_EXHAUSTED;
CANNOT_DESTROY_DEFAULT_CONTEXT;
}
sgl_logger_t :: struct {
func : (a0: *u8, a1: u32, a2: u32, a3: *u8, a4: u32, a5: *u8, a6: *void) #c_call;
user_data : *void;
}
sgl_pipeline :: struct {
id : u32;
}
sgl_context :: struct {
id : u32;
}
sgl_error_t :: struct {
any : bool;
vertices_full : bool;
uniforms_full : bool;
commands_full : bool;
stack_overflow : bool;
stack_underflow : bool;
no_context : bool;
}
sgl_context_desc_t :: struct {
max_vertices : s32;
max_commands : s32;
color_format : sg_pixel_format;
depth_format : sg_pixel_format;
sample_count : s32;
}
sgl_allocator_t :: struct {
alloc_fn : (a0: u64, a1: *void) -> *void #c_call;
free_fn : (a0: *void, a1: *void) #c_call;
user_data : *void;
}
sgl_desc_t :: struct {
max_vertices : s32;
max_commands : s32;
context_pool_size : s32;
pipeline_pool_size : s32;
color_format : sg_pixel_format;
depth_format : sg_pixel_format;
sample_count : s32;
face_winding : sg_face_winding;
allocator : sgl_allocator_t;
logger : sgl_logger_t;
}

View File

@ -0,0 +1,155 @@
// machine generated, do not edit
/*
sokol_glue.h -- glue helper functions for sokol headers
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_GLUE_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
...optionally provide the following macros to override defaults:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_GLUE_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GLUE_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
If sokol_glue.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_GLUE_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
OVERVIEW
========
sokol_glue.h provides glue helper functions between sokol_gfx.h and sokol_app.h,
so that sokol_gfx.h doesn't need to depend on sokol_app.h but can be
used with different window system glue libraries.
PROVIDED FUNCTIONS
==================
sg_environment sglue_environment(void)
Returns an sg_environment struct initialized by calling sokol_app.h
functions. Use this in the sg_setup() call like this:
sg_setup(&(sg_desc){
.environment = sglue_environment(),
...
});
sg_swapchain sglue_swapchain(void)
Returns an sg_swapchain struct initialized by calling sokol_app.h
functions. Use this in sg_begin_pass() for a 'swapchain pass' like
this:
sg_begin_pass(&(sg_pass){ .swapchain = sglue_swapchain(), ... });
LICENSE
=======
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#import,dir "../gfx"(DEBUG = USE_DLL, USE_GL = USE_DLL, USE_DLL = USE_DLL);
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_glue_clib :: #library "sokol_glue_windows_x64_gl_debug"; }
else { sokol_glue_clib :: #library "sokol_glue_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_glue_clib :: #library "sokol_glue_windows_x64_d3d11_debug"; }
else { sokol_glue_clib :: #library "sokol_glue_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_windows_x64_gl_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_windows_x64_d3d11_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_glue_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_arm64_gl_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_x64_gl_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_arm64_metal_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_x64_metal_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_linux_x64_gl_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_glue_clib :: #library,no_dll "sokol_glue_wasm_gl_debug"; }
else { sokol_glue_clib :: #library,no_dll "sokol_glue_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
sglue_environment :: () -> sg_environment #foreign sokol_glue_clib;
sglue_swapchain :: () -> sg_swapchain #foreign sokol_glue_clib;

View File

@ -0,0 +1,184 @@
// machine generated, do not edit
/*
sokol_log.h -- common logging callback for sokol headers
Project URL: https://github.com/floooh/sokol
Example code: https://github.com/floooh/sokol-samples
Do this:
#define SOKOL_IMPL or
#define SOKOL_LOG_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Optionally provide the following defines when building the implementation:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
SOKOL_LOG_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_GFX_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
Optionally define the following for verbose output:
SOKOL_DEBUG - by default this is defined if _DEBUG is defined
OVERVIEW
========
sokol_log.h provides a default logging callback for other sokol headers.
To use the default log callback, just include sokol_log.h and provide
a function pointer to the 'slog_func' function when setting up the
sokol library:
For instance with sokol_audio.h:
#include "sokol_log.h"
...
saudio_setup(&(saudio_desc){ .logger.func = slog_func });
Logging output goes to stderr and/or a platform specific logging subsystem
(which means that in some scenarios you might see logging messages duplicated):
- Windows: stderr + OutputDebugStringA()
- macOS/iOS/Linux: stderr + syslog()
- Emscripten: console.info()/warn()/error()
- Android: __android_log_write()
On Windows with sokol_app.h also note the runtime config items to make
stdout/stderr output visible on the console for WinMain() applications
via sapp_desc.win32_console_attach or sapp_desc.win32_console_create,
however when running in a debugger on Windows, the logging output should
show up on the debug output UI panel.
In debug mode, a log message might look like this:
[sspine][error][id:12] /Users/floh/projects/sokol/util/sokol_spine.h:3472:0:
SKELETON_DESC_NO_ATLAS: no atlas object provided in sspine_skeleton_desc.atlas
The source path and line number is formatted like compiler errors, in some IDEs (like VSCode)
such error messages are clickable.
In release mode, logging is less verbose as to not bloat the executable with string data, but you still get
enough information to identify the type and location of an error:
[sspine][error][id:12][line:3472]
RULES FOR WRITING YOUR OWN LOGGING FUNCTION
===========================================
- must be re-entrant because it might be called from different threads
- must treat **all** provided string pointers as optional (can be null)
- don't store the string pointers, copy the string data instead
- must not return for log level panic
LICENSE
=======
zlib/libpng license
Copyright (c) 2023 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_log_clib :: #library "sokol_log_windows_x64_gl_debug"; }
else { sokol_log_clib :: #library "sokol_log_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_log_clib :: #library "sokol_log_windows_x64_d3d11_debug"; }
else { sokol_log_clib :: #library "sokol_log_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_windows_x64_gl_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_windows_x64_d3d11_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_log_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_macos_arm64_gl_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_macos_x64_gl_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_macos_arm64_metal_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_macos_x64_metal_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_linux_x64_gl_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_log_clib :: #library,no_dll "sokol_log_wasm_gl_debug"; }
else { sokol_log_clib :: #library,no_dll "sokol_log_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
/*
Plug this function into the 'logger.func' struct item when initializing any of the sokol
headers. For instance for sokol_audio.h it would look like this:
saudio_setup(&(saudio_desc){
.logger = {
.func = slog_func
}
});
*/
slog_func :: (tag: *u8, log_level: u32, log_item: u32, message: *u8, line_nr: u32, filename: *u8, user_data: *void) -> void #foreign sokol_log_clib;

View File

@ -0,0 +1,560 @@
// machine generated, do not edit
/*
sokol_shape.h -- create simple primitive shapes for sokol_gfx.h
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_SHAPE_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Include the following headers before including sokol_shape.h:
sokol_gfx.h
...optionally provide the following macros to override defaults:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_SHAPE_API_DECL- public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_SHAPE_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
If sokol_shape.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_SHAPE_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
FEATURE OVERVIEW
================
sokol_shape.h creates vertices and indices for simple shapes and
builds structs which can be plugged into sokol-gfx resource
creation functions:
The following shape types are supported:
- plane
- cube
- sphere (with poles, not geodesic)
- cylinder
- torus (donut)
Generated vertices look like this:
typedef struct sshape_vertex_t {
float x, y, z;
uint32_t normal; // packed normal as BYTE4N
uint16_t u, v; // packed uv coords as USHORT2N
uint32_t color; // packed color as UBYTE4N (r,g,b,a);
} sshape_vertex_t;
Indices are generally 16-bits wide (SG_INDEXTYPE_UINT16) and the indices
are written as triangle-lists (SG_PRIMITIVETYPE_TRIANGLES).
EXAMPLES:
=========
Create multiple shapes into the same vertex- and index-buffer and
render with separate draw calls:
https://github.com/floooh/sokol-samples/blob/master/sapp/shapes-sapp.c
Same as the above, but pre-transform shapes and merge them into a single
shape that's rendered with a single draw call.
https://github.com/floooh/sokol-samples/blob/master/sapp/shapes-transform-sapp.c
STEP-BY-STEP:
=============
Setup an sshape_buffer_t struct with pointers to memory buffers where
generated vertices and indices will be written to:
```c
sshape_vertex_t vertices[512];
uint16_t indices[4096];
sshape_buffer_t buf = {
.vertices = {
.buffer = SSHAPE_RANGE(vertices),
},
.indices = {
.buffer = SSHAPE_RANGE(indices),
}
};
```
To find out how big those memory buffers must be (in case you want
to allocate dynamically) call the following functions:
```c
sshape_sizes_t sshape_plane_sizes(uint32_t tiles);
sshape_sizes_t sshape_box_sizes(uint32_t tiles);
sshape_sizes_t sshape_sphere_sizes(uint32_t slices, uint32_t stacks);
sshape_sizes_t sshape_cylinder_sizes(uint32_t slices, uint32_t stacks);
sshape_sizes_t sshape_torus_sizes(uint32_t sides, uint32_t rings);
```
The returned sshape_sizes_t struct contains vertex- and index-counts
as well as the equivalent buffer sizes in bytes. For instance:
```c
sshape_sizes_t sizes = sshape_sphere_sizes(36, 12);
uint32_t num_vertices = sizes.vertices.num;
uint32_t num_indices = sizes.indices.num;
uint32_t vertex_buffer_size = sizes.vertices.size;
uint32_t index_buffer_size = sizes.indices.size;
```
With the sshape_buffer_t struct that was setup earlier, call any
of the shape-builder functions:
```c
sshape_buffer_t sshape_build_plane(const sshape_buffer_t* buf, const sshape_plane_t* params);
sshape_buffer_t sshape_build_box(const sshape_buffer_t* buf, const sshape_box_t* params);
sshape_buffer_t sshape_build_sphere(const sshape_buffer_t* buf, const sshape_sphere_t* params);
sshape_buffer_t sshape_build_cylinder(const sshape_buffer_t* buf, const sshape_cylinder_t* params);
sshape_buffer_t sshape_build_torus(const sshape_buffer_t* buf, const sshape_torus_t* params);
```
Note how the sshape_buffer_t struct is both an input value and the
return value. This can be used to append multiple shapes into the
same vertex- and index-buffers (more on this later).
The second argument is a struct which holds creation parameters.
For instance to build a sphere with radius 2, 36 "cake slices" and 12 stacks:
```c
sshape_buffer_t buf = ...;
buf = sshape_build_sphere(&buf, &(sshape_sphere_t){
.radius = 2.0f,
.slices = 36,
.stacks = 12,
});
```
If the provided buffers are big enough to hold all generated vertices and
indices, the "valid" field in the result will be true:
```c
assert(buf.valid);
```
The shape creation parameters have "useful defaults", refer to the
actual C struct declarations below to look up those defaults.
You can also provide additional creation parameters, like a common vertex
color, a debug-helper to randomize colors, tell the shape builder function
to merge the new shape with the previous shape into the same draw-element-range,
or a 4x4 transform matrix to move, rotate and scale the generated vertices:
```c
sshape_buffer_t buf = ...;
buf = sshape_build_sphere(&buf, &(sshape_sphere_t){
.radius = 2.0f,
.slices = 36,
.stacks = 12,
// merge with previous shape into a single element-range
.merge = true,
// set vertex color to red+opaque
.color = sshape_color_4f(1.0f, 0.0f, 0.0f, 1.0f),
// set position to y = 2.0
.transform = {
.m = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 2.0f, 0.0f, 1.0f },
}
}
});
assert(buf.valid);
```
The following helper functions can be used to build a packed
color value or to convert from external matrix types:
```c
uint32_t sshape_color_4f(float r, float g, float b, float a);
uint32_t sshape_color_3f(float r, float g, float b);
uint32_t sshape_color_4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
uint32_t sshape_color_3b(uint8_t r, uint8_t g, uint8_t b);
sshape_mat4_t sshape_mat4(const float m[16]);
sshape_mat4_t sshape_mat4_transpose(const float m[16]);
```
After the shape builder function has been called, the following functions
are used to extract the build result for plugging into sokol_gfx.h:
```c
sshape_element_range_t sshape_element_range(const sshape_buffer_t* buf);
sg_buffer_desc sshape_vertex_buffer_desc(const sshape_buffer_t* buf);
sg_buffer_desc sshape_index_buffer_desc(const sshape_buffer_t* buf);
sg_vertex_buffer_layout_state sshape_vertex_buffer_layout_state(void);
sg_vertex_attr_state sshape_position_vertex_attr_state(void);
sg_vertex_attr_state sshape_normal_vertex_attr_state(void);
sg_vertex_attr_state sshape_texcoord_vertex_attr_state(void);
sg_vertex_attr_state sshape_color_vertex_attr_state(void);
```
The sshape_element_range_t struct contains the base-index and number of
indices which can be plugged into the sg_draw() call:
```c
sshape_element_range_t elms = sshape_element_range(&buf);
...
sg_draw(elms.base_element, elms.num_elements, 1);
```
To create sokol-gfx vertex- and index-buffers from the generated
shape data:
```c
// create sokol-gfx vertex buffer
sg_buffer_desc vbuf_desc = sshape_vertex_buffer_desc(&buf);
sg_buffer vbuf = sg_make_buffer(&vbuf_desc);
// create sokol-gfx index buffer
sg_buffer_desc ibuf_desc = sshape_index_buffer_desc(&buf);
sg_buffer ibuf = sg_make_buffer(&ibuf_desc);
```
The remaining functions are used to populate the vertex-layout item
in sg_pipeline_desc, note that these functions don't depend on the
created geometry, they always return the same result:
```c
sg_pipeline pip = sg_make_pipeline(&(sg_pipeline_desc){
.layout = {
.buffers[0] = sshape_vertex_buffer_layout_state(),
.attrs = {
[0] = sshape_position_vertex_attr_state(),
[1] = ssape_normal_vertex_attr_state(),
[2] = sshape_texcoord_vertex_attr_state(),
[3] = sshape_color_vertex_attr_state()
}
},
...
});
```
Note that you don't have to use all generated vertex attributes in the
pipeline's vertex layout, the sg_vertex_buffer_layout_state struct returned
by sshape_vertex_buffer_layout_state() contains the correct vertex stride
to skip vertex components.
WRITING MULTIPLE SHAPES INTO THE SAME BUFFER
============================================
You can merge multiple shapes into the same vertex- and
index-buffers and either render them as a single shape, or
in separate draw calls.
To build a single shape made of two cubes which can be rendered
in a single draw-call:
```
sshape_vertex_t vertices[128];
uint16_t indices[16];
sshape_buffer_t buf = {
.vertices.buffer = SSHAPE_RANGE(vertices),
.indices.buffer = SSHAPE_RANGE(indices)
};
// first cube at pos x=-2.0 (with default size of 1x1x1)
buf = sshape_build_cube(&buf, &(sshape_box_t){
.transform = {
.m = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{-2.0f, 0.0f, 0.0f, 1.0f },
}
}
});
// ...and append another cube at pos pos=+1.0
// NOTE the .merge = true, this tells the shape builder
// function to not advance the current shape start offset
buf = sshape_build_cube(&buf, &(sshape_box_t){
.merge = true,
.transform = {
.m = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{-2.0f, 0.0f, 0.0f, 1.0f },
}
}
});
assert(buf.valid);
// skipping buffer- and pipeline-creation...
sshape_element_range_t elms = sshape_element_range(&buf);
sg_draw(elms.base_element, elms.num_elements, 1);
```
To render the two cubes in separate draw-calls, the element-ranges used
in the sg_draw() calls must be captured right after calling the
builder-functions:
```c
sshape_vertex_t vertices[128];
uint16_t indices[16];
sshape_buffer_t buf = {
.vertices.buffer = SSHAPE_RANGE(vertices),
.indices.buffer = SSHAPE_RANGE(indices)
};
// build a red cube...
buf = sshape_build_cube(&buf, &(sshape_box_t){
.color = sshape_color_3b(255, 0, 0)
});
sshape_element_range_t red_cube = sshape_element_range(&buf);
// append a green cube to the same vertex-/index-buffer:
buf = sshape_build_cube(&bud, &sshape_box_t){
.color = sshape_color_3b(0, 255, 0);
});
sshape_element_range_t green_cube = sshape_element_range(&buf);
// skipping buffer- and pipeline-creation...
sg_draw(red_cube.base_element, red_cube.num_elements, 1);
sg_draw(green_cube.base_element, green_cube.num_elements, 1);
```
...that's about all :)
LICENSE
=======
zlib/libpng license
Copyright (c) 2020 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#import,dir "../gfx"(DEBUG = USE_DLL, USE_GL = USE_DLL, USE_DLL = USE_DLL);
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_shape_clib :: #library "sokol_shape_windows_x64_gl_debug"; }
else { sokol_shape_clib :: #library "sokol_shape_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_shape_clib :: #library "sokol_shape_windows_x64_d3d11_debug"; }
else { sokol_shape_clib :: #library "sokol_shape_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_windows_x64_gl_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_windows_x64_d3d11_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_shape_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_arm64_gl_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_x64_gl_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_arm64_metal_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_x64_metal_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_linux_x64_gl_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_shape_clib :: #library,no_dll "sokol_shape_wasm_gl_debug"; }
else { sokol_shape_clib :: #library,no_dll "sokol_shape_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
// shape builder functions
sshape_build_plane :: (buf: *sshape_buffer_t, params: *sshape_plane_t) -> sshape_buffer_t #foreign sokol_shape_clib;
sshape_build_box :: (buf: *sshape_buffer_t, params: *sshape_box_t) -> sshape_buffer_t #foreign sokol_shape_clib;
sshape_build_sphere :: (buf: *sshape_buffer_t, params: *sshape_sphere_t) -> sshape_buffer_t #foreign sokol_shape_clib;
sshape_build_cylinder :: (buf: *sshape_buffer_t, params: *sshape_cylinder_t) -> sshape_buffer_t #foreign sokol_shape_clib;
sshape_build_torus :: (buf: *sshape_buffer_t, params: *sshape_torus_t) -> sshape_buffer_t #foreign sokol_shape_clib;
// query required vertex- and index-buffer sizes in bytes
sshape_plane_sizes :: (tiles: u32) -> sshape_sizes_t #foreign sokol_shape_clib;
sshape_box_sizes :: (tiles: u32) -> sshape_sizes_t #foreign sokol_shape_clib;
sshape_sphere_sizes :: (slices: u32, stacks: u32) -> sshape_sizes_t #foreign sokol_shape_clib;
sshape_cylinder_sizes :: (slices: u32, stacks: u32) -> sshape_sizes_t #foreign sokol_shape_clib;
sshape_torus_sizes :: (sides: u32, rings: u32) -> sshape_sizes_t #foreign sokol_shape_clib;
// extract sokol-gfx desc structs and primitive ranges from build state
sshape_element_range :: (buf: *sshape_buffer_t) -> sshape_element_range_t #foreign sokol_shape_clib;
sshape_vertex_buffer_desc :: (buf: *sshape_buffer_t) -> sg_buffer_desc #foreign sokol_shape_clib;
sshape_index_buffer_desc :: (buf: *sshape_buffer_t) -> sg_buffer_desc #foreign sokol_shape_clib;
sshape_vertex_buffer_layout_state :: () -> sg_vertex_buffer_layout_state #foreign sokol_shape_clib;
sshape_position_vertex_attr_state :: () -> sg_vertex_attr_state #foreign sokol_shape_clib;
sshape_normal_vertex_attr_state :: () -> sg_vertex_attr_state #foreign sokol_shape_clib;
sshape_texcoord_vertex_attr_state :: () -> sg_vertex_attr_state #foreign sokol_shape_clib;
sshape_color_vertex_attr_state :: () -> sg_vertex_attr_state #foreign sokol_shape_clib;
// helper functions to build packed color value from floats or bytes
sshape_color_4f :: (r: float, g: float, b: float, a: float) -> u32 #foreign sokol_shape_clib;
sshape_color_3f :: (r: float, g: float, b: float) -> u32 #foreign sokol_shape_clib;
sshape_color_4b :: (r: u8, g: u8, b: u8, a: u8) -> u32 #foreign sokol_shape_clib;
sshape_color_3b :: (r: u8, g: u8, b: u8) -> u32 #foreign sokol_shape_clib;
// adapter function for filling matrix struct from generic float[16] array
sshape_mat4 :: (m: *float) -> sshape_mat4_t #foreign sokol_shape_clib;
sshape_mat4_transpose :: (m: *float) -> sshape_mat4_t #foreign sokol_shape_clib;
sshape_range :: struct {
ptr : *void;
size : u64;
}
sshape_mat4_t :: struct {
m : [4][4]float;
}
sshape_vertex_t :: struct {
x : float;
y : float;
z : float;
normal : u32;
u : u16;
v : u16;
color : u32;
}
sshape_element_range_t :: struct {
base_element : s32;
num_elements : s32;
}
sshape_sizes_item_t :: struct {
num : u32;
size : u32;
}
sshape_sizes_t :: struct {
vertices : sshape_sizes_item_t;
indices : sshape_sizes_item_t;
}
sshape_buffer_item_t :: struct {
buffer : sshape_range;
data_size : u64;
shape_offset : u64;
}
sshape_buffer_t :: struct {
valid : bool;
vertices : sshape_buffer_item_t;
indices : sshape_buffer_item_t;
}
sshape_plane_t :: struct {
width : float;
depth : float;
tiles : u16;
color : u32;
random_colors : bool;
merge : bool;
transform : sshape_mat4_t;
}
sshape_box_t :: struct {
width : float;
height : float;
depth : float;
tiles : u16;
color : u32;
random_colors : bool;
merge : bool;
transform : sshape_mat4_t;
}
sshape_sphere_t :: struct {
radius : float;
slices : u16;
stacks : u16;
color : u32;
random_colors : bool;
merge : bool;
transform : sshape_mat4_t;
}
sshape_cylinder_t :: struct {
radius : float;
height : float;
slices : u16;
stacks : u16;
color : u32;
random_colors : bool;
merge : bool;
transform : sshape_mat4_t;
}
sshape_torus_t :: struct {
radius : float;
ring_radius : float;
sides : u16;
rings : u16;
color : u32;
random_colors : bool;
merge : bool;
transform : sshape_mat4_t;
}

View File

@ -0,0 +1,187 @@
// machine generated, do not edit
/*
sokol_time.h -- simple cross-platform time measurement
Project URL: https://github.com/floooh/sokol
Do this:
#define SOKOL_IMPL or
#define SOKOL_TIME_IMPL
before you include this file in *one* C or C++ file to create the
implementation.
Optionally provide the following defines with your own implementations:
SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
SOKOL_TIME_API_DECL - public function declaration prefix (default: extern)
SOKOL_API_DECL - same as SOKOL_TIME_API_DECL
SOKOL_API_IMPL - public function implementation prefix (default: -)
If sokol_time.h is compiled as a DLL, define the following before
including the declaration or implementation:
SOKOL_DLL
On Windows, SOKOL_DLL will define SOKOL_TIME_API_DECL as __declspec(dllexport)
or __declspec(dllimport) as needed.
void stm_setup();
Call once before any other functions to initialize sokol_time
(this calls for instance QueryPerformanceFrequency on Windows)
uint64_t stm_now();
Get current point in time in unspecified 'ticks'. The value that
is returned has no relation to the 'wall-clock' time and is
not in a specific time unit, it is only useful to compute
time differences.
uint64_t stm_diff(uint64_t new, uint64_t old);
Computes the time difference between new and old. This will always
return a positive, non-zero value.
uint64_t stm_since(uint64_t start);
Takes the current time, and returns the elapsed time since start
(this is a shortcut for "stm_diff(stm_now(), start)")
uint64_t stm_laptime(uint64_t* last_time);
This is useful for measuring frame time and other recurring
events. It takes the current time, returns the time difference
to the value in last_time, and stores the current time in
last_time for the next call. If the value in last_time is 0,
the return value will be zero (this usually happens on the
very first call).
uint64_t stm_round_to_common_refresh_rate(uint64_t duration)
This oddly named function takes a measured frame time and
returns the closest "nearby" common display refresh rate frame duration
in ticks. If the input duration isn't close to any common display
refresh rate, the input duration will be returned unchanged as a fallback.
The main purpose of this function is to remove jitter/inaccuracies from
measured frame times, and instead use the display refresh rate as
frame duration.
NOTE: for more robust frame timing, consider using the
sokol_app.h function sapp_frame_duration()
Use the following functions to convert a duration in ticks into
useful time units:
double stm_sec(uint64_t ticks);
double stm_ms(uint64_t ticks);
double stm_us(uint64_t ticks);
double stm_ns(uint64_t ticks);
Converts a tick value into seconds, milliseconds, microseconds
or nanoseconds. Note that not all platforms will have nanosecond
or even microsecond precision.
Uses the following time measurement functions under the hood:
Windows: QueryPerformanceFrequency() / QueryPerformanceCounter()
MacOS/iOS: mach_absolute_time()
emscripten: emscripten_get_now()
Linux+others: clock_gettime(CLOCK_MONOTONIC)
zlib/libpng license
Copyright (c) 2018 Andre Weissflog
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#module_parameters(DEBUG := false, USE_GL := false, USE_DLL := false);
#scope_export;
#if OS == .WINDOWS {
#if USE_DLL {
#if USE_GL {
#if DEBUG { sokol_time_clib :: #library "sokol_time_windows_x64_gl_debug"; }
else { sokol_time_clib :: #library "sokol_time_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_time_clib :: #library "sokol_time_windows_x64_d3d11_debug"; }
else { sokol_time_clib :: #library "sokol_time_windows_x64_d3d11_release"; }
}
} else {
#if USE_GL {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_windows_x64_gl_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_windows_x64_gl_release"; }
} else {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_windows_x64_d3d11_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_windows_x64_d3d11_release"; }
}
}
}
else #if OS == .MACOS {
#if USE_DLL {
#if USE_GL && CPU == .ARM64 && DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_debug.dylib"; }
else #if USE_GL && CPU == .ARM64 && !DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_arm64_gl_release.dylib"; }
else #if USE_GL && CPU == .X64 && DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_debug.dylib"; }
else #if USE_GL && CPU == .X64 && !DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_x64_gl_release.dylib"; }
else #if !USE_GL && CPU == .ARM64 && DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .ARM64 && !DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_arm64_metal_release.dylib"; }
else #if !USE_GL && CPU == .X64 && DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_debug.dylib"; }
else #if !USE_GL && CPU == .X64 && !DEBUG { sokol_time_clib :: #library "../dylib/sokol_dylib_macos_x64_metal_release.dylib"; }
} else {
#if USE_GL {
#if CPU == .ARM64 {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_macos_arm64_gl_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_macos_arm64_gl_release"; }
} else {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_macos_x64_gl_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_macos_x64_gl_release"; }
}
} else {
#if CPU == .ARM64 {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_macos_arm64_metal_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_macos_arm64_metal_release"; }
} else {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_macos_x64_metal_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_macos_x64_metal_release"; }
}
}
}
} else #if OS == .LINUX {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_linux_x64_gl_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_linux_x64_gl_release"; }
} else #if OS == .WASM {
#if DEBUG { sokol_time_clib :: #library,no_dll "sokol_time_wasm_gl_debug"; }
else { sokol_time_clib :: #library,no_dll "sokol_time_wasm_gl_release"; }
} else {
log_error("This OS is currently not supported");
}
stm_setup :: () -> void #foreign sokol_time_clib;
stm_now :: () -> u64 #foreign sokol_time_clib;
stm_diff :: (new_ticks: u64, old_ticks: u64) -> u64 #foreign sokol_time_clib;
stm_since :: (start_ticks: u64) -> u64 #foreign sokol_time_clib;
stm_laptime :: (last_time: *u64) -> u64 #foreign sokol_time_clib;
stm_round_to_common_refresh_rate :: (frame_ticks: u64) -> u64 #foreign sokol_time_clib;
stm_sec :: (ticks: u64) -> float64 #foreign sokol_time_clib;
stm_ms :: (ticks: u64) -> float64 #foreign sokol_time_clib;
stm_us :: (ticks: u64) -> float64 #foreign sokol_time_clib;
stm_ns :: (ticks: u64) -> float64 #foreign sokol_time_clib;

Binary file not shown.

61
src/arbtri.jai Normal file
View File

@ -0,0 +1,61 @@
Arb_Tri :: struct {
pos: [3]Vector3;
col: [3]Vector4;
uv: [3]Vector2;
}
Arb_Tri_State :: struct {
active : bool = false;
trilist : [..]Arb_Tri;
}
arbTriState : Arb_Tri_State;
arb_tri_add :: (tri: Arb_Tri) {
if !arbTriState.active {
array_reset_keeping_memory(*arbTriState.trilist);
arbTriState.active = true;
}
array_add(*arbTriState.trilist, tri);
}
arb_tri_flush :: () {
if !arbTriState.active {
return;
}
transform_to_screen_x :: (coord: float) -> float {
w, h := get_window_size();
return (coord / cast(float) w) * 2.0 - 1.0;
}
transform_to_screen_y :: (coord: float) -> float {
w, h := get_window_size();
return (coord / cast(float) h) * 2.0 - 1.0;
}
arbTriState.active = false;
for tri, i : arbTriState.trilist {
bgn := i * 3 * 9;
for 0..2 {
gArbtriMem[bgn + it * 9 + 0] = transform_to_screen_x(tri.pos[it].x);
gArbtriMem[bgn + it * 9 + 1] = transform_to_screen_y(tri.pos[it].y) * -1.0;
gArbtriMem[bgn + it * 9 + 2] = 0;
gArbtriMem[bgn + it * 9 + 3] = tri.col[it].x;
gArbtriMem[bgn + it * 9 + 4] = tri.col[it].y;
gArbtriMem[bgn + it * 9 + 5] = tri.col[it].z;
gArbtriMem[bgn + it * 9 + 6] = tri.col[it].w;
gArbtriMem[bgn + it * 9 + 7] = tri.uv[it].x;
gArbtriMem[bgn + it * 9 + 8] = tri.uv[it].y;
}
}
sg_update_buffer(gPipelines.arbtri.bind.vertex_buffers[0], *(sg_range.{ ptr = gArbtriMem.data, size = size_of(type_of(gArbtriMem)) }));
sg_apply_pipeline(gPipelines.arbtri.pipeline);
sg_apply_bindings(*gPipelines.arbtri.bind);
sg_draw(0, xx (arbTriState.trilist.count * 3), 1);
}

1
src/buffers.jai Normal file
View File

@ -0,0 +1 @@

9
src/events.jai Normal file
View File

@ -0,0 +1,9 @@
mpos : Vector2;
handle_event :: (e: *sapp_event) {
if e.type == .MOUSE_MOVE {
mpos.x = e.mouse_x;
mpos.y = e.mouse_y;
}
}

20
src/load.jai Normal file
View File

@ -0,0 +1,20 @@
MAX_FILE_SIZE :: 200_000;
buf : [MAX_FILE_SIZE]u8;
init_font_loads :: () {
print("SENDING LOAD!!!!\n");
sfetch_send(*(sfetch_request_t.{
path = "./resources/DroidSerif-Regular.ttf".data,
callback = fontcb,
buffer = .{
ptr = buf.data,
size = buf.count
}
}));
}
fontcb :: (res: *sfetch_response_t) #c_call {
push_context,defer_pop default_context;
print("RDY! Finished? % Fetched? % \n", res.fetched, res.finished);
state.font_default = fonsAddFontMem(state.fons, "sans", res.data.ptr, xx res.data.size, 0);
}

100
src/main.jai Normal file
View File

@ -0,0 +1,100 @@
#import "Basic";
#import "Math";
#load "ui/ui.jai";
#load "pipelines.jai";
#load "time.jai";
#load "arbtri.jai";
#load "events.jai";
#load "load.jai";
#load "./shaders/jai/shader_triangle.jai";
state: struct {
pass_action: sg_pass_action;
dpi_scale: float;
fons: *FONScontext;
font_default: s32;
};
Window_Info :: struct {
width: s32;
height: s32;
title: *u8;
};
get_window_info :: () -> Window_Info {
return Window_Info.{
1200,
1200,
"trueno!"
};
}
round_pow2 :: (v: float) -> s32 {
vi := (cast(u32) v) - 1;
for i : 0..4 {
vi |= (vi >> (1<<i));
}
return cast(s32) (vi + 1);
}
init :: () {
sg_setup(*(sg_desc.{
environment = cast,force(sg_environment) sglue_environment(),
logger = .{ func = slog_func },
}));
sgl_setup(*(sgl_desc_t.{
logger = .{ func = slog_func },
}));
sfetch_setup(*(sfetch_desc_t.{
logger = .{ func = slog_func },
}));
stm_setup();
state.dpi_scale = sapp_dpi_scale();
atlas_dim := round_pow2(512.0 * state.dpi_scale);
fons_context := sfons_create(*(sfons_desc_t.{
width = atlas_dim,
height = atlas_dim,
}));
state.fons = fons_context;
state.font_default = FONS_INVALID;
// file_data := read_entire_file("./");
// state.font_default = fonsAddFontMem(state.fons, "sans", *file_data[0], xx file_data.count, 0);
create_pipelines();
// a pass action to clear framebuffer to black
state.pass_action.colors[0] = .{ load_action = .CLEAR, clear_value = .{ r = 0.5, g = 0.5, b = 0.9, a = 1 } };
init_ui();
init_font_loads();
}
frame :: () {
dpis := state.dpi_scale;
sfetch_dowork();
fonsClearState(state.fons);
sgl_defaults();
sgl_matrix_mode_projection();
sgl_ortho(0.0, sapp_widthf(), sapp_heightf(), 0.0, -1.0, +1.0);
black := sfons_rgba(0, 0, 0, 255);
tick_ui();
sg_begin_pass(*(sg_pass.{ action = state.pass_action, swapchain = cast,force(sg_swapchain) sglue_swapchain() }));
render_ui();
sfons_flush(state.fons);
arb_tri_flush();
sgl_draw();
sg_end_pass();
sg_commit();
reset_temporary_storage();
}
cleanup :: () {
sg_shutdown();
}
get_window_size :: () -> (s32, s32) {
return sapp_width(), sapp_height();
}

27
src/pipelines.jai Normal file
View File

@ -0,0 +1,27 @@
Pipeline_Binding :: struct {
pipeline: sg_pipeline;
bind: sg_bindings;
}
gPipelines : struct {
arbtri: Pipeline_Binding;
}
create_pipelines :: () {
create_arbtri_pipeline();
}
gArbtriMem : [1000*3*9]float;
create_arbtri_pipeline :: () {
pipeline: sg_pipeline_desc;
shader_desc := triangle_shader_desc(sg_query_backend());
pipeline.shader = sg_make_shader(*shader_desc);
pipeline.layout.attrs[ATTR_triangle_position] = .{ format = .FLOAT3 };
pipeline.layout.attrs[ATTR_triangle_color0] = .{ format = .FLOAT4 };
pipeline.layout.attrs[ATTR_triangle_uv] = .{ format = .FLOAT2 };
gPipelines.arbtri.pipeline = sg_make_pipeline(*pipeline);
buffer := sg_buffer_desc.{ usage = .DYNAMIC, size = size_of(type_of(gArbtriMem)) };
gPipelines.arbtri.bind.vertex_buffers[0] = sg_make_buffer(*buffer);
}

View File

@ -0,0 +1,52 @@
#import,dir "../../modules/sokol-jai/sokol/app";
#import,dir "../../modules/sokol-jai/sokol/gfx";
#import,dir "../../modules/sokol-jai/sokol/gl";
#import,dir "../../modules/sokol-jai/sokol/glue";
#import,dir "../../modules/sokol-jai/sokol/fontstash";
#import,dir "../../modules/sokol-jai/sokol/log";
#import,dir "../../modules/sokol-jai/sokol/time";
#import,dir "../../modules/sokol-jai/sokol/fetch";
#load "../main.jai";
default_context: #Context;
sapp_init :: () {
push_context,defer_pop default_context;
context.logger = logger;
wi := get_window_info();
sapp_run(*(sapp_desc.{
init_cb = init_plat,
frame_cb = frame_plat,
cleanup_cb = cleanup_plat,
event_cb = event_plat,
width = wi.width,
height = wi.height,
window_title = wi.title,
// icon = .{ sokol_default = true },
logger = .{ func = slog_func },
}));
}
init_plat :: () #c_call {
push_context,defer_pop default_context;
init();
}
frame_plat :: () #c_call {
push_context,defer_pop default_context;
frame();
}
event_plat :: (e: *sapp_event) #c_call {
push_context,defer_pop default_context;
handle_event(e);
}
cleanup_plat :: () #c_call {
push_context,defer_pop default_context;
cleanup();
}

View File

@ -0,0 +1,9 @@
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
extern void _main();
int main() {
_main();
return 0;
}

View File

@ -0,0 +1,18 @@
#load "common.jai";
main :: () {
push_context,defer_pop default_context;
sapp_init();
}
log_warn :: (format_string: string, args: .. Any, loc := #caller_location, flags := Log_Flags.NONE, user_flags : u32 = 0, section : *Log_Section = null) {
log(format_string, ..args, loc = loc, flags = flags | .WARNING, user_flags = user_flags, section = section);
} @PrintLike
log_content :: (format_string: string, args: .. Any, loc := #caller_location, flags := Log_Flags.NONE, user_flags : u32 = 0, section : *Log_Section = null) {
log(format_string, ..args, loc = loc, flags = flags | .CONTENT, user_flags = user_flags, section = section);
} @PrintLike
logger :: (message: string, data: *void, info: Log_Info) {
print("%\n", message);
}

View File

@ -0,0 +1,20 @@
#load "common.jai";
#program_export
_main :: () #c_call {
push_context,defer_pop default_context;
sapp_init();
}
log_warn :: (format_string: string, args: .. Any, loc := #caller_location, flags := Log_Flags.NONE, user_flags : u32 = 0, section : *Log_Section = null) {
log(format_string, ..args, loc = loc, flags = flags | .WARNING, user_flags = user_flags, section = section);
} @PrintLike
log_content :: (format_string: string, args: .. Any, loc := #caller_location, flags := Log_Flags.NONE, user_flags : u32 = 0, section : *Log_Section = null) {
log(format_string, ..args, loc = loc, flags = flags | .CONTENT, user_flags = user_flags, section = section);
} @PrintLike
logger :: (message: string, data: *void, info: Log_Info) {
wasm_write_string :: (count: s64, data: *void, log_flag: Log_Flags) #foreign; // You will need to provide this function as JS code in your WASM environment. :JaiWasm:
wasm_write_string(message.count, message.data, info.common_flags);
}

View File

@ -0,0 +1,26 @@
mergeInto(LibraryManager.library, {
$UTF8ToString__sig: 'ip', // Override the signature of UTF8ToString to use BigInt instead of Number
wasm_write_string: (s_count, s_data, log_flag) => {
function js_string_from_jai_string(pointer, length) {
const text_decoder = new TextDecoder();
const u8 = new Uint8Array(wasmMemory.buffer)
const bytes = u8.subarray(Number(pointer), Number(pointer) + Number(length));
return text_decoder.decode(bytes);
}
const string = js_string_from_jai_string(s_data, s_count);
switch (log_flag) {
case /* ERROR */ 0x1: { console.error(string); } break;
case /* WARNING */ 0x2: { console.warn(string); } break;
case /* CONTENT */ 0x4: { console.info(`%c${string}`, "color: #3949ab;"); } break;
default: { console.log(string); }
}
// Module.print(string);
},
wasm_debug_break: () => {
debugger;
},
});

View File

@ -0,0 +1,79 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="UTF-8"/>
<title>${name}</title>
<style type="text/css">
body {
margin: 0;
background-color: black;
}
.game-title {
pointer-events: none;
position: absolute;
bottom: 10px;
margin-top: 0px;
padding-left: 10px;
color: white;
text-decoration: none;
z-index: 1;
text-align: left;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 30px;
}
.game-menu-item {
pointer-events: auto;
font-size: 18px;
padding-left: 10px;
font-family: Arial, Helvetica, sans-serif;
}
.game-menu-link {
text-decoration: none;
color: white;
}
.game {
position: absolute;
top: 0px;
left: 0px;
margin: 0px;
border: 0;
width: 100%;
height: 100%;
overflow: hidden;
display: block;
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
}
</style>
</head>
<body style="background:black">
<div class="game-title">${name}
<span class="game-menu-item"><a class="game-menu-link" href="index.html">home</a></span>
</div>
<canvas class="game" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script type="text/javascript">
var Module = {
onRuntimeInitialized: function () {
const originalSet = HEAPU8.set.bind(HEAPU8);
HEAPU8.set = function(array, offset) {
if (typeof offset === 'bigint') {
offset = Number(offset);
}
return originalSet(array, offset);
};
},
preRun: [],
print: (...args) => console.log('[stdout]: ' + args.join(' ')),
printErr: (...args) => console.log('[stderr]: ' + args.join(' ')),
};
window.onerror = (event) => console.log('[onerror]: ' + event.message);
</script>
{{{ SCRIPT }}}
</body>
</html>

5
src/shaders/compile_shaders.sh Executable file
View File

@ -0,0 +1,5 @@
for filename in *.glsl; do
if [ -f "$filename" ]; then
./sokol-shdc -i "$filename" -o "./jai/${filename/.glsl/.jai}" -l glsl430:glsl300es -f sokol_jai
fi
done

View File

@ -0,0 +1,175 @@
/*
#version:1# (machine generated, don't edit!)
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
Cmdline:
sokol-shdc -i shader_triangle.glsl -o ./jai/shader_triangle.jai -l glsl430:glsl300es -f sokol_jai
Overview:
=========
Shader program: 'triangle':
Get shader desc: triangle_shader_desc(sg_query_backend())
Vertex Shader: vs
Fragment Shader: fs
Attributes:
ATTR_triangle_position => 0
ATTR_triangle_color0 => 1
ATTR_triangle_uv => 2
Bindings:
*/
ATTR_triangle_position :: 0;
ATTR_triangle_color0 :: 1;
ATTR_triangle_uv :: 2;
/*
#version 430
layout(location = 0) in vec4 position;
layout(location = 0) out vec4 color;
layout(location = 1) in vec4 color0;
layout(location = 2) in vec4 uv;
void main()
{
gl_Position = position;
color = color0;
color.x = fma(9.9999999392252902907785028219223e-09, uv.x, color.x);
}
*/
vs_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,
0x69,0x6f,0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,
0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,
0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,
0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x6c,
0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x32,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x75,0x76,0x3b,0x0a,
0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,
0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,
0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,
0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x2e,0x78,0x20,0x3d,0x20,0x66,0x6d,0x61,
0x28,0x39,0x2e,0x39,0x39,0x39,0x39,0x39,0x39,0x39,0x33,0x39,0x32,0x32,0x35,0x32,
0x39,0x30,0x32,0x39,0x30,0x37,0x37,0x38,0x35,0x30,0x32,0x38,0x32,0x31,0x39,0x32,
0x32,0x33,0x65,0x2d,0x30,0x39,0x2c,0x20,0x75,0x76,0x2e,0x78,0x2c,0x20,0x63,0x6f,
0x6c,0x6f,0x72,0x2e,0x78,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 430
layout(location = 0) out vec4 frag_color;
layout(location = 0) in vec4 color;
void main()
{
frag_color = color;
}
*/
fs_source_glsl430 := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x34,0x33,0x30,0x0a,0x0a,0x6c,0x61,
0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,
0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,
0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,
0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,
0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
layout(location = 0) in vec4 position;
out vec4 color;
layout(location = 1) in vec4 color0;
layout(location = 2) in vec4 uv;
void main()
{
gl_Position = position;
color = color0;
color.x = 9.9999999392252902907785028219223e-09 * uv.x + color.x;
}
*/
vs_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,
0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,
0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,
0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x6c,0x61,0x79,
0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,
0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x75,0x76,0x3b,0x0a,0x0a,0x76,
0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,
0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x70,
0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,
0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x20,0x20,0x20,
0x20,0x63,0x6f,0x6c,0x6f,0x72,0x2e,0x78,0x20,0x3d,0x20,0x39,0x2e,0x39,0x39,0x39,
0x39,0x39,0x39,0x39,0x33,0x39,0x32,0x32,0x35,0x32,0x39,0x30,0x32,0x39,0x30,0x37,
0x37,0x38,0x35,0x30,0x32,0x38,0x32,0x31,0x39,0x32,0x32,0x33,0x65,0x2d,0x30,0x39,
0x20,0x2a,0x20,0x75,0x76,0x2e,0x78,0x20,0x2b,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x2e,
0x78,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
/*
#version 300 es
precision mediump float;
precision highp int;
layout(location = 0) out highp vec4 frag_color;
in highp vec4 color;
void main()
{
frag_color = color;
}
*/
fs_source_glsl300es := u8.[
0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
0x70,0x72,0x65,0x63,0x69,0x73,0x69,0x6f,0x6e,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,
0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3b,0x0a,0x70,0x72,0x65,0x63,0x69,0x73,0x69,
0x6f,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x69,0x6e,0x74,0x3b,0x0a,0x0a,0x6c,
0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,
0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,
0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x69,
0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,
0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,
0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,
0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
];
triangle_shader_desc :: (backend: sg_backend) -> sg_shader_desc {
desc: sg_shader_desc;
desc.label = "triangle_shader";
if backend == {
case .GLCORE;
desc.vertex_func.source = xx *vs_source_glsl430;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_source_glsl430;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.attrs[1].base_type = .FLOAT;
desc.attrs[1].glsl_name = "color0";
desc.attrs[2].base_type = .FLOAT;
desc.attrs[2].glsl_name = "uv";
case .GLES3;
desc.vertex_func.source = xx *vs_source_glsl300es;
desc.vertex_func.entry = "main";
desc.fragment_func.source = xx *fs_source_glsl300es;
desc.fragment_func.entry = "main";
desc.attrs[0].base_type = .FLOAT;
desc.attrs[0].glsl_name = "position";
desc.attrs[1].base_type = .FLOAT;
desc.attrs[1].glsl_name = "color0";
desc.attrs[2].base_type = .FLOAT;
desc.attrs[2].glsl_name = "uv";
}
return desc;
}

View File

@ -0,0 +1,24 @@
@vs vs
in vec4 position;
in vec4 color0;
in vec4 uv;
out vec4 color;
void main() {
gl_Position = position;
color = color0;
color.x += 0.00000001 * uv.x;
}
@end
@fs fs
in vec4 color;
out vec4 frag_color;
void main() {
frag_color = color;
}
@end
@program triangle vs fs

BIN
src/shaders/sokol-shdc Executable file

Binary file not shown.

3
src/time.jai Normal file
View File

@ -0,0 +1,3 @@
get_time :: () -> float64 {
return stm_sec(stm_now());
}

180
src/ui/ui.jai Normal file
View File

@ -0,0 +1,180 @@
GR :: #import "GetRect_LeftHanded"()(Type_Indicator = Ui_Type_Indicator);
Ui_Font :: struct {
em_width: u32 = 1;
character_height: u32 = 30;
}
Ui_Texture :: struct {
name: string;
}
Ui_Rect :: struct {
x, y, w, h: s32;
};
Ui_Type_Indicator :: struct {
Texture : Type : Ui_Texture;
Window_Type: Type : s32;
Font: Type: Ui_Font;
Font_Effects: Type: u32;
};
Font :: Ui_Font;
defaultFont: Font;
ui_texture_counter : u32 = 0;
texture_load_from_memory :: (texture: *Ui_Texture, memory: []u8, srgb: bool, build_mipmaps: bool) -> bool {
// texname := tprint("ui_tex_%", ui_texture_counter);
// load_png_texture_from_memory(*GpuContext, copy_string(texname), memory);
// ui_texture_counter += 1;
// texture.name = copy_string(texname);
return true;
}
gScissor : Ui_Rect;
gScissorActive : bool = false;
get_render_size :: () -> (s32, s32) {
return 700, 700;
}
set_scissor :: (x0: s32, y0: s32, x1: s32, y1: s32) {
w,h := get_render_size();
gScissor = .{x0, y0, x1 - x0, y1 - y0};
gScissorActive = true;
}
clear_scissor :: () {
gScissorActive = false;
}
gCurrentTexture : *Ui_Texture = null;
set_shader_for_color :: (enable_blend := false) {
// immediate_flush(); // We want to do the flush so we can set the sampler for the entire set.
// gCurrentTexture = null;
}
set_shader_for_images :: (texture: *Ui_Texture) {
// if ENABLE_UI_DEBUG_LOGGING { print("Setting shader for textures.."); }
// immediate_flush(); // We want to do the flush so we can set the sampler for the entire set.
// gCurrentTexture = texture;
}
gPreppedText: string;
gPreppedTextWidth : s32;
prepare_text :: (font: *Ui_Type_Indicator.Font, text: string, effects: Ui_Type_Indicator.Font_Effects = 0) -> s64 {
fonsSetFont(state.fons, state.font_default);
fonsSetSize(state.fons, xx font.character_height);
w := fonsTextBounds(state.fons, 0.0, 0.0, text.data, text.data + text.count, null);
gPreppedText = text;
gPreppedTextWidth = cast(s32) w;
return cast(s64) w;
}
draw_prepared_text :: (font: *Ui_Type_Indicator.Font, x: s64, y: s64, text_color: Vector4, effects: Ui_Type_Indicator.Font_Effects = 0) {
color := sfons_rgba(xx (255.0 * text_color.x), xx (255.0 * text_color.y), xx (255.0 * text_color.z), xx (255.0 * text_color.w));
fonsSetColor(state.fons, color);
result := cast(*u8) temporary_alloc(gPreppedText.count + 1); // Add 1 for the zero.
memcpy(result, gPreppedText.data, gPreppedText.count);
result[gPreppedText.count] = 0;
fonsDrawText(state.fons, xx x, xx y, result, null);
}
get_mouse_pointer_position :: (window: Ui_Type_Indicator.Window_Type, right_handed: bool) -> (x: int, y: int, success: bool) {
return xx mpos.x, xx mpos.y, true;
}
get_font_at_size :: (memory: [] u8, pixel_height: int) -> *Font {
f : *Font = New(Font);
// f.character_height = cast(u32) pixel_height;
// f.em_width = cast(u32) get_font_letter_width(109, cast (s32) pixel_height);
return f;
}
// TODO: Figure out what to do with the normal?
immediate_triangle :: (p0: Vector3, p1: Vector3, p2: Vector3, c0 := Vector4.{1,1,1,1}, c1 := Vector4.{1,1,1,1}, c2 := Vector4.{1,1,1,1}, uv0 := Vector2.{}, uv1 := Vector2.{}, uv2 := Vector2.{}, normal := Vector3.{z=1}) {
tri: Arb_Tri;
tri.pos[0] = p0;
tri.pos[1] = p1;
tri.pos[2] = p2;
tri.col[0] = c0;
tri.col[1] = c1;
tri.col[2] = c2;
// This UV symbolizes that the sampler should not be used.
nullUV : Vector2 = .{-4, -2};
if gCurrentTexture == null {
tri.uv[0] = nullUV;
tri.uv[1] = nullUV;
tri.uv[2] = nullUV;
} else {
tri.uv[0] = uv0;
tri.uv[1] = uv2;
tri.uv[2] = uv1;
}
arb_tri_add(tri);
}
immediate_quad :: (p0: Vector2, p1: Vector2, p2: Vector2, p3: Vector2, color := Vector4.{1,1,1,1}, uv0 := Vector2.{0,0}, uv1 := Vector2.{1,0}, uv2 := Vector2.{1,1}, uv3 := Vector2.{0, 1}) {
to_3d_vec :: (v: Vector2) -> Vector3 {
return .{v.x, v.y, 0.0};
}
immediate_triangle(to_3d_vec(p0), to_3d_vec(p1), to_3d_vec(p2), color, color, color, uv0, uv1, uv2);
immediate_triangle(to_3d_vec(p0), to_3d_vec(p2), to_3d_vec(p3), color, color, color, uv0, uv2, uv3);
}
immediate_flush :: () {
// arb_tri_flush();
}
init_ui :: () {
dp : GR.Draw_Procs = .{
texture_load_from_memory = texture_load_from_memory,
set_scissor = set_scissor,
clear_scissor = clear_scissor,
set_shader_for_color = set_shader_for_color,
set_shader_for_images = set_shader_for_images,
prepare_text = prepare_text,
draw_prepared_text = draw_prepared_text,
get_mouse_pointer_position = get_mouse_pointer_position,
get_font_at_size = get_font_at_size,
immediate_triangle = immediate_triangle, // implemented
immediate_quad = immediate_quad, // implemented
immediate_flush = immediate_flush // implemented
};
GR.ui_init("", *dp);
}
tick_ui :: () {
w,h := get_window_size();
GR.ui_per_frame_update(1, xx w, xx h, get_time());
}
checkboxTest : bool = false;
get_font_at_size :: (pixel_height: int) -> *Font {
list : []u8;
return get_font_at_size(list, pixel_height);
}
idk : bool;
render_ui :: () {
proc := GR.default_theme_procs[3];
my_theme := proc();
GR.set_default_theme(my_theme); // Just in case we don't explicitly pass themes sometimes...!
r := GR.get_rect(10, 10, 400, 30);
pressed := GR.button(r, "GetRect render lfg!!", *my_theme.button_theme);
r.y += 150;
GR.base_checkbox(r, "CHECK!!!", idk, null);
}

BIN
walloc.o Executable file

Binary file not shown.