GLFM est une API C pour le développement d'applications mobiles avec OpenGL ES. Il est largement inspiré de GLFW.
GLFM fonctionne sur iOS 9, tvOS 9, Android 4.1 (API 16) et WebGL 1.0 (via Emscripten).
De plus, GLFM fournit un support Metal sur iOS et tvOS.
IOS | tvOS | Androïde | Web | |
---|---|---|---|---|
OpenGL ES 2, OpenGL ES 3 | ✔️ | ✔️ | ✔️ | ✔️ |
Métal | ✔️ | ✔️ | N / A | N / A |
Rétine / haute DPI | ✔️ | ✔️ | ✔️ | ✔️ |
Orientation de l'appareil | ✔️ | N / A | ✔️ | |
Événements tactiles | ✔️ | ✔️ | ✔️ | ✔️ |
Événements de survol de la souris | ✔️ 1 | ✔️ | ||
Événements de la molette de la souris | ✔️ | |||
Style du curseur de la souris | ✔️ 1 | ✔️ | ||
Événements de code clé | ✔️ 2 | ✔️ | ✔️ | ✔️ |
Événements clés répétés | ✔️ | ✔️ | ||
Événements de saisie de caractères | ✔️ | ✔️ 3 | ✔️ | ✔️ |
Clavier virtuel | ✔️ | ✔️ | ||
Événements de visibilité du clavier virtuel | ✔️ | ✔️ | ||
Accéléromètre, magnétomètre, gyroscope, rotation de l'appareil | ✔️ | N / A | ✔️ | |
Retour haptique | ✔️ 4 | N / A | ✔️ | |
Presse-papiers | ✔️ | N / A | ✔️ | ✔️ |
Encarts Chrome ("zone sûre") | ✔️5 | ✔️ | ✔️ | |
Chrome insère les événements modifiés | ✔️5 | ✔️ | ✔️ | |
Événements ciblés | ✔️ | ✔️ | ✔️ | ✔️ |
Redimensionner les événements | ✔️ | ✔️ | ✔️ | ✔️ |
Événements d’avertissement de mémoire | ✔️ | ✔️ | ✔️ | |
Événements de perte de contexte OpenGL (surface détruite) | ✔️ | ✔️ | ✔️ | ✔️ |
1. iPad uniquement. Nécessite iOS 13.4 ou plus récent
2. Nécessite iOS/tvOS 13.4 ou version ultérieure
3. Nécessite tvOS 13.4 ou plus récent
4. Nécessite iOS 13 ou une version plus récente
5. Nécessite iOS/tvOS 11 ou plus récent
De plus, il existe une prise en charge préliminaire de macOS avec OpenGL 3.2. La version macOS est utile à des fins de développement, mais n'est pas de qualité commerciale. Il n'y a pas de fonction pour définir la taille de la fenêtre, par exemple.
GLFM a une portée limitée et n'est pas conçu pour fournir tout ce dont une application a besoin. Par exemple, GLFM ne fournit pas (et ne fournira jamais) les éléments suivants :
Au lieu de cela, GLFM peut être utilisé avec d'autres bibliothèques multiplateformes qui fournissent ce dont une application a besoin.
Un fichier CMakeLists.txt
est fourni pour plus de commodité, bien que CMake ne soit pas requis.
Sans CMake :
include
et src
) à votre projet.void glfmMain(GLFMDisplay *display)
dans un fichier C/C++. Pour les versions release, définissez NDEBUG
pour supprimer les instructions de journalisation superflues. NDEBUG
est automatiquement défini pour les versions dans Android Studio, mais pas dans Xcode.
Cet exemple initialise l'affichage dans glfmMain()
et dessine un triangle dans onDraw()
. Un exemple plus détaillé est disponible ici.
#include "glfm.h"
static GLint program = 0 ;
static GLuint vertexBuffer = 0 ;
static GLuint vertexArray = 0 ;
static void onDraw ( GLFMDisplay * display );
static void onSurfaceDestroyed ( GLFMDisplay * display );
void glfmMain ( GLFMDisplay * display ) {
glfmSetDisplayConfig ( display ,
GLFMRenderingAPIOpenGLES2 ,
GLFMColorFormatRGBA8888 ,
GLFMDepthFormatNone ,
GLFMStencilFormatNone ,
GLFMMultisampleNone );
glfmSetRenderFunc ( display , onDraw );
glfmSetSurfaceDestroyedFunc ( display , onSurfaceDestroyed );
}
static void onSurfaceDestroyed ( GLFMDisplay * display ) {
// When the surface is destroyed, all existing GL resources are no longer valid.
program = 0 ;
vertexBuffer = 0 ;
vertexArray = 0 ;
}
static GLuint compileShader ( const GLenum type , const GLchar * shaderString , GLint shaderLength ) {
GLuint shader = glCreateShader ( type );
glShaderSource ( shader , 1 , & shaderString , & shaderLength );
glCompileShader ( shader );
return shader ;
}
static void onDraw ( GLFMDisplay * display ) {
if ( program == 0 ) {
const GLchar vertexShader [] =
"#version 100n"
"attribute highp vec4 position;n"
"void main() {n"
" gl_Position = position;n"
"}" ;
const GLchar fragmentShader [] =
"#version 100n"
"void main() {n"
" gl_FragColor = vec4(0.85, 0.80, 0.75, 1.0);n"
"}" ;
program = glCreateProgram ();
GLuint vertShader = compileShader ( GL_VERTEX_SHADER , vertexShader , sizeof ( vertexShader ) - 1 );
GLuint fragShader = compileShader ( GL_FRAGMENT_SHADER , fragmentShader , sizeof ( fragmentShader ) - 1 );
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 );
}
int width , height ;
glfmGetDisplaySize ( display , & width , & height );
glViewport ( 0 , 0 , width , height );
glClearColor ( 0.08f , 0.07f , 0.07f , 1.0f );
glClear ( GL_COLOR_BUFFER_BIT );
#if defined( GL_VERSION_3_0 ) && GL_VERSION_3_0
if ( vertexArray == 0 ) {
glGenVertexArrays ( 1 , & vertexArray );
}
glBindVertexArray ( vertexArray );
#endif
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 );
}
Voir glfm.h
Utilisez cmake
pour générer un projet Xcode :
cmake -D GLFM_BUILD_EXAMPLES=ON -B build/apple -G Xcode
open build/apple/GLFM.xcodeproj
Dans Xcode, passez à la cible glfm_touch
et exécutez sur un simulateur ou un appareil.
Utilisez emcmake
pour définir les variables d'environnement pour cmake
, puis construisez :
emcmake cmake -D GLFM_BUILD_EXAMPLES=ON -B build/emscripten && cmake --build build/emscripten
Ensuite, exécutez localement :
emrun build/emscripten/examples
Ou exécutez un exemple spécifique :
emrun build/emscripten/examples/glfm_touch.html
Il n'existe pas de générateur CMake pour les projets Android Studio, mais vous pouvez inclure CMakeLists.txt
dans un projet nouveau ou existant.
[path/to/glfm]/build/android
et appuyez sur « Terminer ».AndroidManifest.xml
, ajoutez le principal
comme ceci : xml version = " 1.0 " encoding = " utf-8 " ?>
< manifest xmlns : android = " http://schemas.android.com/apk/res/android " >
< 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 " >
< activity android : name = " android.app.NativeActivity "
android : exported = " true "
android : configChanges = " orientation|screenLayout|screenSize|keyboardHidden|keyboard " >
< meta-data
android : name = " android.app.lib_name "
android : value = " glfm_touch " />
< intent-filter >
< action android : name = " android.intent.action.MAIN " />
< category android : name = " android.intent.category.LAUNCHER " />
intent-filter >
activity >
application >
manifest >
app/build.gradle
, ajoutez les sections externalNativeBuild
et sourceSets.main
comme ceci : apply plugin : ' com.android.application '
android {
compileSdkVersion 34
ndkVersion ' 23.2.8568313 ' // Last version to support API 16, 17, 18
defaultConfig {
applicationId " com.brackeen.glfmexample "
minSdkVersion 16
targetSdkVersion 34
versionCode 1
versionName " 1.0 "
// Add externalNativeBuild in defaultConfig (1/2)
externalNativeBuild {
cmake {
arguments " -DGLFM_BUILD_EXAMPLES=ON "
}
}
}
// Add sourceSets.main and externalNativeBuild (2/2)
sourceSets . main {
assets . srcDirs = [ " ../../../examples/assets " ]
}
externalNativeBuild {
cmake {
path " ../../../CMakeLists.txt "
}
}
namespace ' com.brackeen.glfmexample '
}
glfmMain
ou depuis les fonctions de rappel). Quel IDE dois-je utiliser ? Pourquoi n’y a-t-il pas d’implémentation de bureau ? Utilisez Xcode ou Android Studio. Pour le bureau, utilisez GLFW avec l'IDE de votre choix.
Si vous préférez ne pas utiliser les simulateurs mobiles pour le développement quotidien, une bonne solution consiste à utiliser GLFW à la place, puis à porter ultérieurement votre application sur GLFM. Tous les appels OpenGL ne seront pas parfaitement portés vers OpenGL ES, mais pour une portabilité OpenGL maximale, utilisez OpenGL 3.2 Core Profile sur ordinateur et OpenGL ES 2.0 sur mobile.
Pourquoi le point d'entrée est-il glfmMain()
et non main()
?
Sinon, cela ne fonctionnerait pas sur iOS. Pour initialiser l'environnement Objective-C, la fonction main()
doit créer un pool de libération automatique et appeler la fonction UIApplicationMain()
, qui ne renvoie jamais . Sur iOS, GLFM n'appelle glfmMain()
qu'après l'initialisation de UIApplicationDelegate
et UIViewController
.
Pourquoi GLFM est-il piloté par les événements ? Pourquoi GLFM reprend-il la boucle principale ?
Sinon, cela ne fonctionnerait pas sur iOS (voir ci-dessus) ou sur HTML5, qui est piloté par les événements.