How to develop OpenGL ES (GLES) 2.0 applications on Linux?
Mesa supports it. If you want to restrict yourself to OpenGL ES only then you'll need to build it into a separate directory and then add the appropriate include and library directories.
Update:
You can (still) use PowerVR SDK and now it supports Vulkan as well. Updated links:
- PowerVR SDK page: https://www.imgtec.com/developers/powervr-sdk-tools/powervr-sdk/
- Installers download page: https://www.imgtec.com/developers/powervr-sdk-tools/installers/
- Github repo: https://github.com/powervr-graphics/Native_SDK
At the time of my original answer, PowerVR SDK was the most complete solution (Mesa gained full OpenGL ES 2.0 support with its 3.1 release according to its Wikipedia page).
Now, Mesa and Mali SDK can also be a choice. For detailed info on those, please refer to this detailed answer by Ciro Santilli 冠状病毒审查六四事件法轮功
Original Answer:
You can use POWERVR SDK to emulate Opengl es on your PC. You can download the SDK here. The archive provides the necessary steps to install the emulation libraries as a documentation file and includes tutorials and demo applications with source codes.
GLFW, Mesa, Ubuntu 16.04 AMD64
This was not easy to setup on Ubuntu 14.04, but now it just works.
sudo apt-get install libglfw3-dev libgles2-mesa-dev
gcc glfw_triangle.c -lGLESv2 -lglfw
Output:
glfw_triangle.c
#include <stdio.h>
#include <stdlib.h>
#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
static const GLuint WIDTH = 800;
static const GLuint HEIGHT = 600;
static const GLchar* vertex_shader_source =
"#version 100\n"
"attribute vec3 position;\n"
"void main() {\n"
" gl_Position = vec4(position, 1.0);\n"
"}\n";
static const GLchar* fragment_shader_source =
"#version 100\n"
"void main() {\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
static const GLfloat vertices[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
GLint common_get_shader_program(const char *vertex_shader_source, const char *fragment_shader_source) {
enum Consts {INFOLOG_LEN = 512};
GLchar infoLog[INFOLOG_LEN];
GLint fragment_shader;
GLint shader_program;
GLint success;
GLint vertex_shader;
/* Vertex shader */
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_source, NULL);
glCompileShader(vertex_shader);
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Fragment shader */
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_source, NULL);
glCompileShader(fragment_shader);
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(fragment_shader, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n%s\n", infoLog);
}
/* Link shaders */
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader);
glAttachShader(shader_program, fragment_shader);
glLinkProgram(shader_program);
glGetProgramiv(shader_program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shader_program, INFOLOG_LEN, NULL, infoLog);
printf("ERROR::SHADER::PROGRAM::LINKING_FAILED\n%s\n", infoLog);
}
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return shader_program;
}
int main(void) {
GLuint shader_program, vbo;
GLint pos;
GLFWwindow* window;
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
window = glfwCreateWindow(WIDTH, HEIGHT, __FILE__, NULL, NULL);
glfwMakeContextCurrent(window);
printf("GL_VERSION : %s\n", glGetString(GL_VERSION) );
printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER) );
shader_program = common_get_shader_program(vertex_shader_source, fragment_shader_source);
pos = glGetAttribLocation(shader_program, "position");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glViewport(0, 0, WIDTH, HEIGHT);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glEnableVertexAttribArray(pos);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
}
glDeleteBuffers(1, &vbo);
glfwTerminate();
return EXIT_SUCCESS;
}
The key line lines of code are:
#define GLFW_INCLUDE_ES2
#include <GLFW/glfw3.h>
GLFW_INCLUDE_ES2
is documented at: http://www.glfw.org/docs/latest/build_guide.html#build_macros and a quick look at the source shows that it forwards to GLES:
#elif defined(GLFW_INCLUDE_ES2)
#include <GLES2/gl2.h>
#if defined(GLFW_INCLUDE_GLEXT)
#include <GLES2/gl2ext.h>
#endif
This source seems to be written in the common subset of GLES and OpenGL (like much of GLES), and also compiles with -lGL
if we remove the #define GLFW_INCLUDE_ES2
.
If we add things which are not in GLES like immediate rendering glBegin
, link fails as expected.
See also: https://askubuntu.com/questions/244133/how-do-i-get-egl-and-opengles-libraries-for-ubuntu-running-on-virtualbox
Credits: genpfult made the code much more correct.
ARM Mali OpenGL ES SDK
- download from: http://malideveloper.arm.com/resources/sdks/opengl-es-sdk-for-linux/
- open the documentation HTML on a browser
- follow the "Quick Start Guide", it's simple
Contains several interesting open source examples + windowing system boilerplate (X11 + EGL).
The build system supports easy cross compilation for ARM / Mali SoCs, but I haven't tested that yet.
The key component included seems to be the "OpenGL ES Emulator" http://malideveloper.arm.com/resources/tools/opengl-es-emulator/ which "maps OpenGL ES 3.2 API calls to the OpenGL API". But that does not ship with source, only precompiled.
Uses a custom enterprisey EULA that appears to be permissive, but yeah, ask your lawyer.
Tested on SDK v2.4.4.