forked from urho3d/urho3d
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathReference.dox
2394 lines (1594 loc) · 199 KB
/
Reference.dox
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
namespace Urho3D
{
/**
\page Containers Container types
Urho3D implements its own string type and template containers instead of using STL. The rationale for this consists of the following:
- Increased performance in some cases, for example when using the PODVector class.
- Guaranteed binary size of strings and containers, to allow eg. embedding inside the Variant object.
- Reduced compile time.
- Straightforward naming and implementation that aids in debugging and profiling.
- Convenient member functions can be added, for example String::Split() or Vector::Compact().
- Consistency with the rest of the classes, see \ref CodingConventions "Coding conventions".
The classes in question are String, Vector, PODVector, List, HashSet and HashMap. PODVector is only to be used when the elements of the vector need no construction or destruction and can be moved with a block memory copy.
The list, set and map classes use a fixed-size allocator internally. This can also be used by the application, either by using the procedural functions AllocatorInitialize(), AllocatorUninitialize(), AllocatorReserve() and AllocatorFree(), or through the template class Allocator.
In script, the String class is exposed as it is. The template containers can not be directly exposed to script, but instead a template Array type exists, which behaves like a Vector, but does not expose iterators. In addition the VariantMap is available, which is a HashMap<ShortStringHash, Variant>.
\page ObjectTypes %Object types and factories
Classes that derive from Object contain type-identification, they can be created through object factories, and they can send and receive \ref Events "events". Examples of these are all Component, Resource and UIElement subclasses. To be able to be constructed by a factory, they need to have a constructor that takes a Context pointer as the only parameter.
%Object factory registration and object creation through factories are directly accessible only in C++, not in script.
The definition of an Object subclass must contain the OBJECT(className) macro. Type identification is available both as text (GetTypeName() or GetTypeNameStatic()) and as a 16-bit hash of the type name (GetType() or GetTypeStatic()).
To register an object factory for a specific type, call the \ref Context::RegisterFactory "RegisterFactory()" template function on Context. You can get its pointer from any Object either via the \ref Object::context_ "context_" member variable, or by calling \ref Object::GetContext "GetContext()". An example:
\code
context_->RegisterFactory<MyClass>();
\endcode
To create an object using a factory, call Context's \ref Context::CreateObject "CreateObject()" function. This takes the 16-bit hash of the type name as a parameter. The created object (or null if there was no matching factory registered) will be returned inside a SharedPtr<Object>. For example:
\code
SharedPtr<Object> newComponent = context_->CreateObject(type));
\endcode
\page Subsystems Subsystems
Any Object can be registered to the Context as a subsystem, by using the function \ref Context::RegisterSubsystem "RegisterSubsystem()". They can then be accessed by any other Object inside the same context by calling \ref Object::GetSubsystem "GetSubsystem()". Only one instance of each object type can exist as a subsystem.
After Engine initialization, the following subsystems will always exist:
- Time: manages frame updates, frame number and elapsed time counting, and controls the frequency of the operating system low-resolution timer.
- WorkQueue: executes background tasks in worker threads.
- FileSystem: provides directory operations.
- Log: provides logging services.
- ResourceCache: loads resources and keeps them cached for later access.
- Network: provides UDP networking and scene replication.
- Input: handles keyboard and mouse input. Will be inactive in headless mode.
- UI: the graphical user interface. Will be inactive in headless mode.
- Audio: provides sound output. Will be inactive if sound disabled.
- Engine: creates the other subsystems and controls the main loop iteration and framerate limiting.
The following subsystems are optional, so GetSubsystem() may return null if they have not been created:
- Profiler: Provides hierarchical function execution time measurement using the operating system performance counter. Exists if profiling has been compiled in (configurable from the root CMakeLists.txt)
- Graphics: Manages the application window, the rendering context and resources. Exists if not in headless mode.
- Renderer: Renders scenes in 3D and manages rendering quality settings. Exists if not in headless mode.
- Script: Provides the AngelScript execution environment. Needs to be created and registered manually.
- Console: provides an interactive AngelScript console and log display. Created by calling \ref Engine::CreateConsole "CreateConsole()".
- DebugHud: displays rendering mode information and statistics and profiling data. Created by calling \ref Engine::CreateDebugHud "CreateDebugHud()".
In script, the subsystems are available through the following global properties:
time, fileSystem, log, cache, network, input, ui, audio, engine, graphics, renderer, script, console, debugHud. Note that WorkQueue and Profiler are not available to script due to their low-level nature.
\page Events Events
The Urho3D event system allows for data transport and function invocation without the sender and receiver having to explicitly know of each other. Both the event sender and receiver must derive from Object. An event receiver must subscribe to each event type it wishes to receive: one can either subscribe to the event coming from any sender, or from a specific sender. The latter is useful for example when handling events from the user interface elements.
Events themselves do not need to be registered. They are identified by 32-bit hashes of their names. Event parameters (the data payload) are optional and are contained inside a VariantMap, identified by 16-bit parameter name hashes. For the inbuilt Urho3D events, event type (E_UPDATE, E_KEYDOWN, E_MOUSEMOVE etc.) and parameter hashes (P_TIMESTEP, P_DX, P_DY etc.) are defined as constants inside include files such as CoreEvents.h or InputEvents.h.
When subscribing to an event, a handler function must be specified. In C++ these must have the signature void HandleEvent(StringHash eventType, VariantMap& eventData). The HANDLER(className, function) macro helps in defining the required class-specific function pointers. For example:
\code
SubscribeToEvent(E_UPDATE, HANDLER(MyClass, MyEventHandler));
\endcode
In script events are identified by their string names instead of name hashes (though these are internally converted to hashes.) %Script event handlers can either have the same signature as in C++, or a simplified signature void HandleEvent() when event type and parameters are not required. The same event subscription would look like:
\code
SubscribeToEvent("Update", "MyEventHandler");
\endcode
In C++ events must always be handled by a member function. In script procedural event handling is also possible; in this case the ScriptFile where the event handler function is located becomes the event receiver. See \ref Scripting "Scripting" for more details.
Events can also be unsubscribed from. See \ref Object::UnsubscribeFromEvent "UnsubscribeFromEvent()" for details.
To send an event, fill the event parameters (if necessary) and call \ref Object::SendEvent "SendEvent()". For example, this (in C++) is how the Engine subsystem sends the Update event on each frame. Note how for the inbuilt Urho3D events, the parameter name hashes are always put inside a namespace (the event's name) to prevent name clashes:
\code
using namespace Update;
VariantMap eventData;
eventData[P_TIMESTEP] = timeStep_;
SendEvent(E_UPDATE, eventData);
\endcode
In script event parameters, like event types, are referred to with strings, so the same code would look like:
\code
VariantMap eventData;
eventData["TimeStep"] = timeStep;
SendEvent("Update", eventData);
\endcode
\section Events_AnotherObject Sending events through another object
Because the \ref Object::SendEvent "SendEvent()" function is public, an event can be "masqueraded" as originating from any object, even when not actually sent by that object's member function code. This can be used to simplify communication, particularly between components in the scene. For example, the \ref Physics "physics simulation" signals collision events by using the participating \ref Node "scene nodes" as senders. This means that any component can easily subscribe to its own node's collisions without having to know of the actual physics components involved. The same principle can also be used in any game-specific messaging, for example making a "damage received" event originate from the scene node, though it itself has no concept of damage or health.
\page MainLoop %Engine initialization and main loop
Before a Urho3D application can enter its main loop, the Engine subsystem object must be created and initialized by calling its \ref Engine::Initialize "Initialize()" function. Parameters sent in a VariantMap can be used to direct how the Engine initializes itself and the subsystems. One way to configure the parameters is to parse them from the command line like the Urho3DPlayer application does: this is accomplished by the helper function \ref Engine::ParseParameters "ParseParameters()".
The full list of supported parameters, their datatypes and default values:
- Headless (bool) Headless mode enable. Default false.
- LogLevel (int) %Log verbosity level. Default LOG_INFO in release builds and LOG_DEBUG in debug builds.
- LogQuiet (bool) %Log quiet mode, ie. to not write warning/info/debug log entries into standard output. Default false.
- LogName (string) %Log filename. Default "Urho3D.log".
- FrameLimiter (bool) Whether to cap maximum framerate to 200 (desktop) or 60 (Android/iOS.) Default true.
- WorkerThreads (bool) Whether to create worker threads for the %WorkQueue subsystem according to available CPU cores. Default true.
- ResourcePaths (string) A semicolon-separated list of resource paths to use. If corresponding packages (ie. Data.pak for Data directory) exist they will be used instead. Default "CoreData;Data".
- ResourcePackages (string) A semicolon-separated list of resource packages to use. Default empty.
- AutoloadPaths (string) A semicolon-separated list of autoload paths to use. Any resource packages and subdirectories inside an autoload path will be added to the resource system. Default "Extra".
- ForceSM2 (bool) Whether to force %Shader %Model 2, effective in Direct3D9 mode only. Default false.
- ExternalWindow (void ptr) External window handle to use instead of creating an application window. Default null.
- WindowIcon (string) %Window icon image resource name. Default empty (use application default icon.)
- WindowTitle (string) %Window title. Default "Urho3D".
- WindowWidth (int) %Window horizontal dimension. Default 0 (use desktop resolution, or 1024 in windowed mode.)
- WindowHeight (int) %Window vertical dimension. Default 0 (use desktop resolution, or 768 in windowed mode.)
- WindowResizable (bool) Whether window is resizable. Default false.
- FullScreen (bool) Whether to create a full-screen window. Default true.
- Borderless (bool) Whether to create the window as borderless. Default false.
- TripleBuffer (bool) Whether to use triple-buffering. Default false.
- VSync (bool) Whether to wait for vertical sync when presenting rendering window contents. Default false.
- FlushGPU (bool) Whether to flush GPU command buffer each frame for less input latency. Effective only on Direct3D9. Default false.
- Multisample (int) Hardware multisampling level. Default 1 (no multisampling.)
- Orientations (string) Space-separated list of allowed orientations. Effective only on iOS. All possible values are "LandscapeLeft", "LandscapeRight", "Portrait" and "PortraitUpsideDown". Default "LandscapeLeft LandscapeRight".
- DumpShaders (string) Filename to dump used shader variations to for precaching.
- %RenderPath (string) Default renderpath resource name. Default empty, which causes forward rendering (Bin/CoreData/RenderPaths/Forward.xml) to be used.
- Shadows (bool) Shadow rendering enable. Default true.
- LowQualityShadows (bool) Low-quality (1 sample) shadow mode. Default false.
- MaterialQuality (int) %Material quality level. Default 2 (high)
- TextureQuality (int) %Texture quality level. Default 2 (high)
- TextureFilterMode (int) %Texture default filter mode. Default 2 (trilinear)
- TextureAnisotropy (int) %Texture anisotropy level. Default 4. This has only effect for anisotropically filtered textures.
- %Sound (bool) %Sound enable. Default true.
- SoundBuffer (int) %Sound buffer length in milliseconds. Default 100.
- SoundMixRate (int) %Sound output frequency in Hz. Default 44100.
- SoundStereo (bool) Stereo sound output mode. Default true.
- SoundInterpolation (bool) Interpolated sound output mode to improve quality. Default true.
- TouchEmulation (bool) %Touch emulation on desktop platform. Default false.
\section MainLoop_Frame Main loop iteration
The main loop iteration (also called a frame) is driven by the Engine. In contrast it is the program's (for example Urho3DPlayer) responsibility to continuously loop this iteration by calling \ref Engine::RunFrame "RunFrame()". This function calls in turn the Time subsystem's \ref Time::BeginFrame "BeginFrame()" and \ref Time::EndFrame "EndFrame()" functions, and sends various update events in between. The event order is:
- E_BEGINFRAME: signals the beginning of the new frame. Input and Network react to this to check for operating system window messages and arrived network packets.
- E_UPDATE: application-wide logic update event. By default each update-enabled Scene reacts to this and triggers the scene update (more on this below.)
- E_POSTUPDATE: application-wide logic post-update event. The UI subsystem updates its logic here.
- E_RENDERUPDATE: Renderer updates its viewports here to prepare for rendering, and the UI generates render commands necessary to render the user interface.
- E_POSTRENDERUPDATE: by default nothing hooks to this. This can be used to implement logic that requires the rendering views to be up-to-date, for example to do accurate raycasts. Scenes may not be modified at this point; especially scene objects may not be deleted or crashes may occur.
- E_ENDFRAME: signals the end of the frame. Before this, rendering the frame and measuring the next frame's timestep will have occurred.
The update of each Scene causes further events to be sent:
- E_SCENEUPDATE: variable timestep scene update. This is a good place to implement any scene logic that does not need to happen at a fixed step.
- E_SCENESUBSYSTEMUPDATE: update scene-wide subsystems. Currently only the PhysicsWorld component listens to this, which causes it to step the physics simulation and send the following two events for each simulation step:
- E_PHYSICSPRESTEP: called before the simulation iteration. Happens at a fixed rate (the physics FPS.) If fixed timestep logic updates are needed, this is a good event to listen to.
- E_PHYSICSPOSTSTEP: called after the simulation iteration. Happens at the same rate as E_PHYSICSPRESTEP.
- E_SMOOTHINGUPDATE: update SmoothedTransform components in network client scenes.
- E_SCENEPOSTUPDATE: variable timestep scene post-update. ParticleEmitter and AnimationController update themselves as a response to this event.
Variable timestep logic updates are preferable to fixed timestep, because they are only executed once per frame. In contrast, if the rendering framerate is low, several physics simulation steps will be performed on each frame to keep up the apparent passage of time, and if this also causes a lot of logic code to be executed for each step, the program may bog down further if the CPU can not handle the load. Note that the Engine's \ref Engine::SetMinFps "minimum FPS", by default 10, sets a hard cap for the timestep to prevent spiraling down to a complete halt; if exceeded, animation and physics will instead appear to slow down.
\section MainLoop_ApplicationState Main loop and the application activation state
The application window's state (has input focus, minimized or not) can be queried from the Input subsystem. It can also effect the main loop in the following ways:
- Rendering is always skipped when the window is minimized.
- To avoid spinning the CPU and GPU unnecessarily, it is possible to define a smaller maximum FPS when no input focus. See \ref Engine::SetMaxInactiveFps "SetMaxInactiveFps()"
- It is also possible to automatically pause update events and audio when the window is minimized. Use \ref Engine::SetPauseMinimized "SetPauseMinimized()" to control this behaviour. By default it is not enabled on desktop, and enabled on mobile devices (Android and iOS.) For singleplayer games this is recommended to avoid unwanted progression while away from the program. However in a multiplayer game this should not be used, as the missing scene updates would likely desync the client with the server.
- On mobile devices the window becoming minimized can mean that it will never become maximized again, in case the OS decides it needs to free memory and kills your program. Therefore you should listen for the E_INPUTFOCUS event from the Input subsystem and immediately save your program state as applicable if the program loses input focus or is minimized.
- On mobile devices it is also unsafe to access or create any graphics resources while the window is minimized (as the graphics context may be destroyed during this time); doing so can crash the program. It is recommended to leave the pause-minimized feature on to ensure you do not have to check for this in your update code.
Note that on iOS calling \ref Engine::Exit "Exit()" is a no-op as there is no officially sanctioned way to manually exit your program. On Android it will cause the activity to manually exit.
\section MainLoop_ApplicationFramework Application framework
The Application class provides a minimal framework for a Urho3D C++ application with a main loop. It has virtual functions Setup(), Start() and Stop() which can be defined by the application subclass. The header file also provides a macro for defining a program entry point, which
will instantiate the Context object and then the user-specified application class. A minimal example, which would just display a blank rendering window and exit by pressing ESC:
\code
#include "Application.h"
#include "Engine.h"
#include "InputEvents.h"
class MyApp : public Application
{
public:
MyApp(Context* context) :
Application(context)
{
}
virtual void Setup()
{
// Called before engine initialization. engineParameters_ member variable can be modified here
}
virtual void Start()
{
// Called after engine initialization. Setup application & subscribe to events here
SubscribeToEvent(E_KEYDOWN, HANDLER(MyApp, HandleKeyDown));
}
virtual void Stop()
{
// Perform optional cleanup after main loop has terminated
}
void HandleKeyDown(StringHash eventType, VariantMap& eventData)
{
using namespace KeyDown;
// Check for pressing ESC. Note the engine_ member variable for convenience access to the Engine object
int key = eventData[P_KEY].GetInt();
if (key == KEY_ESC)
engine_->Exit();
}
};
DEFINE_APPLICATION_MAIN(MyApp)
\endcode
\page SceneModel %Scene model
Urho3D's scene model can be described as a component-based scene graph. The Scene consists of a hierarchy of scene nodes, starting from the root node, which also represents the whole scene. Each Node has a 3D transform (position, rotation and scale), a name and an ID, and a freeform VariantMap for \ref Node::GetVars "user variables", but no other functionality.
\section SceneModel_Components Components
Rendering 3D objects, sound playback, physics and scripted logic updates are all enabled by creating different \ref Component "Components" into the nodes by calling \ref Node::CreateComponent "CreateComponent()". As with events, in C++ components are identified by type name hashes, and template forms of the component creation and retrieval functions exist for convenience. For example:
\code
Light* light = node->CreateComponent<Light>();
\endcode
In script, strings are used to identify component types instead, so the same code would look like:
\code
Light@ light = node.CreateComponent("Light");
\endcode
Because components are created using \ref ObjectTypes "object factories", a factory must be registered for each component type.
Components created into the Scene itself have a special role: to implement scene-wide functionality. They should be created before all other components, and include the following:
- Octree: implements spatial partitioning and accelerated visibility queries. Without this 3D objects can not be rendered.
- PhysicsWorld: implements physics simulation. Physics components such as RigidBody or CollisionShape can not function properly without this.
- DebugRenderer: implements debug geometry rendering.
"Ordinary" components like Light, Camera or StaticModel should not be created directly into the Scene, but rather into child nodes.
\section SceneModel_Identification Identification and scene hierarchy
Unlike nodes, components do not have names; components inside the same node are only identified by their type, and index in the node's component list, which is filled in creation order. See the various overloads of \ref Node::GetComponent "GetComponent()" or \ref Node::GetComponents "GetComponents()" for details.
When created, both nodes and components get scene-global integer IDs. They can be queried from the Scene by using the functions \ref Scene::GetNodeByID "GetNodeByID()" and \ref Scene::GetComponentByID "GetComponentByID()". This is much faster than for example doing recursive name-based scene node queries.
There is no inbuilt concept of an entity or a game object; rather it is up to the programmer to decide the node hierarchy, and in which nodes to place any scripted logic. Typically, free-moving objects in the 3D world would be created as children of the root node. Nodes can be created either with or without a name, see \ref Node::CreateChild "CreateChild()". Uniqueness of node names is not enforced.
Whenever there is some hierarchical composition, it is recommended (and in fact necessary, because components do not have their own 3D transforms) to create a child node. For example if a character was holding an object in his hand, the object should have its own node, which would be parented to the character's hand bone (also a Node.) The exception is the physics CollisionShape, which can be offsetted and rotated individually in relation to the node. See \ref Physics "Physics" for more details. Note that Scene's own transform is purposefully ignored as an optimization when calculating world derived transforms of child nodes, so changing it has no effect and it should be left as it is (position at origin, no rotation, no scaling.)
%Scene nodes can be freely reparented. In contrast components are always created to the node they belong to, and can not be moved between nodes. Both child nodes and components are stored using SharedPtr containers; this means that detaching a child node from its parent or removing a component will also destroy it, if no other references to it exist. Both Node & Component provide the \ref Node::Remove "Remove()" function to accomplish this without having to go through the parent. Note that no operations on the node or component in question are safe after calling that function.
It is also legal to create a Node that does not belong to a scene. This is useful for example with a camera moving in a scene that may be loaded or saved, because then the camera will not be saved along with the actual scene, and will not be destroyed when the scene is loaded. However, note that creating geometry, physics or script components to an unattached node, and then moving it into a scene later will cause those components to not work correctly.
\section SceneModel_Update Scene updates
A Scene whose updates are enabled (default) will be automatically updated on each main loop iteration. See \ref Scene::SetUpdateEnabled "SetUpdateEnabled()".
Nodes and components can be excluded from the scene update by disabling them, see \ref Node::SetEnabled "SetEnabled()". Disabling for example a drawable component also makes it invisible, a sound source component becomes inaudible etc. If a node is disabled, all of its components are treated as disabled regardless of their own enable/disable state.
\section SceneModel_Logic Creating logic functionality
To implement your game logic you typically either create script objects (when using scripting) or new components (when using C++). %Script objects exist in a C++ placeholder component, but can be basically thought of as components themselves. For a simple example to get you started, check the 05_AnimatingScene sample, which creates a Rotator object to scene nodes to perform rotation on each frame update.
Unless you have extremely serious reasons for doing so, you should not subclass the Node class in C++ for implementing your own logic. Doing so will theoretically work, but has the following drawbacks:
- Loading and saving will not work properly without changes. It assumes that the root node is a %Scene, and all the child nodes are of the %Node class. It will not know how to instantiate your custom subclass.
- The Editor does not know how to edit your subclass.
\section SceneModel_LoadSave Loading and saving scenes
Scenes can be loaded and saved in either binary or XML format; see the functions \ref Scene::Load "Load()", \ref Scene::LoadXML "LoadXML()", \ref Scene::Save "Save()" and \ref Scene::SaveXML "SaveXML()". See \ref Serialization
"Serialization" for the technical details on how this works. When a scene is loaded, all existing content in it (child nodes and components) is removed first.
Nodes and components that are marked temporary will not be saved. See \ref Serializable::SetTemporary "SetTemporary()".
To be able to track the progress of loading a (large) scene without having the program stall for the duration of the loading, a scene can also be loaded asynchronously. This means that on each frame the scene loads child nodes until a certain amount of milliseconds has been exceeded. See \ref Scene::LoadAsync "LoadAsync()" and \ref Scene::LoadAsyncXML "LoadAsyncXML()". Use the functions \ref Scene::IsAsyncLoading "IsAsyncLoading()" and \ref Scene::GetAsyncProgress "GetAsyncProgress()" to track the loading progress; the latter returns a float value between 0 and 1, where 1 is fully loaded. The scene will not update or render before it is fully loaded.
\section SceneModel_Instantiation Object prefabs
Just loading or saving whole scenes is not flexible enough for eg. games where new objects need to be dynamically created. On the other hand, creating complex objects and setting their properties in code will also be tedious. For this reason, it is also possible to save a scene node (and its child nodes, components and attributes) to either binary or XML to be able to instantiate it later into a scene. Such a saved object is often referred to as a prefab. There are three ways to do this:
- In code by calling \ref Node::Save "Save()" or \ref Node::SaveXML "SaveXML()" on the Node in question.
- In the editor, by selecting the node in the hierarchy window and choosing "Save node as" from the "File" menu.
- Using the "node" command in AssetImporter, which will save the scene node hierarchy and any models contained in the input asset (eg. a Collada file)
To instantiate the saved node into a scene, call \ref Scene::Instantiate "Instantiate()" or \ref Scene::InstantiateXML "InstantiateXML()" depending on the format. The node will be created as a child of the Scene but can be freely reparented after that. Position and rotation for placing the node need to be specified. The NinjaSnowWar example uses XML format for its object prefabs; these exist in the Bin/Data/Objects directory.
\section SceneModel_FurtherInformation Further information
For more information on the component-based scene model, see for example http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/. Note that the Urho3D scene model is not a pure Entity-Component-System design, which would have the components just as bare data containers, and only systems acting on them. Instead the Urho3D components contain logic of their own, and actively communicate with the systems (such as rendering, physics or script engine) they depend on.
\page Resources Resources
Resources include most things in Urho3D that are loaded from mass storage during initialization or runtime:
- Animation
- Image
- Model
- Material
- ScriptFile
- Shader
- Sound
- Technique
- Texture2D
- TextureCube
- XMLFile
They are managed and loaded by the ResourceCache subsystem. Like with all other \ref ObjectTypes "typed objects", resource types are identified by 16-bit type name hashes (C++) or type names (script). An object factory must be registered for each resource type.
The resources themselves are identified by their file paths, relative to the registered resource directories or \ref PackageFile "package files". By default, the engine registers the resource directories Data and CoreData, or the packages Data.pak and CoreData.pak if they exist.
If loading a resource fails, an error will be logged and a null pointer is returned.
Typical C++ example of requesting a resource from the cache, in this case, a texture for a UI element. Note the use of a convenience template argument to specify the resource type, instead of using the type hash.
\code
healthBar->SetTexture(GetSubsystem<ResourceCache>()->GetResource<Texture2D>("Textures/HealthBarBorder.png"));
\endcode
The same in script would look like this (note the use of a property instead of a setter function):
\code
healthBar.texture = cache.GetResource("Texture2D", "Textures/HealthBarBorder.png");
\endcode
Resources can also be created manually and stored to the resource cache as if they had been loaded from disk.
Memory budgets can be set per resource type: if resources consume more memory than allowed, the oldest resources will be removed from the cache if not in use anymore. By default the memory budgets are set to unlimited.
\page Scripting Scripting
To enable AngelScript scripting support, the Script subsystem needs to be created and registered after initializing the Engine. This is accomplished by the following code, seen eg. in Tools/Urho3DPlayer/Urho3DPlayer.cpp:
\code
context_->RegisterSubsystem(new Script(context_));
\endcode
There are three ways the AngelScript language can be interacted with in Urho3D:
\section Scripting_Immediate Immediate execution
Immediate execution takes one line of AngelScript, compiles it, and executes. This is not recommended for anything that needs high performance, but can be used for example to implement a developer console. Call the Script subsystem's \ref Script::Execute "Execute()" function to use. For example:
\code
GetSubsystem<Script>()->Execute("Print(\"Hello World!\");");
\endcode
It may be useful to be able to access a specific scene or a script file while executing immediate script code. These can be set on the Script subsystem by calling \ref Script::SetDefaultScene "SetDefaultScene()" and \ref Script::SetDefaultScriptFile "SetDefaultScriptFile()".
\section Scripting_Procedural Calling a function from a script file
This requires a successfully loaded ScriptFile resource, whose \ref ScriptFile::Execute "Execute()" function will be used. To identify the function to be called, its full declaration is needed. Parameters are passed in a VariantVector. For example:
\code
ScriptFile* file = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>("Scripts/MyScript.as");
VariantVector parameters;
parameters.Push(Variant(100)); // Add an int parameter
file->Execute("void MyFunction(int)", parameters); // Execute
\endcode
\ref ScriptFile::Execute "Execute()" also has an overload which takes a function pointer instead of querying by declaration. Using a pointer is naturally faster than a query, but also more risky: in case the ScriptFile resource is unloaded or reloaded, any function pointers will be invalidated.
\section Scripting_Object Instantiating a script object
The component ScriptInstance can be used to instantiate a specific class from within a script file. After instantiation, the the script object can respond to scene updates, \ref Events "events" and \ref Serialization "serialization" much like a component written in C++ would do, if it has the appropriate methods implemented. For example:
\code
ScriptInstance* instance = node->CreateComponent<ScriptInstance>();
instance->CreateObject(GetSubsystem<ResourceCache>()->GetResource<ScriptFile>("Scripts/MyClass.as"), "MyClass");
\endcode
The class must implement the empty interface ScriptObject to make its base class statically known. This enables accessing any script object in the scene using ScriptInstance's \ref ScriptInstance::GetScriptObject "GetScriptObject()" function.
The following methods that implement the component behaviour will be checked for. None of them are required.
- void Start()
- void Stop()
- void DelayedStart()
- void Update(float)
- void PostUpdate(float)
- void FixedUpdate(float)
- void FixedPostUpdate(float)
- void Save(Serializer&)
- void Load(Deserializer&)
- void WriteNetworkUpdate(Serializer&)
- void ReadNetworkUpdate(Deserializer&)
- void ApplyAttributes()
- void TransformChanged()
The update methods above correspond to the variable timestep scene update and post-update, and the fixed timestep physics world update and post-update. The application-wide update events are not handled by default.
The Start() and Stop() methods do not have direct counterparts in C++ components. Start() is called just after the script object has been created. Stop() is called just before the script object is destroyed. This happens when the ScriptInstance is destroyed, or if the script class is changed.
When a scene node hierarchy with script objects is instantiated (such as when loading a scene) any child nodes may not have been created yet when Start() is executed, and can thus not be relied upon for initialization. The DelayedStart() method can be used in this case instead: if defined, it is called immediately before any of the Update() calls.
TransformChanged() is called whenever the scene node transform changes, similar to C++ components' OnMarkedDirty() function. Due to an optimization mechanism for repeated scene graph updates, you need to "undirty" the scene node by for example reading its world position to get further transform changed notifications.
Subscribing to \ref Events "events" in script behaves differently depending on whether \ref Object::SubscribeToEvent "SubscribeToEvent()" is called from a script object's method, or from a procedural script function. If called from an instantiated script object, the ScriptInstance becomes the event receiver on the C++ side, and calls the specified handler method when the event arrives. If called from a function, the ScriptFile will be the event receiver and the handler must be a free function in the same script file. The third case is if the event is subscribed to from a script object that does not belong to a ScriptInstance. In that case the ScriptFile will create a proxy C++ object on demand to be able to forward the event to the script object.
The script object's enabled state can be controlled through the \ref ScriptInstance::SetEnabled "SetEnabled()" function. When disabled, the scripted update methods or event handlers will not be called. This can be used to reduce CPU load in a large or densely populated scene.
There are shortcut methods on the script side for creating and accessing a node's script object: node.CreateScriptObject() and node.GetScriptObject(). Alternatively, if the node has only one ScriptInstance, and a specific class is not needed, the node's scriptObject property can also be used. CreateScriptObject() takes the script file name (or alternatively, a ScriptFile object handle) and class name as parameters and creates a ScriptInstance component automatically, then creates the script object. For example:
\code
ScriptObject@ object = node.CreateScriptObject("Scripts/MyClass.as", "MyClass");
\endcode
Note that these are not actual Node member functions on the C++ side, as the %Scene classes are not allowed to depend on scripting.
\section Scripting_ObjectSerialization Script object serialization
After instantiation, the script object's public member variables that can be converted into Variant, and that don't begin with an underscore are automatically available as attributes of the ScriptInstance, and will be serialized.
Node and Component handles are also converted into nodeID and componentID attributes automatically. Note: this automatic attribute mechanism means that a ScriptInstance's attribute list changes dynamically depending on the class that has been instantiated.
If the script object contains more complex data structures, you can also serialize and deserialize into a binary buffer manually by implementing the Load() and Save() methods.
%Network replication of the script object variables must be handled manually by implementing WriteNetworkUpdate() and ReadNetworkUpdate() methods, that also write and read a binary buffer. These methods should write/read all replicated of variables of the object. Additionally, the ScriptInstance must be marked for network replication by calling MarkNetworkUpdate() whenever the replicated data changes. Because this replication mechanism can not sync per variable, but always sends the whole binary buffer if even one bit of the data changes, also consider using the automatically replicated node user variables.
\section Script_DelayedCalls Delayed method calls
Delayed method calls can be used in script objects to implement time-delayed actions. Use the DelayedExecute() function in script object code to add a method to be executed later. The parameters are the delay in seconds, repeat flag, the full declaration of the function, and optionally parameters, which must be placed in a Variant array. For example:
\code
class Test : ScriptObject
{
void Start()
{
Array<Variant> parameters;
parameters.Push(Variant(100));
DelayedExecute(1.0, false, "void Trigger(int)", parameters);
}
void Trigger(int parameter)
{
Print("Delayed function triggered with parameter " + parameter);
}
}
\endcode
Delayed method calls can be removed by full declaration using the ClearDelayedExecute() function. If an empty declaration (default) is given as parameter, all delayed calls are removed.
When a scene is saved/loaded, any pending delayed calls are also saved and restored properly.
\section Script_ScriptAPI The script API
Much of the Urho3D classes are exposed to scripts, however things that require low-level access or high performance (like direct vertex buffer access) are not. Also for scripting convenience some things have been changed from the C++ API:
- The template array and string classes are exposed as Array<type> and String.
- Public member variables are exposed without the underscore appended. For example x, y, z in Vector3.
- Whenever only a single parameter is needed, setter and getter functions are replaced with properties. Such properties start with a lowercase letter. If an index parameter is needed, the property will be indexed. Indexed properties are in plural.
- The element count property of arrays and other dynamic structures such as VariantMap and ResourceRefList is called "length", though the corresponding C++ function is usually Size().
- Subsystems exist as global properties: time, fileSystem, log, cache, network, input, ui, audio, engine, graphics, renderer, script, console, debugHud.
- Additional global properties exist for accessing the script object's node, the scene and the scene-wide components: node, scene, octree, physicsWorld, debugRenderer. When an object method is not executing, these are null. An exception: when the default scene for immediate execution has been set by calling \ref Script::SetDefaultScene "SetDefaultScene()", it is always available as "scene".
- The currently executing script object's ScriptInstance component is available through the global property self.
- The currently executing script file is available through the global property scriptFile.
- The first script object created to a node is available as its scriptObject property.
- Printing raw output to the log is simply called Print(). The rest of the logging functions are accessed by calling log.Debug(), log.Info(), log.Warning() and log.Error().
- Functions that would take a StringHash or ShortStringHash parameter usually take a string instead. For example sending events, requesting resources and accessing components.
- Most of StringUtils have been exposed as methods of the string class. For example String.ToBool().
- Template functions for getting components or resources by type are not supported. Instead automatic type casts are performed as necessary.
Check the automatically built \ref ScriptAPI "Scripting API" documentation for the exact function signatures. Note that the API documentation can be regenerated to the Urho3D log file by calling \ref Script::DumpAPI "DumpAPI()" function on the Script subsystem or by using \ref Tools_ScriptCompiler "ScriptCompiler tool".
\section Script_Bytecode Precompiling scripts to bytecode
Instead of compiling scripts from source on-the-fly during startup, they can also be precompiled to bytecode, then loaded. Use the \ref Tools_ScriptCompiler "ScriptCompiler" utility for this. In this case the resource request has to be pointed to the compiled file, which by default has the .asc extension:
\code
ScriptFile* file = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>("Scripts/MyScript.asc");
\endcode
\section Scripting_Limitations Limitations
There are some complexities of the scripting system one has to watch out for:
- During the execution of the script object's constructor, the object is not yet associated with the ScriptInstance, and therefore subscribing to events, adding delayed method calls, or trying to access the node or scene will fail. The use of the constructor is best reserved for initializing member variables only.
- When the resource request for a particular ScriptFile is initially made, the script file and the files it includes are compiled into an AngelScript script module. Each script module has its own class hierarchy that is not usable from other script modules, unless the classes are declared shared. See AngelScript documentation for more details.
- If a ScriptFile resource is reloaded, all the script objects created from it will be destroyed, then recreated. They will lose any stored state as their constructors and Start() methods will be run again. This is rarely useful when running an actual game, but may be helpful during development.
\section Scripting_Modifications AngelScript modifications
The following changes have been made to AngelScript in Urho3D:
- For performance reasons and to guarantee immediate removal of expired objects, AngelScript garbage collection has been disabled for script classes and the Array type. This has the downside that circular references will not be detected. Therefore, whenever you have object handles in your script, think of them as if they were C++ shared pointers and avoid creating circular references with them. For safety, consider using the value type WeakHandle, which is a WeakPtr<RefCounted> exposed to script and can be used to point to any engine object (but not to script objects.) An example of using WeakHandle:
\code
WeakHandle rigidBodyWeak = node.CreateComponent("RigidBody");
RigidBody@ rigidBodyShared = rigidBodyWeak.Get(); // Is null if expired
\endcode
- %Object handle assignment can be done without the @ symbol if the object in question does not support value assignment. All exposed Urho3D C++ classes that derive from RefCounted never support value assignment. For example, when assigning the Model and Material of a StaticModel component:
\code
object.model = cache.GetResource("Model", "Models/Mushroom.mdl");
object.material = cache.GetResource("Material", "Materials/Mushroom.xml");
\endcode
In unmodified AngelScript, this would have to be written as:
\code
@object.model = cache.GetResource("Model", "Models/Mushroom.mdl");
@object.material = cache.GetResource("Material", "Materials/Mushroom.xml");
\endcode
\page LuaScripting Lua scripting
Lua scripting in Urho3D has its dedicated LuaScript subsystem that must be instantiated before the scripting capabilities can be used. Lua support is not compiled in by default but must be enabled by the CMake
build option -DURHO3D_LUA=1. For more details see \ref Build_Options "Build options". Instantiating the subsystem is done like this:
\code
context_->RegisterSubsystem(new LuaScript(context_));
\endcode
Like AngelScript, Lua scripting supports immediate compiling and execution of single script lines, loading script files and executing procedural functions from them, and instantiating script objects
to scene nodes using the LuaScriptInstance component.
\section LuaScripting_Immediate Immediate execution
Use \ref LuaScript::ExecuteString "ExecuteString()" to compile and run a line of Lua script. This should not be used for performance-critical operations.
\section LuaScripting_ScriptFiles Script files and functions
In contrast to AngelScript modules, which exist as separate entities and do not share functions or variables unless explicitly marked shared, in the Lua subsystem everything is loaded and executed in one Lua state, so scripts can naturally access everything loaded so far. To load and execute a Lua script file, call \ref LuaScript::ExecuteFile "ExecuteFile()".
After that, the functions in the script file are available for calling. Use \ref LuaScript::GetFunction "GetFunction()" to get a Lua function by name. This returns a LuaFunction object, on which you should call \ref LuaFunction::BeginCall "BeginCall()" first, followed by pushing the function parameters if any, and finally execute the function with \ref LuaFunction::EndCall "EndCall()".
\section LuaScripting_ScriptObjects Script objects
By using the LuaScriptInstance component, Lua script objects can be added to scene nodes. After the component has been created, there are two ways to specify the object to instantiate: either specifying both the script file name and the object class name, in which case the script file is loaded and executed first, or specifying only the class name, in which case the Lua code containing the class definition must already have been executed. An example of creating a script object in C++ from the LuaIntegration sample, where a class called Rotator is instantiated from the script file Rotator.lua:
\code
LuaScriptInstance* instance = node->CreateComponent<LuaScriptInstance>();
instance->CreateObject("LuaScripts/Rotator.lua", "Rotator");
\endcode
After instantiation, use \ref LuaScriptInstance::GetScriptObjectFunction "GetScriptObjectFunction()" to get the object's functions by name; calling happens like above.
Like their AngelScript counterparts, script object classes can define functions which are automatically called by LuaScriptInstance for operations like initialization, scene update, or load/save. These functions are listed below. Refer to the \ref Scripting "AngelScript scripting" page for details.
- Start()
- Stop()
- Update(timeStep)
- PostUpdate(timeStep)
- FixedUpdate(timeStep)
- FixedPostUpdate(timeStep)
- Save(serializer)
- Load(deserializer)
- WriteNetworkUpdate(serializer)
- ReadNetworkUpdate(deserializer)
- ApplyAttributes()
- TransformChanged()
\section LuaScripting_Events Event handling
Like in AngelScript, both procedural and object event handling is supported. In procedural event handling the LuaScript subsystem acts as the event receiver on the C++ side, and forwards the event to a Lua function. Use SubscribeToEvent and give the event name and the function to use as the handler. Optionally a specific sender object can be given as the first argument instead. For example, subscribing to the application-wide Update event, and getting its timestep parameter in the event handler function.
\code
SubscribeToEvent("Update", "HandleUpdate")
...
function HandleUpdate(eventType, eventData)
local timeStep = eventData:GetFloat("TimeStep")
...
end
\endcode
When subscribing a script object to receive an event, use the form self:SubscribeToEvent instead. The function to use as the handler is given as "ClassName:FunctionName". For example subscribing to the NodeCollision physics event, and getting the participating other scene node and the contact point VectorBuffer in the handler function. Note that in Lua retrieving an object pointer from a VariantMap requires the object type as the first parameter:
\code
CollisionDetector = ScriptObject()
function CollisionDetector:Start()
self:SubscribeToEvent(self.node, "NodeCollision", "CollisionDetector:HandleNodeCollision")
end
function CollisionDetector:HandleNodeCollision(eventType, eventData)
local otherNode = eventData:GetPtr("Node", "OtherNode")
local contacts = eventData:GetBuffer("Contacts")
...
end
\endcode
\section LuaScripting_API The script API
The binding of Urho3D C++ classes is accomplished with the tolua++ library, which for the most part binds the exact same function parameters as C++. Compared to the AngelScript API, you will always have the classes' Get / Set functions available, but in addition convenience properties also exist.
As seen above from the event handling examples, VariantMap handling has some differences to both C++ and AngelScript. To get a value, supply its key name as a string. To get a pointer to an object, supply first the object type, then the key name.
For the rest of the functions and classes, see the generated \ref LuaScriptAPI "Lua script API reference". Also, look at the Lua counterparts of the sample applications in the Bin/Data/LuaScripts directory and compare them to the C++ and AngelScript versions to familiarize yourself with how things are done on the Lua side.
\section LuaScripting_Allocation Object allocation & Lua garbage collection
There are two ways to allocate a C++ object in Lua scripting, which behave differently with respect to Lua's automatic garbage collection:
1) Call object's contructor:
\code
local scene = Scene()
\endcode
tolua++ will register this C++ object with garbage collection, and Lua will collect it eventually. Do not use this form if you will add the
object to an object hierarchy that is kept alive on the C++ side with SharedPtr's, for example child scene nodes or %UI child elements.
Otherwise the object will be double-deleted, resulting in a crash.
2) Call the new function:
\code
local text = Text:new()
\endcode
When using this form the object will not collected by Lua, so it is safe to pass into C++ object hierarchies.
Otherwise, to prevent memory leaks it needs to be deleted manually by calling the delete function on it:
\code
text:delete()
\endcode
When you call the \ref ResourceCache::GetFile "GetFile()" function of ResourceCache from Lua, the file you receive must also be manually deleted like described above once you are done with it.
\page Rendering Rendering
Much of the rendering functionality in Urho3D is built on two subsystems, Graphics and Renderer.
\section Rendering_Graphics Graphics
Graphics implements the low-level functionality:
- Creating the window and the rendering context
- Setting the screen mode
- Keeping track of GPU resources
- Keeping track of rendering context state (current rendertarget, vertex and index buffers, textures, shaders and renderstates)
- Loading shaders
- Performing primitive rendering operations
- Handling lost device
Screen resolution, fullscreen/windowed, vertical sync and hardware multisampling level are all set at once by calling Graphics's \ref Graphics::SetMode "SetMode()" function. There is also an experimental option of rendering to an existing window by passing its OS-specific handle to \ref Graphics::SetExternalWindow "SetExternalWindow()" before setting the initial screen mode.
When setting the initial screen mode, Graphics does a few checks:
- For Direct3D9, the supported shader model is checked. 2 is minimum, but 3 will be used if available. For testing, SM2 can be forced by calling \ref Graphics::SetForceSM2 "SetForceSM2()" before setting the initial screen mode.
- For OpenGL, version 2.0 with EXT_framebuffer_object, EXT_packed_depth_stencil and EXT_texture_filter_anisotropic extensions is checked for.
- Is hardware instancing supported? This requires %Shader %Model 3 on Direct3D9 and the ARB_instanced_arrays extension on OpenGL.
- Are hardware shadow maps supported? Both AMD & NVIDIA style shadow maps can be used. If neither are available, no shadows will be rendered.
- Are light pre-pass and deferred rendering modes supported? These require sufficient multiple rendertarget support, and R32F texture format support.
%Shader model 2 has the following limitations due to limited pixel shader instruction count:
- Directional light shadows support a maximum of 3 cascade splits instead of 4.
- Shadowed point lights do not support specular calculations in forward rendering.
- Complex materials do not combine the ambient pass with the first forward light (lit base pass optimization.)
- Complex forward rendered materials (eg. normal + specular map + alpha masking) combined with shadow mapping or height fog may not work.
\section Rendering_Renderer Renderer
Renderer implements the actual rendering of 3D views each frame, and controls global settings such as texture quality, material quality, specular lighting and shadow map base resolution.
To render, it needs a Scene with an Octree component, and a Camera that does not necessarily have to belong to the scene. The octree stores all visible components (derived from Drawable) to allow querying for them in an accelerated manner. The needed information is collected in a Viewport object, which can be assigned with Renderer's \ref Renderer::SetViewport "SetViewport()" function.
By default there is one viewport, but the amount can be increased with the function \ref Renderer::SetNumViewports "SetNumViewports()". The viewport(s) should cover the entire screen or otherwise hall-of-mirrors artifacts may occur. By specifying a zero screen rectangle the whole window will be used automatically. The viewports will be rendered in ascending order, so if you want for example to have a small overlay window on top of the main viewport, use viewport index 0 for the main view, and 1 for the overlay.
Viewports can also be defined for rendertarget textures. See \ref AuxiliaryViews "Auxiliary views" for details.
Each viewport defines a command sequence for rendering the scene, the \ref RenderPaths "render path". By default there exist forward, light pre-pass and deferred render paths in the Bin/CoreData/RenderPaths directory, see \ref Renderer::SetDefaultRenderPath "SetDefaultRenderPath()" to set the default for new viewports. If not overridden from the command line, forward rendering is the default. Deferred rendering modes will be advantageous once there is a large number of per-pixel lights affecting each object, but their disadvantages are the lack of hardware multisampling and inability to choose the lighting model per material. In place of multisample antialiasing, a FXAA post-processing edge filter can be used, see the MultipleViewports sample application (Bin/Data/Scripts/09_MultipleViewports.as) for an example of how to use.
The steps for rendering each viewport on each frame are roughly the following:
- Query the octree for visible objects and lights in the camera's view frustum.
- Check the influence of each visible light on the objects. If the light casts shadows, query the octree for shadowcaster objects.
- Construct render operations (batches) for the visible objects, according to the scene passes in the render path command sequence.
- Perform the render path command sequence during the rendering step at the end of the frame.
In the default render paths, the rendering operations proceed in the following order:
- Opaque geometry ambient pass, or G-buffer pass in deferred rendering modes.
- Opaque geometry per-pixel lighting passes. For shadow casting lights, the shadow map is rendered first.
- (%Light pre-pass only) Opaque geometry material pass, which renders the objects with accumulated per-pixel lighting.
- Post-opaque pass for custom render ordering such as the skybox.
- Refractive geometry pass.
- Transparent geometry pass. Transparent, alpha-blended objects are sorted according to distance and rendered back-to-front to ensure correct blending.
- Post-alpha pass, can be used for 3D overlays that should appear on top of everything else.
\section Rendering_Drawable Rendering components
The rendering-related components defined by the %Graphics and %UI libraries are:
- Octree: spatial partitioning of Drawables for accelerated visibility queries. Needs to be created to the Scene (root node.)
- Camera: describes a viewpoint for rendering, including projection parameters (FOV, near/far distance, perspective/orthographic)
- Drawable: Base class for anything visible.
- StaticModel: non-skinned geometry. Can LOD transition according to distance.
- StaticModelGroup: renders several object instances while culling and receiving light as one unit.
- Skybox: a subclass of StaticModel that appears to always stay in place.
- AnimatedModel: skinned geometry that can do skeletal and vertex morph animation.
- AnimationController: drives animations forward automatically and controls animation fade-in/out.
- BillboardSet: a group of camera-facing billboards, which can have varying sizes, rotations and texture coordinates.
- ParticleEmitter: a subclass of BillboardSet that emits particle billboards.
- Light: illuminates the scene. Can optionally cast shadows.
- Terrain: renders heightmap terrain.
- CustomGeometry: renders runtime-defined unindexed geometry. The geometry data is not serialized or replicated over the network.
- DecalSet: renders decal geometry on top of objects.
- Zone: defines ambient light and fog settings for objects inside the zone volume.
- Text3D: text that is rendered into the 3D view.
Additionally there are 2D drawable components defined by the \ref Urho2D "Urho2D" sublibrary.
\section Rendering_Optimizations Optimizations
The following techniques will be used to reduce the amount of CPU and GPU work when rendering. By default they are all on:
- Software rasterized occlusion: after the octree has been queried for visible objects, the objects that are marked as occluders are rendered on the CPU to a small hierarchical-depth buffer, and it will be used to test the non-occluders for visibility. Use \ref Renderer::SetMaxOccluderTriangles "SetMaxOccluderTriangles()" and \ref Renderer::SetOccluderSizeThreshold "SetOccluderSizeThreshold()" to configure the occlusion rendering.
- Hardware instancing: rendering operations with the same geometry, material and light will be grouped together and performed as one draw call. Objects with a large amount of triangles will not be rendered as instanced, as that could actually be detrimental to performance. Use \ref Renderer::SetMaxInstanceTriangles "SetMaxInstanceTriangles()" to set the threshold. Note that even when instancing is not available, or the triangle count of objects is too large, they still benefit from the grouping, as render state only needs to be set once before rendering each group, reducing the CPU cost.
- %Light stencil masking: in forward rendering, before objects lit by a spot or point light are re-rendered additively, the light's bounding shape is rendered to the stencil buffer to ensure pixels outside the light range are not processed.
Note that many more optimization opportunities are possible at the content level, for example using geometry & material LOD, grouping many static objects into one object for less draw calls, minimizing the amount of subgeometries (submeshes) per object for less draw calls, using texture atlases to avoid render state changes, using compressed (and smaller) textures, and setting maximum draw distances for objects, lights and shadows.
\section Rendering_GPUResourceLoss Handling GPU resource loss
On Direct3D9 and Android OpenGL ES 2.0 it is possible to lose the rendering context (and therefore GPU resources) due to the application window being minimized to the background. Also, to work around possible GPU driver bugs the desktop OpenGL context will be voluntarily destroyed and recreated when changing screen mode or toggling between fullscreen and windowed. Therefore, on all graphics APIs one must be prepared for losing GPU resources.
Textures that have been loaded from a file, as well as vertex & index buffers that have shadowing enabled will restore their contents automatically, the rest have to be restored manually. On Direct3D9 non-dynamic (managed) textures and buffers will never be lost, as the runtime automatically backs them up to system memory.
See \ref GPUObject::IsDataLost "IsDataLost()" function in VertexBuffer, IndexBuffer, Texture2D, TextureCube and Texture3D classes for detecting data loss. Inbuilt classes such as Model, BillboardSet and Font already handle data loss for their internal GPU resources, so checking for it is only necessary for custom buffers and textures. Watch out especially for trying to render with an index buffer that has uninitialized data after a loss, as this can cause a crash inside the GPU driver due to referencing non-existent (garbage) vertices.
\section Rendering_Further Further details
See also \ref Materials "Materials", \ref Shaders "Shaders", \ref Lights "Lights and shadows", \ref RenderPaths "Render path", \ref SkeletalAnimation "Skeletal animation", \ref Particles "Particle systems", \ref Zones "Zones", and \ref AuxiliaryViews "Auxiliary views".
See \ref RenderingModes "Rendering modes" for detailed discussion on the forward, light pre-pass and deferred rendering modes.
See \ref APIDifferences "Differences between Direct3D9 and OpenGL" for what to watch out for when using the low-level rendering functionality directly.
\page RenderingModes Rendering modes
The default render paths supplied with Urho3D implement forward, light pre-pass and deferred rendering modes. Where they differ is how per-pixel lighting is calculated for opaque objects; transparent objects always use forward rendering. Note that on OpenGL ES 2.0 only forward rendering is available.
\section RenderingModes_Forward Forward rendering
Forward rendering begins with an ambient light pass for the objects; this also adds any per-vertex lights. Then, the objects are re-rendered for each per-pixel light affecting them (basic multipass rendering), up to the maximum per-pixel light count which is by default unlimited, but can be reduced with \ref Drawable::SetMaxLights "SetMaxLights()". The render operations are sorted by light, ie. render the effect of the first light on all affected objects first, then the second etc. If shadow maps are re-used (default on), a shadow casting light's shadow map will be updated immediately before rendering the lit objects. When shadow maps are not re-used, all shadow maps are updated first even before drawing the ambient pass.
Materials can also define an optimization pass, called "litbase", for forward rendering where the ambient light and the first per-pixel light are combined. This pass can not be used, however, if there are per-vertex lights affecting the object, or if the ambient light has a per-vertex gradient.
\section RenderingModes_Prepass Light pre-pass rendering
%Light pre-pass requires a minimum of two passes per object. First the normal, specular power, depth and lightmask (8 low bits only) of opaque objects are rendered to the following G-buffer:
- RT0: World-space normal and specular power (D3DFMT_A8R8G8B8)
- RT1: Linear depth (D3DFMT_R32F)
- DS: Hardware depth and lightmask (D3DFMT_D24S8)
After the G-buffer is complete, light volumes (spot and point lights) or fullscreen quads (directional lights) will be rendered to a light accumulation buffer to calculate the diffuse and specular light at each opaque pixel. Specular light is stored as intensity only. Stencil compare (AND operation) with the 8 low bits of the light's lightmask will be used for light culling. Similarly to forward rendering, shadow maps will be updated before each light as necessary.
Finally the opaque objects are re-rendered during the material pass, which combines ambient and vertex lighting with per-pixel lighting from the light accumulation buffer. After this rendering proceeds to the post-opaque and refract passes, transparent object rendering pass, and the post-alpha pass, just like forward rendering.
\section RenderingModes_Deferred Deferred rendering
Deferred rendering needs to render each opaque object only once to the G-buffer, but this rendering pass is much heavier than in light pre-pass rendering, as also ambient, emissive and diffuse albedo information is output at the same time. The G-buffer is the following:
- RT0: Final rendertarget with ambient, per-vertex and emissive color (D3DFMT_X8R8G8B8)
- RT1: Diffuse albedo and specular intensity (D3DFMT_A8R8G8B8)
- RT2: World-space normal and specular power (D3DFMT_A8R8G8B8)
- RT3: Linear depth (D3DFMT_R32F)
- DS: Hardware depth and lightmask (D3DFMT_D24S8)
After the G-buffer has been rendered, light volumes will be rendered into the final rendertarget to accumulate per-pixel lighting. As the material albedo is available, all lighting calculations are final and output both the diffuse and specular color at the same time. After light accumulation rendering proceeds to post-opaque, refract, transparent, and post-alpha passes, as in other rendering modes.
\section RenderingModes_Comparision Advantages and disadvantages
Whether using forward or deferred rendering modes is more advantageous depends on the scene and lighting complexity.
If the scene contains a large number of complex objects lit by multiple lights, forward rendering quickly increases the total draw call and vertex count due to re-rendering the objects for each light. However, light pre-pass and deferred rendering have a higher fixed cost due to the generation of the G-buffer. Also, in forward per-pixel lighting more calculations (such as light direction and shadow map coordinates) can be done at the vertex shader level, while in deferred all calculations need to happen per-pixel. This means that for a low light count, for example 1-2 per object, forward rendering will run faster based on the more efficient lighting calculations alone.
Forward rendering makes it possible to use hardware multisampling and different shading models in different materials if needed, while neither is possible in the deferred modes. Also, only forward rendering allows to calculate the material's diffuse and specular light response with the most accuracy. %Light pre-pass rendering needs to reconstruct light specular color from the accumulated diffuse light color, which is inaccurate in case of overlapping lights. Deferred rendering on the other hand can not use the material's full specular color, it only stores a monochromatic intensity based on the green component into the G-buffer.
%Light pre-pass rendering has a much more lightweight G-buffer pass, but it must render all opaque geometry twice. %Light accumulation in pre-pass mode is slightly faster than in deferred. Despite this, unless there is significant overdraw, in vertex-heavy scenes deferred rendering will likely be faster than light pre-pass.
Finally note that due to OpenGL framebuffer object limitations an extra framebuffer blit has to happen at the end in both light pre-pass and deferred rendering, which costs some performance. Also, because multiple rendertargets on OpenGL must have the same format, an R32F texture can not be used for linear depth, but instead 24-bit depth is manually encoded and decoded into RGB channels.
\page APIDifferences Differences between Direct3D9 and OpenGL
These differences need to be observed when using the low-level rendering functionality directly. The high-level rendering architecture, including the Renderer and UI subsystems and the Drawable subclasses already handle most of them transparently to the user.
- The post-projection depth range is (0,1) for Direct3D9 and (-1,1) for OpenGL. The Camera can be queried either for an API-specific or API-independent (Direct3D9 convention) projection matrix.
- To render with 1:1 texel-to-pixel mapping, on Direct3D9 UV coordinates have to be shifted a half-pixel to the right and down, or alternatively vertex positions can be shifted a half-pixel left and up.
- On Direct3D9 the depth-stencil surface can be equal or larger in size than the color rendertarget. On OpenGL the sizes must always match. Furthermore, OpenGL can not use the backbuffer depth-stencil surface when rendering to a texture. To overcome these limitations, Graphics will create correctly sized depth-stencil surfaces on demand whenever a texture is set as a color rendertarget, and a null depth-stencil is specified.
- On Direct3D9 the viewport will be reset to full size when the first color rendertarget is changed. On OpenGL this does not happen. To ensure correct operation on both APIs, always use this sequence: first set the rendertargets, then the depth-stencil surface and finally the viewport.
- On OpenGL modifying a texture will cause it to be momentarily set on the first texture unit. If another texture was set there, the assignment will be lost. Graphics performs a check to not assign textures redundantly, so it is safe and recommended to always set all needed textures before rendering.
- Modifying an index buffer on OpenGL will similarly cause the existing index buffer assignment to be lost. Therefore, always set the vertex and index buffers before rendering.
- %Shader resources are stored in different locations depending on the API: Bin/CoreData/Shaders/HLSL for Direct3D9, and Bin/CoreData/Shaders/GLSL for OpenGL.
- To ensure similar UV addressing for render-to-texture viewports on both APIs, on OpenGL texture viewports will be rendered upside down.
OpenGL ES 2.0 has further limitations:
- Of the DXT formats, only DXT1 compressed textures will be uploaded as compressed, and only if the EXT_texture_compression_dxt1 extension is present. Other DXT formats will be uploaded as uncompressed RGBA. ETC1 (Android) and PVRTC (iOS) compressed textures are supported through the .ktx and .pvr file formats.
- %Texture formats such as 16-bit and 32-bit floating point are not available. Corresponding integer 8-bit formats will be returned instead.
- %Light pre-pass and deferred rendering are not supported due to missing multiple rendertarget support, and limited rendertarget formats.
- Wireframe and point fill modes are not supported.
- Due to texture unit limit (usually 8), point light shadow maps are not supported.
- To reduce fillrate, the stencil buffer is not reserved and the stencil test is not available. As a consequence, the light stencil masking optimization is not used.
- For improved performance, shadow mapping quality is reduced: there is no smooth PCF filtering and directional lights do not support shadow cascades. Consider also using the low shadow quality (1 sample) to avoid dependent texture reads in the pixel shader, which have an especially high performance cost on iOS hardware.
- Custom clip planes are not currently supported.
- 3D textures are not currently supported.
\page Materials Materials
Material and Technique resources define how to render 3D scene geometry. On the disk, they are XML data. Default and example materials exist in the Bin/CoreData/Materials & Bin/Data/Materials subdirectories, and techniques exist in the Bin/CoreData/Techniques subdirectory.
A material defines the textures, shader parameters and culling mode to use, and refers to one or several techniques. A technique defines the actual rendering passes, the shaders to use in each, and all other rendering states such as depth test, depth write, and blending.
A material definition looks like this:
\code
<material>
<technique name="TechniqueName" quality="q" loddistance="d" />
<texture unit="diffuse|normal|specular|emissive|environment" name="TextureName" />
<texture ... />
<parameter name="name" value="x y z w" />
<parameter ... />
<cull value="cw|ccw|none" />
<shadowcull value="cw|ccw|none" />
<depthbias constant="x" slopescaled="y" />
</material>
\endcode
Several techniques can be defined for different quality levels and LOD distances. %Technique quality levels are specified from 0 (low) to 2 (high). When rendering, the highest available technique that does not exceed the Renderer's material quality setting will be chosen, see \ref Renderer::SetMaterialQuality "SetMaterialQuality()". It is also possible for a technique to require %Shader %Model 3, in this case it will be skipped on SM2 hardware.
The techniques for different LOD levels and quality settings must appear in a specific order:
- Most distant & highest quality
- ...
- Most distant & lowest quality
- Second most distant & highest quality
- ...
%Material shader parameters can be floats or vectors up to 4 components, or matrices.
Default culling mode is counterclockwise. The shadowcull element specifies the culling mode to use in the shadow pass. Note that material's depth bias settings do not apply in the shadow pass; during shadow rendering the light's depth bias is used instead.
\section Materials_Textures Material textures
Diffuse maps specify the surface color in the RGB channels. Optionally they can use the alpha channel for blending and alpha testing. They should preferably be compressed to DXT1 (no alpha or 1-bit alpha) or DXT5 (smooth alpha) format.
Normal maps encode the tangent-space surface normal for normal mapping. There are two options for storing normals, which require choosing the correct material technique, as the pixel shader is different in each case:
- Store as RGB. In this case use the DiffNormal techniques. This is the default used by AssetImporter, to ensure no conversion of normal textures needs to happen.
- Store as xGxR, ie. Y-component in the green channel, and X-component in the alpha. In this case use the DiffNormalPacked techniques: Z will be reconstructed in the pixel shader. This encoding lends itself well to DXT5 compression. To convert normal maps to this format, you can use AMD's The Compressonator utility, see http://developer.amd.com/Resources/archive/ArchivedTools/gpu/compressonator/Pages/default.aspx
Make sure the normal map is oriented correctly: an even surface should have the color value R 0.5 G 0.5 B 1.0.
Models using a normal-mapped material need to have tangent vectors in their vertex data; the easiest way to ensure this is to use the switch -t (generate tangents) when using either AssetImporter or OgreImporter to import models to Urho3D format. If there are no tangents, the light attenuation on the normal-mapped material will behave in a completely erratic fashion.
Specular maps encode the specular surface color as RGB. Note that deferred rendering is only able to use monochromatic specular intensity from the G channel, while forward and light pre-pass rendering use fully colored specular. DXT1 format should suit these textures well.
Textures can have an accompanying XML file which specifies load-time parameters, such as addressing, mipmapping, and number of mip levels to skip on each quality level:
\code
<texture>
<address coord="u|v|w" mode="wrap|mirror|clamp|border" />
<border color="r g b a" />
<filter mode="nearest|bilinear|trilinear|anisotropic|default" />
<mipmap enable="false|true" />
<quality low="x" medium="y" high="z" />
<srgb enable="false|true" />
</texture>
\endcode
The sRGB flag controls both whether the texture should be sampled with sRGB to linear conversion, and if used as a rendertarget, pixels should be converted back to sRGB when writing to it.
To control whether the backbuffer should use sRGB conversion on write, call \ref Graphics::SetSRGB "SetSRGB()" on the Graphics subsystem.
\section Materials_Techniques Techniques and passes
A technique definition looks like this:
\code
<technique vs="VertexShaderName" ps="PixelShaderName" vsdefines="DEFINE1 DEFINE2" psdefines="DEFINE3 DEFINE4" sm3="false|true" >
<pass name="base|litbase|light|alpha|litalpha|postopaque|refract|postalpha|prepass|material|deferred|depth|shadow" sm3="false|true"
vs="VertexShaderName" ps="PixelShaderName" vsdefines="DEFINE1 DEFINE2" psdefines="DEFINE3 DEFINE4"
lighting="unlit|pervertex|perpixel"
blend="replace|add|multiply|alpha|addalpha|premulalpha|invdestalpha|subtract|subtractalpha"
depthtest="always|equal|less|lessequal|greater|greaterequal"
depthwrite="true|false"
alphamask="true|false" />
<pass ... />
<pass ... />
</technique>
\endcode
The sm3 attribute in the technique root element allows the technique to specify it requires %Shader %Model 3 hardware. Omitting it is same as specifying false (works on both SM2 & 3.) The sm3 attribute can also be specified per pass, to disable for example a too complex lit base optimization pass on SM2.
Shaders are referred to by giving the name of a shader without path and file extension. For example "Basic" or "LitSolid". The engine will add the correct path and file extension (Shaders/HLSL/LitSolid.hlsl for Direct3D9, and Shaders/GLSL/LitSolid.glsl for OpenGL) automatically. The same shader source file contains both the vertex and pixel shader. In addition, compilation defines can be specified, which are passed to the shader compiler. For example the define "DIFFMAP" typically enables diffuse mapping in the pixel shader.
Shaders and their compilation defines can be specified on both the technique and pass level. If a pass does not override the default shaders specified on the technique level, it still can specify additional compilation defines to be used. However, if a pass overrides the shaders, then the technique-level defines are not used.
The technique definition does not need to enumerate shaders used for different geometry types (non-skinned, skinned, instanced, billboard) and different per-vertex and per-pixel light combinations. Instead the engine will add certain hardcoded compilation defines for these. See \ref Shaders "Shaders" for details.
The purposes of the different passes are:
- base: Renders ambient light, per-vertex lights and fog for an opaque object.
- litbase: Renders the first per-pixel light, ambient light and fog for an opaque object. This is an optional pass for optimization.
- light: Renders one per-pixel light's contribution additively for an opaque object.
- alpha: Renders ambient light, per-vertex lights and fog for a transparent object.
- litalpha: Renders one per-pixel light's contribution additively for a transparent object
- postopaque: Custom rendering pass after opaque geometry. Can be used to render the skybox.
- refract: Custom rendering pass after postopaque pass. Can sample the viewport texture from the environment texture unit to render refractive objects.
- postalpha: Custom rendering pass after transparent geometry.
- prepass: %Light pre-pass only - renders normals, specular power and depth to the G-buffer.
- material: %Light pre-pass only - renders opaque geometry final color by combining ambient light, per-vertex lights and per-pixel light accumulation.
- deferred: Deferred rendering only - renders ambient light and per-vertex lights to the output rendertarget, and diffuse albedo, normals, specular intensity + power and depth to the G-buffer.
- depth: Renders linear depth to a rendertarget for post-processing effects.
- shadow: Renders to a hardware shadow map (depth only) for shadow map generation.
More custom passes can be defined and referred to in the \ref RenderPaths "render path definition". For the built-in passes listed above, the lighting shader permutations to load (unlit, per-vertex or per-pixel) are recognized automatically, but for custom passes they need to be explicitly specified. The default is unlit.
The optional "litbase" pass reduces draw call count by combining ambient lighting with the first per-pixel light affecting an object. However, it has intentional limitations to not require too many shader permutations: there must be no vertex lights affecting the object, and the ambient lighting can not have a gradient. In case of excessive overdraw, it is possibly better not to define it, but instead allow the base pass (which is computationally very lightweight) to run first, initializing the Z buffer for later passes.
"Alphamask" is not an actual rendering state, but a hint which tells that the pixel shader will use discard based on alpha. Because this may interfere with the early-Z culling, materials without the alpha masking hint will be drawn first.
The refract pass requires pingponging the scene rendertarget to a texture, but this will not be performed if there is no refractive geometry to render, so there is no unnecessary cost to it.
\page Shaders Shaders
Urho3D uses an ubershader-like approach: permutations of each shader will be built with different compilation defines, to produce eg. static or skinned, deferred or forward or shadowed/unshadowed rendering.
The building of these permutations happens on demand: technique and renderpath definition files both refer to shaders and the compilation defines to use with them. In addition the engine will add inbuilt defines related to geometry type and lighting. It is not generally possible to enumerate beforehand all the possible permutations that can be built out of a single shader.
On Direct3D9 compiled shader bytecode is saved to disk in a "Cache" subdirectory next to the shader source code, so that the possibly time-consuming compile can be skipped on the next time the shader permutation is needed. On OpenGL such mechanism is not available.
\section Shaders_InbuiltDefines Inbuilt compilation defines
When rendering scene objects, the engine expects certain shader permutations to exist for different geometry types and lighting conditions. These correspond to the following compilation defines:
Vertex shader: