Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example: SDL2 + OpenGLES + Emscripten #336

Closed
wants to merge 1 commit into from

Conversation

redblobgames
Copy link

This is a hybrid of examples/sdl_opengl and examples/opengl3. Emscripten/WebGL is based on OpenGL ES 2, which doesn't support the fixed pipeline, but also doesn't support the modern OpenGL shader syntax.

  • SDL2 code adapted from examples/sdl_opengl, modified for Emscripten
  • OpenGL ES code adapted from examples/opengl3, modified for GL ES 2
  • Readme updated with compiler command for emscripten

* SDL2 code adapted from examples/sdl_opengl, modified for Emscripten
* OpenGL ES code adapted from examples/opengl3, modified for GL ES 2
* Readme updated with compiler command for emscripten
@ocornut
Copy link
Owner

ocornut commented Sep 19, 2015

Thanks Amit. I have only skimmed at this and haven't used Emscripten before so it's a good base to start with (got it to build, this thing is truly black magic).

My intuition is this could possibly become the main SDL example, but I am losing track of whether using glVertexAttribPointer() etc. was ever a problem for the regular OpenGL3 example.

@redblobgames
Copy link
Author

I agree, emscripten is black magic :-)

WebGL is GL ES 2, which requires the use of shaders and vertex buffer objects, but doesn't support vertex array objects except with an extension. (I'm an OpenGL newbie so I could be wrong about that.) The OpenGL3 example uses vertex array objects (which seem to be recommended for newer OpenGL) so I changed the ES code not to use them. I tried to make this emscripten example work with SDL + OpenGL 2.1 without emscripten too, but I've only tested that on Mac.

@ocornut
Copy link
Owner

ocornut commented Oct 30, 2015

@chetan-prime
Copy link

I haven't tested this example through emscripted / html.
But I can confirm that this works great in native c++ for the Raspberry Pi with GLES2 . All the other imgui examples I found were for GL2/GL3 which the RPi and many other embedded devices don't support. Works fine without any changes to the c++ code , just minor changes to the Makefile.
Performance is really good using SDL2 w/ GLES2 libraries

@drudru
Copy link

drudru commented Feb 9, 2017

@chetan-prime - hi do you have a fork of the repo where you have these changes? I tried last night but I could not get it to work.

@chetan-prime
Copy link

chetan-prime commented Feb 11, 2017

@drudru I doubt this code will work with the latest imgui as it has changed quite a bit since then.
imgui-2016-07-navigation.zip
This is the version of imgui against which I was able to successfully build this with almost 0 changes. I'm not sure which commit of imgui I was using so I've attached the source zip I downloaded from github
I can confirm solid 60fps on an RPi1 building this against SDL2 for raspbian

@drudru
Copy link

drudru commented Feb 12, 2017

@chetan-prime

Thank you! I got it to compile. It is 60fpgs and it looks nice!

Your build helped me figure out how to get a clean compile. However, I ended up with a blank screen. On a hunch, I looked at the linked libraries via 'ldd'. The executable was not linking to the right libraries with the command in the Makefile.

What I ended up doing is installing Simple2d. This supports the Raspberry Pi and builds SDL2 from source. It has the right compiler args for the RPI EGL libs.

So I just did:

g++ `simple2d --libs` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp -o sdl2example

... and all is good.

Thanks.

laanwj added a commit to laanwj/imgui that referenced this pull request Sep 27, 2017
Should work with emscripten, as well as mobile hardware.

Inspired by: ocornut#336
@laanwj
Copy link

laanwj commented Sep 27, 2017

Thanks, this was useful to me, I wanted to use imgui with OpenGL ES 2 and it was good to have an example.

The OpenGL3 example uses vertex array objects

These would work in OpenGL ES 3. So would the new GLSL syntax, AFAIK.

Many devices are still stuck with ES 2.0 drivers though, even now.

