meta: new build system (and emscripten fullscreen)

* Update the build system to support intermediate installs (instead of
  exposing CMake targets that were only usable from within the main
  CMakeLists.txt).
* Finish the emscripten build and add detailed instructions in
  README.md.
* Get rid of runtime GLSL files by embedding them into a C file. This
  solves the annoying problem of where to install them and how to find
  them at runtime.
* Provide FindAzur.cmake to access the library. At the moment the module
  still needs to be found which requires a set(CMAKE_MODULE_PATH) in
  user applications. I consider this an acceptable compromise.
* Automatically go soft-fullscreen in the emscripten application.
This commit is contained in:
Lephenixnoir 2022-06-05 13:03:26 +01:00
parent 019cf416fa
commit 2e63daa59a
Signed by untrusted user: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
12 changed files with 464 additions and 111 deletions

View File

@ -1,27 +1,42 @@
#-----------------------------------------------------------------------------#
# ," /\ ", Azur: A game engine for CASIO fx-CG and PC #
# | _/__\_ | Designed by Lephe' and the Planète Casio community. #
# "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> #
#-----------------------------------------------------------------------------#
# Build system for third-party libraries bundled with Azur
#---
# gl3w
#---
# Use GL3W as an OpenGL loader on desktop
# Use GL3W to load the OpenGL 3.3 core profile
if(AZUR_GRAPHICS_OPENGL_3_3)
add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/gl3w/src/gl3w.c"
COMMAND ./gl3w_gen.py
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/gl3w")
add_library(gl3w gl3w/src/gl3w.c)
target_include_directories(gl3w PUBLIC gl3w/include)
set_target_properties(gl3w PROPERTIES
OUTPUT_NAME "azur_${AZUR_PLATFORM}_gl3w")
# Link with GLX for GL3W to find the extensions, and -ldl
target_link_libraries(gl3w INTERFACE PkgConfig::glx -ldl)
# Library file: libazur_*_gl3w.a
install(TARGETS gl3w DESTINATION ${LIBDIR})
# Headers
install(DIRECTORY gl3w/include/ DESTINATION ${INCDIR}/azur/gl3w)
endif()
#---
# GLM
#---
# Define the header-only library
add_library(glm INTERFACE)
# TODO: Get rid of the dependency GLM by using libnum instead
# Set the include directory
target_include_directories(glm INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/glm")
# Headers
install(DIRECTORY glm/glm/ DESTINATION ${INCDIR}/azur/glm/glm)
#---
# The Dear ImGui library for SDL + OpenGL3/OpenGLES2
@ -36,7 +51,7 @@ set(SOURCES
imgui/backends/imgui_impl_opengl3.cpp
imgui/backends/imgui_impl_sdl.cpp)
# Use Freetype if the library is installed, or the emscripten port
# Use Freetype if the library is available; on emscripten there is a port
if(AZUR_PLATFORM_EMSCRIPTEN)
list(APPEND SOURCES imgui/misc/freetype/imgui_freetype.cpp)
else()
@ -47,32 +62,34 @@ else()
endif()
add_library(imgui ${SOURCES})
set_target_properties(imgui PROPERTIES
OUTPUT_NAME "azur_${AZUR_PLATFORM}_imgui")
# Try to reduce the size of the binary code by including individual functions
# from the archive, instead of whole files
# from the archive, instead of whole files. (The interface library described in
# FindAzur.cmake sets -Wl,--gc-sections.)
target_compile_options(imgui PRIVATE -ffunction-sections)
target_compile_options(imgui INTERFACE -Wl,--gc-sections)
# Use the included ImGui loader on desktop
if(AZUR_GRAPHICS_OPENGL_3_3)
# Nothing do, loader is built-in
# Use the autonomous GLES 2.0 loader otherwise
elseif(AZUR_GRAPHICS_OPENGL_ES_2_0)
target_compile_definitions(imgui PUBLIC
-DIMGUI_IMPL_OPENGL_ES2)
endif()
# FreeType2 settings
if(freetype2_FOUND)
target_compile_definitions(imgui PUBLIC -DIMGUI_ENABLE_FREETYPE)
target_include_directories(imgui PRIVATE imgui/misc/freetype)
target_link_libraries(imgui PUBLIC PkgConfig::freetype2)
elseif(AZUR_PLATFORM_EMSCRIPTEN)
if(AZUR_PLATFORM_EMSCRIPTEN)
target_compile_definitions(imgui PUBLIC -DIMGUI_ENABLE_FREETYPE)
target_include_directories(imgui PRIVATE imgui/misc/freetype)
target_compile_options(imgui PUBLIC -sUSE_FREETYPE=1)
target_link_options(imgui INTERFACE -sUSE_FREETYPE=1)
elseif(freetype2_FOUND)
target_compile_definitions(imgui PUBLIC -DIMGUI_ENABLE_FREETYPE)
target_include_directories(imgui PRIVATE imgui/misc/freetype)
target_link_libraries(imgui PUBLIC PkgConfig::freetype2)
endif()
# Provide include directories
target_include_directories(imgui PUBLIC imgui imgui/backends)
# Library file: libazur_*_imgui.a
install(TARGETS imgui DESTINATION ${LIBDIR})
# Headers
install(DIRECTORY imgui/ DESTINATION ${INCDIR}/azur/imgui
FILES_MATCHING PATTERN "*.h"
PATTERN examples EXCLUDE
PATTERN docs EXCLUDE
PATTERN .github EXCLUDE)

View File

@ -1,33 +1,54 @@
cmake_minimum_required(VERSION 3.19)
project(AzurEngine VERSION 0.1)
#-----------------------------------------------------------------------------#
# ," /\ ", Azur: A game engine for CASIO fx-CG and PC #
# | _/__\_ | Designed by Lephe' and the Planète Casio community. #
# "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> #
#-----------------------------------------------------------------------------#
# Main build system
#
# The build system consists of this CMakeLists.txt file, the CMakeLists.txt
# files of each component folder, and importantly the FindAzur.cmake file
# which loads the library for users.
#
# We build and install third-party dependencies along the engine to alleviate
# some packaging/distribution issues. Currently, these are:
#
# o GL3W, which we rely on to load the OpenGL core profile on PC
# o Dear ImGui, for introspection and debugging tools
#
# The following variables can be set on the command-line at cmake time:
#
# -DCMAKE_BUILD_TYPE:
# Debug Debug build with -O0 -g
# Release Release build with -Os [default]
#
# -DAZUR_PLATFORM:
# gint Build for gint for fx-CG
# linux Build for Linux with SDL and OpenGL 3.3
# emscripten Build for Emscripten with SDL and OpenGL ES 2.0
#
# -DCMAKE_INSTALL_PREFIX:
# The usual install prefix. It must be different for each platform. For gint,
# it defaults to the compiler's data folder as usual. The environment
# variable AZUR_PATH_<platform> is recognized by the find module.
#---
#---
# Configuration
#
# -DCMAKE_BUILD_TYPE
# Debug Debug build with -O0 -g
# Release Release build with -Os [default]
#
# -DAZUR_PLATFORM
# gint Build for gint for fx-CG
# linux Build for Linux with SDL and OpenGL 3.3
# emscripten Build for Emscripten with SDL and OpenGL ES 2.0
#
# -DCMAKE_INSTALL_PREFIX
#---
cmake_minimum_required(VERSION 3.15)
project(Azur VERSION 0.1 LANGUAGES C CXX ASM)
set(CMAKE_INSTALL_MESSAGE LAZY)
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set("${CMAKE_BUILD_TYPE}" Release)
endif()
# Debug build
if("${CMAKE_BUILD_TYPE}" STREQUAL Debug)
set(AZUR_DEBUG TRUE)
else()
set(AZUR_DEBUG FALSE)
endif()
# When using [fxsdk build-cg], assume gint
# Detect when the fxSDK is used, and assume gint. This allows one to simply run
# `fxsdk build-cg` to build the engine.
if("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
set(AZUR_PLATFORM gint)
endif()
@ -35,17 +56,21 @@ endif()
# Default install paths
set(LIBDIR "lib")
set(INCDIR "include")
set(MODPATH "lib/cmake")
# Target configuration: gint
if("${AZUR_PLATFORM}" STREQUAL "gint")
#---
# Target-specific configuration
#---
if(AZUR_PLATFORM STREQUAL gint)
set(AZUR_PLATFORM_GENERIC TRUE)
set(AZUR_TOOLKIT_GINT TRUE)
set(AZUR_GRAPHICS_GINT_CG TRUE)
set(AZUR_TERMINAL_NONE TRUE)
find_package(Gint 2.4 REQUIRED)
# Link with gint and libprof (we only do this to get include directories)
find_package(Gint 2.8 REQUIRED)
find_package(LibProf 2.4 REQUIRED)
link_libraries(LibProf::LibProf Gint::Gint)
# Default to the fxSDK install path
@ -57,26 +82,25 @@ if("${AZUR_PLATFORM}" STREQUAL "gint")
if(CMAKE_INSTALL_PREFIX STREQUAL "${FXSDK_COMPILER_INSTALL}")
set(LIBDIR ".")
set(INCDIR "include")
set(MODPATH "${FXSDK_CMAKE_MODULE_PATH}")
endif()
endif()
# Target configuration: linux
if(AZUR_PLATFORM STREQUAL linux)
set(AZUR_PLATFORM_GENERIC TRUE)
set(AZUR_TOOLKIT_SDL TRUE)
set(AZUR_GRAPHICS_OPENGL_3_3 TRUE)
set(AZUR_TERMINAL_ANSI TRUE)
# Once again, we link only for the include paths
find_package(PkgConfig REQUIRED)
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
pkg_check_modules(sdl2_image REQUIRED SDL2_image IMPORTED_TARGET)
pkg_check_modules(opengl REQUIRED opengl IMPORTED_TARGET)
pkg_check_modules(glx REQUIRED glx IMPORTED_TARGET)
link_libraries(PkgConfig::sdl2_image PkgConfig::sdl2 PkgConfig::opengl -lm)
endif()
# Platform configuration: emscripten
if(AZUR_PLATFORM STREQUAL emscripten)
set(AZUR_PLATFORM_EMSCRIPTEN TRUE)
set(AZUR_TOOLKIT_SDL TRUE)
@ -119,3 +143,10 @@ endif()
add_subdirectory(libnum)
add_subdirectory(azur)
#---
# Install
#---
# CMake module to find the library
install(FILES FindAzur.cmake DESTINATION ${MODPATH})

162
FindAzur.cmake Normal file
View File

@ -0,0 +1,162 @@
# 1. Find the library's install path and data
set(AZUR_PATH "$ENV{AZUR_PATH_${AZUR_PLATFORM}}")
if(NOT "${FXSDK_PLATFORM_LONG}" STREQUAL "")
set(AZUR_PLATFORM gint)
set(AZUR_PATH "${FXSDK_COMPILER_INSTALL}")
set(AZUR_LIB "${AZUR_PATH}/libazur_${AZUR_PLATFORM}.a")
set(AZUR_INCLUDE "${AZUR_PATH}/include")
message("(Azur) Using the fxSDK compiler path: ${AZUR_LIB}")
message("(Azur) Will take includes from: ${AZUR_INCLUDE}")
elseif(NOT "${AZUR_PATH}" STREQUAL "")
set(AZUR_LIB "${AZUR_PATH}/lib/libazur_${AZUR_PLATFORM}.a")
set(AZUR_INCLUDE "${AZUR_PATH}/include")
if(NOT EXISTS "${AZUR_LIB}")
message(SEND_ERROR
"AZUR_PATH was set to ${AZUR_PATH}, but ${AZUR_LIB} does not exist")
endif()
message("(Azur) Found AZUR_PATH_${AZUR_PLATFORM}: ${AZUR_LIB}")
message("(Azur) Will take includes from: ${AZUR_INCLUDE}")
else()
find_library(AZUR_PATH "azur_${AZUR_PLATFORM}")
if("${AZUR_PATH}" STREQUAL "AZUR_PATH-NOTFOUND")
message(SEND_ERROR
"Could not find libazur_${AZUR_PLATFORM}.a!\n"
"You can specify the installation path with the environment variable "
"AZUR_PATH, such as AZUR_PATH=/path/to/lib\n")
else()
set(AZUR_LIB "${AZUR_PATH}/lib/libazur_${AZUR_PLATFORM}.a")
set(AZUR_INCLUDE "${AZUR_PATH}/include")
message("(Azur) Found Azur at: ${AZUR_LIB}")
message("(Azur) Will take includes from: ${AZUR_INCLUDE}")
endif()
endif()
# 2. Find the library version and configuration
if(NOT EXISTS "${AZUR_INCLUDE}/azur/config.h")
message(SEND_ERROR
"Could not find <azur/config.h> at ${AZUR_INCLUDE}/azur/config.h\n"
"Is libazur.a installed alongside the headers?")
endif()
execute_process(
COMMAND sed "s/#define AZUR_VERSION \"\\([^\"]\\{1,\\}\\)\"/\\1/p; d"
"${AZUR_INCLUDE}/azur/config.h"
OUTPUT_VARIABLE AZUR_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
message("(Azur) Library version found in header: ${AZUR_VERSION}")
set(AZUR_3RDPARTY "")
set(AZUR_LIB_GL3W "${AZUR_PATH}/lib/libazur_${AZUR_PLATFORM}_gl3w.a")
set(AZUR_LIB_IMGUI "${AZUR_PATH}/lib/libazur_${AZUR_PLATFORM}_imgui.a")
if(EXISTS "${AZUR_INCLUDE}/azur/gl3w" AND EXISTS "${AZUR_LIB_GL3W}")
list(APPEND AZUR_3RDPARTY "gl3w")
message("(Azur) Found gl3w at: ${AZUR_LIB_GL3W}")
endif()
if(EXISTS "${AZUR_INCLUDE}/azur/imgui" AND EXISTS "${AZUR_LIB_IMGUI}")
list(APPEND AZUR_3RDPARTY "imgui")
message("(Azur) Found Dear ImGui at: ${AZUR_LIB_IMGUI}")
endif()
if(EXISTS "${AZUR_INCLUDE}/azur/glm")
list(APPEND AZUR_3RDPARTY "glm")
message("(Azur) Found GLM at: ${AZUR_INCLUDE}/azur/glm")
endif()
message("(Azur) Summary of external libraries found: ${AZUR_3RDPARTY}")
# 3. Handle usual find_package() arguments and perform version check
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Azur
REQUIRED_VARS AZUR_LIB AZUR_INCLUDE
VERSION_VAR AZUR_VERSION)
# 4. Find dependencies
if(AZUR_PLATFORM STREQUAL linux)
find_package(PkgConfig REQUIRED)
endif()
# 5. Generate targets
if(Azur_FOUND)
if(NOT TARGET Azur::Azur)
add_library(Azur::Azur UNKNOWN IMPORTED)
endif()
set_target_properties(Azur::Azur PROPERTIES
IMPORTED_LOCATION "${AZUR_LIB}"
INTERFACE_INCLUDE_DIRECTORIES "${AZUR_INCLUDE}"
INTERFACE_COMPILE_OPTIONS "-DAZUR_PLATFORM=${AZUR_PLATFORM}")
if(AZUR_PLATFORM STREQUAL linux)
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
pkg_check_modules(sdl2_image REQUIRED SDL2_image IMPORTED_TARGET)
pkg_check_modules(opengl REQUIRED opengl IMPORTED_TARGET)
target_link_libraries(Azur::Azur INTERFACE
PkgConfig::sdl2_image PkgConfig::sdl2 PkgConfig::opengl -lm)
elseif(AZUR_PLATFORM STREQUAL emscripten)
set(PORTS -sUSE_SDL=2 -sUSE_SDL_IMAGE=2 -sSDL2_IMAGE_FORMATS=["png"])
add_compile_options(${PORTS})
add_link_options(${PORTS} -O3)
endif()
endif()
if("gl3w" IN_LIST AZUR_3RDPARTY)
if(NOT TARGET Azur::gl3w)
add_library(Azur::gl3w UNKNOWN IMPORTED)
endif()
set_target_properties(Azur::gl3w PROPERTIES
IMPORTED_LOCATION "${AZUR_LIB_GL3W}"
INTERFACE_INCLUDE_DIRECTORIES "${AZUR_INCLUDE}/azur/gl3w")
if(AZUR_PLATFORM STREQUAL linux)
pkg_check_modules(glx REQUIRED glx IMPORTED_TARGET)
target_link_libraries(Azur::gl3w INTERFACE PkgConfig::glx -ldl)
target_link_libraries(Azur::Azur INTERFACE Azur::gl3w)
endif()
endif()
if("glm" IN_LIST AZUR_3RDPARTY)
if(NOT TARGET Azur::GLM)
add_library(Azur::GLM INTERFACE IMPORTED)
endif()
set_target_properties(Azur::GLM PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${AZUR_INCLUDE}/azur/glm")
endif()
if("imgui" IN_LIST AZUR_3RDPARTY)
if(NOT TARGET Azur::ImGui)
add_library(Azur::ImGui UNKNOWN IMPORTED)
endif()
set_target_properties(Azur::ImGui PROPERTIES
IMPORTED_LOCATION "${AZUR_LIB_IMGUI}"
INTERFACE_INCLUDE_DIRECTORIES
"${AZUR_INCLUDE}/azur/imgui;${AZUR_INCLUDE}/azur/imgui/backends"
INTERFACE_LINK_OPTIONS "-Wl,--gc-sections")
if(AZUR_PLATFORM STREQUAL emscripten)
target_link_options(Azur::ImGui INTERFACE -sUSE_FREETYPE=1)
target_compile_definitions(Azur::ImGui INTERFACE -DIMGUI_ENABLE_FREETYPE)
target_include_directories(Azur::ImGui INTERFACE
"${AZUR_INCLUDE}/azur/imgui/misc/freetype")
else()
pkg_check_modules(freetype2 freetype2 IMPORTED_TARGET)
if(freetype2_FOUND)
target_link_libraries(Azur::ImGui INTERFACE PkgConfig::freetype2)
target_compile_definitions(Azur::ImGui INTERFACE -DIMGUI_ENABLE_FREETYPE)
endif()
endif()
endif()

View File

@ -4,6 +4,15 @@ Azur is a game engine for the fx-CG series of graphing calculators that also sup
Azur aims to implement real-world game engine mechanics such as ECS, animation and visual effects, physics, and state serialization. It doesn't try to be super fancy with them, but it does try to get the structure right.
Current status:
- [x] Build system supporting gint (fxSDK), Linux (SDL 2/OpenGL 3.3) and emscripten (SDL 2/OpenGL ES 2.0)
- [x] Platform-independent initialization/main loop/etc management.
- [x] Specialized fragmented-rendering pipeline for gint, providing high-performance graphics.
- [ ] Bare-bones fixed-point computation library.
- [ ] Experimental ECS system under design.
Currently Azur is barely more than the native systems it uses (gint/OpenGL), with no solid unified APIs. It is mostly useful for writing high-performance gint games.
## Projects in this repository
The following are Azur libraries:
@ -20,30 +29,65 @@ The following external projects are Azur by some of Azur's features, and maintai
## Building
You *must* install into a different folder for each platform, as the headers would otherwise clash (particulary the auto-generated `<azur/config.h>`. The library names are different (eg. `libazur_emscripten.a`), but this is just to avoid confusing errors; the folders must still be different.
**Building for fx-CG**
Use the [fxSDK toolchain](https://gitea.planet-casio.com/Lephenixnoir/fxsdk).
Use the [fxSDK toolchain](https://gitea.planet-casio.com/Lephenixnoir/fxsdk). When building with the fxSDK, `AZUR_PLATFORM=gint` is assumed and the compiler's data folder is used to install the library.
```
% fxsdk build-cg
% fxsdk build-cg install
```
**Building for Linux**
I recommend using a user-writable folder like `~/.local`. You can record the path in the environment variable `AZUR_PATH_linux`, in which case the find module for Azur will pick it up automatically regardless of whether CMake searches that particular folder by default.
```
% cmake -B build-linux -DAZUR_PLATFORM=linux -DCMAKE_INSTALL_PREFIX="$HOME/.local"
% make -C build-linux
% make -C build-linux install -j$(nproc)
# Later (eg. in ~/.profile):
% export AZUR_PATH_linux="$HOME/.local"
```
**Building for emscripten**
You will need the [emscripten toolchain](https://emscripten.org/).
You will need the [emscripten toolchain](https://emscripten.org/). I recommend to use a dedicated install folder since this is essentially a cross-compiling target.
```
% emcmake cmake -B build-emscripten -D AZUR_PLATFORM=emscripten
% make -C build-emscripten
% emcmake cmake -B build-emscripten -D AZUR_PLATFORM=emscripten -DCMAKE_INSTALL_PREFIX="$HOME/.prefix-emscripten"
% make -C build-emscripten install -j$(nproc)
# Later (eg. in ~/.profile):
% export AZUR_PATH_emscripten="$HOME/.prefix-emscripten"
```
## Using in an application
Users building programs with Azur for Linux or emscripten should export the environment variables `AZUR_PATH_linux` or `AZUR_PATH_emscripten` as described above. The variable `AZUR_PLATFORM` should also be set on the command-line with `-D` during configuration, or hardcoded if the application only supports one target.
The application's `CMakeLists.txt` can then do:
```cmake
list(APPEND CMAKE_MODULE_PATH "$ENV{AZUR_PATH_${AZUR_PLATFORM}}/lib/cmake")
find_package(Azur 0.1 REQUIRED)
```
When using gint, only the `find_package()` is necessary. The fxSDK handles the rest.
The find module then exports up to three targets that can be linked against: `Azur::Azur`, `Azur::GLM` and `Azur::ImGui` (gint only has the first). The result might look like this:
```cmake
if(AZUR_PLATFORM STREQUAL gint)
target_link_libraries(myprogram Azur::Azur)
else() # Linux and emscripten
target_link_libraries(myprogram Azur::Azur Azur::GLM Azur::ImGui)
endif()
```
## History note
Back in 2021 I made a single repository for this engine, along with other programs that I intended to write with it. At the time I didn't intend to distribute the engine in any serious fashion, but that changed after people expressed interest in playing with [After Burner](https://www.planet-casio.com/Fr/programmes/programme4238-1-after-burner-lephenixnoir-jeux-add-ins.html). I split the repository in May 2022 with `git filter-branch`, and edited the history so old commits can still be built, but don't expect that to work out-of-the-box.
Back in 2021 I made a single repository for this engine, along with other programs that I intended to write with it. At the time I didn't intend to distribute the engine in any serious fashion, but that changed after people expressed interest in playing with [After Burner](https://www.planet-casio.com/Fr/programmes/programme4238-1-after-burner-lephenixnoir-jeux-add-ins.html).
I split the original repository in May 2022 with `git filter-branch`, extracting Azur-related contents to this repository. I edited the history so that old commits can still be built, but mostly for the sake of preserving history; don't expect to be able to use these early commits out-of-the-box.

View File

@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.15)
project(Azur VERSION 0.1 LANGUAGES CXX C ASM)
#-----------------------------------------------------------------------------#
# ," /\ ", Azur: A game engine for CASIO fx-CG and PC #
# | _/__\_ | Designed by Lephe' and the Planète Casio community. #
# "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> #
#-----------------------------------------------------------------------------#
# Main library build system
configure_file(include/azur/config.h.in include/azur/config.h)
@ -11,12 +15,24 @@ set(ASSETS)
if(AZUR_TOOLKIT_SDL AND AZUR_GRAPHICS_OPENGL)
list(APPEND SOURCES
src/sdl_opengl/init.c
src/sdl_opengl/util.c)
src/sdl_opengl/util.c
"${CMAKE_CURRENT_BINARY_DIR}/src/glsl.c")
list(APPEND ASSETS
glsl/vs_prelude_gles2.glsl
glsl/fs_prelude_gles2.glsl
glsl/vs_prelude_gl3.glsl
glsl/fs_prelude_gl3.glsl
glsl/vs_tex2d.glsl
glsl/fs_tex2d.glsl)
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/src/glsl.c"
COMMAND mkdir -p "${CMAKE_CURRENT_BINARY_DIR}/src"
COMMAND python gen_glsl.py "${CMAKE_CURRENT_BINARY_DIR}/src/glsl.c"
${ASSETS}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMENT "Generating a C file with prebuilt shaders"
DEPENDS gen_glsl.py ${ASSETS})
endif()
# gint rendering
@ -53,41 +69,25 @@ endif()
add_library(azur STATIC ${SOURCES})
# File preloading on emscripten
if(AZUR_PLATFORM_EMSCRIPTEN)
set_target_properties(azur PROPERTIES
INTERFACE_LINK_OPTIONS
"SHELL:--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/glsl@/azur/glsl"
LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/glsl")
set_target_properties(azur PROPERTIES OUTPUT_NAME "azur_${AZUR_PLATFORM}")
# Add assets to link dependencies
set(ASSETS_ABSOLUTE)
foreach(ASSET IN LISTS ASSETS)
list(APPEND ASSETS_ABSOLUTE "${CMAKE_CURRENT_SOURCE_DIR}/${ASSET}")
endforeach()
set_target_properties(azur PROPERTIES LINK_DEPENDS "${ASSETS_ABSOLUTE}")
endif()
# Use ImGui's integrated GL3W loader (which we build separately)
# Link with GL3W to load the OpenGL 3.3 core profile
if(AZUR_GRAPHICS_OPENGL_3_3)
target_link_libraries(azur PUBLIC gl3w)
endif()
target_include_directories(azur
PUBLIC "${PROJECT_SOURCE_DIR}/include"
PUBLIC "${PROJECT_BINARY_DIR}/include"
)
target_include_directories(azur PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}/include")
#---
# Install
#---
# Library file: libazur.a
# Library file: libazur_*.a
install(TARGETS azur DESTINATION ${LIBDIR})
# Headers: azur/*.h
install(DIRECTORY include/ DESTINATION ${INCDIR} FILES_MATCHING PATTERN "*.h")
# Generated header: azur/config.h
install(FILES "${PROJECT_BINARY_DIR}/include/azur/config.h"
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/include/azur/config.h"
DESTINATION ${INCDIR}/azur)
# CMake module loading the library: TODO
# install(FILES cmake/FindAzur.cmake DESTINATION "${FXSDK_CMAKE_MODULE_PATH}")

34
azur/gen_glsl.py Normal file
View File

@ -0,0 +1,34 @@
#-----------------------------------------------------------------------------#
# ," /\ ", Azur: A game engine for CASIO fx-CG and PC #
# | _/__\_ | Designed by Lephe' and the Planète Casio community. #
# "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> #
#-----------------------------------------------------------------------------#
# gen_glsl.py: Trivial utility to embed GLSL files into the library
#
# Azur comes with a set of default shaders, but installing GLSL files to be
# loaded at runtime comes with a number of install/distribution constraints.
# For simplicity, we embed the files into the library by generating a C file
# with a bunch of strings and compiling it.
#---
import sys
import os
if len(sys.argv) < 2 or "-h" in sys.argv or "--help" in sys.argv:
print(f"usage: {sys.argv[0]} <OUTPUT.c> <INPUT.glsl...>")
def encode(string):
# Escape characters that have special meaning in C
string = string.replace("\\", "\\\\").replace("\"", "\\\"")
# Enforce proper newlines
return "\n".join(f'"{s}\\n"' for s in string.split("\n"))
inputs = []
for input_file in sys.argv[2:]:
with open(input_file, "r") as fp:
name = os.path.splitext(os.path.basename(input_file))[0]
inputs.append((name, fp.read()))
with open(sys.argv[1], "w") as fp:
for (name, data) in inputs:
fp.write(f"char const *azur_glsl__{name} =\n{encode(data)};\n\n")

View File

@ -4,6 +4,7 @@
#pragma once
#define AZUR_VERSION "@Azur_VERSION@"
#define AZUR_VERSION_MAJOR @Azur_VERSION_MAJOR@
#define AZUR_VERSION_MINOR @Azur_VERSION_MINOR@

View File

@ -7,7 +7,7 @@
AZUR_BEGIN_DECLS
#ifdef AZUR_GRAPHICS_OPENGL_3_3
# include "GL/gl3w.h"
# include <GL/gl3w.h>
# include <SDL2/SDL_opengl.h>
#endif /* OpenGL 3.3 */
@ -44,15 +44,22 @@ GLuint azgl_compile_shader_source(GLenum type, char const *code, ssize_t size);
it, and returns the program ID (0 if link fails). */
GLuint azgl_link_program(GLuint shader_1, ... /* 0-terminated */);
/* azgl_load_program(): Load a program from shader source files.
/* azgl_load_program_file(): Load a program from shader source files.
This function runs both azgl_compile_shader_file() and azgl_link_program()
for all specified files. Each argument should be a pair with a shader type
and a file name, with a final 0.
Returns the program ID, or 0 if any loading/compilation/link step fails. */
GLuint azgl_load_program(
GLuint azgl_load_program_file(
GLenum type_1, char const *path_1,
... /* Pairs repeat until 0-terminated */);
/* azgl_load_program_source(): Load a program from shader source strings.
Like azgl_load_program_file(), but takes code directly as input. */
GLuint azgl_load_program_source(
GLenum type_1, char const *code_1,
... /* Pairs repeat until 0-terminated */);
AZUR_END_DECLS

View File

@ -4,7 +4,7 @@
#ifdef AZUR_DEBUG
static int _level = AZLOG_DEBUG;
#else
static int _level = AZLOG_ERROR;
static int _level = AZLOG_INFO;
#endif
#ifdef AZUR_TERMINAL_ANSI
@ -39,6 +39,8 @@ void azlog_write(int level, char const *file, int line, char const *func,
fprintf(stderr, CYAN "%s:%d: " STOP YELLOW "%s: " STOP,
file, line, func);
#else
(void)file;
(void)line;
fprintf(stderr, "%s: ", func);
#endif

View File

@ -10,6 +10,35 @@ static SDL_GLContext glcontext = NULL;
static void main_loop_quit(void);
#ifdef AZUR_PLATFORM_EMSCRIPTEN
#include <emscripten/html5.h>
static EM_BOOL fullscreen_callback(int ev, void const *_, void *window0)
{
double w, h;
emscripten_get_element_css_size("canvas", &w, &h);
SDL_Window *window = window0;
SDL_SetWindowSize(window, (int)w, (int)h);
azlog(INFO, "Canvas size updated: now %dx%d", (int)w, (int)h);
return EM_TRUE;
}
static void enter_fullscreen(SDL_Window *window)
{
EmscriptenFullscreenStrategy strategy = {
.scaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF,
.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT,
.canvasResizedCallback = fullscreen_callback,
.canvasResizedCallbackUserData = window,
};
emscripten_enter_soft_fullscreen("canvas", &strategy);
azlog(INFO, "Entered fullscreen! (info)");
azlog(ERROR, "Entered fullscreen! (error)");
}
#endif /* AZUR_PLATFORM_EMSCRIPTEN */
int azur_init(char const *title, int window_width, int window_height)
{
int rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
@ -72,6 +101,10 @@ int azur_init(char const *title, int window_width, int window_height)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#ifdef AZUR_PLATFORM_EMSCRIPTEN
enter_fullscreen(window);
#endif
return 0;
}

View File

@ -58,23 +58,27 @@ static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
char const *origin)
{
/* Shader prelude; this gives shader version, some macro definitions and
some "selctors" which altogether give some degree of compatibility
some "selectors" which altogether provide some degree of compatibility
between GLSL and GLSL ES. */
static char const *vs_prelude = NULL;
static char const *fs_prelude = NULL;
if(!vs_prelude) {
#if defined AZUR_GRAPHICS_OPENGL_ES_2_0
vs_prelude = load_file("azur/glsl/vs_prelude_gles2.glsl", NULL);
extern char const *azur_glsl__vs_prelude_gles2;
vs_prelude = azur_glsl__vs_prelude_gles2;
#elif defined AZUR_GRAPHICS_OPENGL_3_3
vs_prelude = load_file("azur/glsl/vs_prelude_gl3.glsl", NULL);
extern char const *azur_glsl__vs_prelude_gl3;
vs_prelude = azur_glsl__vs_prelude_gl3;
#endif
}
if(!fs_prelude) {
#if defined AZUR_GRAPHICS_OPENGL_ES_2_0
fs_prelude = load_file("azur/glsl/fs_prelude_gles2.glsl", NULL);
extern char const *azur_glsl__fs_prelude_gles2;
fs_prelude = azur_glsl__fs_prelude_gles2;
#elif defined AZUR_GRAPHICS_OPENGL_3_3
fs_prelude = load_file("azur/glsl/fs_prelude_gl3.glsl", NULL);
extern char const *azur_glsl__fs_prelude_gl3;
fs_prelude = azur_glsl__fs_prelude_gl3;
#endif
}
@ -83,7 +87,7 @@ static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
prelude = vs_prelude;
else if(type == GL_FRAGMENT_SHADER)
prelude = fs_prelude;
else
if(prelude == NULL)
prelude = "";
GLuint id = glCreateShader(type);
@ -95,8 +99,11 @@ static GLuint azgl_compile_shader(GLenum type, char const *code, ssize_t size,
GLint rc = GL_FALSE;
GLsizei log_length = 0;
if(size < 0)
size = (int)strlen(code);
char const *string_array[] = { prelude, code };
GLint size_array[] = { strlen(prelude), size ? size : (int)strlen(code) };
GLint size_array[] = { strlen(prelude), size };
azlog(INFO, "Compiling shader: %s\n", origin);
glShaderSource(id, 2, string_array, size_array);
@ -135,7 +142,7 @@ GLuint azgl_compile_shader_file(GLenum type, char const *path)
return id;
}
GLuint azgl_compiler_shader_source(GLenum type, char const *code, ssize_t size)
GLuint azgl_compile_shader_source(GLenum type, char const *code, ssize_t size)
{
return azgl_compile_shader(type, code, size, "<inline>");
}
@ -199,21 +206,20 @@ GLuint azgl_link_program(GLuint shader_1, ... /* 0-terminated */)
return azgl_link(shaders, count);
}
GLuint azgl_load_program(GLenum type, char const *path, ...)
static GLuint azgl_load_program(bool is_file, GLenum type, char const *input,
va_list *args)
{
va_list args;
va_start(args, path);
GLuint shaders[32];
int count = 0;
do {
shaders[count++] = azgl_compile_shader_file(type, path);
type = va_arg(args, GLenum);
path = va_arg(args, char const *);
shaders[count++] = is_file
? azgl_compile_shader_file(type, input)
: azgl_compile_shader_source(type, input, -1);
type = va_arg(*args, GLenum);
input = va_arg(*args, char const *);
}
while(count < 32 && type != 0);
va_end(args);
GLuint prog = azgl_link(shaders, count);
@ -222,3 +228,21 @@ GLuint azgl_load_program(GLenum type, char const *path, ...)
return prog;
}
GLuint azgl_load_program_file(GLenum type, char const *path, ...)
{
va_list args;
va_start(args, path);
GLuint prog = azgl_load_program(true, type, path, &args);
va_end(args);
return prog;
}
GLuint azgl_load_program_source(GLenum type, char const *code, ...)
{
va_list args;
va_start(args, code);
GLuint prog = azgl_load_program(false, type, code, &args);
va_end(args);
return prog;
}

View File

@ -1,16 +1,14 @@
cmake_minimum_required(VERSION 3.15)
project(libnum VERSION 0.1)
#-----------------------------------------------------------------------------#
# ," /\ ", Azur: A game engine for CASIO fx-CG and PC #
# | _/__\_ | Designed by Lephe' and the Planète Casio community. #
# "._`\/'_." License: MIT <https://opensource.org/licenses/MIT> #
#-----------------------------------------------------------------------------#
# libnum build system
# Most of the code is in the headers
add_library(num STATIC src/static_checks.cpp test.cpp)
add_library(num STATIC
src/static_checks.cpp)
target_include_directories(num
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_compile_options(num PRIVATE -std=c++17)
#---
# Install
#---
target_include_directories(num PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
# Library file: libnum.a
install(TARGETS num DESTINATION ${LIBDIR})