[gles] expose GLES surface and GLES API to orca apps.
- Allow orca app to request either Canvas or GLES surfaces - Add bounds check specifications to the json bindings spec format and to the bindings generator scripts. - Generate GLES API json bindings spec from gl.xml - Remove APIs that can't be bound with current wasm memory model (ie buffer mapping) - Manually link remaining APIs, except glGetString - Add fluid simulation sample - Add abort messages for wasm loading and runtime fatal errors - Adapt orca build tool to generate GLES json spec from gl.xml - Adapt glesTriangle and fluid samples build scripts to new orca build tool
This commit is contained in:
parent
3fae3252a1
commit
e4d9955e83
|
@ -17,11 +17,15 @@ build
|
|||
|
||||
Debug/*
|
||||
|
||||
scripts/__pycache__
|
||||
src/gles_api.json
|
||||
src/bindgen_core_api.c
|
||||
src/bindgen_gles_api.c
|
||||
sdk/io_stubs.c
|
||||
sdk/orca_surface.c
|
||||
sdk/gl31.h
|
||||
*bind_gen.c
|
||||
gles_gen.log
|
||||
|
||||
.vscode/launch.json
|
||||
.vscode/settings.json
|
||||
|
|
62
build.bat
62
build.bat
|
@ -1,62 +0,0 @@
|
|||
@echo off
|
||||
|
||||
set target=%1%
|
||||
if "%~1%" == "" set target=orca
|
||||
|
||||
if not exist bin mkdir bin
|
||||
if not exist bin\obj mkdir bin\obj
|
||||
|
||||
if %target% == wasm3 (
|
||||
echo building wasm3
|
||||
|
||||
set wasm3_includes=/I .\ext\wasm3\source
|
||||
set wasm3_sources=/I .\ext\wasm3\source\*.c
|
||||
|
||||
for %%f in ( .\ext\wasm3\source\*.c ) do (
|
||||
cl /nologo /Zi /Zc:preprocessor /O2 /c /Fo:bin\obj\%%~nf.obj %wasm3_includes% %%f
|
||||
)
|
||||
lib /nologo /out:bin\wasm3.lib bin\obj\*.obj
|
||||
)
|
||||
|
||||
if %target% == milepost (
|
||||
echo building milepost
|
||||
cd milepost
|
||||
build.bat
|
||||
cd ..
|
||||
)
|
||||
|
||||
if %target% == orca (
|
||||
echo building orca
|
||||
|
||||
::copy libraries
|
||||
copy milepost\bin\milepost.dll bin
|
||||
copy milepost\bin\milepost.dll.lib bin
|
||||
|
||||
::generate wasm3 api bindings
|
||||
python3 scripts\bindgen.py core src\core_api.json^
|
||||
--wasm3-bindings src\core_api_bind_gen.c
|
||||
|
||||
python3 scripts\bindgen.py gles src\gles_api.json^
|
||||
--wasm3-bindings src\gles_api_bind_gen.c
|
||||
|
||||
python3 scripts\bindgen.py canvas src\canvas_api.json^
|
||||
--guest-stubs sdk\orca_surface.c^
|
||||
--guest-include graphics.h^
|
||||
--wasm3-bindings src\canvas_api_bind_gen.c
|
||||
|
||||
python3 scripts\bindgen.py clock src\clock_api.json^
|
||||
--guest-stubs sdk\orca_clock.c^
|
||||
--guest-include platform_clock.h^
|
||||
--wasm3-bindings src\clock_api_bind_gen.c
|
||||
|
||||
python3 scripts\bindgen.py io^
|
||||
src\io_api.json^
|
||||
--guest-stubs sdk\io_stubs.c^
|
||||
--wasm3-bindings src\io_api_bind_gen.c
|
||||
|
||||
::compile orca
|
||||
set INCLUDES=/I src /I sdk /I ext\wasm3\source /I milepost\src /I milepost\ext
|
||||
set LIBS=/LIBPATH:bin milepost.dll.lib wasm3.lib
|
||||
|
||||
cl /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% src\main.c /link %LIBS% /out:bin\orca.exe
|
||||
)
|
97
build.sh
97
build.sh
|
@ -1,97 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -exo pipefail
|
||||
|
||||
target="$1"
|
||||
|
||||
if [ -z $target ] ; then
|
||||
target='orca'
|
||||
fi
|
||||
target=$(echo $target | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
if [ ! \( -e bin \) ] ; then
|
||||
mkdir ./bin
|
||||
fi
|
||||
|
||||
if [ ! \( -e resources \) ] ; then
|
||||
mkdir ./resources
|
||||
fi
|
||||
|
||||
|
||||
if [ $target = milepost ] ; then
|
||||
echo "building milepost"
|
||||
pushd milepost > /dev/null
|
||||
./build.sh lib "$2"
|
||||
popd > /dev/null
|
||||
|
||||
elif [ $target = wasm3 ] ; then
|
||||
|
||||
echo "building wasm3"
|
||||
mkdir ./bin/obj
|
||||
for file in ./ext/wasm3/source/*.c ; do
|
||||
name=$(basename $file)
|
||||
name=${name/.c/.o}
|
||||
clang -c -g -O2 -foptimize-sibling-calls -Wno-extern-initializer -Dd_m3VerboseErrorMessages -o ./bin/obj/$name -I./ext/wasm3/source $file
|
||||
done
|
||||
ar -rcs ./bin/libwasm3.a ./bin/obj/*.o
|
||||
rm -rf ./bin/obj
|
||||
|
||||
elif [ $target = orca ] ; then
|
||||
echo "building orca"
|
||||
|
||||
if [ ! \( -e milepost/bin/libmilepost.dylib \) -o ! \( -e milepost/bin/mtl_renderer.metallib \) ] ; then
|
||||
./build.sh milepost
|
||||
fi
|
||||
|
||||
if [ ! \( -e ./bin/libwasm3.a \) ] ; then
|
||||
./build.sh wasm3
|
||||
fi
|
||||
|
||||
# copy libraries
|
||||
cp milepost/bin/mtl_renderer.metallib bin/
|
||||
cp milepost/bin/libmilepost.dylib bin/
|
||||
cp milepost/bin/libGLESv2.dylib bin/
|
||||
cp milepost/bin/libEGL.dylib bin/
|
||||
|
||||
INCLUDES="-Isrc -Isdk -Imilepost/src -Imilepost/src/util -Imilepost/src/platform -Iext/wasm3/source -Imilepost/ext/"
|
||||
LIBS="-Lbin -lmilepost -lwasm3"
|
||||
FLAGS="-g -DLOG_COMPILE_DEBUG -mmacos-version-min=10.15.4 -maes"
|
||||
|
||||
# generate wasm3 api bindings
|
||||
|
||||
python3 ./scripts/bindgen.py core \
|
||||
src/core_api.json \
|
||||
--wasm3-bindings ./src/core_api_bind_gen.c
|
||||
|
||||
python3 ./scripts/bindgen.py gles \
|
||||
src/gles_api.json \
|
||||
--wasm3-bindings ./src/gles_api_bind_gen.c
|
||||
|
||||
python3 ./scripts/bindgen.py canvas \
|
||||
src/canvas_api.json \
|
||||
--guest-stubs sdk/orca_surface.c \
|
||||
--guest-include graphics.h \
|
||||
--wasm3-bindings ./src/canvas_api_bind_gen.c
|
||||
|
||||
python3 ./scripts/bindgen.py clock \
|
||||
src/clock_api.json \
|
||||
--guest-stubs sdk/orca_clock.c \
|
||||
--guest-include platform_clock.h \
|
||||
--wasm3-bindings ./src/clock_api_bind_gen.c
|
||||
|
||||
python3 ./scripts/bindgen.py io \
|
||||
src/io_api.json \
|
||||
--guest-stubs sdk/io_stubs.c \
|
||||
--wasm3-bindings ./src/io_api_bind_gen.c
|
||||
|
||||
# compile orca
|
||||
clang $FLAGS $INCLUDES $LIBS -o bin/orca src/main.c
|
||||
|
||||
# fix libs imports
|
||||
install_name_tool -change "./bin/libmilepost.dylib" "@rpath/libmilepost.dylib" bin/orca
|
||||
install_name_tool -add_rpath "@executable_path/" bin/orca
|
||||
|
||||
|
||||
else
|
||||
echo "unknown build target $target"
|
||||
fi
|
2
milepost
2
milepost
|
@ -1 +1 @@
|
|||
Subproject commit c103c001f7c8e780602193f22360201810802438
|
||||
Subproject commit d01dc832fbbc7b1e720476178a2c49a737717e0f
|
|
@ -0,0 +1,3 @@
|
|||
Fluid
|
||||
profile.dtrace
|
||||
profile.spall
|
|
@ -0,0 +1,33 @@
|
|||
@echo off
|
||||
|
||||
:: compile wasm module
|
||||
set wasmFlags=--target=wasm32^
|
||||
--no-standard-libraries ^
|
||||
-fno-builtin ^
|
||||
-Wl,--no-entry ^
|
||||
-Wl,--export-dynamic ^
|
||||
-g ^
|
||||
-O2 ^
|
||||
-mbulk-memory ^
|
||||
-D__ORCA__ ^
|
||||
-isystem ..\..\cstdlib\include -I ..\..\sdk -I..\..\milepost\ext -I ..\..\milepost -I ..\..\milepost\src
|
||||
|
||||
set shaders=src/shaders/advect.glsl^
|
||||
src/shaders/blit_div_fragment.glsl^
|
||||
src/shaders/blit_div_vertex.glsl^
|
||||
src/shaders/blit_fragment.glsl^
|
||||
src/shaders/blit_residue_fragment.glsl^
|
||||
src/shaders/blit_vertex.glsl^
|
||||
src/shaders/common_vertex.glsl^
|
||||
src/shaders/divergence.glsl^
|
||||
src/shaders/jacobi_step.glsl^
|
||||
src/shaders/multigrid_correct.glsl^
|
||||
src/shaders/multigrid_restrict_residual.glsl^
|
||||
src/shaders/splat.glsl^
|
||||
src/shaders/subtract_pressure.glsl
|
||||
|
||||
call python3 ../../milepost/scripts/embed_text.py --prefix=glsl_ --output src/glsl_shaders.h %shaders%
|
||||
|
||||
clang %wasmFlags% -o .\module.wasm ..\..\sdk\orca.c ..\..\cstdlib\src\*.c src\main.c
|
||||
|
||||
python3 ..\..\scripts\mkapp.py --orca-dir ..\.. --icon icon.png --name Fluid module.wasm
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -x /usr/local/opt/llvm/bin/clang ]]; then
|
||||
CLANG=/usr/local/opt/llvm/bin/clang
|
||||
elif [[ -x /opt/homebrew/opt/llvm/bin/clang ]]; then
|
||||
CLANG=/opt/homebrew/opt/llvm/bin/clang
|
||||
else
|
||||
echo "Could not find Homebrew clang; this script will probably not work."
|
||||
CLANG=clang
|
||||
fi
|
||||
|
||||
STDLIB_DIR=../../cstdlib
|
||||
ORCA_SDK_DIR=../../sdk
|
||||
MILEPOST_DIR=../../milepost
|
||||
|
||||
python3 ../../milepost/scripts/embed_text.py --prefix=glsl_ --output src/glsl_shaders.h src/shaders/*.glsl
|
||||
|
||||
wasmFlags="--target=wasm32 \
|
||||
--no-standard-libraries \
|
||||
-fno-builtin \
|
||||
-Wl,--no-entry \
|
||||
-Wl,--export-dynamic \
|
||||
-g \
|
||||
-O2 \
|
||||
-mbulk-memory \
|
||||
-D__ORCA__ \
|
||||
-I $STDLIB_DIR/include \
|
||||
-I $ORCA_SDK_DIR \
|
||||
-I $MILEPOST_DIR/ext -I $MILEPOST_DIR -I $MILEPOST_DIR/src"
|
||||
|
||||
$CLANG $wasmFlags -o ./module.wasm ../../sdk/orca.c ../../cstdlib/src/*.c src/main.c
|
||||
|
||||
orca bundle --orca-dir ../.. --icon icon.png --name Fluid module.wasm
|
Binary file not shown.
After Width: | Height: | Size: 168 KiB |
|
@ -0,0 +1,551 @@
|
|||
/*********************************************************************
|
||||
*
|
||||
* file: glsl_shaders.h
|
||||
* note: string literals auto-generated by embed_text.py
|
||||
* date: 08/082023
|
||||
*
|
||||
**********************************************************************/
|
||||
#ifndef __GLSL_SHADERS_H__
|
||||
#define __GLSL_SHADERS_H__
|
||||
|
||||
|
||||
//NOTE: string imported from src/shaders/advect.glsl
|
||||
const char* glsl_advect =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D src;\n"
|
||||
"uniform sampler2D velocity;\n"
|
||||
"uniform float delta;\n"
|
||||
"uniform float dissipation;\n"
|
||||
"\n"
|
||||
"vec2 u(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" return(texelFetch(velocity, coord, 0).xy);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec4 q(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x < 0\n"
|
||||
" || coord.x >= textureSize(src, 0).x\n"
|
||||
" || coord.y < 0\n"
|
||||
" || coord.y >= textureSize(src, 0).y)\n"
|
||||
" {\n"
|
||||
" return(vec4(0.));\n"
|
||||
" }\n"
|
||||
" return(texelFetch(src, coord, 0));\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec4 bilerpSrc(vec2 pos)\n"
|
||||
"{\n"
|
||||
" vec2 offset = fract(pos);\n"
|
||||
"\n"
|
||||
" ivec2 bl = ivec2(floor(pos));\n"
|
||||
"\n"
|
||||
" ivec2 br = bl + ivec2(1, 0);\n"
|
||||
" ivec2 tl = bl + ivec2(0, 1);\n"
|
||||
" ivec2 tr = bl + ivec2(1, 1);\n"
|
||||
"\n"
|
||||
" vec4 lerpTop = (1.-offset.x)*q(tl) + offset.x*q(tr);\n"
|
||||
" vec4 lerpBottom = (1.-offset.x)*q(bl) + offset.x*q(br);\n"
|
||||
" vec4 result = (1.-offset.y)*lerpBottom + offset.y*lerpTop;\n"
|
||||
"\n"
|
||||
" return(result);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" float texWidth = float(textureSize(velocity, 0).x);\n"
|
||||
"\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));\n"
|
||||
"\n"
|
||||
" vec2 samplePos = vec2(pixelCoord) - texWidth * delta * u(pixelCoord);\n"
|
||||
" fragColor = bilerpSrc(samplePos) / (1. + dissipation*delta);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/blit_div_fragment.glsl
|
||||
const char* glsl_blit_div_fragment =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"\n"
|
||||
"vec3 color_map(float v)\n"
|
||||
"{\n"
|
||||
" float logv = log(abs(v))/log(10.0);\n"
|
||||
" float f = floor(logv + 7.0);\n"
|
||||
" float i = floor(4.0*(logv + 7.0 - f));\n"
|
||||
"\n"
|
||||
" if(f < 0.0) return vec3(0.0);\n"
|
||||
" if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 6.0) return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" return vec3(1.0);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(tex, 0).xy)));\n"
|
||||
" float f = texelFetch(tex, pixelCoord, 0).x;\n"
|
||||
" fragColor = vec4(color_map(f), 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/blit_div_vertex.glsl
|
||||
const char* glsl_blit_div_vertex =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"\n"
|
||||
"in vec2 pos;\n"
|
||||
"out vec2 texCoord;\n"
|
||||
"\n"
|
||||
"uniform mat4 mvp;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" texCoord = 0.5*(pos + vec2(1,1));\n"
|
||||
" gl_Position = mvp * vec4(pos, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/blit_fragment.glsl
|
||||
const char* glsl_blit_fragment =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" fragColor = texture(tex, texCoord);\n"
|
||||
" fragColor.a = 1.0;\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/blit_residue_fragment.glsl
|
||||
const char* glsl_blit_residue_fragment =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D xTex;\n"
|
||||
"uniform sampler2D bTex;\n"
|
||||
"\n"
|
||||
"float x(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(xTex, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(xTex, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(xTex, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float b(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(bTex, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(bTex, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(bTex, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"vec3 color_map(float v)\n"
|
||||
"{\n"
|
||||
" float logv = log(abs(v))/log(10.0);\n"
|
||||
" float f = floor(logv + 7.0);\n"
|
||||
" float i = floor(4.0*(logv + 7.0 - f));\n"
|
||||
"\n"
|
||||
" if(f < 0.0) return vec3(0.0);\n"
|
||||
" if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 6.0) return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0);\n"
|
||||
" if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0);\n"
|
||||
" return vec3(1.0);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(xTex, 0).xy)));\n"
|
||||
"\n"
|
||||
" float tl = x(pixelCoord + ivec2(-1, 1));\n"
|
||||
" float tr = x(pixelCoord + ivec2(1, 1));\n"
|
||||
" float bl = x(pixelCoord + ivec2(-1, -1));\n"
|
||||
" float br = x(pixelCoord + ivec2(1, -1));\n"
|
||||
"\n"
|
||||
" float residue = b(pixelCoord) - (-tl - tr - bl - br + 4.*x(pixelCoord));\n"
|
||||
" fragColor = vec4(color_map(residue), 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/blit_vertex.glsl
|
||||
const char* glsl_blit_vertex =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"\n"
|
||||
"in vec2 pos;\n"
|
||||
"out vec2 texCoord;\n"
|
||||
"\n"
|
||||
"uniform mat4 mvp;\n"
|
||||
"uniform ivec2 gridSize;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" float margin = 32.;\n"
|
||||
" float ratio = 1. - 2.*margin/float(gridSize.x);\n"
|
||||
"\n"
|
||||
" texCoord = margin/float(gridSize.x) + ratio*(0.5*(pos + vec2(1,1)));\n"
|
||||
" gl_Position = mvp * vec4(pos, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/common_vertex.glsl
|
||||
const char* glsl_common_vertex =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"\n"
|
||||
"in vec2 pos;\n"
|
||||
"out vec2 texCoord;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" texCoord = 0.5*(pos + vec2(1,1));\n"
|
||||
" gl_Position = vec4(pos, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/divergence.glsl
|
||||
const char* glsl_divergence =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D src;\n"
|
||||
"\n"
|
||||
"vec2 u(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" return(texelFetch(src, coord, 0).xy);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));\n"
|
||||
"\n"
|
||||
" if( pixelCoord.x <= 0\n"
|
||||
" || pixelCoord.x >= textureSize(src, 0).x\n"
|
||||
" || pixelCoord.y <= 0\n"
|
||||
" || pixelCoord.y >= textureSize(src, 0).y)\n"
|
||||
" {\n"
|
||||
" fragColor = vec4(0, 0, 0, 1);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" vec2 tl = u(pixelCoord + ivec2(-1, 0));\n"
|
||||
" vec2 tr = u(pixelCoord);\n"
|
||||
" vec2 bl = u(pixelCoord + ivec2(-1, -1));\n"
|
||||
" vec2 br = u(pixelCoord + ivec2(0, -1));\n"
|
||||
"\n"
|
||||
" float r = (tr.x + br.x)/2.;\n"
|
||||
" float l = (tl.x + bl.x)/2.;\n"
|
||||
" float t = (tl.y + tr.y)/2.;\n"
|
||||
" float b = (bl.y + br.y)/2.;\n"
|
||||
"\n"
|
||||
" fragColor = vec4(-2.*(r - l + t - b), 0, 0, 1);\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/jacobi_step.glsl
|
||||
const char* glsl_jacobi_step =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D xTex;\n"
|
||||
"uniform sampler2D bTex;\n"
|
||||
"\n"
|
||||
"float x(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(xTex, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(xTex, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(xTex, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float b(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(bTex, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(bTex, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(bTex, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));\n"
|
||||
"\n"
|
||||
" if( pixelCoord.x <= 0\n"
|
||||
" || pixelCoord.y <= 0)\n"
|
||||
" {\n"
|
||||
" fragColor = vec4(0, 0, 0, 1);\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" float tl = x(pixelCoord + ivec2(-1, 1));\n"
|
||||
" float tr = x(pixelCoord + ivec2(1, 1));\n"
|
||||
" float bl = x(pixelCoord + ivec2(-1, -1));\n"
|
||||
" float br = x(pixelCoord + ivec2(1, -1));\n"
|
||||
"\n"
|
||||
" float jacobi = (tl + tr + bl + br + b(pixelCoord))/4.;\n"
|
||||
" fragColor = vec4(jacobi, 0, 0, 1);\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/multigrid_correct.glsl
|
||||
const char* glsl_multigrid_correct =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D src;\n"
|
||||
"uniform sampler2D error;\n"
|
||||
"uniform float invGridSize;\n"
|
||||
"\n"
|
||||
"float e(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(error, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(error, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(error, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float p(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(src, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(src, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(src, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));\n"
|
||||
" vec2 coarseCoord = vec2(pixelCoord)/2.;\n"
|
||||
" vec2 offset = fract(coarseCoord);\n"
|
||||
"\n"
|
||||
" ivec2 bl = ivec2(floor(coarseCoord));\n"
|
||||
" ivec2 br = bl + ivec2(1, 0);\n"
|
||||
" ivec2 tl = bl + ivec2(0, 1);\n"
|
||||
" ivec2 tr = bl + ivec2(1, 1);\n"
|
||||
"\n"
|
||||
" float topLerp = (1.-offset.x)*e(tl)+ offset.x*e(tr);\n"
|
||||
" float bottomLerp = (1.-offset.x)*e(bl) + offset.x*e(br);\n"
|
||||
" float bilerpError = (1.-offset.y)*bottomLerp + offset.y*topLerp;\n"
|
||||
"\n"
|
||||
" fragColor = vec4(p(pixelCoord) + bilerpError, 0, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/multigrid_restrict_residual.glsl
|
||||
const char* glsl_multigrid_restrict_residual =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D xTex;\n"
|
||||
"uniform sampler2D bTex;\n"
|
||||
"\n"
|
||||
"float x(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(xTex, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(xTex, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(xTex, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float b(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(bTex, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(bTex, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(bTex, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float residual(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" ivec2 vr = coord + ivec2(1, 0);\n"
|
||||
" ivec2 vl = coord - ivec2(1, 0);\n"
|
||||
" ivec2 vt = coord + ivec2(0, 1);\n"
|
||||
" ivec2 vb = coord - ivec2(0, 1);\n"
|
||||
"\n"
|
||||
" return((x(vl) + x(vr) + x(vt) + x(vb) + b(coord) - 4.*x(coord))*4.);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));\n"
|
||||
"\n"
|
||||
" float restricted = residual(2*pixelCoord + ivec2(-1, -1))\n"
|
||||
" + residual(2*pixelCoord + ivec2(1, -1))\n"
|
||||
" + residual(2*pixelCoord + ivec2(1, 1))\n"
|
||||
" + residual(2*pixelCoord + ivec2(-1, 1))\n"
|
||||
" + 2.*residual(2*pixelCoord + ivec2(-1, 0))\n"
|
||||
" + 2.*residual(2*pixelCoord + ivec2(1, 0))\n"
|
||||
" + 2.*residual(2*pixelCoord + ivec2(0, -1))\n"
|
||||
" + 2.*residual(2*pixelCoord + ivec2(0, 1))\n"
|
||||
" + 4.*residual(2*pixelCoord);\n"
|
||||
" restricted /= 16.;\n"
|
||||
" fragColor = vec4(restricted, 0, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/splat.glsl
|
||||
const char* glsl_splat =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D src;\n"
|
||||
"uniform vec2 splatPos;\n"
|
||||
"uniform vec3 splatColor;\n"
|
||||
"uniform float radius;\n"
|
||||
"uniform float additive;\n"
|
||||
"uniform float blending;\n"
|
||||
"\n"
|
||||
"uniform float randomize;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" float d2 = dot(texCoord - splatPos, texCoord - splatPos);\n"
|
||||
" float intensity = exp(-10.*d2/radius);\n"
|
||||
" vec2 force = splatColor.xy;\n"
|
||||
"\n"
|
||||
" vec3 u = texture(src, texCoord).xyz;\n"
|
||||
" vec3 uAdd = u + intensity*splatColor.xyz;\n"
|
||||
" vec3 uBlend = u*(1.-intensity) + intensity * splatColor;\n"
|
||||
"\n"
|
||||
" fragColor = vec4(uAdd*additive + uBlend*blending, 1);\n"
|
||||
"}\n";
|
||||
|
||||
//NOTE: string imported from src/shaders/subtract_pressure.glsl
|
||||
const char* glsl_subtract_pressure =
|
||||
"#version 300 es\n"
|
||||
"\n"
|
||||
"precision highp float;\n"
|
||||
"precision highp sampler2D;\n"
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"out vec4 fragColor;\n"
|
||||
"\n"
|
||||
"uniform sampler2D src;\n"
|
||||
"uniform sampler2D pressure;\n"
|
||||
"uniform float invGridSize;\n"
|
||||
"\n"
|
||||
"vec2 u(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" return(texelFetch(src, coord, 0).xy);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float p(ivec2 coord)\n"
|
||||
"{\n"
|
||||
" if( coord.x <= 0\n"
|
||||
" || coord.x >= textureSize(pressure, 0).x\n"
|
||||
" || coord.y <= 0\n"
|
||||
" || coord.y >= textureSize(pressure, 0).y)\n"
|
||||
" {\n"
|
||||
" return(0.);\n"
|
||||
" }\n"
|
||||
" return(texelFetch(pressure, coord, 0).x);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));\n"
|
||||
"\n"
|
||||
" float tl = p(pixelCoord + ivec2(0, 1));\n"
|
||||
" float tr = p(pixelCoord + ivec2(1, 1));\n"
|
||||
" float bl = p(pixelCoord);\n"
|
||||
" float br = p(pixelCoord + ivec2(1, 0));\n"
|
||||
"\n"
|
||||
" float r = (tr + br)/2.;\n"
|
||||
" float l = (tl + bl)/2.;\n"
|
||||
" float t = (tl + tr)/2.;\n"
|
||||
" float b = (bl + br)/2.;\n"
|
||||
"\n"
|
||||
" vec2 gradP = vec2(r - l, t - b);\n"
|
||||
"\n"
|
||||
" fragColor = vec4(u(pixelCoord) - gradP, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
#endif // __GLSL_SHADERS_H__
|
|
@ -0,0 +1,928 @@
|
|||
/************************************************************//**
|
||||
*
|
||||
* @file: main.cpp
|
||||
* @author: Martin Fouilleul
|
||||
* @date: 27/02/2022
|
||||
* @revision:
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include"orca.h"
|
||||
#include"glsl_shaders.h"
|
||||
|
||||
//----------------------------------------------------------------
|
||||
//NOTE(martin): GL vertex struct and identifiers
|
||||
//----------------------------------------------------------------
|
||||
typedef struct Vertex { float x, y; } Vertex;
|
||||
|
||||
typedef struct advect_program
|
||||
{
|
||||
GLuint prog;
|
||||
|
||||
GLint pos;
|
||||
GLint src;
|
||||
GLint velocity;
|
||||
GLint delta;
|
||||
GLint dissipation;
|
||||
|
||||
} advect_program;
|
||||
|
||||
typedef struct div_program
|
||||
{
|
||||
GLuint prog;
|
||||
GLint pos;
|
||||
GLint src;
|
||||
|
||||
} div_program;
|
||||
|
||||
typedef struct jacobi_program
|
||||
{
|
||||
GLuint prog;
|
||||
GLint pos;
|
||||
GLint xTex;
|
||||
GLint bTex;
|
||||
|
||||
} jacobi_program;
|
||||
|
||||
typedef struct blit_residue_program
|
||||
{
|
||||
GLuint prog;
|
||||
|
||||
GLint pos;
|
||||
GLint mvp;
|
||||
GLint xTex;
|
||||
GLint bTex;
|
||||
} blit_residue_program;
|
||||
|
||||
typedef struct multigrid_restrict_residual_program
|
||||
{
|
||||
GLuint prog;
|
||||
GLint pos;
|
||||
GLint xTex;
|
||||
GLint bTex;
|
||||
|
||||
} multigrid_restrict_residual_program;
|
||||
|
||||
typedef struct multigrid_correct_program
|
||||
{
|
||||
GLuint prog;
|
||||
GLint pos;
|
||||
GLint src;
|
||||
GLint error;
|
||||
GLint invGridSize;
|
||||
|
||||
} multigrid_correct_program;
|
||||
|
||||
typedef struct subtract_program
|
||||
{
|
||||
GLuint prog;
|
||||
|
||||
GLint pos;
|
||||
GLint src;
|
||||
GLint pressure;
|
||||
GLint invGridSize;
|
||||
|
||||
} subtract_program;
|
||||
|
||||
typedef struct blit_program
|
||||
{
|
||||
GLuint prog;
|
||||
|
||||
GLint pos;
|
||||
GLint mvp;
|
||||
GLint gridSize;
|
||||
GLint tex;
|
||||
} blit_program;
|
||||
|
||||
typedef struct splat_program
|
||||
{
|
||||
GLuint prog;
|
||||
|
||||
GLint pos;
|
||||
GLint src;
|
||||
GLint splatPos;
|
||||
GLint splatColor;
|
||||
GLint radius;
|
||||
GLint additive;
|
||||
GLint blending;
|
||||
GLint randomize;
|
||||
|
||||
} splat_program;
|
||||
|
||||
typedef struct frame_buffer
|
||||
{
|
||||
GLuint textures[2];
|
||||
GLuint fbos[2];
|
||||
} frame_buffer;
|
||||
|
||||
advect_program advectProgram;
|
||||
div_program divProgram;
|
||||
jacobi_program jacobiProgram;
|
||||
multigrid_restrict_residual_program multigridRestrictResidualProgram;
|
||||
multigrid_correct_program multigridCorrectProgram;
|
||||
|
||||
subtract_program subtractProgram;
|
||||
splat_program splatProgram;
|
||||
blit_program blitProgram;
|
||||
blit_program blitDivProgram;
|
||||
blit_residue_program blitResidueProgram;
|
||||
|
||||
frame_buffer colorBuffer;
|
||||
frame_buffer velocityBuffer;
|
||||
|
||||
const int MULTIGRID_COUNT = 4;
|
||||
frame_buffer pressureBuffer[4];
|
||||
frame_buffer divBuffer[4];
|
||||
|
||||
GLuint vertexBuffer;
|
||||
|
||||
//----------------------------------------------------------------
|
||||
//NOTE(martin): initialization
|
||||
//----------------------------------------------------------------
|
||||
|
||||
GLuint compile_shader(const char* vs, const char* fs)
|
||||
{
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vs, 0);
|
||||
glCompileShader(vertexShader);
|
||||
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fs, 0);
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
GLuint prog = glCreateProgram();
|
||||
glAttachShader(prog, vertexShader);
|
||||
glAttachShader(prog, fragmentShader);
|
||||
glLinkProgram(prog);
|
||||
|
||||
|
||||
//TODO errors
|
||||
int status = 0;
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
||||
if(status != GL_TRUE)
|
||||
{
|
||||
log_error("program failed to link: ");
|
||||
int logSize = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logSize);
|
||||
|
||||
mem_arena_scope scratch = mem_scratch_begin();
|
||||
char* log = mem_arena_alloc(scratch.arena, logSize);
|
||||
|
||||
glGetProgramInfoLog(prog, logSize, 0, log);
|
||||
log_error("%s\n", log);
|
||||
|
||||
mem_scratch_end(scratch);
|
||||
}
|
||||
|
||||
int err = glGetError();
|
||||
if(err)
|
||||
{
|
||||
log_error("gl error %i\n", err);
|
||||
}
|
||||
|
||||
return(prog);
|
||||
}
|
||||
|
||||
void init_advect(advect_program* program)
|
||||
{
|
||||
log_info("compiling advect...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_advect);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
program->velocity = glGetUniformLocation(program->prog, "velocity");
|
||||
program->delta = glGetUniformLocation(program->prog, "delta");
|
||||
program->dissipation = glGetUniformLocation(program->prog, "dissipation");
|
||||
}
|
||||
|
||||
void init_div(div_program* program)
|
||||
{
|
||||
log_info("compiling div...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_divergence);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
}
|
||||
|
||||
void init_jacobi(jacobi_program* program)
|
||||
{
|
||||
log_info("compiling jacobi...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_jacobi_step);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
||||
program->bTex = glGetUniformLocation(program->prog, "bTex");
|
||||
}
|
||||
|
||||
void init_multigrid_restrict_residual(multigrid_restrict_residual_program* program)
|
||||
{
|
||||
log_info("compiling multigrid restrict residual...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_multigrid_restrict_residual);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
||||
program->bTex = glGetUniformLocation(program->prog, "bTex");
|
||||
}
|
||||
|
||||
void init_multigrid_correct(multigrid_correct_program* program)
|
||||
{
|
||||
log_info("compiling multigrid correct...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_multigrid_correct);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
program->error = glGetUniformLocation(program->prog, "error");
|
||||
program->invGridSize = glGetUniformLocation(program->prog, "invGridSize");
|
||||
}
|
||||
|
||||
void init_subtract(subtract_program* program)
|
||||
{
|
||||
log_info("compiling subtract...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_subtract_pressure);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
program->pressure = glGetUniformLocation(program->prog, "pressure");
|
||||
program->invGridSize = glGetUniformLocation(program->prog, "invGridSize");
|
||||
}
|
||||
|
||||
void init_splat(splat_program* program)
|
||||
{
|
||||
log_info("compiling splat...");
|
||||
program->prog = compile_shader(glsl_common_vertex, glsl_splat);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->src = glGetUniformLocation(program->prog, "src");
|
||||
program->splatPos = glGetUniformLocation(program->prog, "splatPos");
|
||||
program->splatColor = glGetUniformLocation(program->prog, "splatColor");
|
||||
program->radius = glGetUniformLocation(program->prog, "radius");
|
||||
program->additive = glGetUniformLocation(program->prog, "additive");
|
||||
program->blending = glGetUniformLocation(program->prog, "blending");
|
||||
program->randomize = glGetUniformLocation(program->prog, "randomize");
|
||||
}
|
||||
|
||||
void init_blit(blit_program* program)
|
||||
{
|
||||
log_info("compiling blit...");
|
||||
program->prog = compile_shader(glsl_blit_vertex, glsl_blit_fragment);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||
program->tex = glGetUniformLocation(program->prog, "tex");
|
||||
program->gridSize = glGetUniformLocation(program->prog, "gridSize");
|
||||
}
|
||||
|
||||
void init_blit_div(blit_program* program)
|
||||
{
|
||||
log_info("compiling blit div...");
|
||||
program->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_div_fragment);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||
program->tex = glGetUniformLocation(program->prog, "tex");
|
||||
}
|
||||
|
||||
void init_blit_residue(blit_residue_program* program)
|
||||
{
|
||||
log_info("compiling blit residue...");
|
||||
program->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_residue_fragment);
|
||||
program->pos = glGetAttribLocation(program->prog, "pos");
|
||||
program->mvp = glGetUniformLocation(program->prog, "mvp");
|
||||
program->xTex = glGetUniformLocation(program->prog, "xTex");
|
||||
program->bTex = glGetUniformLocation(program->prog, "bTex");
|
||||
}
|
||||
|
||||
|
||||
GLuint create_texture(int width, int height, GLenum internalFormat, GLenum format, GLenum type, char* initData)
|
||||
{
|
||||
GLuint texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, initData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
return(texture);
|
||||
}
|
||||
|
||||
GLuint create_fbo(GLuint texture)
|
||||
{
|
||||
GLuint fbo;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||
return(fbo);
|
||||
}
|
||||
|
||||
void init_frame_buffer(frame_buffer* framebuffer,
|
||||
int width,
|
||||
int height,
|
||||
GLenum internalFormat,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
char* initData)
|
||||
{
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
framebuffer->textures[i] = create_texture(width, height, internalFormat, format, type, initData);
|
||||
framebuffer->fbos[i] = create_fbo(framebuffer->textures[i]);
|
||||
}
|
||||
|
||||
GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if(err != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
log_info("Frame buffer incomplete, %i", err);
|
||||
}
|
||||
}
|
||||
|
||||
void frame_buffer_swap(frame_buffer* buffer)
|
||||
{
|
||||
GLuint tmp = buffer->fbos[0];
|
||||
buffer->fbos[0] = buffer->fbos[1];
|
||||
buffer->fbos[1] = tmp;
|
||||
|
||||
tmp = buffer->textures[0];
|
||||
buffer->textures[0] = buffer->textures[1];
|
||||
buffer->textures[1] = tmp;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------
|
||||
//NOTE(martin): entry point
|
||||
//----------------------------------------------------------------
|
||||
|
||||
#define texWidth (256)
|
||||
#define texHeight (256)
|
||||
|
||||
float colorInitData[texWidth][texHeight][4] = {0};
|
||||
float velocityInitData[texWidth][texHeight][4] = {0};
|
||||
|
||||
const float EPSILON = 1.,
|
||||
INV_GRID_SIZE = 1./(float)texWidth,
|
||||
DELTA = 1./120.;
|
||||
|
||||
const GLenum TEX_INTERNAL_FORMAT = GL_RGBA32F;
|
||||
const GLenum TEX_FORMAT = GL_RGBA;
|
||||
const GLenum TEX_TYPE = GL_FLOAT;
|
||||
|
||||
#define square(x) ((x)*(x))
|
||||
|
||||
/*
|
||||
void reset_texture(GLuint texture, float width, float height, char* initData)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, TEX_INTERNAL_FORMAT, width, height, 0, TEX_FORMAT, TEX_TYPE, initData);
|
||||
}
|
||||
|
||||
static bool resetCmd = false;
|
||||
|
||||
void reset()
|
||||
{
|
||||
// resetCmd = true;
|
||||
log_info("reset");
|
||||
|
||||
reset_texture(colorBuffer.textures[0], texWidth, texHeight, (char*)colorInitData);
|
||||
reset_texture(colorBuffer.textures[1], texWidth, texHeight, (char*)colorInitData);
|
||||
reset_texture(velocityBuffer.textures[0], texWidth, texHeight, (char*)velocityInitData);
|
||||
reset_texture(velocityBuffer.textures[1], texWidth, texHeight, (char*)velocityInitData);
|
||||
|
||||
int gridFactor = 1;
|
||||
for(int i=0; i<MULTIGRID_COUNT; i++)
|
||||
{
|
||||
reset_texture(pressureBuffer[i].textures[0], texWidth/gridFactor, texHeight/gridFactor, 0);
|
||||
reset_texture(pressureBuffer[i].textures[1], texWidth/gridFactor, texHeight/gridFactor, 0);
|
||||
|
||||
gridFactor *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
typedef struct mouse_input
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float deltaX;
|
||||
float deltaY;
|
||||
bool down;
|
||||
|
||||
} mouse_input;
|
||||
|
||||
mouse_input mouseInput = {0};
|
||||
|
||||
int frameWidth = 800;
|
||||
int frameHeight = 600;
|
||||
|
||||
|
||||
ORCA_EXPORT void OnMouseDown(int button)
|
||||
{
|
||||
mouseInput.down = true;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnMouseUp(int button)
|
||||
{
|
||||
mouseInput.down = false;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnMouseMove(float x, float y, float dx, float dy)
|
||||
{
|
||||
mouseInput.x = x * 2;
|
||||
mouseInput.y = y * 2;
|
||||
mouseInput.deltaX = dx * 2;
|
||||
mouseInput.deltaY = dy * 2;
|
||||
}
|
||||
|
||||
void init_color_checker()
|
||||
{
|
||||
for(int i=0; i<texHeight; i++)
|
||||
{
|
||||
for(int j=0; j<texWidth; j++)
|
||||
{
|
||||
float u = j/(float)texWidth;
|
||||
float v = i/(float)texWidth;
|
||||
float value = ((int)(u*10)%2) == ((int)(v*10)%2) ? 1. : 0.;
|
||||
|
||||
for(int k = 0; k<3; k++)
|
||||
{
|
||||
colorInitData[i][j][k] = value;
|
||||
}
|
||||
colorInitData[i][j][3] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_velocity_vortex()
|
||||
{
|
||||
for(int i=0; i<texHeight; i++)
|
||||
{
|
||||
for(int j=0; j<texWidth; j++)
|
||||
{
|
||||
float x = 2*j/(float)texWidth - 1;
|
||||
float y = 2*i/(float)texWidth - 1;
|
||||
velocityInitData[i][j][0] = sinf(2*M_PI*y);
|
||||
velocityInitData[i][j][1] = sinf(2*M_PI*x);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply_splat(float splatPosX, float splatPosY, float radius, float splatVelX, float splatVelY, float r, float g, float b, bool randomize)
|
||||
{
|
||||
glUseProgram(splatProgram.prog);
|
||||
|
||||
if(randomize)
|
||||
{
|
||||
glUniform1f(splatProgram.randomize, 1.);
|
||||
}
|
||||
else
|
||||
{
|
||||
glUniform1f(splatProgram.randomize, 0.);
|
||||
}
|
||||
|
||||
// force
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(splatProgram.src, 0);
|
||||
|
||||
glUniform2f(splatProgram.splatPos, splatPosX, splatPosY);
|
||||
glUniform3f(splatProgram.splatColor, splatVelX, splatVelY, 0);
|
||||
glUniform1f(splatProgram.additive, 1);
|
||||
glUniform1f(splatProgram.blending, 0);
|
||||
|
||||
glUniform1f(splatProgram.radius, radius);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&velocityBuffer);
|
||||
|
||||
// dye
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, colorBuffer.fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
|
||||
glUniform1i(splatProgram.src, 0);
|
||||
|
||||
glUniform2f(splatProgram.splatPos, splatPosX, splatPosY);
|
||||
glUniform3f(splatProgram.splatColor, r, g, b);
|
||||
glUniform1f(splatProgram.additive, 0);
|
||||
glUniform1f(splatProgram.blending, 1);
|
||||
glUniform1f(splatProgram.radius, radius);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&colorBuffer);
|
||||
|
||||
}
|
||||
|
||||
void jacobi_solve(frame_buffer* x, frame_buffer* b, float invGridSize, int iterationCount)
|
||||
{
|
||||
glUseProgram(jacobiProgram.prog);
|
||||
|
||||
for(int i=0; i<iterationCount; i++)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, x->fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, x->textures[0]);
|
||||
glUniform1i(jacobiProgram.xTex, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, b->textures[0]);
|
||||
glUniform1i(jacobiProgram.bTex, 1);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(x);
|
||||
}
|
||||
}
|
||||
|
||||
void multigrid_coarsen_residual(frame_buffer* output, frame_buffer* x, frame_buffer* b, float invFineGridSize)
|
||||
{
|
||||
//NOTE: compute residual and downsample to coarser grid, put result in coarser buffer
|
||||
glUseProgram(multigridRestrictResidualProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, output->fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, x->textures[0]);
|
||||
glUniform1i(multigridRestrictResidualProgram.xTex, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, b->textures[0]);
|
||||
glUniform1i(multigridRestrictResidualProgram.bTex, 1);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(output);
|
||||
}
|
||||
|
||||
void multigrid_prolongate_and_correct(frame_buffer* x, frame_buffer* error, float invFineGridSize)
|
||||
{
|
||||
//NOTE: correct finer pressure
|
||||
glUseProgram(multigridCorrectProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, x->fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, x->textures[0]);
|
||||
glUniform1i(multigridCorrectProgram.src, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, error->textures[0]);
|
||||
glUniform1i(multigridCorrectProgram.error, 1);
|
||||
|
||||
glUniform1f(multigridCorrectProgram.invGridSize, invFineGridSize);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(x);
|
||||
}
|
||||
|
||||
void multigrid_clear(frame_buffer* error)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, error->fbos[0]);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void input_splat(float t)
|
||||
{
|
||||
//NOTE: apply force and dye
|
||||
if(mouseInput.down && (mouseInput.deltaX || mouseInput.deltaY))
|
||||
{
|
||||
// account for margin
|
||||
float margin = 32;
|
||||
|
||||
float offset = margin/texWidth;
|
||||
float ratio = 1 - 2*margin/texWidth;
|
||||
|
||||
float splatPosX = (mouseInput.x/frameWidth)*ratio + offset;
|
||||
float splatPosY = (1 - mouseInput.y/frameHeight)*ratio + offset;
|
||||
|
||||
float splatVelX = (10000.*DELTA*mouseInput.deltaX/frameWidth)*ratio;
|
||||
float splatVelY = (-10000.*DELTA*mouseInput.deltaY/frameWidth)*ratio;
|
||||
|
||||
float intensity = 100*sqrtf(square(ratio*mouseInput.deltaX/frameWidth) + square(ratio*mouseInput.deltaY/frameHeight));
|
||||
|
||||
float r = intensity * (sinf(2*M_PI*0.1*t) + 1);
|
||||
float g = 0.5*intensity * (cosf(2*M_PI*0.1/M_E*t + 654) + 1);
|
||||
float b = intensity * (sinf(2*M_PI*0.1/M_SQRT2*t + 937) + 1);
|
||||
|
||||
float radius = 0.005;
|
||||
|
||||
apply_splat(splatPosX, splatPosY, radius, splatVelX, splatVelY, r, g, b, false);
|
||||
|
||||
mouseInput.deltaX = 0;
|
||||
mouseInput.deltaY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
float testDiv[texWidth/2][texWidth/2][4];
|
||||
|
||||
mg_surface surface;
|
||||
|
||||
ORCA_EXPORT void OnInit()
|
||||
{
|
||||
log_info("Hello, world (from C)");
|
||||
|
||||
surface = mg_surface_gles();
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
// init_color_checker();
|
||||
// init_velocity_vortex();
|
||||
|
||||
// init programs
|
||||
init_advect(&advectProgram);
|
||||
init_div(&divProgram);
|
||||
init_jacobi(&jacobiProgram);
|
||||
init_multigrid_restrict_residual(&multigridRestrictResidualProgram);
|
||||
init_multigrid_correct(&multigridCorrectProgram);
|
||||
init_blit_residue(&blitResidueProgram);
|
||||
|
||||
init_subtract(&subtractProgram);
|
||||
init_splat(&splatProgram);
|
||||
init_blit(&blitProgram);
|
||||
init_blit_div(&blitDivProgram);
|
||||
|
||||
// init frame buffers
|
||||
log_info("create color buffer");
|
||||
init_frame_buffer(&colorBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)colorInitData);
|
||||
log_info("create velocity buffer");
|
||||
init_frame_buffer(&velocityBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)velocityInitData);
|
||||
|
||||
int gridFactor = 1;
|
||||
for(int i=0; i<MULTIGRID_COUNT; i++)
|
||||
{
|
||||
log_info("create div buffer %i", i);
|
||||
init_frame_buffer(&divBuffer[i], texWidth/gridFactor, texHeight/gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
|
||||
log_info("create pressure buffer %i", i);
|
||||
init_frame_buffer(&pressureBuffer[i], texWidth/gridFactor, texHeight/gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
|
||||
gridFactor *= 2;
|
||||
}
|
||||
|
||||
// init vertex buffer
|
||||
static Vertex vertices[6] =
|
||||
{
|
||||
{-1, -1},
|
||||
{ 1, -1},
|
||||
{ 1, 1},
|
||||
{-1, -1},
|
||||
{ 1, 1},
|
||||
{ -1, 1}
|
||||
};
|
||||
|
||||
//WARN: we assume blitProgram.pos == advectProgram.pos, is there a situation where it wouldn't be true??
|
||||
GLuint vertexBuffer = 0;
|
||||
glGenBuffers(1, &vertexBuffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, 6*sizeof(Vertex), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(blitProgram.pos, 2, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
|
||||
for(int i=0; i<texWidth/2; i++)
|
||||
{
|
||||
for(int j=0; j<texHeight/2; j++)
|
||||
{
|
||||
testDiv[i][j][0] = 0.5 + 0.5*cosf(j/100.*3.14159 + i/100.*1.2139);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
{
|
||||
frameWidth = width*2;
|
||||
frameHeight = height*2;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh()
|
||||
{
|
||||
float aspectRatio = texWidth/texHeight; //TODO replace with actual aspect ratio?
|
||||
|
||||
static float t = 0;
|
||||
t += 1./60.;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
glViewport(0, 0, texWidth, texHeight);
|
||||
|
||||
//NOTE: advect velocity thru itself
|
||||
glUseProgram(advectProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(advectProgram.src, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(advectProgram.velocity, 1);
|
||||
|
||||
glUniform1f(advectProgram.delta, DELTA);
|
||||
glUniform1f(advectProgram.dissipation, 0.01);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&velocityBuffer);
|
||||
|
||||
/*
|
||||
//DEBUG
|
||||
static bool splatTrig = false;
|
||||
static bool splat = false;
|
||||
static float splatStart = 0;
|
||||
static int splatDir = 0;
|
||||
|
||||
static int frameCount = 0;
|
||||
|
||||
if(resetCmd)
|
||||
{
|
||||
frameCount = 0;
|
||||
splat = true;
|
||||
splatStart = frameT;
|
||||
}
|
||||
|
||||
if(splat)
|
||||
{
|
||||
if(frameT - splatStart >= 0.5)
|
||||
{
|
||||
splat = false;
|
||||
splatDir++;
|
||||
splatDir = splatDir % 3;
|
||||
}
|
||||
float dirX = 0;
|
||||
float dirY = 0;
|
||||
if(splatDir == 0)
|
||||
{
|
||||
dirX = 0;
|
||||
dirY = 0.3;
|
||||
}
|
||||
if(splatDir == 1)
|
||||
{
|
||||
dirX = 0.3;
|
||||
dirY = 0;
|
||||
}
|
||||
if(splatDir == 2)
|
||||
{
|
||||
dirX = 0.2121;
|
||||
dirY = 0.2121;
|
||||
}
|
||||
apply_splat(0.5, 0.5, dirX, dirY, 1.5, 1., 0.1, false);
|
||||
}
|
||||
resetCmd = false;
|
||||
|
||||
if(frameCount>20)
|
||||
{
|
||||
return;
|
||||
}
|
||||
frameCount++;
|
||||
*/
|
||||
|
||||
input_splat(t);
|
||||
|
||||
|
||||
//NOTE: compute divergence of advected velocity
|
||||
glUseProgram(divProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, divBuffer[0].fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(divProgram.src, 0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&divBuffer[0]);
|
||||
|
||||
//NOTE: compute pressure
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, pressureBuffer[0].fbos[1]);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
#if 0
|
||||
multigrid_clear(&pressureBuffer[0]);
|
||||
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, texWidth*texHeight);
|
||||
#else
|
||||
multigrid_clear(&pressureBuffer[0]);
|
||||
|
||||
for(int i=0; i<1; i++)
|
||||
{
|
||||
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 2);
|
||||
multigrid_coarsen_residual(&divBuffer[1], &pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE);
|
||||
|
||||
multigrid_clear(&pressureBuffer[1]);
|
||||
jacobi_solve(&pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 2);
|
||||
multigrid_coarsen_residual(&divBuffer[2], &pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE);
|
||||
|
||||
multigrid_clear(&pressureBuffer[2]);
|
||||
jacobi_solve(&pressureBuffer[2], &divBuffer[2], 4*INV_GRID_SIZE, 30);
|
||||
|
||||
multigrid_prolongate_and_correct(&pressureBuffer[1], &pressureBuffer[2], 2*INV_GRID_SIZE);
|
||||
jacobi_solve(&pressureBuffer[1], &divBuffer[1], 2*INV_GRID_SIZE, 8);
|
||||
|
||||
multigrid_prolongate_and_correct(&pressureBuffer[0], &pressureBuffer[1], INV_GRID_SIZE);
|
||||
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 4);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//NOTE: subtract pressure gradient to advected velocity
|
||||
glUseProgram(subtractProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(subtractProgram.src, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, pressureBuffer[0].textures[0]);
|
||||
glUniform1i(subtractProgram.pressure, 1);
|
||||
|
||||
glUniform1f(subtractProgram.invGridSize, INV_GRID_SIZE);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&velocityBuffer);
|
||||
|
||||
//NOTE: Advect color through corrected velocity field
|
||||
glUseProgram(advectProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, colorBuffer.fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
|
||||
glUniform1i(advectProgram.src, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(advectProgram.velocity, 1);
|
||||
|
||||
glUniform1f(advectProgram.delta, DELTA);
|
||||
|
||||
glUniform1f(advectProgram.dissipation, 0.001);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&colorBuffer);
|
||||
|
||||
//NOTE: Blit color texture to screen
|
||||
|
||||
//NOTE: blit residue to screen
|
||||
glViewport(0, 0, frameWidth, frameHeight);
|
||||
|
||||
float displayMatrix[16] = {
|
||||
1/aspectRatio, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1 };
|
||||
|
||||
/*
|
||||
glUseProgram(blitResidueProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, pressureBuffer[0].textures[0]);
|
||||
glUniform1i(blitResidueProgram.xTex, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, divBuffer[0].textures[0]);
|
||||
glUniform1i(blitResidueProgram.bTex, 1);
|
||||
|
||||
glUniformMatrix4fv(blitResidueProgram.mvp, 1, GL_FALSE, displayMatrix);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
//*/
|
||||
//*
|
||||
glUseProgram(blitProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
|
||||
glUniform1i(blitProgram.tex, 0);
|
||||
|
||||
glUniform2i(blitProgram.gridSize, texWidth, texHeight);
|
||||
|
||||
glUniformMatrix4fv(blitProgram.mvp, 1, GL_FALSE, displayMatrix);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
/*/
|
||||
|
||||
//NOTE: recompute divergence of (corrected) velocity
|
||||
glUseProgram(divProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, divBuffer[0].fbos[1]);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
|
||||
glUniform1i(divProgram.src, 0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
frame_buffer_swap(&divBuffer[0]);
|
||||
|
||||
//NOTE: Blit divergence to screen
|
||||
glViewport(0, 0, canvas_width(), canvas_height());
|
||||
glUseProgram(blitDivProgram.prog);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, divBuffer[0].textures[0]);
|
||||
glUniform1i(blitDivProgram.tex, 0);
|
||||
|
||||
glUniformMatrix4fv(blitDivProgram.mvp, 1, GL_FALSE, displayMatrix);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
|
||||
//*/
|
||||
|
||||
mg_surface_present(surface);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D src;
|
||||
uniform sampler2D velocity;
|
||||
uniform float delta;
|
||||
uniform float dissipation;
|
||||
|
||||
vec2 u(ivec2 coord)
|
||||
{
|
||||
return(texelFetch(velocity, coord, 0).xy);
|
||||
}
|
||||
|
||||
vec4 q(ivec2 coord)
|
||||
{
|
||||
if( coord.x < 0
|
||||
|| coord.x >= textureSize(src, 0).x
|
||||
|| coord.y < 0
|
||||
|| coord.y >= textureSize(src, 0).y)
|
||||
{
|
||||
return(vec4(0.));
|
||||
}
|
||||
return(texelFetch(src, coord, 0));
|
||||
}
|
||||
|
||||
vec4 bilerpSrc(vec2 pos)
|
||||
{
|
||||
vec2 offset = fract(pos);
|
||||
|
||||
ivec2 bl = ivec2(floor(pos));
|
||||
|
||||
ivec2 br = bl + ivec2(1, 0);
|
||||
ivec2 tl = bl + ivec2(0, 1);
|
||||
ivec2 tr = bl + ivec2(1, 1);
|
||||
|
||||
vec4 lerpTop = (1.-offset.x)*q(tl) + offset.x*q(tr);
|
||||
vec4 lerpBottom = (1.-offset.x)*q(bl) + offset.x*q(br);
|
||||
vec4 result = (1.-offset.y)*lerpBottom + offset.y*lerpTop;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float texWidth = float(textureSize(velocity, 0).x);
|
||||
|
||||
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
|
||||
|
||||
vec2 samplePos = vec2(pixelCoord) - texWidth * delta * u(pixelCoord);
|
||||
fragColor = bilerpSrc(samplePos) / (1. + dissipation*delta);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
vec3 color_map(float v)
|
||||
{
|
||||
float logv = log(abs(v))/log(10.0);
|
||||
float f = floor(logv + 7.0);
|
||||
float i = floor(4.0*(logv + 7.0 - f));
|
||||
|
||||
if(f < 0.0) return vec3(0.0);
|
||||
if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0);
|
||||
if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0);
|
||||
if(f < 6.0) return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i/4.0);
|
||||
if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0);
|
||||
return vec3(1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(tex, 0).xy)));
|
||||
float f = texelFetch(tex, pixelCoord, 0).x;
|
||||
fragColor = vec4(color_map(f), 1.0);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
|
||||
in vec2 pos;
|
||||
out vec2 texCoord;
|
||||
|
||||
uniform mat4 mvp;
|
||||
|
||||
void main()
|
||||
{
|
||||
texCoord = 0.5*(pos + vec2(1,1));
|
||||
gl_Position = mvp * vec4(pos, 0, 1);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragColor = texture(tex, texCoord);
|
||||
fragColor.a = 1.0;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D xTex;
|
||||
uniform sampler2D bTex;
|
||||
|
||||
float x(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(xTex, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(xTex, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(xTex, coord, 0).x);
|
||||
}
|
||||
|
||||
float b(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(bTex, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(bTex, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(bTex, coord, 0).x);
|
||||
}
|
||||
|
||||
vec3 color_map(float v)
|
||||
{
|
||||
float logv = log(abs(v))/log(10.0);
|
||||
float f = floor(logv + 7.0);
|
||||
float i = floor(4.0*(logv + 7.0 - f));
|
||||
|
||||
if(f < 0.0) return vec3(0.0);
|
||||
if(f < 1.0) return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 2.0) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 3.0) return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i/4.0);
|
||||
if(f < 4.0) return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 5.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i/4.0);
|
||||
if(f < 6.0) return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i/4.0);
|
||||
if(f < 7.0) return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i/4.0);
|
||||
if(f < 8.0) return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i/4.0);
|
||||
return vec3(1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(xTex, 0).xy)));
|
||||
|
||||
float tl = x(pixelCoord + ivec2(-1, 1));
|
||||
float tr = x(pixelCoord + ivec2(1, 1));
|
||||
float bl = x(pixelCoord + ivec2(-1, -1));
|
||||
float br = x(pixelCoord + ivec2(1, -1));
|
||||
|
||||
float residue = b(pixelCoord) - (-tl - tr - bl - br + 4.*x(pixelCoord));
|
||||
fragColor = vec4(color_map(residue), 1);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
|
||||
in vec2 pos;
|
||||
out vec2 texCoord;
|
||||
|
||||
uniform mat4 mvp;
|
||||
uniform ivec2 gridSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
float margin = 32.;
|
||||
float ratio = 1. - 2.*margin/float(gridSize.x);
|
||||
|
||||
texCoord = margin/float(gridSize.x) + ratio*(0.5*(pos + vec2(1,1)));
|
||||
gl_Position = mvp * vec4(pos, 0, 1);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
|
||||
in vec2 pos;
|
||||
out vec2 texCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
texCoord = 0.5*(pos + vec2(1,1));
|
||||
gl_Position = vec4(pos, 0, 1);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D src;
|
||||
|
||||
vec2 u(ivec2 coord)
|
||||
{
|
||||
return(texelFetch(src, coord, 0).xy);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
|
||||
|
||||
if( pixelCoord.x <= 0
|
||||
|| pixelCoord.x >= textureSize(src, 0).x
|
||||
|| pixelCoord.y <= 0
|
||||
|| pixelCoord.y >= textureSize(src, 0).y)
|
||||
{
|
||||
fragColor = vec4(0, 0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec2 tl = u(pixelCoord + ivec2(-1, 0));
|
||||
vec2 tr = u(pixelCoord);
|
||||
vec2 bl = u(pixelCoord + ivec2(-1, -1));
|
||||
vec2 br = u(pixelCoord + ivec2(0, -1));
|
||||
|
||||
float r = (tr.x + br.x)/2.;
|
||||
float l = (tl.x + bl.x)/2.;
|
||||
float t = (tl.y + tr.y)/2.;
|
||||
float b = (bl.y + br.y)/2.;
|
||||
|
||||
fragColor = vec4(-2.*(r - l + t - b), 0, 0, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D xTex;
|
||||
uniform sampler2D bTex;
|
||||
|
||||
float x(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(xTex, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(xTex, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(xTex, coord, 0).x);
|
||||
}
|
||||
|
||||
float b(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(bTex, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(bTex, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(bTex, coord, 0).x);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
|
||||
|
||||
if( pixelCoord.x <= 0
|
||||
|| pixelCoord.y <= 0)
|
||||
{
|
||||
fragColor = vec4(0, 0, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
float tl = x(pixelCoord + ivec2(-1, 1));
|
||||
float tr = x(pixelCoord + ivec2(1, 1));
|
||||
float bl = x(pixelCoord + ivec2(-1, -1));
|
||||
float br = x(pixelCoord + ivec2(1, -1));
|
||||
|
||||
float jacobi = (tl + tr + bl + br + b(pixelCoord))/4.;
|
||||
fragColor = vec4(jacobi, 0, 0, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D src;
|
||||
uniform sampler2D error;
|
||||
uniform float invGridSize;
|
||||
|
||||
float e(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(error, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(error, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(error, coord, 0).x);
|
||||
}
|
||||
|
||||
float p(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(src, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(src, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(src, coord, 0).x);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
|
||||
vec2 coarseCoord = vec2(pixelCoord)/2.;
|
||||
vec2 offset = fract(coarseCoord);
|
||||
|
||||
ivec2 bl = ivec2(floor(coarseCoord));
|
||||
ivec2 br = bl + ivec2(1, 0);
|
||||
ivec2 tl = bl + ivec2(0, 1);
|
||||
ivec2 tr = bl + ivec2(1, 1);
|
||||
|
||||
float topLerp = (1.-offset.x)*e(tl)+ offset.x*e(tr);
|
||||
float bottomLerp = (1.-offset.x)*e(bl) + offset.x*e(br);
|
||||
float bilerpError = (1.-offset.y)*bottomLerp + offset.y*topLerp;
|
||||
|
||||
fragColor = vec4(p(pixelCoord) + bilerpError, 0, 0, 1);
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D xTex;
|
||||
uniform sampler2D bTex;
|
||||
|
||||
float x(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(xTex, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(xTex, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(xTex, coord, 0).x);
|
||||
}
|
||||
|
||||
float b(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(bTex, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(bTex, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(bTex, coord, 0).x);
|
||||
}
|
||||
|
||||
float residual(ivec2 coord)
|
||||
{
|
||||
ivec2 vr = coord + ivec2(1, 0);
|
||||
ivec2 vl = coord - ivec2(1, 0);
|
||||
ivec2 vt = coord + ivec2(0, 1);
|
||||
ivec2 vb = coord - ivec2(0, 1);
|
||||
|
||||
return((x(vl) + x(vr) + x(vt) + x(vb) + b(coord) - 4.*x(coord))*4.);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
|
||||
|
||||
float restricted = residual(2*pixelCoord + ivec2(-1, -1))
|
||||
+ residual(2*pixelCoord + ivec2(1, -1))
|
||||
+ residual(2*pixelCoord + ivec2(1, 1))
|
||||
+ residual(2*pixelCoord + ivec2(-1, 1))
|
||||
+ 2.*residual(2*pixelCoord + ivec2(-1, 0))
|
||||
+ 2.*residual(2*pixelCoord + ivec2(1, 0))
|
||||
+ 2.*residual(2*pixelCoord + ivec2(0, -1))
|
||||
+ 2.*residual(2*pixelCoord + ivec2(0, 1))
|
||||
+ 4.*residual(2*pixelCoord);
|
||||
restricted /= 16.;
|
||||
fragColor = vec4(restricted, 0, 0, 1);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D src;
|
||||
uniform vec2 splatPos;
|
||||
uniform vec3 splatColor;
|
||||
uniform float radius;
|
||||
uniform float additive;
|
||||
uniform float blending;
|
||||
|
||||
uniform float randomize;
|
||||
|
||||
void main()
|
||||
{
|
||||
float d2 = dot(texCoord - splatPos, texCoord - splatPos);
|
||||
float intensity = exp(-10.*d2/radius);
|
||||
vec2 force = splatColor.xy;
|
||||
|
||||
vec3 u = texture(src, texCoord).xyz;
|
||||
vec3 uAdd = u + intensity*splatColor.xyz;
|
||||
vec3 uBlend = u*(1.-intensity) + intensity * splatColor;
|
||||
|
||||
fragColor = vec4(uAdd*additive + uBlend*blending, 1);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#version 300 es
|
||||
|
||||
precision highp float;
|
||||
precision highp sampler2D;
|
||||
|
||||
in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D src;
|
||||
uniform sampler2D pressure;
|
||||
uniform float invGridSize;
|
||||
|
||||
vec2 u(ivec2 coord)
|
||||
{
|
||||
return(texelFetch(src, coord, 0).xy);
|
||||
}
|
||||
|
||||
float p(ivec2 coord)
|
||||
{
|
||||
if( coord.x <= 0
|
||||
|| coord.x >= textureSize(pressure, 0).x
|
||||
|| coord.y <= 0
|
||||
|| coord.y >= textureSize(pressure, 0).y)
|
||||
{
|
||||
return(0.);
|
||||
}
|
||||
return(texelFetch(pressure, coord, 0).x);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
|
||||
|
||||
float tl = p(pixelCoord + ivec2(0, 1));
|
||||
float tr = p(pixelCoord + ivec2(1, 1));
|
||||
float bl = p(pixelCoord);
|
||||
float br = p(pixelCoord + ivec2(1, 0));
|
||||
|
||||
float r = (tr + br)/2.;
|
||||
float l = (tl + bl)/2.;
|
||||
float t = (tl + tr)/2.;
|
||||
float b = (bl + br)/2.;
|
||||
|
||||
vec2 gradP = vec2(r - l, t - b);
|
||||
|
||||
fragColor = vec4(u(pixelCoord) - gradP, 0, 1);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Triangle
|
||||
profile.dtrace
|
||||
profile.spall
|
|
@ -0,0 +1,17 @@
|
|||
@echo off
|
||||
|
||||
:: compile wasm module
|
||||
set wasmFlags=--target=wasm32^
|
||||
--no-standard-libraries ^
|
||||
-fno-builtin ^
|
||||
-Wl,--no-entry ^
|
||||
-Wl,--export-dynamic ^
|
||||
-g ^
|
||||
-O2 ^
|
||||
-mbulk-memory ^
|
||||
-D__ORCA__ ^
|
||||
-isystem ..\..\cstdlib\include -I ..\..\sdk -I..\..\milepost\ext -I ..\..\milepost -I ..\..\milepost\src
|
||||
|
||||
clang %wasmFlags% -o .\module.wasm ..\..\sdk\orca.c ..\..\cstdlib\src\*.c src\main.c
|
||||
|
||||
python3 ..\..\scripts\mkapp.py --orca-dir ..\.. --name Triangle module.wasm
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ -x /usr/local/opt/llvm/bin/clang ]]; then
|
||||
CLANG=/usr/local/opt/llvm/bin/clang
|
||||
elif [[ -x /opt/homebrew/opt/llvm/bin/clang ]]; then
|
||||
CLANG=/opt/homebrew/opt/llvm/bin/clang
|
||||
else
|
||||
echo "Could not find Homebrew clang; this script will probably not work."
|
||||
CLANG=clang
|
||||
fi
|
||||
|
||||
STDLIB_DIR=../../cstdlib
|
||||
ORCA_SDK_DIR=../../sdk
|
||||
MILEPOST_DIR=../../milepost
|
||||
|
||||
wasmFlags="--target=wasm32 \
|
||||
--no-standard-libraries \
|
||||
-fno-builtin \
|
||||
-Wl,--no-entry \
|
||||
-Wl,--export-dynamic \
|
||||
-g \
|
||||
-O2 \
|
||||
-mbulk-memory \
|
||||
-D__ORCA__ \
|
||||
-I $STDLIB_DIR/include \
|
||||
-I $ORCA_SDK_DIR \
|
||||
-I $MILEPOST_DIR/ext -I $MILEPOST_DIR -I $MILEPOST_DIR/src"
|
||||
|
||||
$CLANG $wasmFlags -o ./module.wasm ../../sdk/orca.c ../../cstdlib/src/*.c src/main.c
|
||||
|
||||
orca bundle --orca-dir ../.. --name Triangle module.wasm
|
|
@ -0,0 +1,114 @@
|
|||
#include <keys.h>
|
||||
#include <graphics.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <orca.h>
|
||||
|
||||
vec2 frameSize = {100, 100};
|
||||
|
||||
mg_surface surface;
|
||||
|
||||
unsigned int program;
|
||||
|
||||
const char* vshaderSource =
|
||||
"attribute vec4 vPosition;\n"
|
||||
"uniform mat4 transform;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = transform*vPosition;\n"
|
||||
"}\n";
|
||||
|
||||
const char* fshaderSource =
|
||||
"precision mediump float;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
void compile_shader(GLuint shader, const char* source)
|
||||
{
|
||||
glShaderSource(shader, 1, &source, 0);
|
||||
glCompileShader(shader);
|
||||
|
||||
int err = glGetError();
|
||||
if(err)
|
||||
{
|
||||
log_info("gl error");
|
||||
}
|
||||
}
|
||||
|
||||
char* ORCA_IMPORT(orca_mem_grow)(u64 size);
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
{
|
||||
surface = mg_surface_gles();
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
|
||||
log_info("GLES extensions: %s\n", extensions);
|
||||
|
||||
int extensionCount = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
||||
for(int i=0; i<extensionCount; i++)
|
||||
{
|
||||
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
|
||||
log_info("GLES extension %i: %s\n", i, extension);
|
||||
}
|
||||
|
||||
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
|
||||
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
program = glCreateProgram();
|
||||
|
||||
compile_shader(vshader, vshaderSource);
|
||||
compile_shader(fshader, fshaderSource);
|
||||
|
||||
glAttachShader(program, vshader);
|
||||
glAttachShader(program, fshader);
|
||||
glLinkProgram(program);
|
||||
glUseProgram(program);
|
||||
|
||||
|
||||
GLfloat vertices[] = {
|
||||
-0.866/2, -0.5/2, 0, 0.866/2, -0.5/2, 0, 0, 0.5, 0};
|
||||
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
glEnableVertexAttribArray(0);
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
|
||||
{
|
||||
log_info("frame resize %u, %u", width, height);
|
||||
frameSize.x = width;
|
||||
frameSize.y = height;
|
||||
}
|
||||
|
||||
ORCA_EXPORT void OnFrameRefresh(void)
|
||||
{
|
||||
f32 aspect = frameSize.x/frameSize.y;
|
||||
|
||||
mg_surface_prepare(surface);
|
||||
|
||||
glClearColor(0, 1, 1, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
static float alpha = 0;
|
||||
|
||||
glViewport(0, 0, frameSize.x * 2, frameSize.y * 2);
|
||||
|
||||
GLfloat matrix[] = {cosf(alpha)/aspect, sinf(alpha), 0, 0,
|
||||
-sinf(alpha)/aspect, cosf(alpha), 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1};
|
||||
alpha += 2*M_PI/120;
|
||||
|
||||
glUniformMatrix4fv(0, 1, false, matrix);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
mg_surface_present(surface);
|
||||
}
|
|
@ -45,9 +45,6 @@ mg_image ballImage;
|
|||
mg_image paddleImage;
|
||||
mg_font pongFont;
|
||||
|
||||
// TODO(ben): Why is this here? Why isn't it forward-declared by some header?
|
||||
mg_surface mg_surface_main(void);
|
||||
|
||||
f32 lerp(f32 a, f32 b, f32 t);
|
||||
mp_rect blockRect(int i);
|
||||
int checkCollision(mp_rect block);
|
||||
|
@ -69,7 +66,7 @@ str8 loadFile(mem_arena* arena, str8 filename) {
|
|||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
{
|
||||
surface = mg_surface_main();
|
||||
surface = mg_surface_canvas();
|
||||
canvas = mg_canvas_create();
|
||||
|
||||
waterImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/underwater.jpg")), false);
|
||||
|
|
|
@ -12,12 +12,10 @@ mg_font font;
|
|||
ui_context ui;
|
||||
mem_arena textArena = {0};
|
||||
|
||||
mg_surface mg_surface_main(void);
|
||||
|
||||
ORCA_EXPORT void OnInit(void)
|
||||
{
|
||||
//TODO create surface for main window
|
||||
surface = mg_surface_main();
|
||||
surface = mg_surface_canvas();
|
||||
canvas = mg_canvas_create();
|
||||
ui_init(&ui);
|
||||
|
||||
|
|
|
@ -108,48 +108,104 @@ def bindgen(apiName, spec, **kwargs):
|
|||
if gen_stub == False:
|
||||
s += ';\n\n'
|
||||
else:
|
||||
s += '\n{\n\t'
|
||||
s += '\n{\n'
|
||||
|
||||
|
||||
# NOTE: check and cast arguments
|
||||
retTag = decl['ret']['tag']
|
||||
|
||||
if retTag == 'i':
|
||||
s += '*((i32*)&_sp[0]) = '
|
||||
elif retTag == 'I':
|
||||
s += '*((i64*)&_sp[0]) = '
|
||||
elif retTag == 'f':
|
||||
s += '*((f32*)&_sp[0]) = '
|
||||
elif retTag == 'F':
|
||||
s += '*((f64*)&_sp[0]) = '
|
||||
elif retTag == 'S':
|
||||
retTypeName = decl['ret']['name']
|
||||
retTypeCName = decl['ret'].get('cname', retTypeName)
|
||||
s += '*(' + retTypeCName + '*)((char*)_mem + *(i32*)&_sp[0]) = '
|
||||
|
||||
s += cname + '('
|
||||
|
||||
firstArgIndex = 0
|
||||
if retTag != 'v':
|
||||
firstArgIndex = 1
|
||||
|
||||
for i, arg in enumerate(decl['args']):
|
||||
for argIndex, arg in enumerate(decl['args']):
|
||||
|
||||
argName = arg['name']
|
||||
typeName = arg['type']['name']
|
||||
typeCName = arg['type'].get('cname', typeName)
|
||||
argTag = arg['type']['tag']
|
||||
|
||||
s += '\t'
|
||||
|
||||
if argTag == 'i':
|
||||
s += '*(i32*)&_sp[' + str(firstArgIndex + i) + ']'
|
||||
s += typeCName + ' ' + argName + ' = ('+typeCName+')*(i32*)&_sp[' + str(firstArgIndex + argIndex) + '];\n'
|
||||
elif argTag == 'I':
|
||||
s += '*(i64*)&_sp[' + str(firstArgIndex + i) + ']'
|
||||
s += typeCName + ' ' + argName + ' = ('+typeCName+')*(i64*)&_sp[' + str(firstArgIndex + argIndex) + '];\n'
|
||||
elif argTag == 'f':
|
||||
s += '*(f32*)&_sp[' + str(firstArgIndex + i) + ']'
|
||||
s += typeCName + ' ' + argName + ' = ('+typeCName+')*(f32*)&_sp[' + str(firstArgIndex + argIndex) + '];\n'
|
||||
elif argTag == 'F':
|
||||
s += '*(f64*)&_sp[' + str(firstArgIndex + i) + ']'
|
||||
s += typeCName + ' ' + argName + ' = ('+typeCName+')*(f64*)&_sp[' + str(firstArgIndex + argIndex) + '];\n'
|
||||
elif argTag == 'p':
|
||||
s += '(void*)((char*)_mem + *(i32*)&_sp[' + str(firstArgIndex + i) + '])'
|
||||
s += typeCName + ' ' + argName + ' = ('+ typeCName +')((char*)_mem + *(u32*)&_sp[' + str(firstArgIndex + argIndex) + ']);\n'
|
||||
elif argTag == 'S':
|
||||
s += '*(' + typeCName + '*)((char*)_mem + *(i32*)&_sp[' + str(firstArgIndex + i) + '])'
|
||||
s += typeCName + ' ' + argName + ' = *('+ typeCName +'*)((char*)_mem + *(u32*)&_sp[' + str(firstArgIndex + argIndex) + ']);\n'
|
||||
else:
|
||||
print('unrecognized type ' + c + ' in procedure signature\n')
|
||||
break
|
||||
|
||||
# check pointer arg length
|
||||
for arg in decl['args']:
|
||||
|
||||
argName = arg['name']
|
||||
typeName = arg['type']['name']
|
||||
typeCName = arg['type'].get('cname', typeName)
|
||||
argTag = arg['type']['tag']
|
||||
argLen = arg.get('len')
|
||||
|
||||
if argTag == 'p' and argLen != None:
|
||||
|
||||
s += '\t{\n'
|
||||
s += '\t\tORCA_ASSERT(((char*)'+ argName + ' >= (char*)_mem) && (((char*)'+ argName +' - (char*)_mem) < m3_GetMemorySize(runtime)), "parameter \''+argName+'\' is out of bounds");\n'
|
||||
s += '\t\tORCA_ASSERT((char*)' + argName + ' + '
|
||||
|
||||
proc = argLen.get('proc')
|
||||
if proc != None:
|
||||
s += proc + '(runtime, '
|
||||
lenProcArgs = argLen['args']
|
||||
for i, lenProcArg in enumerate(lenProcArgs):
|
||||
s += lenProcArg
|
||||
if i < len(lenProcArgs)-1:
|
||||
s += ', '
|
||||
s += ')'
|
||||
else:
|
||||
components = argLen.get('components')
|
||||
countArg = argLen.get('count')
|
||||
|
||||
if components != None:
|
||||
s += str(components)
|
||||
if countArg != None:
|
||||
s += '*'
|
||||
if countArg != None:
|
||||
s += countArg
|
||||
|
||||
if typeCName.endswith('**') or (typeCName.startswith('void') == False and typeCName.startswith('const void') == False):
|
||||
s += '*sizeof('+typeCName[:-1]+')'
|
||||
|
||||
s += ' <= ((char*)_mem + m3_GetMemorySize(runtime)), "parameter \''+argName+'\' overflows wasm memory");\n'
|
||||
s += '\t}\n'
|
||||
|
||||
s += '\t'
|
||||
|
||||
if retTag == 'i':
|
||||
s += '*((i32*)&_sp[0]) = (i32)'
|
||||
elif retTag == 'I':
|
||||
s += '*((i64*)&_sp[0]) = (i64)'
|
||||
elif retTag == 'f':
|
||||
s += '*((f32*)&_sp[0]) = (f32)'
|
||||
elif retTag == 'F':
|
||||
s += '*((f64*)&_sp[0]) = (f64)'
|
||||
elif retTag == 'S':
|
||||
retTypeName = decl['ret']['name']
|
||||
retTypeCName = decl['ret'].get('cname', retTypeName)
|
||||
s += '*(' + retTypeCName + '*)((char*)_mem + *(i32*)&_sp[0]) = '
|
||||
elif retTag == 'p':
|
||||
print("Warning: " + name + ": pointer return type not supported yet")
|
||||
|
||||
s += cname + '('
|
||||
|
||||
for i, arg in enumerate(decl['args']):
|
||||
s += arg['name']
|
||||
|
||||
if i+1 < len(decl['args']):
|
||||
s += ', '
|
||||
|
||||
|
@ -158,8 +214,9 @@ def bindgen(apiName, spec, **kwargs):
|
|||
print(s, file=host_bindings)
|
||||
|
||||
# link function
|
||||
s = 'int bindgen_link_' + apiName + '_api(IM3Module module)\n{\n\t'
|
||||
s += 'M3Result res;\n'
|
||||
s = 'int bindgen_link_' + apiName + '_api(IM3Module module)\n{\n'
|
||||
s += ' M3Result res;\n'
|
||||
s += ' int ret = 0;\n'
|
||||
|
||||
for decl in data:
|
||||
name = decl['name']
|
||||
|
@ -185,11 +242,14 @@ def bindgen(apiName, spec, **kwargs):
|
|||
m3Sig += ')'
|
||||
|
||||
|
||||
s += '\tres = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
|
||||
s += '\tif(res != m3Err_none && res != m3Err_functionLookupFailed) { log_error("error: %s\\n", res); return(-1); }\n\n'
|
||||
s += ' res = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3Sig + '", ' + cname + '_stub);\n'
|
||||
s += ' if(res != m3Err_none && res != m3Err_functionLookupFailed)\n'
|
||||
s += ' {\n'
|
||||
s += ' log_error("Couldn\'t link function ' + name + ' (%s)\\n", res);\n'
|
||||
s += ' ret = -1;\n'
|
||||
s += ' }\n\n'
|
||||
|
||||
|
||||
s += '\treturn(0);\n}\n'
|
||||
s += '\treturn(ret);\n}\n'
|
||||
|
||||
print(s, file=host_bindings)
|
||||
|
||||
|
|
|
@ -171,6 +171,8 @@ def macos_make_app(args):
|
|||
<string>icon.icns</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>MetalCaptureEnabled</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
"""
|
||||
|
|
|
@ -10,6 +10,7 @@ from zipfile import ZipFile
|
|||
|
||||
from . import checksum
|
||||
from .bindgen import bindgen
|
||||
from .gles_gen import gles_gen
|
||||
from .log import *
|
||||
from .utils import pushd, removeall
|
||||
|
||||
|
@ -374,6 +375,12 @@ def gen_all_bindings():
|
|||
bindgen("core", "src/core_api.json",
|
||||
wasm3_bindings="src/core_api_bind_gen.c",
|
||||
)
|
||||
|
||||
gles_gen("milepost/ext/gl.xml",
|
||||
"src/gles_api.json",
|
||||
"sdk/gl31.h"
|
||||
)
|
||||
|
||||
bindgen("gles", "src/gles_api.json",
|
||||
wasm3_bindings="src/gles_api_bind_gen.c",
|
||||
)
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
from .reg_modified import *
|
||||
import xml.etree.ElementTree as et
|
||||
from argparse import ArgumentParser
|
||||
|
||||
# remove APIs that can't be sandboxed
|
||||
removeProc = [
|
||||
"glMapBuffer",
|
||||
"glMapBufferRange",
|
||||
"glUnmapBuffer",
|
||||
"glFlushMappedBufferRange",
|
||||
"glGetBufferPointerv"
|
||||
]
|
||||
|
||||
def gen_gles_header(spec, filename):
|
||||
# Generates the GLES header, wrapping gl functions
|
||||
# prototypes in ORCA_IMPORT() macro
|
||||
|
||||
gles2through31Pat = '2\.[0-9]|3\.[01]'
|
||||
allVersions = '.*'
|
||||
|
||||
genOpts = CGeneratorOptions(
|
||||
filename=filename,
|
||||
apiname='gles2',
|
||||
profile='common',
|
||||
versions=gles2through31Pat,
|
||||
emitversions=allVersions,
|
||||
protectProto=False,
|
||||
procMacro='ORCA_IMPORT',
|
||||
removeProc = removeProc)
|
||||
|
||||
reg = Registry()
|
||||
tree = et.parse(spec)
|
||||
reg.loadElementTree(tree)
|
||||
|
||||
logFile = open('./gles_gen.log', 'w')
|
||||
gen = COutputGenerator(diagFile=logFile)
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
logFile.close()
|
||||
|
||||
|
||||
def get_bindgen_tag_for_type(typeName):
|
||||
typeToTags = {
|
||||
"void": "v",
|
||||
|
||||
"GLenum": "i",
|
||||
"GLbitfield": "i",
|
||||
|
||||
"GLboolean": "i",
|
||||
"GLbyte": "i",
|
||||
"GLubyte": "i",
|
||||
"GLchar": "i",
|
||||
|
||||
"GLshort": "i",
|
||||
"GLushort": "i",
|
||||
"GLhalf": "i",
|
||||
"GLhalfARB": "i",
|
||||
|
||||
"GLuint": "i",
|
||||
"GLint": "i",
|
||||
"GLclampx": "i",
|
||||
"GLsizei": "i",
|
||||
"GLfixed": "i",
|
||||
|
||||
"GLintptr": "i",
|
||||
"GLsizeiptr": "i",
|
||||
|
||||
"GLuint64": "I",
|
||||
"GLint64": "I",
|
||||
|
||||
"GLfloat": "f",
|
||||
"GLclampf": "f",
|
||||
|
||||
"GLdouble": "F",
|
||||
"GLclampd": "F",
|
||||
|
||||
#NOTE: we treat sync objects as opaque 64bit values
|
||||
#TODO we should _also_ make sure that Wasm code treat them as 64bit values
|
||||
"GLsync": "I"
|
||||
}
|
||||
|
||||
if typeName[len(typeName)-1] == '*':
|
||||
return "p"
|
||||
else:
|
||||
tag = typeToTags.get(typeName)
|
||||
return tag
|
||||
|
||||
|
||||
def gen_compsize_len_entry(name, argName, compsizeArgs):
|
||||
|
||||
entry = '\t\t\t"len": {\n'
|
||||
entry += '\t\t\t\t"proc": "orca_'+ name +'_'+argName+'_length",\n'
|
||||
entry += '\t\t\t\t"args": ['
|
||||
|
||||
for i, compsizeArg in enumerate(compsizeArgs):
|
||||
entry += '"' + compsizeArg + '"'
|
||||
if i < len(compsizeArgs)-1:
|
||||
entry += ', '
|
||||
entry += ']\n'
|
||||
entry += '\t\t\t}'
|
||||
return entry
|
||||
|
||||
def gen_argcount_len_entry(name, argName, tokens):
|
||||
|
||||
entry = '\t\t\t"len": {'
|
||||
if len(tokens) == 2:
|
||||
if tokens[1].isnumeric() == False:
|
||||
print("Warning: function " + name + ": couldn't parse parameter '" + argName + "' lenght attribute")
|
||||
entry += '"count": "' + tokens[0] + '", "components": '+ tokens[1]
|
||||
elif len(tokens) == 1:
|
||||
if tokens[0].isnumeric():
|
||||
entry += '"components":'+ tokens[0]
|
||||
else:
|
||||
entry += '"count": "'+ tokens[0] + '"'
|
||||
else:
|
||||
print("Warning: function " + name + ": couldn't parse parameter '" + argName + "' lenght attribute")
|
||||
|
||||
entry += '}'
|
||||
return entry
|
||||
|
||||
def gen_gles_bindgen_json(spec, filename):
|
||||
|
||||
# Gather gles 3.1 required functions
|
||||
tree = et.parse(spec)
|
||||
api = []
|
||||
|
||||
for feature in tree.iterfind('feature[@api="gles2"]'):
|
||||
if float(feature.get('number')) > 3.1:
|
||||
break
|
||||
|
||||
for require in feature.iter('require'):
|
||||
if require.get('profile') == 'compatibility':
|
||||
continue
|
||||
for command in require.iter('command'):
|
||||
if command.get('name') not in removeProc:
|
||||
api.append(command.get('name'))
|
||||
|
||||
for remove in feature.iter('remove'):
|
||||
for command in remove.iter('command'):
|
||||
api.remove(command.get('name'))
|
||||
|
||||
# put all GL commands in a dict
|
||||
commands = dict()
|
||||
commandsSpec = tree.find('./commands')
|
||||
for command in commandsSpec.iter('command'):
|
||||
name = command.find('proto/name')
|
||||
commands[name.text] = command
|
||||
|
||||
# TODO: Generate json descriptions for commands in api
|
||||
|
||||
manualBind = [
|
||||
"glShaderSource",
|
||||
"glGetVertexAttribPointerv",
|
||||
"glVertexAttribPointer",
|
||||
"glVertexAttribIPointer",
|
||||
"glGetString",
|
||||
"glGetStringi",
|
||||
"glGetUniformIndices"
|
||||
]
|
||||
|
||||
json = '[\n'
|
||||
for name in api:
|
||||
if name in manualBind:
|
||||
continue
|
||||
|
||||
command = commands.get(name)
|
||||
if command == None:
|
||||
print("Couldn't find definition for required command '" + name + "'")
|
||||
exit(-1)
|
||||
|
||||
proto = command.find("proto")
|
||||
ptype = proto.find("ptype")
|
||||
|
||||
retType = ''
|
||||
if proto.text != None:
|
||||
retType += proto.text
|
||||
|
||||
if ptype != None:
|
||||
if ptype.text != None:
|
||||
retType += ptype.text
|
||||
if ptype.tail != None:
|
||||
retType += ptype.tail
|
||||
|
||||
retType = retType.strip()
|
||||
|
||||
retTag = get_bindgen_tag_for_type(retType)
|
||||
if retTag == None:
|
||||
print("Couldn't find tag for GL type '" + retType + "'")
|
||||
exit(-1)
|
||||
|
||||
entry = '{\n\t"name": "' + name + '",\n'
|
||||
entry += '\t"cname": "' + name + '",\n'
|
||||
entry += '\t"ret": { "name": "' + retType + '", "tag": "' + retTag + '"},\n'
|
||||
|
||||
entry += '\t"args": [ '
|
||||
|
||||
# iterate through params
|
||||
for param in command.iter('param'):
|
||||
|
||||
argNode = param.find('name')
|
||||
argName = argNode.text
|
||||
|
||||
typeNode = param.find('ptype')
|
||||
|
||||
typeName = ''
|
||||
|
||||
if param.text != None:
|
||||
typeName += param.text
|
||||
|
||||
if typeNode != None:
|
||||
if typeNode.text != None:
|
||||
typeName += typeNode.text
|
||||
if typeNode.tail != None:
|
||||
typeName += typeNode.tail
|
||||
|
||||
typeName = typeName.strip()
|
||||
|
||||
if typeName.endswith('**'):
|
||||
print("Warning: function " + name + ": parameter " + argName + " has 2 (or more) levels of indirection")
|
||||
|
||||
typeTag = get_bindgen_tag_for_type(typeName)
|
||||
|
||||
if typeTag == None:
|
||||
print("Couldn't find tag for GL type '" + typeName + "' in function '"+ name +"'")
|
||||
exit(-1)
|
||||
|
||||
entry += '\n'
|
||||
entry += '\t\t{\n\t\t\t"name": "'+ argName +'",\n'
|
||||
entry += '\t\t\t"type": {"name": "'+ typeName +'", "tag": "'+ typeTag +'"}'
|
||||
|
||||
lenString = param.get('len')
|
||||
|
||||
nullStringProcWithNoLen = [
|
||||
"glBindAttribLocation",
|
||||
"glGetAttribLocation",
|
||||
"glGetUniformLocation"
|
||||
]
|
||||
|
||||
drawIndirectProc = [
|
||||
"glDrawArraysIndirect",
|
||||
"glDrawElementsIndirect"
|
||||
]
|
||||
|
||||
if typeTag == "p":
|
||||
if lenString == None:
|
||||
if name in drawIndirectProc:
|
||||
entry += ',\n'
|
||||
entry += gen_compsize_len_entry(name, argName, ['indirect'])
|
||||
elif name in nullStringProcWithNoLen:
|
||||
entry += ',\n'
|
||||
entry += gen_compsize_len_entry(name, argName, ['name'])
|
||||
else:
|
||||
print("Warning: function " + name + ": parameter " + argName + " has no len attribute")
|
||||
|
||||
elif lenString != None:
|
||||
entry += ',\n'
|
||||
|
||||
tokens = lenString.split('*')
|
||||
|
||||
if lenString.startswith("COMPSIZE"):
|
||||
tmp = lenString
|
||||
if tmp.startswith("COMPSIZE("):
|
||||
tmp = tmp[len("COMPSIZE("):]
|
||||
if tmp.endswith(")"):
|
||||
tmp = tmp[:-1]
|
||||
|
||||
compsizeArgs = list(filter(None, tmp.split(",")))
|
||||
|
||||
if len(compsizeArgs) == 0:
|
||||
# special case glGetUniformBlockIndex which isn't specified correctly in gl.xml
|
||||
if name == 'glGetUniformBlockIndex':
|
||||
compsizeArgs = ['uniformBlockName']
|
||||
|
||||
entry += gen_compsize_len_entry(name, argName, compsizeArgs)
|
||||
|
||||
else:
|
||||
entry += gen_argcount_len_entry(name, argName, tokens)
|
||||
|
||||
entry += '\n\t\t},'
|
||||
|
||||
entry = entry[:-1]
|
||||
entry += '\n\t]\n}'
|
||||
|
||||
json += entry
|
||||
json += ',\n'
|
||||
|
||||
json = json[:-2]
|
||||
json += '\n]'
|
||||
|
||||
# write json to jsonFile
|
||||
f = open(filename, 'w')
|
||||
f.write(json)
|
||||
f.close()
|
||||
|
||||
def gles_gen(spec, json, header):
|
||||
gen_gles_header(spec, header)
|
||||
gen_gles_bindgen_json(spec, json)
|
||||
|
||||
#----------------------------------------
|
||||
# driver
|
||||
#----------------------------------------
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("-s", "--spec")
|
||||
parser.add_argument("--header")
|
||||
parser.add_argument("-j", "--json")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
glesHeader = args.header
|
||||
jsonFile = args.json
|
||||
|
||||
gles_gen(args.spec, jsonFile, glesHeader)
|
File diff suppressed because it is too large
Load Diff
12
sdk/orca.h
12
sdk/orca.h
|
@ -19,10 +19,22 @@
|
|||
#include"platform/platform_clock.h"
|
||||
#include"platform/platform_io.h"
|
||||
|
||||
#include"math.h"
|
||||
|
||||
#include"graphics.h"
|
||||
#include"gl31.h"
|
||||
|
||||
#if COMPILER_CLANG
|
||||
#define ORCA_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#error "Orca apps can only be compiled with clang for now"
|
||||
#endif
|
||||
|
||||
|
||||
mg_surface mg_surface_canvas();
|
||||
mg_surface mg_surface_gles();
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__ORCA_H_
|
||||
|
|
|
@ -36,12 +36,6 @@
|
|||
{"name": "pixels",
|
||||
"type": {"name": "u8*", "tag": "p"}}]
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_main",
|
||||
"cname": "orca_surface_main",
|
||||
"ret": {"name": "mg_surface", "tag": "S"},
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_prepare",
|
||||
"cname": "mg_surface_prepare",
|
||||
|
@ -75,4 +69,17 @@
|
|||
"type": {"name": "u32", "tag": "i"}},
|
||||
{"name": "elements",
|
||||
"type": {"name": "mg_path_elt*", "tag": "p"}}]
|
||||
}]
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_canvas",
|
||||
"cname": "orca_surface_canvas",
|
||||
"ret": {"name": "mg_surface", "tag": "S"},
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "mg_surface_gles",
|
||||
"cname": "orca_surface_gles",
|
||||
"ret": {"name": "mg_surface", "tag": "S"},
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,60 +1,4 @@
|
|||
[
|
||||
{
|
||||
"name": "cosf",
|
||||
"cname": "cosf",
|
||||
"ret": {"name": "float", "tag": "f"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "float", "tag": "f"}}]
|
||||
},
|
||||
{
|
||||
"name": "sinf",
|
||||
"cname": "sinf",
|
||||
"ret": {"name": "float", "tag": "f"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "float", "tag": "f"}}]
|
||||
},
|
||||
{
|
||||
"name": "floorf",
|
||||
"cname": "floorf",
|
||||
"ret": {"name": "float", "tag": "f"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "float", "tag": "f"}}]
|
||||
},
|
||||
{
|
||||
"name": "sqrtf",
|
||||
"cname": "sqrtf",
|
||||
"ret": {"name": "float", "tag": "f"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "float", "tag": "f"}}]
|
||||
},
|
||||
{
|
||||
"name": "cos",
|
||||
"cname": "cos",
|
||||
"ret": {"name": "double", "tag": "F"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "double", "tag": "F"}}]
|
||||
},
|
||||
{
|
||||
"name": "sin",
|
||||
"cname": "sin",
|
||||
"ret": {"name": "double", "tag": "F"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "double", "tag": "F"}}]
|
||||
},
|
||||
{
|
||||
"name": "sqrt",
|
||||
"cname": "sqrt",
|
||||
"ret": {"name": "double", "tag": "F"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "double", "tag": "F"}}]
|
||||
},
|
||||
{
|
||||
"name": "fabs",
|
||||
"cname": "fabs",
|
||||
"ret": {"name": "double", "tag": "F"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "double", "tag": "F"}}]
|
||||
},
|
||||
{
|
||||
"name": "orca_log",
|
||||
"cname": "orca_log",
|
||||
|
|
|
@ -1,383 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "glCreateProgram",
|
||||
"cname": "glCreateProgram",
|
||||
"ret": {"name": "int", "tag": "i"},
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "glCreateShader",
|
||||
"cname": "glCreateShader",
|
||||
"ret": {"name": "int", "tag": "i"},
|
||||
"args": [ {"name": "shaderType",
|
||||
"type": {"name": "GLenum", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glCompileShader",
|
||||
"cname": "glCompileShader",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "shader",
|
||||
"type": {"name": "GLuint", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glAttachShader",
|
||||
"cname": "glAttachShader",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "program",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "shader",
|
||||
"type": {"name": "GLuint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glLinkProgram",
|
||||
"cname": "glLinkProgram",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "program",
|
||||
"type": {"name": "GLuint", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glUseProgram",
|
||||
"cname": "glUseProgram",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "program",
|
||||
"type": {"name": "GLuint", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glGetError",
|
||||
"cname": "glGetError",
|
||||
"ret": {"name": "GLenum", "tag": "i"},
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"name": "glClearColor",
|
||||
"cname": "glClearColor",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "red",
|
||||
"type": {"name": "GLfloat", "tag": "f"}},
|
||||
{"name": "green",
|
||||
"type": {"name": "GLfloat", "tag": "f"}},
|
||||
{"name": "blue",
|
||||
"type": {"name": "GLfloat", "tag": "f"}},
|
||||
{"name": "alpha",
|
||||
"type": {"name": "GLfloat", "tag": "f"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glClear",
|
||||
"cname": "glClear",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "mask",
|
||||
"type": {"name": "GLbitfield", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glViewport",
|
||||
"cname": "glViewport",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "x",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "y",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "width",
|
||||
"type": {"name": "GLsizei", "tag": "i"}},
|
||||
{"name": "height",
|
||||
"type": {"name": "GLsizei", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glGetShaderiv",
|
||||
"cname": "glGetShaderiv",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "shader",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "pname",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "params",
|
||||
"type": {"name": "GLint*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glGetShaderInfoLog",
|
||||
"cname": "glGetShaderInfoLog",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "shader",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "maxLength",
|
||||
"type": {"name": "GLsizei", "tag": "i"}},
|
||||
{"name": "length",
|
||||
"type": {"name": "GLsizei", "tag": "p"}},
|
||||
{"name": "infoLog",
|
||||
"type": {"name": "GLchar", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glBindFramebuffer",
|
||||
"cname": "glBindFramebuffer",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "framebuffer",
|
||||
"type": {"name": "GLuint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glBindTexture",
|
||||
"cname": "glBindTexture",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "texture",
|
||||
"type": {"name": "GLuint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glActiveTexture",
|
||||
"cname": "glActiveTexture",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "texture",
|
||||
"type": {"name": "GLuint", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glGenBuffers",
|
||||
"cname": "glGenBuffers",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "n",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "buffers",
|
||||
"type": {"name": "GLuint*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glGenTextures",
|
||||
"cname": "glGenTextures",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "n",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "textures",
|
||||
"type": {"name": "GLuint*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glGenFramebuffers",
|
||||
"cname": "glGenFramebuffers",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "n",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "framebuffers",
|
||||
"type": {"name": "GLuint*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glFramebufferTexture2D",
|
||||
"cname": "glFramebufferTexture2D",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "attachment",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "textarget",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "texture",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "level",
|
||||
"type": {"name": "GLint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glCheckFramebufferStatus",
|
||||
"cname": "glCheckFramebufferStatus",
|
||||
"ret": {"name": "GLenum", "tag": "i"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glTexImage2D",
|
||||
"cname": "glTexImage2D",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "level",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "internalformat",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "width",
|
||||
"type": {"name": "GLsizei", "tag": "i"}},
|
||||
{"name": "height",
|
||||
"type": {"name": "GLsizei", "tag": "i"}},
|
||||
{"name": "border",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "format",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "type",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "data",
|
||||
"type": {"name": "void*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glTexParameteri",
|
||||
"cname": "glTexParameteri",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "pname",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "param",
|
||||
"type": {"name": "GLint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glBindBuffer",
|
||||
"cname": "glBindBuffer",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "buffer",
|
||||
"type": {"name": "GLuint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glBufferData",
|
||||
"cname": "glBufferData",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "target",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "size",
|
||||
"type": {"name": "GLsizeiptr", "tag": "i"}},
|
||||
{"name": "data",
|
||||
"type": {"name": "void*", "tag": "p"}},
|
||||
{"name": "usage",
|
||||
"type": {"name": "GLenum", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glUniform1i",
|
||||
"cname": "glUniform1i",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "location",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "v0",
|
||||
"type": {"name": "GLint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glUniform2i",
|
||||
"cname": "glUniform2i",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "location",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "v0",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "v1",
|
||||
"type": {"name": "GLint", "tag": "i"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glUniform1f",
|
||||
"cname": "glUniform1f",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "location",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "v0",
|
||||
"type": {"name": "GLfloat", "tag": "f"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glUniform2f",
|
||||
"cname": "glUniform2f",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "location",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "v0",
|
||||
"type": {"name": "GLfloat", "tag": "f"}},
|
||||
{"name": "v1",
|
||||
"type": {"name": "GLfloat", "tag": "f"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glUniform3f",
|
||||
"cname": "glUniform3f",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "location",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "v0",
|
||||
"type": {"name": "GLfloat", "tag": "f"}},
|
||||
{"name": "v1",
|
||||
"type": {"name": "GLfloat", "tag": "f"}},
|
||||
{"name": "v2",
|
||||
"type": {"name": "GLfloat", "tag": "f"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glUniformMatrix4fv",
|
||||
"cname": "glUniformMatrix4fv",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "location",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "count",
|
||||
"type": {"name": "GLsizei", "tag": "i"}},
|
||||
{"name": "transpose",
|
||||
"type": {"name": "GLboolean", "tag": "i"}},
|
||||
{"name": "value",
|
||||
"type": {"name": "GLfloat*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glGetAttribLocation",
|
||||
"cname": "glGetAttribLocation",
|
||||
"ret": {"name": "GLint", "tag": "i"},
|
||||
"args": [ {"name": "program",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "name",
|
||||
"type": {"name": "GLchar*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glGetUniformLocation",
|
||||
"cname": "glGetUniformLocation",
|
||||
"ret": {"name": "GLint", "tag": "i"},
|
||||
"args": [ {"name": "program",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "name",
|
||||
"type": {"name": "GLchar*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name": "glVertexAttribPointer",
|
||||
"cname": "glVertexAttribPointer",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "index",
|
||||
"type": {"name": "GLuint", "tag": "i"}},
|
||||
{"name": "size",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "type",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "normalized",
|
||||
"type": {"name": "GLboolean", "tag": "i"}},
|
||||
{"name": "stride",
|
||||
"type": {"name": "GLsizei", "tag": "i"}},
|
||||
{"name": "pointer",
|
||||
"type": {"name": "void*", "tag": "p"}}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "glEnableVertexAttribArray",
|
||||
"cname": "glEnableVertexAttribArray",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "index",
|
||||
"type": {"name": "GLuint", "tag": "i"}}]
|
||||
},
|
||||
{
|
||||
"name": "glDrawArrays",
|
||||
"cname": "glDrawArrays",
|
||||
"ret": {"name": "void", "tag": "v"},
|
||||
"args": [ {"name": "mode",
|
||||
"type": {"name": "GLenum", "tag": "i"}},
|
||||
{"name": "first",
|
||||
"type": {"name": "GLint", "tag": "i"}},
|
||||
{"name": "count",
|
||||
"type": {"name": "GLsizei", "tag": "i"}}
|
||||
]
|
||||
}
|
||||
]
|
File diff suppressed because it is too large
Load Diff
257
src/main.c
257
src/main.c
|
@ -18,9 +18,6 @@
|
|||
#include"memory_impl.c"
|
||||
#include"io_impl.c"
|
||||
|
||||
|
||||
#define LOG_SUBSYSTEM "Orca"
|
||||
|
||||
int orca_assert(const char* file, const char* function, int line, const char* src, const char* note)
|
||||
{
|
||||
mem_arena* scratch = mem_scratch();
|
||||
|
@ -38,7 +35,47 @@ int orca_assert(const char* file, const char* function, int line, const char* sr
|
|||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Assertion Failed", msgCStr, 1, options);
|
||||
|
||||
//TODO: should terminate more gracefully...
|
||||
//TODO: could terminate more gracefully?
|
||||
exit(-1);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int orca_assert_fmt(const char* file, const char* function, int line, const char* src, const char* fmt, ...)
|
||||
{
|
||||
mem_arena* scratch = mem_scratch();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str8 msg = str8_pushfv(scratch, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return(orca_assert(file, function, line, src, msg.ptr));
|
||||
}
|
||||
|
||||
void orca_abort_fmt(const char* file, const char* function, int line, const char* fmt, ...)
|
||||
{
|
||||
mem_arena* scratch = mem_scratch();
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
str8 note = str8_pushfv(scratch, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
str8 msg = str8_pushf(scratch,
|
||||
"Fatal error in function %s() in file \"%s\", line %i:\n%.*s\n",
|
||||
function,
|
||||
file,
|
||||
line,
|
||||
(int)note.len,
|
||||
note.ptr);
|
||||
|
||||
const char* msgCStr = str8_to_cstring(scratch, msg);
|
||||
log_error(msgCStr);
|
||||
|
||||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Fatal Error", msgCStr, 1, options);
|
||||
|
||||
//TODO: could terminate more gracefully?
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
@ -170,9 +207,50 @@ void orca_log(log_level level,
|
|||
msg);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_main(void)
|
||||
typedef struct orca_surface_create_data
|
||||
{
|
||||
return(__orcaApp.surface);
|
||||
mp_window window;
|
||||
mg_surface_api api;
|
||||
mg_surface surface;
|
||||
|
||||
} orca_surface_create_data;
|
||||
|
||||
i32 orca_surface_callback(void* user)
|
||||
{
|
||||
orca_surface_create_data* data = (orca_surface_create_data*)user;
|
||||
data->surface = mg_surface_create_for_window(data->window, data->api);
|
||||
|
||||
//NOTE: this will be called on main thread, so we need to deselect the surface here,
|
||||
// and reselect it on the orca thread
|
||||
mg_surface_deselect();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_canvas(void)
|
||||
{
|
||||
orca_surface_create_data data = {
|
||||
.surface = mg_surface_nil(),
|
||||
.window = __orcaApp.window,
|
||||
.api = MG_CANVAS
|
||||
};
|
||||
|
||||
mp_dispatch_on_main_thread_sync(__orcaApp.window, orca_surface_callback, (void*)&data);
|
||||
mg_surface_prepare(data.surface);
|
||||
return(data.surface);
|
||||
}
|
||||
|
||||
mg_surface orca_surface_gles(void)
|
||||
{
|
||||
orca_surface_create_data data = {
|
||||
.surface = mg_surface_nil(),
|
||||
.window = __orcaApp.window,
|
||||
.api = MG_GLES
|
||||
};
|
||||
|
||||
mp_dispatch_on_main_thread_sync(__orcaApp.window, orca_surface_callback, (void*)&data);
|
||||
mg_surface_prepare(data.surface);
|
||||
return(data.surface);
|
||||
}
|
||||
|
||||
void orca_surface_render_commands(mg_surface surface,
|
||||
|
@ -302,8 +380,25 @@ void orca_runtime_init(orca_runtime* runtime)
|
|||
#include"clock_api_bind_gen.c"
|
||||
#include"io_api_bind_gen.c"
|
||||
|
||||
#include"gles_api_bind_manual.c"
|
||||
#include"gles_api_bind_gen.c"
|
||||
#include"manual_gles_api.c"
|
||||
|
||||
|
||||
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg)
|
||||
{
|
||||
M3ErrorInfo errInfo = {0};
|
||||
m3_GetErrorInfo(runtime, &errInfo);
|
||||
if(errInfo.message && res == errInfo.result)
|
||||
{
|
||||
orca_abort_fmt(file, function, line, "%s: %s (%s)", msg, res, errInfo.message);
|
||||
}
|
||||
else
|
||||
{
|
||||
orca_abort_fmt(file, function, line, "%s: %s", msg, res);
|
||||
}
|
||||
}
|
||||
|
||||
#define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg)
|
||||
|
||||
i32 orca_runloop(void* user)
|
||||
{
|
||||
|
@ -318,16 +413,7 @@ i32 orca_runloop(void* user)
|
|||
FILE* file = fopen(modulePath.ptr, "rb");
|
||||
if(!file)
|
||||
{
|
||||
log_error("Couldn't load wasm module at %s\n", modulePath.ptr);
|
||||
|
||||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Error",
|
||||
"The application couldn't load: web assembly module not found",
|
||||
1,
|
||||
options);
|
||||
|
||||
mp_request_quit();
|
||||
return(-1);
|
||||
ORCA_ABORT("The application couldn't load: web assembly module not found");
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
|
@ -343,41 +429,44 @@ i32 orca_runloop(void* user)
|
|||
app->runtime.m3Env = m3_NewEnvironment();
|
||||
|
||||
app->runtime.m3Runtime = m3_NewRuntime(app->runtime.m3Env, stackSize, NULL);
|
||||
m3_RuntimeSetMemoryCallbacks(app->runtime.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->runtime.wasmMemory);
|
||||
//NOTE: host memory will be freed when runtime is freed.
|
||||
m3_RuntimeSetMemoryCallbacks(app->runtime.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->runtime.wasmMemory);
|
||||
|
||||
//TODO check errors
|
||||
m3_ParseModule(app->runtime.m3Env, &app->runtime.m3Module, (u8*)app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len);
|
||||
m3_LoadModule(app->runtime.m3Runtime, app->runtime.m3Module);
|
||||
M3Result res = m3_ParseModule(app->runtime.m3Env, &app->runtime.m3Module, (u8*)app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't parse its web assembly module");
|
||||
}
|
||||
|
||||
res = m3_LoadModule(app->runtime.m3Runtime, app->runtime.m3Module);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't load its web assembly module into the runtime");
|
||||
}
|
||||
m3_SetModuleName(app->runtime.m3Module, bundleNameCString);
|
||||
|
||||
mem_arena_clear(mem_scratch());
|
||||
|
||||
//NOTE: bind orca APIs
|
||||
bindgen_link_core_api(app->runtime.m3Module);
|
||||
bindgen_link_canvas_api(app->runtime.m3Module);
|
||||
bindgen_link_clock_api(app->runtime.m3Module);
|
||||
bindgen_link_io_api(app->runtime.m3Module);
|
||||
bindgen_link_gles_api(app->runtime.m3Module);
|
||||
manual_link_gles_api(app->runtime.m3Module);
|
||||
{
|
||||
int err = 0;
|
||||
err |= bindgen_link_core_api(app->runtime.m3Module);
|
||||
err |= bindgen_link_canvas_api(app->runtime.m3Module);
|
||||
err |= bindgen_link_clock_api(app->runtime.m3Module);
|
||||
err |= bindgen_link_io_api(app->runtime.m3Module);
|
||||
err |= bindgen_link_gles_api(app->runtime.m3Module);
|
||||
err |= manual_link_gles_api(app->runtime.m3Module);
|
||||
|
||||
if(err)
|
||||
{
|
||||
ORCA_ABORT("The application couldn't link one or more functions to its web assembly module (see console log for more information)");
|
||||
}
|
||||
}
|
||||
//NOTE: compile
|
||||
M3Result res = m3_CompileModule(app->runtime.m3Module);
|
||||
res = m3_CompileModule(app->runtime.m3Module);
|
||||
if(res)
|
||||
{
|
||||
M3ErrorInfo errInfo = {0};
|
||||
m3_GetErrorInfo(app->runtime.m3Runtime, &errInfo);
|
||||
|
||||
log_error("wasm error: %s\n", errInfo.message);
|
||||
|
||||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Error",
|
||||
"The application couldn't load: can't compile web assembly module",
|
||||
1,
|
||||
options);
|
||||
|
||||
mp_request_quit();
|
||||
return(-1);
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't compile its web assembly module");
|
||||
}
|
||||
|
||||
//NOTE: Find and type check event handlers.
|
||||
|
@ -451,28 +540,15 @@ i32 orca_runloop(void* user)
|
|||
app->rootDir = cmp.handle;
|
||||
}
|
||||
|
||||
//NOTE: prepare GL surface
|
||||
mg_surface_prepare(app->surface);
|
||||
|
||||
IM3Function* exports = app->runtime.exports;
|
||||
|
||||
//NOTE: call init handler
|
||||
if(exports[G_EXPORT_ON_INIT])
|
||||
{
|
||||
M3Result err = m3_Call(exports[G_EXPORT_ON_INIT], 0, 0);
|
||||
if(err != NULL)
|
||||
M3Result res = m3_Call(exports[G_EXPORT_ON_INIT], 0, 0);
|
||||
if(res)
|
||||
{
|
||||
log_error("runtime error: %s\n", err);
|
||||
|
||||
str8 msg = str8_pushf(mem_scratch(), "Runtime error: %s\n", err);
|
||||
const char* options[] = {"OK"};
|
||||
mp_alert_popup("Error",
|
||||
msg.ptr,
|
||||
1,
|
||||
options);
|
||||
|
||||
mp_request_quit();
|
||||
return(-1);
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +558,11 @@ i32 orca_runloop(void* user)
|
|||
u32 width = (u32)content.w;
|
||||
u32 height = (u32)content.h;
|
||||
const void* args[2] = {&width, &height};
|
||||
m3_Call(exports[G_EXPORT_FRAME_RESIZE], 2, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_FRAME_RESIZE], 2, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
|
||||
ui_set_context(&app->debugOverlay.ui);
|
||||
|
@ -505,7 +585,11 @@ i32 orca_runloop(void* user)
|
|||
memcpy(eventPtr, event, sizeof(*event));
|
||||
|
||||
const void* args[1] = {&app->runtime.rawEventOffset};
|
||||
m3_Call(exports[G_EXPORT_RAW_EVENT], 1, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_RAW_EVENT], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
#else
|
||||
log_error("OnRawEvent() is not supported on big endian platforms");
|
||||
#endif
|
||||
|
@ -527,7 +611,11 @@ i32 orca_runloop(void* user)
|
|||
u32 width = (u32)event->move.content.w;
|
||||
u32 height = (u32)event->move.content.h;
|
||||
const void* args[2] = {&width, &height};
|
||||
m3_Call(exports[G_EXPORT_FRAME_RESIZE], 2, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_FRAME_RESIZE], 2, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -539,7 +627,11 @@ i32 orca_runloop(void* user)
|
|||
{
|
||||
int key = event->key.code;
|
||||
const void* args[1] = {&key};
|
||||
m3_Call(exports[G_EXPORT_MOUSE_DOWN], 1, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_MOUSE_DOWN], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -548,7 +640,11 @@ i32 orca_runloop(void* user)
|
|||
{
|
||||
int key = event->key.code;
|
||||
const void* args[1] = {&key};
|
||||
m3_Call(exports[G_EXPORT_MOUSE_UP], 1, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_MOUSE_UP], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -558,7 +654,11 @@ i32 orca_runloop(void* user)
|
|||
if(exports[G_EXPORT_MOUSE_MOVE])
|
||||
{
|
||||
const void* args[4] = {&event->mouse.x, &event->mouse.y, &event->mouse.deltaX, &event->mouse.deltaY};
|
||||
m3_Call(exports[G_EXPORT_MOUSE_MOVE], 4, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_MOUSE_MOVE], 4, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -576,7 +676,11 @@ i32 orca_runloop(void* user)
|
|||
if(exports[G_EXPORT_KEY_DOWN])
|
||||
{
|
||||
const void* args[1] = {&event->key.code};
|
||||
m3_Call(exports[G_EXPORT_KEY_DOWN], 1, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_KEY_DOWN], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(event->key.action == MP_KEY_RELEASE)
|
||||
|
@ -584,7 +688,11 @@ i32 orca_runloop(void* user)
|
|||
if(exports[G_EXPORT_KEY_UP])
|
||||
{
|
||||
const void* args[1] = {&event->key.code};
|
||||
m3_Call(exports[G_EXPORT_KEY_UP], 1, args);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_KEY_UP], 1, args);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -732,8 +840,11 @@ i32 orca_runloop(void* user)
|
|||
|
||||
if(exports[G_EXPORT_FRAME_REFRESH])
|
||||
{
|
||||
mg_surface_prepare(app->surface);
|
||||
m3_Call(exports[G_EXPORT_FRAME_REFRESH], 0, 0);
|
||||
M3Result res = m3_Call(exports[G_EXPORT_FRAME_REFRESH], 0, 0);
|
||||
if(res)
|
||||
{
|
||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
||||
}
|
||||
}
|
||||
|
||||
if(app->debugOverlay.show)
|
||||
|
@ -761,10 +872,6 @@ int main(int argc, char** argv)
|
|||
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
|
||||
app->window = mp_window_create(windowRect, "orca", 0);
|
||||
|
||||
app->surface = mg_surface_create_for_window(app->window, MG_CANVAS);
|
||||
app->canvas = mg_canvas_create();
|
||||
mg_surface_swap_interval(app->surface, 1);
|
||||
|
||||
app->debugOverlay.show = false;
|
||||
app->debugOverlay.surface = mg_surface_create_for_window(app->window, MG_CANVAS);
|
||||
app->debugOverlay.canvas = mg_canvas_create();
|
||||
|
@ -784,11 +891,6 @@ int main(int argc, char** argv)
|
|||
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
mg_surface_prepare(app->surface);
|
||||
mg_canvas_set_current(app->canvas);
|
||||
mg_render(app->surface, app->canvas);
|
||||
mg_surface_present(app->surface);
|
||||
|
||||
mg_surface_prepare(app->debugOverlay.surface);
|
||||
mg_canvas_set_current(app->debugOverlay.canvas);
|
||||
mg_render(app->debugOverlay.surface, app->debugOverlay.canvas);
|
||||
|
@ -812,9 +914,6 @@ int main(int argc, char** argv)
|
|||
|
||||
mp_thread_join(runloopThread, NULL);
|
||||
|
||||
mg_canvas_destroy(app->canvas);
|
||||
mg_surface_destroy(app->surface);
|
||||
|
||||
mg_canvas_destroy(app->debugOverlay.canvas);
|
||||
mg_surface_destroy(app->debugOverlay.surface);
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
|
||||
const void* glShaderSource_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem)
|
||||
{
|
||||
i32 shader = *(i32*)&_sp[0];
|
||||
i32 count = *(i32*)&_sp[1];
|
||||
i32 stringArrayOffset = *(i32*)&_sp[2];
|
||||
i32 lengthArrayOffset = *(i32*)&_sp[3];
|
||||
|
||||
int* stringOffsetArray = (int*)((char*)_mem + stringArrayOffset);
|
||||
const char** stringArray = (const char**)mem_arena_alloc_array(mem_scratch(), char*, count);
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
stringArray[i] = (char*)_mem + stringOffsetArray[i];
|
||||
}
|
||||
|
||||
int* lengthArray = lengthArrayOffset ? (int*)((char*)_mem + lengthArrayOffset) : 0;
|
||||
|
||||
glShaderSource(shader, count, stringArray, lengthArray);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int manual_link_gles_api(IM3Module module)
|
||||
{
|
||||
M3Result res;
|
||||
res = m3_LinkRawFunction(module, "*", "glShaderSource", "v(iiii)", glShaderSource_stub);
|
||||
if(res) { log_error("error: %s\n", res); return(-1); }
|
||||
|
||||
return(0);
|
||||
}
|
|
@ -112,8 +112,6 @@ typedef struct orca_debug_overlay
|
|||
typedef struct orca_app
|
||||
{
|
||||
mp_window window;
|
||||
mg_surface surface;
|
||||
mg_canvas canvas;
|
||||
|
||||
file_table fileTable;
|
||||
file_handle rootDir;
|
||||
|
@ -128,4 +126,13 @@ orca_app* orca_app_get();
|
|||
orca_runtime* orca_runtime_get();
|
||||
|
||||
|
||||
int orca_assert(const char* file, const char* function, int line, const char* src, const char* note);
|
||||
int orca_assert_fmt(const char* file, const char* function, int line, const char* src, const char* fmt, ...);
|
||||
void orca_abort_fmt(const char* file, const char* function, int line, const char* fmt, ...);
|
||||
|
||||
#define _ORCA_ASSERT_(test, fmt, ...) ((test) || orca_assert_fmt(__FILE__, __FUNCTION__, __LINE__, #test, fmt, ##__VA_ARGS__))
|
||||
#define ORCA_ASSERT(test, ...) _ORCA_ASSERT_(test, ORCA_VA_NOPT("", ##__VA_ARGS__) ORCA_ARG1(__VA_ARGS__) ORCA_VA_COMMA_TAIL(__VA_ARGS__))
|
||||
|
||||
#define ORCA_ABORT(fmt, ...) orca_abort_fmt(__FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif //__ORCA_RUNTIME_H_
|
||||
|
|
Loading…
Reference in New Issue