All Projects → brackeen → Glfm

brackeen / Glfm

Licence: zlib
OpenGL ES and input for iOS, tvOS, Android, and WebGL

Programming Languages

c
50402 projects - #5 most used programming language

Projects that are alternatives of or similar to Glfm

Ouzel
C++ game engine for Windows, macOS, Linux, iOS, tvOS, Android, and web browsers
Stars: ✭ 607 (+66.76%)
Mutual labels:  emscripten, opengles, tvos
Magnum
Lightweight and modular C++11 graphics middleware for games and data visualization
Stars: ✭ 3,728 (+924.18%)
Mutual labels:  emscripten
Web3.swift
A pure swift Ethereum Web3 library
Stars: ✭ 295 (-18.96%)
Mutual labels:  tvos
Jsc.js
JavaScriptCore on WebAssembly
Stars: ✭ 311 (-14.56%)
Mutual labels:  emscripten
Functionkit
A framework for functional types and operations designed to fit naturally into Swift.
Stars: ✭ 302 (-17.03%)
Mutual labels:  tvos
Layoutframeworkbenchmark
Benchmark the performances of various Swift layout frameworks (autolayout, UIStackView, PinLayout, LayoutKit, FlexLayout, Yoga, ...)
Stars: ✭ 316 (-13.19%)
Mutual labels:  tvos
Essentia.js
JavaScript library for music/audio analysis and processing powered by Essentia WebAssembly
Stars: ✭ 294 (-19.23%)
Mutual labels:  emscripten
Viz.js
A hack to put Graphviz on the web.
Stars: ✭ 3,602 (+889.56%)
Mutual labels:  emscripten
Crypto
Swift CommonCrypto wrapper
Stars: ✭ 328 (-9.89%)
Mutual labels:  tvos
Openglcamera2
Android OpenGL Camera 2.0 实现 30 种滤镜和抖音特效
Stars: ✭ 305 (-16.21%)
Mutual labels:  opengles
Layoutkit
LayoutKit is a fast view layout library for iOS, macOS, and tvOS.
Stars: ✭ 3,176 (+772.53%)
Mutual labels:  tvos
Entwine
Testing tools and utilities for Apple's Combine framework.
Stars: ✭ 306 (-15.93%)
Mutual labels:  tvos
Face Landmark Android
Android AR Camera
Stars: ✭ 320 (-12.09%)
Mutual labels:  opengles
Stdweb
A standard library for the client-side Web
Stars: ✭ 3,201 (+779.4%)
Mutual labels:  emscripten
Mvvmcross
The .NET MVVM framework for cross-platform solutions, including Xamarin.iOS, Xamarin.Android, Windows and Mac.
Stars: ✭ 3,594 (+887.36%)
Mutual labels:  tvos
Attributedstring
基于Swift插值方式优雅的构建富文本, 支持点击长按事件, 支持不同类型过滤, 支持自定义视图等.
Stars: ✭ 294 (-19.23%)
Mutual labels:  tvos
Corrade
C++11/C++14 multiplatform utility library
Stars: ✭ 307 (-15.66%)
Mutual labels:  emscripten
Misterfusion
MisterFusion is Swift DSL for AutoLayout. It is the extremely clear, but concise syntax, in addition, can be used in both Swift and Objective-C. Support Safe Area and Size Class.
Stars: ✭ 314 (-13.74%)
Mutual labels:  tvos
Solarized Dark For Xcode
Solarized Dark Theme for Xcode. Compatible with all modern versions of Xcode since 2013!
Stars: ✭ 358 (-1.65%)
Mutual labels:  tvos
Glide
Game engine for making 2d games on iOS, macOS and tvOS, with practical examples and tutorials
Stars: ✭ 353 (-3.02%)
Mutual labels:  tvos

GLFM

Write OpenGL ES code in C/C++ without writing platform-specific code.

