irrlicht/examples/13.RenderToTexture_emscripten/main.cpp

173 lines
5.5 KiB
C++
Raw Normal View History

/** Example 013 Render To Texture on emscripten
*/
#include <irrlicht.h>
#include <emscripten.h>
#include "exampleHelper.h"
using namespace irr;
IrrlichtDevice *device = 0;
video::IVideoDriver* driver = 0;
scene::ISceneManager* smgr = 0;
gui::IGUIEnvironment* guienv = 0;
scene::ICameraSceneNode* fpsCamera = 0;
scene::ICameraSceneNode* fixedCam = 0;
video::IRenderTarget* renderTarget = 0;
scene::ISceneNode* cube = 0;
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;
}
driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0));
if (renderTarget)
{
// draw scene into render target
// set render target
driver->setRenderTargetEx(renderTarget, video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(0,0,0,255));
// make cube invisible and set fixed camera as active camera
cube->setVisible(false);
smgr->setActiveCamera(fixedCam);
// draw whole scene into render buffer
smgr->drawAll();
// set back old render target
// The buffer might have been distorted, so clear it
driver->setRenderTargetEx(0, 0, video::SColor(0));
// make the cube visible and set the user controlled camera as active one
cube->setVisible(true);
smgr->setActiveCamera(fpsCamera);
}
// draw scene normally
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
int main()
{
// create device and exit if creation failed
device = createDevice(video::EDT_WEBGL1, core::dimension2d<u32>(640, 480), 16, false, false);
if (device == 0)
return 1; // could not create selected driver.
driver = device->getVideoDriver();
smgr = device->getSceneManager();
guienv = device->getGUIEnvironment();
const io::path mediaPath = getExampleMediaPath();
// load and display animated fairy mesh
scene::IAnimatedMeshSceneNode* fairy = smgr->addAnimatedMeshSceneNode(
smgr->getMesh(mediaPath + "faerie.md2"));
if (!fairy)
return 1;
fairy->setMaterialTexture(0, driver->getTexture(mediaPath + "faerie2.bmp")); // set diffuse texture
fairy->setMaterialFlag(video::EMF_LIGHTING, true); // enable dynamic lighting
fairy->getMaterial(0).Shininess = 20.0f; // set size of specular highlights
fairy->setPosition(core::vector3df(-10,0,-100));
fairy->setMD2Animation ( scene::EMAT_STAND );
// add white light
smgr->addLightSceneNode(0, core::vector3df(-15,5,-105), video::SColorf(1.0f, 1.0f, 1.0f));
// set ambient light
smgr->setAmbientLight(video::SColor(0,60,60,60));
/*
The next is just some standard stuff: Add a test cube and let it rotate
to make the scene more interesting. The user defined camera and cursor
setup is made later on, right before the render loop.
*/
// create test cube
cube = smgr->addCubeSceneNode(60);
// let the cube rotate and set some light settings
scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
core::vector3df(0.3f, 0.3f,0));
cube->setPosition(core::vector3df(-100,0,-100));
cube->setMaterialFlag(video::EMF_LIGHTING, false); // disable dynamic lighting
cube->addAnimator(anim);
anim->drop();
// set window caption
device->setWindowCaption(L"Irrlicht Engine - Render to Texture and Specular Highlights example");
/*
To test out the render to texture feature, we need a render target
texture. These are not like standard textures, but need to be created
first. To create one, we call IVideoDriver::addRenderTargetTexture()
and specify the size of the texture. Please don't use sizes bigger than
the frame buffer for this, because the render target shares the zbuffer
with the frame buffer.
Because we want to render the scene not from the user camera into the
texture, we add another fixed camera to the scene. But before we do all
this, we check if the current running driver is able to render to
textures. If it is not, we simply display a warning text.
*/
// create render target
if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET))
{
video::ITexture* renderTargetTex = driver->addRenderTargetTexture(core::dimension2d<u32>(256, 256), "RTT1", video::ECF_A8R8G8B8);
video::ITexture* renderTargetDepth = driver->addRenderTargetTexture(core::dimension2d<u32>(256, 256), "DepthStencil", video::ECF_D16);
renderTarget = driver->addRenderTarget();
renderTarget->setTexture(renderTargetTex, renderTargetDepth);
cube->setMaterialTexture(0, renderTargetTex); // set material of cube to render target
// add fixed camera
fixedCam = smgr->addCameraSceneNode(0, core::vector3df(10,10,-80),
core::vector3df(-10,10,-100));
}
else
{
return 1;
}
// add fps camera
fpsCamera = smgr->addCameraSceneNodeFPS();
fpsCamera->setPosition(core::vector3df(-50,50,-150));
/*
Setting fps to 0 or a negative value will use the browsers
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);
return 0;
}