aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/examples/26.OcclusionQuery/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/examples/26.OcclusionQuery/main.cpp426
1 files changed, 213 insertions, 213 deletions
diff --git a/libraries/irrlicht-1.8/examples/26.OcclusionQuery/main.cpp b/libraries/irrlicht-1.8/examples/26.OcclusionQuery/main.cpp
index 17f64b2..02a5440 100644
--- a/libraries/irrlicht-1.8/examples/26.OcclusionQuery/main.cpp
+++ b/libraries/irrlicht-1.8/examples/26.OcclusionQuery/main.cpp
@@ -1,213 +1,213 @@
1/** Example 026 OcclusionQuery 1/** Example 026 OcclusionQuery
2 2
3This Tutorial shows how to speed up rendering by use of the 3This Tutorial shows how to speed up rendering by use of the
4OcclusionQuery feature. The usual rendering tries to avoid rendering of 4OcclusionQuery feature. The usual rendering tries to avoid rendering of
5scene nodes by culling those nodes which are outside the visible area, the 5scene nodes by culling those nodes which are outside the visible area, the
6view frustum. However, this technique does not cope with occluded objects 6view frustum. However, this technique does not cope with occluded objects
7which are still in the line of sight, but occluded by some larger object 7which are still in the line of sight, but occluded by some larger object
8between the object and the eye (camera). Occlusion queries check exactly that. 8between the object and the eye (camera). Occlusion queries check exactly that.
9The queries basically measure the number of pixels that a previous render 9The queries basically measure the number of pixels that a previous render
10left on the screen. 10left on the screen.
11Since those pixels cannot be recognized at the end of a rendering anymore, 11Since those pixels cannot be recognized at the end of a rendering anymore,
12the pixel count is measured directly when rendering. Thus, one needs to render 12the pixel count is measured directly when rendering. Thus, one needs to render
13the occluder (the object in front) first. This object needs to write to the 13the occluder (the object in front) first. This object needs to write to the
14z-buffer in order to become a real occluder. Then the node is rendered and in 14z-buffer in order to become a real occluder. Then the node is rendered and in
15case a z-pass happens, i.e. the pixel is written to the framebuffer, the pixel 15case a z-pass happens, i.e. the pixel is written to the framebuffer, the pixel
16is counted in the query. 16is counted in the query.
17The result of a query is the number of pixels which got through. One can, based 17The result of a query is the number of pixels which got through. One can, based
18on this number, judge if the scene node is visible enough to be rendered, or if 18on this number, judge if the scene node is visible enough to be rendered, or if
19the node should be removed in the next round. Also note that the number of 19the node should be removed in the next round. Also note that the number of
20pixels is a safe over approximation in general. The pixels might be overdrawn 20pixels is a safe over approximation in general. The pixels might be overdrawn
21later on, and the GPU tries to avoid inaccuracies which could lead to false 21later on, and the GPU tries to avoid inaccuracies which could lead to false
22negatives in the queries. 22negatives in the queries.
23 23
24As you might have recognized already, we had to render the node to get the 24As you might have recognized already, we had to render the node to get the
25numbers. So where's the benefit, you might say. There are several ways where 25numbers. So where's the benefit, you might say. There are several ways where
26occlusion queries can help. It is often a good idea to just render the bbox 26occlusion queries can help. It is often a good idea to just render the bbox
27of the node instead of the actual mesh. This is really fast and is a safe over 27of the node instead of the actual mesh. This is really fast and is a safe over
28approximation. If you need a more exact render with the actual geometry, it's 28approximation. If you need a more exact render with the actual geometry, it's
29a good idea to render with just basic solid material. Avoid complex shaders 29a good idea to render with just basic solid material. Avoid complex shaders
30and state changes through textures. There's no need while just doing the 30and state changes through textures. There's no need while just doing the
31occlusion query. At least if the render is not used for the actual scene. This 31occlusion query. At least if the render is not used for the actual scene. This
32is the third way to optimize occlusion queries. Just check the queries every 32is the third way to optimize occlusion queries. Just check the queries every
335th or 10th frame, or even less frequent. This depends on the movement speed 335th or 10th frame, or even less frequent. This depends on the movement speed
34of the objects and camera. 34of the objects and camera.
35*/ 35*/
36 36
37#ifdef _MSC_VER 37#ifdef _MSC_VER
38// We'll also define this to stop MSVC complaining about sprintf(). 38// We'll also define this to stop MSVC complaining about sprintf().
39#define _CRT_SECURE_NO_WARNINGS 39#define _CRT_SECURE_NO_WARNINGS
40#pragma comment(lib, "Irrlicht.lib") 40#pragma comment(lib, "Irrlicht.lib")
41#endif 41#endif
42 42
43#include <irrlicht.h> 43#include <irrlicht.h>
44#include "driverChoice.h" 44#include "driverChoice.h"
45 45
46using namespace irr; 46using namespace irr;
47 47
48/* 48/*
49We need keyboard input events to switch some parameters 49We need keyboard input events to switch some parameters
50*/ 50*/
51class MyEventReceiver : public IEventReceiver 51class MyEventReceiver : public IEventReceiver
52{ 52{
53public: 53public:
54 // This is the one method that we have to implement 54 // This is the one method that we have to implement
55 virtual bool OnEvent(const SEvent& event) 55 virtual bool OnEvent(const SEvent& event)
56 { 56 {
57 // Remember whether each key is down or up 57 // Remember whether each key is down or up
58 if (event.EventType == irr::EET_KEY_INPUT_EVENT) 58 if (event.EventType == irr::EET_KEY_INPUT_EVENT)
59 KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; 59 KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
60 60
61 return false; 61 return false;
62 } 62 }
63 63
64 // This is used to check whether a key is being held down 64 // This is used to check whether a key is being held down
65 virtual bool IsKeyDown(EKEY_CODE keyCode) const 65 virtual bool IsKeyDown(EKEY_CODE keyCode) const
66 { 66 {
67 return KeyIsDown[keyCode]; 67 return KeyIsDown[keyCode];
68 } 68 }
69 69
70 MyEventReceiver() 70 MyEventReceiver()
71 { 71 {
72 for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i) 72 for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
73 KeyIsDown[i] = false; 73 KeyIsDown[i] = false;
74 } 74 }
75 75
76private: 76private:
77 // We use this array to store the current state of each key 77 // We use this array to store the current state of each key
78 bool KeyIsDown[KEY_KEY_CODES_COUNT]; 78 bool KeyIsDown[KEY_KEY_CODES_COUNT];
79}; 79};
80 80
81 81
82/* 82/*
83We create an irr::IrrlichtDevice and the scene nodes. One occluder, one 83We create an irr::IrrlichtDevice and the scene nodes. One occluder, one
84occluded. The latter is a complex sphere, which has many triangles. 84occluded. The latter is a complex sphere, which has many triangles.
85*/ 85*/
86int main() 86int main()
87{ 87{
88 // ask user for driver 88 // ask user for driver
89 video::E_DRIVER_TYPE driverType=driverChoiceConsole(); 89 video::E_DRIVER_TYPE driverType=driverChoiceConsole();
90 if (driverType==video::EDT_COUNT) 90 if (driverType==video::EDT_COUNT)
91 return 1; 91 return 1;
92 92
93 // create device 93 // create device
94 MyEventReceiver receiver; 94 MyEventReceiver receiver;
95 95
96 IrrlichtDevice* device = createDevice(driverType, 96 IrrlichtDevice* device = createDevice(driverType,
97 core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver); 97 core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver);
98 98
99 if (device == 0) 99 if (device == 0)
100 return 1; // could not create selected driver. 100 return 1; // could not create selected driver.
101 101
102 video::IVideoDriver* driver = device->getVideoDriver(); 102 video::IVideoDriver* driver = device->getVideoDriver();
103 scene::ISceneManager* smgr = device->getSceneManager(); 103 scene::ISceneManager* smgr = device->getSceneManager();
104 104
105 smgr->getGUIEnvironment()->addStaticText(L"Press Space to hide occluder.", core::recti(10,10, 200,50)); 105 smgr->getGUIEnvironment()->addStaticText(L"Press Space to hide occluder.", core::recti(10,10, 200,50));
106 106
107 /* 107 /*
108 Create the node to be occluded. We create a sphere node with high poly count. 108 Create the node to be occluded. We create a sphere node with high poly count.
109 */ 109 */
110 scene::ISceneNode * node = smgr->addSphereSceneNode(10, 64); 110 scene::ISceneNode * node = smgr->addSphereSceneNode(10, 64);
111 if (node) 111 if (node)
112 { 112 {
113 node->setPosition(core::vector3df(0,0,60)); 113 node->setPosition(core::vector3df(0,0,60));
114 node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp")); 114 node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
115 node->setMaterialFlag(video::EMF_LIGHTING, false); 115 node->setMaterialFlag(video::EMF_LIGHTING, false);
116 } 116 }
117 117
118 /* 118 /*
119 Now we create another node, the occluder. It's a simple plane. 119 Now we create another node, the occluder. It's a simple plane.
120 */ 120 */
121 scene::ISceneNode* plane = smgr->addMeshSceneNode(smgr->addHillPlaneMesh( 121 scene::ISceneNode* plane = smgr->addMeshSceneNode(smgr->addHillPlaneMesh(
122 "plane", core::dimension2df(10,10), core::dimension2du(2,2)), 0, -1, 122 "plane", core::dimension2df(10,10), core::dimension2du(2,2)), 0, -1,
123 core::vector3df(0,0,20), core::vector3df(270,0,0)); 123 core::vector3df(0,0,20), core::vector3df(270,0,0));
124 124
125 if (plane) 125 if (plane)
126 { 126 {
127 plane->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg")); 127 plane->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
128 plane->setMaterialFlag(video::EMF_LIGHTING, false); 128 plane->setMaterialFlag(video::EMF_LIGHTING, false);
129 plane->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true); 129 plane->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true);
130 } 130 }
131 131
132 /* 132 /*
133 Here we create the occlusion query. Because we don't have a plain mesh scene node 133 Here we create the occlusion query. Because we don't have a plain mesh scene node
134 (ESNT_MESH or ESNT_ANIMATED_MESH), we pass the base geometry as well. Instead, 134 (ESNT_MESH or ESNT_ANIMATED_MESH), we pass the base geometry as well. Instead,
135 we could also pass a simpler mesh or the bounding box. But we will use a time 135 we could also pass a simpler mesh or the bounding box. But we will use a time
136 based method, where the occlusion query renders to the frame buffer and in case 136 based method, where the occlusion query renders to the frame buffer and in case
137 of success (occlusion), the mesh is not drawn for several frames. 137 of success (occlusion), the mesh is not drawn for several frames.
138 */ 138 */
139 driver->addOcclusionQuery(node, ((scene::IMeshSceneNode*)node)->getMesh()); 139 driver->addOcclusionQuery(node, ((scene::IMeshSceneNode*)node)->getMesh());
140 140
141 /* 141 /*
142 We have done everything, just a camera and draw it. We also write the 142 We have done everything, just a camera and draw it. We also write the
143 current frames per second and the name of the driver to the caption of the 143 current frames per second and the name of the driver to the caption of the
144 window to examine the render speedup. 144 window to examine the render speedup.
145 We also store the time for measuring the time since the last occlusion query ran 145 We also store the time for measuring the time since the last occlusion query ran
146 and store whether the node should be visible in the next frames. 146 and store whether the node should be visible in the next frames.
147 */ 147 */
148 smgr->addCameraSceneNode(); 148 smgr->addCameraSceneNode();
149 int lastFPS = -1; 149 int lastFPS = -1;
150 u32 timeNow = device->getTimer()->getTime(); 150 u32 timeNow = device->getTimer()->getTime();
151 bool nodeVisible=true; 151 bool nodeVisible=true;
152 152
153 while(device->run()) 153 while(device->run())
154 { 154 {
155 plane->setVisible(!receiver.IsKeyDown(irr::KEY_SPACE)); 155 plane->setVisible(!receiver.IsKeyDown(irr::KEY_SPACE));
156 156
157 driver->beginScene(true, true, video::SColor(255,113,113,133)); 157 driver->beginScene(true, true, video::SColor(255,113,113,133));
158 /* 158 /*
159 First, we draw the scene, possibly without the occluded element. This is necessary 159 First, we draw the scene, possibly without the occluded element. This is necessary
160 because we need the occluder to be drawn first. You can also use several scene 160 because we need the occluder to be drawn first. You can also use several scene
161 managers to collect a number of possible occluders in a separately rendered 161 managers to collect a number of possible occluders in a separately rendered
162 scene. 162 scene.
163 */ 163 */
164 node->setVisible(nodeVisible); 164 node->setVisible(nodeVisible);
165 smgr->drawAll(); 165 smgr->drawAll();
166 smgr->getGUIEnvironment()->drawAll(); 166 smgr->getGUIEnvironment()->drawAll();
167 167
168 /* 168 /*
169 Once in a while, here every 100 ms, we check the visibility. We run the queries, 169 Once in a while, here every 100 ms, we check the visibility. We run the queries,
170 update the pixel value, and query the result. Since we already rendered the node 170 update the pixel value, and query the result. Since we already rendered the node
171 we render the query invisible. The update is made blocking, as we need the result 171 we render the query invisible. The update is made blocking, as we need the result
172 immediately. If you don't need the result immediately, e.g. because you have other 172 immediately. If you don't need the result immediately, e.g. because you have other
173 things to render, you can call the update non-blocking. This gives the GPU more 173 things to render, you can call the update non-blocking. This gives the GPU more
174 time to pass back the results without flushing the render pipeline. 174 time to pass back the results without flushing the render pipeline.
175 If the update was called non-blocking, the result from getOcclusionQueryResult is 175 If the update was called non-blocking, the result from getOcclusionQueryResult is
176 either the previous value, or 0xffffffff if no value has been generated at all, yet. 176 either the previous value, or 0xffffffff if no value has been generated at all, yet.
177 The result is taken immediately as visibility flag for the node. 177 The result is taken immediately as visibility flag for the node.
178 */ 178 */
179 if (device->getTimer()->getTime()-timeNow>100) 179 if (device->getTimer()->getTime()-timeNow>100)
180 { 180 {
181 driver->runAllOcclusionQueries(false); 181 driver->runAllOcclusionQueries(false);
182 driver->updateAllOcclusionQueries(); 182 driver->updateAllOcclusionQueries();
183 nodeVisible=driver->getOcclusionQueryResult(node)>0; 183 nodeVisible=driver->getOcclusionQueryResult(node)>0;
184 timeNow=device->getTimer()->getTime(); 184 timeNow=device->getTimer()->getTime();
185 } 185 }
186 186
187 driver->endScene(); 187 driver->endScene();
188 188
189 int fps = driver->getFPS(); 189 int fps = driver->getFPS();
190 190
191 if (lastFPS != fps) 191 if (lastFPS != fps)
192 { 192 {
193 core::stringw tmp(L"OcclusionQuery Example ["); 193 core::stringw tmp(L"OcclusionQuery Example [");
194 tmp += driver->getName(); 194 tmp += driver->getName();
195 tmp += L"] fps: "; 195 tmp += L"] fps: ";
196 tmp += fps; 196 tmp += fps;
197 197
198 device->setWindowCaption(tmp.c_str()); 198 device->setWindowCaption(tmp.c_str());
199 lastFPS = fps; 199 lastFPS = fps;
200 } 200 }
201 } 201 }
202 202
203 /* 203 /*
204 In the end, delete the Irrlicht device. 204 In the end, delete the Irrlicht device.
205 */ 205 */
206 device->drop(); 206 device->drop();
207 207
208 return 0; 208 return 0;
209} 209}
210 210
211/* 211/*
212That's it. Compile and play around with the program. 212That's it. Compile and play around with the program.
213**/ 213**/