GLFM is an OpenGL ES layer for mobile devices and the web. GLFM supplies an OpenGL ES context and input events. It is largely inspired by GLFW.

GLFM is written in C and runs on iOS 9, tvOS 9, Android 4.1 (API 16), and WebGL 1.0 (via Emscripten).

Additionally, GLFM provides Metal support on iOS and tvOS.

Features

  • OpenGL ES 2, OpenGL ES 3, and Metal display setup.
  • Retina / high-DPI support.
  • Touch and keyboard events.
  • Accelerometer, magnetometer, gyroscope, and device rotation (iOS/Android only)
  • Events for application state and context loss.

Non-goals

GLFM is limited in scope, and isn't designed to provide everything needed for an app. For example, GLFM doesn't provide (and will never provide) the following:

  • No image loading.
  • No text rendering.
  • No audio.
  • No menus, UI toolkit, or scene graph.
  • No integration with other mobile features like web views, maps, or game scores.

Instead, GLFM can be used with other cross-platform libraries that provide what an app needs.

Use GLFM

A CMakeLists.txt file is provided for convenience, although CMake is not required.

Without CMake:

  1. Add the GLFM source files (in include and src) to your project.
  2. Include a void glfmMain(GLFMDisplay *display) function in a C/C++ file.

Example

This example initializes the display in glfmMain() and draws a triangle in onFrame(). A more detailed example is available here.

#include "glfm.h"
#include <string.h>

static GLint program = 0;
static GLuint vertexBuffer = 0;

static void onFrame(GLFMDisplay *display);
static void onSurfaceCreated(GLFMDisplay *display, int width, int height);
static void onSurfaceDestroyed(GLFMDisplay *display);

void glfmMain(GLFMDisplay *display) {
    glfmSetDisplayConfig(display,
                         GLFMRenderingAPIOpenGLES2,
                         GLFMColorFormatRGBA8888,
                         GLFMDepthFormatNone,
                         GLFMStencilFormatNone,
                         GLFMMultisampleNone);
    glfmSetSurfaceCreatedFunc(display, onSurfaceCreated);
    glfmSetSurfaceResizedFunc(display, onSurfaceCreated);
    glfmSetSurfaceDestroyedFunc(display, onSurfaceDestroyed);
    glfmSetRenderFunc(display, onFrame);
}

static void onSurfaceCreated(GLFMDisplay *display, int width, int height) {
    glViewport(0, 0, width, height);
}

static void onSurfaceDestroyed(GLFMDisplay *display) {
    // When the surface is destroyed, all existing GL resources are no longer valid.
    program = 0;
    vertexBuffer = 0;
}

static GLuint compileShader(const GLenum type, const GLchar *shaderString) {
    const GLint shaderLength = (GLint)strlen(shaderString);
    GLuint shader = glCreateShader(type);
    glShaderSource(shader, 1, &shaderString, &shaderLength);
    glCompileShader(shader);
    return shader;
}

