850 likes | 1.01k Views
Developing Ronimo's multiplatform graphics engine Joost van Dongen Co-founder Lead programmer. Ronimo Games. Currently 21 people (7 coders) Utrecht city centre Exists over 7 years now Indie game developer De Blob, Swords & Soldiers, Awesomenauts, Swords & Soldiers 2. Joost van Dongen.
E N D
Developing Ronimo's multiplatform graphics engine Joost van Dongen Co-founder Lead programmer
Ronimo Games • Currently 21 people (7 coders) • Utrecht city centre • Exists over 7 years now • Indie game developer • De Blob, Swords & Soldiers, Awesomenauts, Swords & Soldiers 2
Joost van Dongen • Lead programmer and co-founder • Studied Game & Media Technology • And Game Design & Development at HKU • Also hobby games: Proun, Cello Fortress
Video? • Video!
Awesomenauts • 2D MOBA • League of Legends + Super Smash Brothers • Over 1.7 million copies sold • 3 VS 3 online • Fast action game • Launched mid-2012 • Very active user base
2D games tech • Often underestimated compared to 3D • Many things similar: certification, file handling, online multiplayer, etc • Just as interesting!
Normal programming • Standard C++ • Normal Visual Studio • Special compiler
Deviations from C++ standard • Visual Studio adds to C++ standard • Other compilers do not • Cannot use those extras • Differences: • std::vector<std::vector<int>> • #include <cmath> • inline for templates
Pragma • Cannot use #pragma once • Must use this instead: #ifndef MYCLASS_H #define MYCLASS_H //code goes here #endif
Other APIs • Biggest difference • Special APIs for all kinds of things • File access, graphics, sound, controllers, networking, etc
Multiplatform • Must write specifics for every platform! • Or use existing engine (Unreal, Unity, etc) • Or partially use specialised middleware (e.g. FMOD)
Compiling multiplatform • Must hide platform-specific code behind defines
void writeFile(const std::string& text) • { • #ifdef _PC • std::ofstream.write(text); • #elif _X360 • xWriteData(text); • #elif _PS3 • ninWrite(text.c_str()); • #else • implement_me; • #endif • }
Practical multiplatform • Big challenge: how to structure this? • Huge structural differences per platform • Lots of platform-specific code • Must keep as much multi-platform as possible
Our structure • Example class structure for file handling: • As much as possible in FileTools itself • Similar systems for other topics
class FileTools • { • virtual void write(string) = 0; • }; • class PS3FileTools: public FileTools • { • virtual void write(string) • { • //blabla real code yo • } • };
FileTools* create() • { • #ifdef _PC • return new PCFileTools(); • #elif _PS3 • return new PS3FileTools(); • #else • implement_me; • #endif • }
Console certification • Console manufacturers test game extensively • Must adhere to certification requirements • Long lists • Hundreds of detailed requirements • Months of work per platform!
Example requirements • "Pause game if controller disconnected" • "Do not crash" • "Load in less than 30 seconds"
Consistency requirements • Not all requirements make sense from developer's standpoint • Make experience similar across platform • "Home menu always accessible" • "Use standard terminology"
Console development flow • Gain development license for console • Order devkits • Ask for concept permission • Get age ratings • Send in for certification • Get failed for stupid oversight or lame detail • Make fixes • Send in again • Wait for release slot
Limited RAM • Traditional challenge on console • Much less RAM than on PC • Won't overflow onto hard disc when out of RAM • Less of an issue on PS4/XBoxOne • Big challenge on Wii/360/PS3 • (88 / 512 / 2x256mb)
Graphics API • Library for communicating with videocard • Call functions to render triangles, use textures, etc
Per platform • PC: DirectX, OpenGL, Mantle • Mac / Linux: OpenGL • iOS / Android: OpenGL ES • PS3: OpenGL, GCM • X360: DirectX 9 • Wii: GX • Wii U: GX2 • Special versions of GL and DX per platform!
Similarities • Basic primitive is always triangle • Textures • Hardware is similar, so APIs wrap around similar concepts
Differences • APIs do same thing differently • Each console has special hardware features • Some consoles lack major features
API difference: texture sampling • GL: per texture • DX: per stage • For performance must only set when needed • Must decide differently per platform glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); device->SetSamplerState(textureIndex, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Speed • Consoles are slower than PCs... • ...but targeting specific hardware gives huge boost • Also much more efficient drivers • Plus economics: no one targets high end PCs
Texture handling • Console: just memory • PC/Mac/Linux: abstracted, no direct access • Console: notify that piece of memory is texture • PC/Mac/Linux: copy texture to video memory • Much more control, much faster streaming on console
EDRam • Xbox 360 only • 10mb of super fast GPU memory • Benefit: super fast • Downside: super small • Full HD with anti-aliasing requires two render passes • Much more complex with deferred shading
Shaders • DirectX on 360: HLSL • OpenGL on PS3: Cg • Need to write all shaders twice? • Nope: languages are 90% same • Can make everything without touching differences
GLSL shaders • GLSL is different • Still very similar • Required on Wii U and iOS • We modified Cg shaders by hand
No shaders on Wii • Wii was technically a Gamecube • Technology from time of Napoleon • No shaders • Instead the ultimate puzzle fun: TEV stages!
TEV stages • Repeat this 16 times: out = a*(1 - c) + b*c + d • Set what a/b/c/d/out are per stage • Can switch states to: if(a.r > b.r) out = c; else out = d; • Can do surprisingly much • Difficult puzzle for advanced stuff!
PS4 and Xbox One • Boring hardware • Just really fast PCs • Awesomenauts port outsourced to Abstraction • I don't know API details
Ronitech rendering structure
Inspired by Ogre • Basic structure inspired by Ogre engine • Object oriented C++ graphics engine • Extremely neat class design • Great engine, good low level access • Few tools for modern standards • Used for De Blob, Snowball Earth, Proun, Cello Fortress
Renderable • Core object for rendering • Functions like these: • setPosition • setScale • setParallax • setTexture • setTextureWrap • setBlendMode • setColour
Flexible for GPU types • Basic structure not based on shaders • Properties can be implemented in various ways • Shaders of course used on most platforms • Looks exact same on Wii without shaders! • setTexture • setColour • setColourCombineMode //add, multiply, blend, etc • setSecondaryTexture • setSecondaryTextureOperation
Inherited to provide geometry • virtual void getVertices(Vector2*& vertices, • Vector2*& textureCoordinates0, • Vector2*& textureCoordinates1, • unsigned int& count, • bool& isTriStrip) = 0; • Implemented by various shape/geometry types: • Rectangle • Circle • RenderText • ParticleSystem • Terrain
Automatic registration • SceneManager keeps track of all Renderables • Renderable registers itself automatically Renderable::Renderable() { SceneManager::get()->addRenderable(this); } Renderable::~Renderable() { SceneManager::get()->removeRenderable(this); }
Rendering order • Everything has alpha in a 2D game • Must render back to front • Order by parallax and depth
Viewports • Viewport defines part of screen to render to • Viewport has a camera • Viewport has a RenderGroup • Automatically renders all Renderables in that RenderGroup
Flexible Viewports • Not just for splitscreen...
Flexible Viewports • ...also for overlays and such
Performance • Videocards insanely fast • Can draw 1000 objects per frame at 60fps • Our main performance bottlenecks: • CPU in general • Fillrate