diff --git a/changes.txt b/changes.txt index 8434095b..6bdd925d 100644 --- a/changes.txt +++ b/changes.txt @@ -1,6 +1,7 @@ -------------------------- Changes in ogl-es (not yet released - will be merged with trunk at some point) +- Add support for emscripten. Thanks @labsin for the patch. - Add IVideoDriver::getAmbientLight function so shaders can access global ambient light easier - Merge material changes for COGLES1MaterialRenderer_LIGHTMAP and COpenGLMaterialRenderer_TRANSPARENT_ALPHA_CHANNEL which had been done in OGL in trunk (r2740) to ensure materials look the same on all platforms. - Added support for PVR textures. Loader offer support for compressed DXT1-5, PVRTC/PVRTC-II, ETC1/ETC2 texture formats. diff --git a/examples/01.HelloWorld_emscripten/Makefile b/examples/01.HelloWorld_emscripten/Makefile index d7b72dd2..bc958589 100644 --- a/examples/01.HelloWorld_emscripten/Makefile +++ b/examples/01.HelloWorld_emscripten/Makefile @@ -39,7 +39,7 @@ all_win32 clean_win32 static_win32: SYSTEM=Win32-gcc all_win32 clean_win32 static_win32: SUF=.exe all_emscripten clean_emscripten: SUF=.html all_emscripten: CXXFLAGS += -fno-exceptions -fno-rtti -fstrict-aliasing -std=gnu++11 -U__STRICT_ANSI__ -all_emscripten: LDFLAGS += -lGL -s FULL_ES2=1 -lSDL --preload-file ../../media@/media -s ALLOW_MEMORY_GROWTH=1 +all_emscripten: LDFLAGS += -lGL -s FULL_ES2=1 -lSDL --preload-file ../../media@/media -s ALLOW_MEMORY_GROWTH=1 -s NO_EXIT_RUNTIME=1 #all_emscripten: LDFLAGS += -lGL -lSDL --preload-file ../../media@/media -s ALLOW_MEMORY_GROWTH=1 static_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ all_win32: LDFLAGS += -lopengl32 -lEGL -lGLESv1_CM -lGLESv2 -lm diff --git a/examples/01.HelloWorld_emscripten/main.cpp b/examples/01.HelloWorld_emscripten/main.cpp index 40247cb0..cc1b1025 100644 --- a/examples/01.HelloWorld_emscripten/main.cpp +++ b/examples/01.HelloWorld_emscripten/main.cpp @@ -1,46 +1,8 @@ -/** Example 001 HelloWorld +/** Example 001 HelloWorld adapted to emscripten -This Tutorial shows how to set up the IDE for using the Irrlicht Engine and how -to write a simple HelloWorld program with it. The program will show how to use -the basics of the VideoDriver, the GUIEnvironment, and the SceneManager. -Microsoft Visual Studio is used as an IDE, but you will also be able to -understand everything if you are using a different one or even another -operating system than windows. - -You have to include the header file in order to use the engine. The -header file can be found in the Irrlicht Engine SDK directory \c include. To let -the compiler find this header file, the directory where it is located has to be -specified. This is different for every IDE and compiler you use. Let's explain -shortly how to do this in Microsoft Visual Studio: - -- If you use Version 6.0, select the Menu Extras -> Options. - Select the directories tab, and select the 'Include' Item in the combo box. - Add the \c include directory of the irrlicht engine folder to the list of - directories. Now the compiler will find the Irrlicht.h header file. We also - need the irrlicht.lib to be found, so stay in that dialog, select 'Libraries' - in the combo box and add the \c lib/VisualStudio directory. - \image html "vc6optionsdir.jpg" - \image latex "vc6optionsdir.jpg" - \image html "vc6include.jpg" - \image latex "vc6include.jpg" - -- If your IDE is Visual Studio .NET, select Tools -> Options. - Select the projects entry and then select VC++ directories. Select 'show - directories for include files' in the combo box, and add the \c include - directory of the irrlicht engine folder to the list of directories. Now the - compiler will find the Irrlicht.h header file. We also need the irrlicht.lib - to be found, so stay in that dialog, select 'show directories for Library - files' and add the \c lib/VisualStudio directory. - \image html "vcnetinclude.jpg" - \image latex "vcnetinclude.jpg" - -That's it. With your IDE set up like this, you will now be able to develop -applications with the Irrlicht Engine. - -Lets start! - -After we have set up the IDE, the compiler will know where to find the Irrlicht -Engine header files so we can include it now in our code. +This Tutorial shows how to run code with emscripten. +Emscripten compiles c++ to asm.js to allow it running inside a webbrowser. +You have to setup the emscripten environment on your system first to use this. */ #include #include "exampleHelper.h" @@ -48,24 +10,12 @@ Engine header files so we can include it now in our code. #include /* -In the Irrlicht Engine, everything can be found in the namespace 'irr'. So if -you want to use a class of the engine, you have to write irr:: before the name -of the class. For example to use the IrrlichtDevice write: irr::IrrlichtDevice. -To get rid of the irr:: in front of the name of every class, we tell the -compiler that we use that namespace from now on, and we will not have to write -irr:: anymore. +The code in here is mostly similar to the usual HelloWorld. +You can find more information about it there. Here we mainly document the +differences needed for emscripten. */ -using namespace irr; -/* -There are 5 sub namespaces in the Irrlicht Engine. Take a look at them, you can -read a detailed description of them in the documentation by clicking on the top -menu item 'Namespace List' or by using this link: -http://irrlicht.sourceforge.net/docu/namespaces.html -Like the irr namespace, we do not want these 5 sub namespaces now, to keep this -example simple. Hence, we tell the compiler again that we do not want always to -write their names. -*/ +using namespace irr; using namespace core; using namespace scene; using namespace video; @@ -73,18 +23,18 @@ using namespace io; using namespace gui; /* -To be able to use the Irrlicht.DLL file, we need to link with the Irrlicht.lib. -We could set this option in the project settings, but to make it easy, we use a -pragma comment lib for VisualStudio. On Windows platforms, we have to get rid -of the console window, which pops up when starting a program with main(). This -is done by the second pragma. We could also use the WinMain method, though -losing platform independence then. +This part not necessary for emscripten, only useful to keep it in +in case you want to run the same code on Windows with VS as well. */ #ifdef _MSC_VER #pragma comment(lib, "Irrlicht.lib") #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif + +/* +Variables on the stack will stay intact between runs of one_iter() +*/ IrrlichtDevice *device = 0; IVideoDriver* driver = 0; ISceneManager* smgr = 0; @@ -99,6 +49,11 @@ void one_iter() { if(!device->run()) { + // Could clean up here in theory, but not sure if it makes a difference + + /* + This tells emscripten to not run any further code. + */ emscripten_cancel_main_loop(); return; } @@ -113,41 +68,18 @@ void one_iter() /* -This is the main method. We can now use main() on every platform. + The main method is also run on emscripten. */ int main() { /* - The most important function of the engine is the createDevice() - function. The IrrlichtDevice is created by it, which is the root - object for doing anything with the engine. createDevice() has 7 - parameters: - - - deviceType: Type of the device. This can currently be the Null-device, - one of the two software renderers, D3D9, or OpenGL. In this - example we use EDT_SOFTWARE, but to try out, you might want to - change it to EDT_BURNINGSVIDEO, EDT_NULL, EDT_DIRECT3D9, or EDT_OPENGL. - - - windowSize: Size of the Window or screen in FullScreenMode to be - created. In this example we use 640x480. - - - bits: Amount of color bits per pixel. This should be 16 or 32. The - parameter is often ignored when running in windowed mode. - - - fullscreen: Specifies if we want the device to run in fullscreen mode - or not. - - - stencilbuffer: Specifies if we want to use the stencil buffer (for - drawing shadows). - - - vsync: Specifies if we want to have vsync enabled, this is only useful - in fullscreen mode. - - - eventReceiver: An object to receive events. We do not want to use this - parameter here, and set it to 0. - - Always check the return value to cope with unsupported drivers, - dimensions, etc. + Create device flags for emscripten are still experimental + and might not all work. + + - deviceType: You have to use video::EDT_OGLES2 which will be translated + to WebGL by emscripten. + It can be useful to have EDT_OGLES2 or EDT_OGLES1 for comparison for + testing on the desktop. */ #ifndef __EMSCRIPTEN__ device = @@ -163,9 +95,7 @@ int main() return 1; /* - Set the caption of the window to some nice text. Note that there is an - 'L' in front of the string. The Irrlicht Engine uses wide character - strings when displaying text. + Window caption will set the title-text in the browser. */ device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo"); @@ -184,25 +114,23 @@ int main() The text is placed at the position (10,10) as top left corner and (260,22) as lower right corner. */ - guienv->addStaticText(L"Hello World! This is the Irrlicht on emscripten!", + guienv->addStaticText(L"Hello World! This is Irrlicht on emscripten!", rect(10,10,260,22), true); /* - Get a media path dedicated for your platform. + Get a media path dedicated for your platform. + We tell emscripten to copy the media folder in the Makefile with: + "--preload-file ../../media@/media" + That copies our ../../media folder in a .data + file which is loaded by the browser. It can then be accessed there + by "/media" name (that's the parameter after the '@'). + Note that usually you would try to copy only as many files + as absolutely necessary to reduce start-up times. */ const io::path mediaPath = getExampleMediaPath(); /* - To show something interesting, we load a Quake 2 model and display it. - We only have to get the Mesh from the Scene Manager with getMesh() and add - a SceneNode to display the mesh with addAnimatedMeshSceneNode(). We - check the return value of getMesh() to become aware of loading problems - and other errors. - - Instead of writing the filename sydney.md2, it would also be possible - to load a Maya object file (.obj), a complete Quake3 map (.bsp) or any - other supported file format. By the way, that cool Quake 2 model - called sydney was modelled by Brian Collins. + Make a model called Sydney show up. */ IAnimatedMesh* mesh = smgr->getMesh(mediaPath + "sydney.md2"); if (!mesh) @@ -213,12 +141,10 @@ int main() IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh ); /* - To let the mesh look a little bit nicer, we change its material. We - disable lighting because we do not have a dynamic light in here, and - the mesh would be totally black otherwise. Then we set the frame loop, - such that the predefined STAND animation is used. And last, we apply a - texture to the mesh. Without it the mesh would be drawn using only a - color. + Disable lighting because we do not have a dynamic light in here, and + the mesh would be totally black otherwise. + Set the frame loop such that the predefined STAND animation is used. + Add a texture to the model. */ if (node) { @@ -234,22 +160,13 @@ int main() */ smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0)); -#ifndef __EMSCRIPTEN__ +#ifndef __EMSCRIPTEN__ // this part only so you can run the same code on desktop /* - Ok, now we have set up the scene, lets draw everything: We run the - device in a while() loop, until the device does not want to run any - more. This would be when the user closes the window or presses ALT+F4 - (or whatever keycode closes a window). + On desktop we run and endless loop until the user closes the window or + presses ALT+F4 (or whatever keycode closes a window). */ while(device->run()) { - /* - Anything can be drawn between a beginScene() and an endScene() - call. The beginScene() call clears the screen with a color and - the depth buffer, if desired. Then we let the Scene Manager and - the GUI Environment draw their content. With the endScene() - call everything is presented on the screen. - */ driver->beginScene(ECBF_COLOR | ECBF_DEPTH, SColor(255,100,101,140)); smgr->drawAll(); @@ -257,18 +174,23 @@ int main() driver->endScene(); } - - /* - After we are done with the render loop, we have to delete the Irrlicht - Device created before with createDevice(). In the Irrlicht Engine, you - have to delete all objects you created with a method or function which - starts with 'create'. The object is simply deleted by calling ->drop(). - See the documentation at irr::IReferenceCounted::drop() for more - information. - */ device->drop(); + #else // __EMSCRIPTEN__ - emscripten_set_main_loop(one_iter, 0, 0); + + /* + Setting fps to 0 or a negative value will use the browser’s + requestAnimationFrame mechanism to call the main loop function. + Emscripten documentation recommends to do that, but you can also set + another fps value and the browser will try to call the main-loop + fps times per second. + The simulate_infinite_loop tells emscripten that this is an application + which will simulate an infinite loop. There is also a flag in the + Makefile about that: -s NO_EXIT_RUNTIME=1 + */ + int fps = 0; + int simulate_infinite_loop = 1; + emscripten_set_main_loop(one_iter, fps, simulate_infinite_loop); #endif //__EMSCRIPTEN__ return 0; diff --git a/source/Irrlicht/Makefile b/source/Irrlicht/Makefile index a5fb13ce..bae6e2cb 100644 --- a/source/Irrlicht/Makefile +++ b/source/Irrlicht/Makefile @@ -125,8 +125,10 @@ staticlib_win32: CPPFLAGS += -D_IRR_STATIC_LIB_ #emscripten specific options staticlib_emscripten: SYSTEM = emscripten -# you might want to disable all features you don't need in Irrlicht here to reduce the .js file size -# emscripten: CXXFLAGS += -DNO_IRR_COMPILE_WITH_XML_ + +# You might want to disable features you don't need in Irrlicht here to reduce the .js file size. +# Thought it seems emscripten is using static-linking, so likely it makes no difference at all. +#emscripten: CXXFLAGS += -DNO_IRR_COMPILE_WITH_XML_ -DNO_IRR_COMPILE_WITH_ZIP_ENCRYPTION_ STATIC_LIB = libIrrlicht.a LIB_PATH = ../../lib/$(SYSTEM)