static void onFrame(GLFMDisplay *display) {
    if (program == 0) {
        const GLchar *vertexShader =
            "attribute highp vec4 position;\n"
            "void main() {\n"
            "   gl_Position = position;\n"
            "}";

        const GLchar *fragmentShader =
            "void main() {\n"
            "  gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
            "}";

        program = glCreateProgram();
        GLuint vertShader = compileShader(GL_VERTEX_SHADER, vertexShader);
        GLuint fragShader = compileShader(GL_FRAGMENT_SHADER, fragmentShader);

        glAttachShader(program, vertShader);
        glAttachShader(program, fragShader);

        glLinkProgram(program);

        glDeleteShader(vertShader);
        glDeleteShader(fragShader);
    }
    if (vertexBuffer == 0) {
        const GLfloat vertices[] = {
             0.0,  0.5, 0.0,
            -0.5, -0.5, 0.0,
             0.5, -0.5, 0.0,
        };
        glGenBuffers(1, &vertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    }

    glClearColor(0.4f, 0.0f, 0.6f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(program);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    glfmSwapBuffers(display);
}

API

See glfm.h

Build the GLFM examples with Xcode 12

Requires CMake 3.18.

mkdir -p build/ios && cd build/ios && cmake -DGLFM_BUILD_EXAMPLE=ON -G Xcode ../..
open GLFM.xcodeproj

Switch to the glfm_example target and run on the simulator or a device.

Build the GLFM examples with Emscripten

Tested with Emscripten 2.0.8.

Make sure EMSDK is set, and build:

mkdir -p build/emscripten && cd build/emscripten
cmake -DGLFM_BUILD_EXAMPLE=ON -DCMAKE_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../..
cmake --build .

Then run locally:

emrun example/glfm_example.html

Build the GLFM examples with Android Studio 4

There is no CMake generator for Android Studio projects, but you can include CMakeLists.txt in a new or existing project.

  1. Select "Start a new Android Studio project".
  2. Select "No Activity".
  3. In "Save location", enter [path/to/glfm]/build/android and press "Finish".
  4. In AndroidManifest.xml, add the main <activity> like so:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.brackeen.glfmexample">

    <uses-feature android:glEsVersion="0x00020000" android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true">

        <!-- Add this activity to your AndroidManifest.xml -->
        <activity android:name="android.app.NativeActivity"
                  android:configChanges="orientation|screenLayout|screenSize|keyboardHidden|keyboard">
            <meta-data
                android:name="android.app.lib_name"
                android:value="glfm_example" />  <!-- or glfm_test_pattern -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>
  1. In app/build.gradle, add the externalNativeBuild and sourceSets.main sections like so:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.brackeen.glfmexample"
        minSdkVersion 15
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        // Add externalNativeBuild in defaultConfig (1/2)
        externalNativeBuild {
            cmake {
                arguments "-DGLFM_BUILD_EXAMPLE=ON"
            }
        }
    }
    
    // Add sourceSets.main and externalNativeBuild (2/2)
    sourceSets.main {
        assets.srcDirs = ["../../../example/assets"]
    }
    externalNativeBuild {
        cmake {
            path "../../../CMakeLists.txt"
        }
    }
}
  1. Press "Sync Now" and "Run 'app'"

Caveats

  • OpenGL ES 3.1 and 3.2 support is only available in Android.
  • GLFM is not thread-safe. All GLFM functions must be called on the main thread (that is, from glfmMain or from the callback functions).
  • On iOS, character input works great, but keyboard events are not ideal. Using the keyboard (on an iOS device via Bluetooth keyboard or on the simulator via a Mac's keyboard), only a few keys are detected (arrows keys and the escape key), and key release events are not reported.
  • On Android, keyboard events work great, but character events are not ideal. Some special characters, like emoji characters, will not work. This is due to an issue in the NDK.
  • Orientation lock probably doesn't work on HTML5.

Questions

What IDE should I use? Why is there no desktop implementation? Use Xcode or Android Studio. For desktop, use GLFW with the IDE of your choice.

If you prefer not using the mobile simulators for everyday development, a good solution is to use GLFW instead, and then later port your app to GLFM. Not all OpenGL calls will port to OpenGL ES perfectly, but for maximum OpenGL portability, use OpenGL 3.2 Core Profile on desktop and OpenGL ES 2.0 on mobile.

Moving forward, GLFM APIs will look more like GLFW's, so porting will get easier as GLFM development continues.

Why is the entry point glfmMain() and not main()?

Otherwise, it wouldn't work on iOS. To initialize the Objective-C environment, the main() function must create an autorelease pool and call the UIApplicationMain() function, which never returns. On iOS, GLFM doesn't call glfmMain() until after the UIApplicationDelegate and UIViewController are initialized.

Why is GLFM event-driven? Why does GLFM take over the main loop?

Otherwise, it wouldn't work on iOS (see above) or on HTML5, which is event-driven.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].