https://github.com/erlangsters/opengl-es-2.0
OpenGL ES 2.0 binding for the BEAM (Erlang and Elixir).
https://github.com/erlangsters/opengl-es-2.0
beam binding elixir erlang erlangsters gles2 gles20 opengl-es
Last synced: 8 days ago
JSON representation
OpenGL ES 2.0 binding for the BEAM (Erlang and Elixir).
- Host: GitHub
- URL: https://github.com/erlangsters/opengl-es-2.0
- Owner: erlangsters
- License: mit
- Created: 2024-09-24T16:51:04.000Z (almost 2 years ago)
- Default Branch: master
- Last Pushed: 2026-07-05T17:31:04.000Z (13 days ago)
- Last Synced: 2026-07-05T19:15:34.900Z (13 days ago)
- Topics: beam, binding, elixir, erlang, erlangsters, gles2, gles20, opengl-es
- Language: Erlang
- Homepage: https://about.erlangsters.org
- Size: 74.2 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# OpenGL ES 2.0 binding for the BEAM
[](https://github.com/erlangsters/opengl-es-2.0)



[](https://github.com/erlangsters/opengl-es-2.0/actions/workflows/build.yml)
[](https://erlangsters.github.io/opengl-es-2.0/)
> [!WARNING]
> This repository is still in development. Until release tags are cut, the
> `master` branch may be rewound.
This repository hosts the generated OpenGL ES 2.0 binding for Erlang and Elixir.
Only the OpenGL ES surface selected for this target is exposed through the
`gl` module. Loading custom OpenGL functions is not supported.
After an EGL context is current, calling OpenGL from Erlang looks like this:
```erlang
{ok, Version} = gl:get_string(version),
io:format("OpenGL version: ~p~n", [Version]).
```
From Elixir, the same module is available as `:gl`:
```elixir
{:ok, version} = :gl.get_string(:version)
IO.puts("OpenGL version: #{version}")
```
It works with the [EGL binding](https://github.com/erlangsters/egl-1.5),
which provides OpenGL contexts and surfaces. The
[GLFW binding](https://github.com/erlangsters/glfw) can be used when an
application needs a window.
Bindings for other versions of OpenGL and OpenGL ES are available from the
[Erlangsters repository list](https://github.com/orgs/erlangsters/repositories?type=all&q=opengl-).
Generated by the Erlangsters [community](https://about.erlangsters.org/) and
released under the MIT [license](https://opensource.org/license/mit).
## Quick preview
All the pieces together, with EGL, OpenGL and optional GLFW for a window, look
roughly like this:
```erlang
glfw:init(),
Display = egl:get_display(default_display),
{ok, _} = egl:initialize(Display),
ConfigAttribs = [
{surface_type, [window_bit]},
{renderable_type, [opengl_es2_bit]}
],
{ok, Configs} = egl:choose_config(Display, ConfigAttribs),
Config = hd(Configs),
ContextAttribs = [
{context_major_version, 2},
{context_minor_version, 0}
],
egl:bind_api(opengl_es_api),
{ok, Context} = egl:create_context(Display, Config, no_context, ContextAttribs),
{ok, Window} = glfw:create_window(640, 480, "Hello World!"),
WindowHandle = glfw:window_egl_handle(Window),
{ok, Surface} = egl:create_window_surface(Display, Config, WindowHandle, []),
ok = egl:make_current(Display, Surface, Surface, Context),
% Here goes your OpenGL initialization code.
Vertices = [
0.0, 0.5, 0.0, 1.0, 0.0, 0.0,
-0.5, -0.5, 0.0, 0.0, 1.0, 0.0,
0.5, -0.5, 0.0, 0.0, 0.0, 1.0
],
{ok, [Buffer]} = gl:gen_buffers(1),
gl:bind_buffer(array_buffer, Buffer),
gl:buffer_data(
array_buffer,
length(Vertices) * 4,
<<<> || Vertex <- Vertices>>,
static_draw
),
loop_window(Display, Surface, Window).
```
Here is how the loop function can look:
```erlang
loop_window(Display, Surface, Window) ->
case glfw:window_should_close(Window) of
true ->
glfw:terminate();
false ->
% Here goes your OpenGL rendering code.
gl:clear([color_buffer_bit]),
egl:swap_buffers(Display, Surface),
glfw:poll_events(),
handle_events(Window),
loop_window(Display, Surface, Window)
end.
```
And here is a small event handler:
```erlang
handle_events(Window) ->
receive
#glfw_window_size{size = {Width, Height}} ->
gl:viewport(0, 0, Width, Height),
handle_events(Window)
after 0 ->
ok
end.
```
For more examples, consult the
[OpenGL samples repository](https://github.com/erlangsters/opengl-samples),
which contains mini-programs written in C, Erlang and Elixir.
## Working with the binding
Before writing larger programs, it is useful to understand the thread-safety
model and the API mapping rules.
**Thread safety**
OpenGL is a C API with thread-affine state: a context is current on one OS
thread at a time. The BEAM schedules Erlang processes across OS threads, so the
binding relies on EGL to preserve a process-oriented context model for OpenGL
calls.
In practice, think of the BEAM process that owns the current EGL context as the
place where the matching OpenGL calls should happen. This mirrors how OpenGL is
usually structured in C while keeping the Erlang process model intact.
The target documentation explains this in more detail:
[Context and testing](docs/context-and-testing.md).
**API mapping**
The generated API follows deterministic mapping rules from the C OpenGL API to
Erlang and Elixir. Function names become lower snake case, enums are atoms, and
OpenGL output parameters become return values.
Most OpenGL code can be translated directly once those rules are familiar. If a
specific function shape is unclear, use the local
[API mapping](docs/api-mapping.md), the generated
[API reference](https://erlangsters.github.io/opengl-es-2.0/), and the
[binding generator documentation](https://github.com/erlangsters/opengl-x.y-generator).
## Using the binding in your project
With Rebar3, add the following to your project's `rebar.config`:
```erlang
{deps, [
{egl, {git, "https://github.com/erlangsters/egl-1.5.git", {tag, "master"}}},
{gl, {git, "https://github.com/erlangsters/opengl-es-2.0.git", {tag, "master"}}}
]}.
```
During early development, `master` is shown for convenience. Pin a release tag
or commit in applications that need reproducible builds.
If you use Erlang.mk, add the Git dependencies to your Makefile:
```make
BUILD_DEPS = egl gl
dep_egl = git https://github.com/erlangsters/egl-1.5 master
dep_gl = git https://github.com/erlangsters/opengl-es-2.0 master
```
## Generating the binding yourself
This repository is generated and hosted for convenience. To reproduce the
generated files, clone the
[OpenGL binding generator](https://github.com/erlangsters/opengl-x.y-generator),
compile it, and generate this target:
```bash
rebar3 escriptize
./_build/default/bin/opengl_gen gles 2.0
```
The generator writes `gl.erl`, `gl.hrl`, and `gl.c` into its working directory.
Those files are then copied into this target repository and built as
`priv/beam-gl.so` by CMake through Rebar3 hooks.
Do not hand-edit generated `gl.erl`, `gl.hrl`, or `gl.c` files in this target
repository.