(also even there some changes would be needed, e.g. glPolygonMode doesn't exist in any of the embedded GLs)

@ocornut
Copy link
Owner

ocornut commented Jun 11, 2018

Resurrecting this old pull-request (never say never).
Will the new examples/ refactor it is becoming easier to merge and maintain bindings as we have less code to duplicate. It would be interesting to return to this and:

  • create a imgui_impl_opengles.cpp renderer (or whatever is compatible with webgl), which in addition to being useful for WebGL can probably be useful for various mobile/phone?
  • fix the existing platform bindings such as imgui_impl_sdl.cpp for them to work with emscripten (probably unless a few tweak and ifdef?)
  • create a imgui_impl_emscripten.cpp binding platform using the emscripten functions directly

Tagging @redblobgames although I imagine the ship has sailed now. Thanks again for pushing it.
And @floooh who recently made https://github.com/floooh/sokol-samples/blob/master/html5/imgui-emsc.cc#L42

@Flix01
Copy link

Flix01 commented Jun 14, 2018

In my fork, AFAIK, the glut/freeGlut, glfw and SDL2 bindings can all be compiled with emscripten.

That's why I don't see emscripten as another binding... it's more similar to a custom clang compiler, that needs some code tweaking when __EMSCRIPTEN__ is defined and a slightly different command-line syntax.

The main problems when porting code are:

  • The game loop must be refactored into a function that runs just one frame at a time (this is the main change in this pull request, as far as I can see). A notable exception to this rule is glut/freeglut, (glutMainLoop() works out of the box: it does not the require emscripten_set_main_loop(...) call): when porting code to emscripten, using glut/freeglut is therefore easier.
  • emscripten needs WebGL shaders (basically in most cases GL_ES2 shaders are compatible with WebGL1 and GL_ES3 shaders are compatible with WebGL2: and both WebGL1 and WebGL2 (using -s USE_WEBGL2=1 in the compiler command-line) are supported by emscripten. In my code I use inline shader code with global definitions that change the required shader parts to make them work in GL_ES too (but it's not a very clean solution).

So I think your first two points make sense.
I'm not familiar with using the emscripten functions directly, so I can't help much with point 3.
However emscripten does not need any local installation of glut/glfw/SDL2 because they are downloaded and compiled on the fly by the command-line so there are no additional issues in using these bindings.

To summarize I think that if we have examples that use glut, glfw, or SDL2 with GL_ES2 or GL_ES3 compatible shaders, then we can start making these examples work with emscripten too.

Hope this helps.

@floooh
Copy link
Contributor

floooh commented Jun 14, 2018

@Flix01 IMHO directly using the emscripten functions for setting up the WebGL context and input handling would be more useful than using one of the compatibility wrappers in the SDK, it's often also less code and they enable better handling of browser-specific issues, like a 'soft fullscreen' where the WebGL canvas resizes dynamically with the browser window.

Here's the example code for this case (dynamically resized WebGL canvas):

https://github.com/floooh/sokol-samples/blob/master/html5/emsc.h

A minimal version without the resize-tracking would be even less code.

@Flix01
Copy link

Flix01 commented Jun 14, 2018

@floooh Thanks. Yes, you're probably right in that there is some advantage in using emscripten functions directly. However, as I've said, I'm not familiar with this approach.

I think it's probably easier to start modifying existent code, but probably you're right: less memory usage means faster loading, and by using SDK wrappers I've always had issues with switching to fullscreen mode in a reliable way!

It seems that @ocornut's 3 points are all worth developing then 😃

[Edit] In any case one of the main advantages of using one of the compatibility wrappers in the SDK is that we can compile the same code outside of emscripten too.

@ocornut
Copy link
Owner

ocornut commented Jul 3, 2018

@Flix01 @floooh If I understand correctly, in imgui_impl_opengl3.cpp only the shaders needs to be changed to support GLES2 and GLES3 ? In this case, we could modify the existing binding to take an enum to specify the GL subset, and support regular GL as well as flavors of GLES and WebGL with the same sources?

edit If that is the case, I am happy to help with providing a design to expose those, but I'd need someone who understand WebGL and GL ES to guide them and provide the shaders.

@ocornut ocornut added the opengl label Jul 3, 2018
@ocornut
Copy link
Owner

ocornut commented Jul 3, 2018

Was sent this good reference from NanoVG
https://github.com/memononen/nanovg/blob/master/src/nanovg_gl.h

Skimming through it it seems like:

  • Shaders needs subtle changes (easy)
  • Differences handling vertex arrays e.g. glGenVertexArrays() is GL3 only
  • No glPixelStore on GL ES 2?

This is not a hard problem to solve but it can't be done blindly. Which platform could I use to test GL ES 2/3 myself?

@Flix01
Copy link

Flix01 commented Jul 3, 2018

As far as I know (but I can tell only about WebGL, not about GLES2):

  • VAO (vertex array objects) are supported by WebGL2 only (I've used plain VBO instead).
  • glPixelStore should work.

Basically I think that WebGL is a subset of GLES2, but I've never target GLES2 myself...
I've just added some __EMSCRIPTEN__ ifdefs around until the code worked "inside and outside" of emscripten...

Probably if you want to target both GLES2 and WebGL in one shot, you must complicate things a bit...

@Flix01
Copy link

Flix01 commented Jul 4, 2018

Which platform could I use to test GL ES 2/3 myself?

On Linux there's libgles2-mesa-dev that can be used directly with glfw3 (according to this link: https://stackoverflow.com/questions/3809236/how-to-develop-opengl-es-gles-2-0-applications-on-linux/39356268#39356268 , where it says GLFW, Mesa, Ubuntu 16.04 AMD64: there's a ready-to-use c source code too).

Don't know about windows.

Possible alternatives are using extensions like: GL_ARB_ES2_compatibility, GL_ARB_ES3_compatibility, GL_ARB_ES3_1_compatibility, GL_ARB_ES3_2_compatibility together with GLX_EXT_create_context_es_profile or GLX_EXT_create_context_es2_profile (I guess there are GLW_ counterparts for Windows), but I haven't found any ready-to-use code for them so far.

@paulocoutinhox
Copy link

Hi,

There is any working impl to use with emscripten?

I want leave a sample in my tool about how to use sdl2, canvas and imgui. Only left the imgui to work.

https://github.com/ezored/sample-wasm

Thanks.

@ocornut
Copy link
Owner

ocornut commented Jan 17, 2019

I thnk all of the SDL, GLFW and OpenGL stuff are working with emscripten. Have you tried them?

@paulocoutinhox
Copy link

I thnk all of the SDL, GLFW and OpenGL stuff are working with emscripten. Have you tried them?

Yes? Do you know if i can use opengl2 or opengl3? What version i can use? Thanks anyway.

@ocornut
Copy link
Owner

ocornut commented Jan 17, 2019

Just try them..

@paulocoutinhox
Copy link

Just try them..

I will try, i only have a direction about what opengl version is compatible with webgl.

I have some doubts. In my sample im not using this codes that i see on this pull-request:

// ON MAIN LOOP: HAVE MORE CODE THAN I HAVE. IN MY SAMPLE I DON'T USE THIS.

glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
glClearColor(g_clear_color.x, g_clear_color.y, g_clear_color.z, g_clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
ImGui::Render();
SDL_GL_SwapWindow(g_window);

// ON INITIALIZATION: HAVE A LOT OF SDL_GL THINGS, I NEED IT? I NEED CREATE GL CONTEXT?

SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, &current);
g_window = SDL_CreateWindow("ImGui SDL2+OpenGLES+Emscripten example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
SDL_GLContext glcontext = SDL_GL_CreateContext(g_window);

I need use that code or no? I don't have any personal contact to talk about, so im asking all here. If you have any contact to talk, please share with me.

Thanks.

@redblobgames
Copy link
Author

Hi prsolucoes, this pull request is from 2015. In 2018, Dear ImGui was refactored to separate the renderer and platform bindings (see release 1.62). The new refactored code has an Emscripten platform binding so you should try that first instead of looking at this pull request. Try examples/example_sdl_opengl3 which uses examples/imgui_impl_opengl3.cpp which says it works with Emscripten. (I have not tried it myself because I am not using ImGui in my current project)

@floooh
Copy link
Contributor

floooh commented Jan 17, 2019

Hi @prsolucoes, WebGL itself is compatible with OpenGLES2, however if you're compiling with the emscripten SDK, this has additional wrappers for "desktop" GL versions, with limited emulation of desktop GL functions on top of WebGL (except the GLSL dialects, those must be GLES2 compatible). Using OpenGL2.x code as base should map best to WebGL.

Also, emscripten has limited support for compiling GLFW and SDL code, if you run into problems with those wrapper APIs, the emscripten discussion group (https://groups.google.com/forum/?nomobile=true#!forum/emscripten-discuss), may be a better place to ask.

@paulocoutinhox
Copy link

Hi,

Ok, im trying use the SDL example of imgui in my sample. But have some doubts and compilation error. I posted it here:

https://groups.google.com/forum/?nomobile=true#!topic/emscripten-discuss/3uV3KTOHTnE

Can anyone help me there?

Thanks.

@paulocoutinhox
Copy link

Hi,

After try a lot i don't have other option instead of put here. I think imgui dont work nativelly with emscripten or im doing something wrong.

I tried use opengl2 and opengl3 but both generate error with emscripten.

Im trying to use opengl3 at least, and when i run, i got:

image

I don't know how to solve it. I tried a lot of params in emscripten compiler, but nothing. I tried the forum on google groups, but nothing.

My source code:
https://github.com/ezored/sample-wasm/blob/imgui/source/local/dependency-app/build/source/cpp/canvas/main.cpp

Without imgui it is working here:
http://public.ezored.com/sample-wasm/wasm-canvas/Release/index.html

Thanks for any help.

@floooh
Copy link
Contributor

floooh commented Jan 24, 2019

...well ImGui works really well with emscripten, see here:

https://floooh.github.io/sokol-html5/wasm/imgui-sapp.html

But unfortunately this doesn't help with your problem because my demos are based on my own WebGL wrapper API (https://github.com/floooh/sokol/blob/master/sokol_gfx.h).

I guess the problem is in the SDL GL context initialization (you're telling it to create a GL 3.2 core profile context, while WebGL2 is GLES 3.0 (ImGui itself doesn't need GLES3 though, it also works fine with GLES2).

The second problem is that your shader code is for desktop GL3.x, this won't work in WebGL, you need GLES2 or GLES3 compatible shaders.

There don't seem to be GLES2 or GLES3 examples in the ImGui examples directory, if there were, those would probably work out of the box. But without those you need to write an ImGui render function yourself (I don't have such code around unfortunately since all my example code is based on wrapper APIs around GL/D3D/Metal).

@ocornut
Copy link
Owner

ocornut commented Jan 25, 2019

There don't seem to be GLES2 or GLES3 examples in the ImGui examples directory, if there were, those would probably work out of the box. But without those you need to write an ImGui render function yourself (I don't have such code around unfortunately since all my example code is based on wrapper APIs around GL/D3D/Metal).

The code in imgui_impl_opengl3.cpp theorically supports GL ES 3 and should probably be modified to allow for GL ES 2. It automatically select different shader based on the #version string.

@paulocoutinhox
Copy link

Hi,

Where you are saying that im using 3.2? Because of this?

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

I tried put 3/0, 2/0, 2/2. But the problems is exactly the same.

I don't understand why its happen.

If i use opengl2, a lot of methods are not supported by emscripten:

error: undefined symbol: glColorPointer
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
error: undefined symbol: glDisableClientState
error: undefined symbol: glEnableClientState
error: undefined symbol: glOrtho
error: undefined symbol: glPolygonMode
error: undefined symbol: glPopAttrib
error: undefined symbol: glPopMatrix
error: undefined symbol: glPushAttrib
error: undefined symbol: glPushMatrix
error: undefined symbol: glTexCoordPointer
Error: Aborting compilation due to previous errors

Thanks.

@ocornut
Copy link
Owner

ocornut commented Apr 14, 2019

This has been a long time coming, sorry Amit!
At the time the example structure required lots of code duplication, which is not required any more.

There's now a examples_emscripten/ folder with a pretty lightweight example (main.cpp is 165 lines including the mini demo embedded in every main file) and this is relying on shared bindings for most. See #2494 for details.

Apologies every one for taking a while to catch on the GL ES / Emscripten wagon. Better late than never.

@ocornut ocornut closed this Apr 14, 2019
@xor2k
Copy link

xor2k commented Jun 29, 2019

So great, thank you a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants