diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/examples/11.PerPixelLighting/main.cpp | 974 |
1 files changed, 487 insertions, 487 deletions
diff --git a/libraries/irrlicht-1.8/examples/11.PerPixelLighting/main.cpp b/libraries/irrlicht-1.8/examples/11.PerPixelLighting/main.cpp index 227aa97..a6e95ba 100644 --- a/libraries/irrlicht-1.8/examples/11.PerPixelLighting/main.cpp +++ b/libraries/irrlicht-1.8/examples/11.PerPixelLighting/main.cpp | |||
@@ -1,487 +1,487 @@ | |||
1 | /** Example 011 Per-Pixel Lighting | 1 | /** Example 011 Per-Pixel Lighting |
2 | 2 | ||
3 | This tutorial shows how to use one of the built in more complex materials in | 3 | This tutorial shows how to use one of the built in more complex materials in |
4 | irrlicht: Per pixel lighted surfaces using normal maps and parallax mapping. It | 4 | irrlicht: Per pixel lighted surfaces using normal maps and parallax mapping. It |
5 | will also show how to use fog and moving particle systems. And don't panic: You | 5 | will also show how to use fog and moving particle systems. And don't panic: You |
6 | do not need any experience with shaders to use these materials in Irrlicht. | 6 | do not need any experience with shaders to use these materials in Irrlicht. |
7 | 7 | ||
8 | At first, we need to include all headers and do the stuff we always do, like in | 8 | At first, we need to include all headers and do the stuff we always do, like in |
9 | nearly all other tutorials. | 9 | nearly all other tutorials. |
10 | */ | 10 | */ |
11 | #include <irrlicht.h> | 11 | #include <irrlicht.h> |
12 | #include "driverChoice.h" | 12 | #include "driverChoice.h" |
13 | 13 | ||
14 | using namespace irr; | 14 | using namespace irr; |
15 | 15 | ||
16 | #ifdef _MSC_VER | 16 | #ifdef _MSC_VER |
17 | #pragma comment(lib, "Irrlicht.lib") | 17 | #pragma comment(lib, "Irrlicht.lib") |
18 | #endif | 18 | #endif |
19 | 19 | ||
20 | /* | 20 | /* |
21 | For this example, we need an event receiver, to make it possible for the user | 21 | For this example, we need an event receiver, to make it possible for the user |
22 | to switch between the three available material types. In addition, the event | 22 | to switch between the three available material types. In addition, the event |
23 | receiver will create some small GUI window which displays what material is | 23 | receiver will create some small GUI window which displays what material is |
24 | currently being used. There is nothing special done in this class, so maybe you | 24 | currently being used. There is nothing special done in this class, so maybe you |
25 | want to skip reading it. | 25 | want to skip reading it. |
26 | */ | 26 | */ |
27 | class MyEventReceiver : public IEventReceiver | 27 | class MyEventReceiver : public IEventReceiver |
28 | { | 28 | { |
29 | public: | 29 | public: |
30 | 30 | ||
31 | MyEventReceiver(scene::ISceneNode* room,scene::ISceneNode* earth, | 31 | MyEventReceiver(scene::ISceneNode* room,scene::ISceneNode* earth, |
32 | gui::IGUIEnvironment* env, video::IVideoDriver* driver) | 32 | gui::IGUIEnvironment* env, video::IVideoDriver* driver) |
33 | { | 33 | { |
34 | // store pointer to room so we can change its drawing mode | 34 | // store pointer to room so we can change its drawing mode |
35 | Room = room; | 35 | Room = room; |
36 | Earth = earth; | 36 | Earth = earth; |
37 | Driver = driver; | 37 | Driver = driver; |
38 | 38 | ||
39 | // set a nicer font | 39 | // set a nicer font |
40 | gui::IGUISkin* skin = env->getSkin(); | 40 | gui::IGUISkin* skin = env->getSkin(); |
41 | gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); | 41 | gui::IGUIFont* font = env->getFont("../../media/fonthaettenschweiler.bmp"); |
42 | if (font) | 42 | if (font) |
43 | skin->setFont(font); | 43 | skin->setFont(font); |
44 | 44 | ||
45 | // add window and listbox | 45 | // add window and listbox |
46 | gui::IGUIWindow* window = env->addWindow( | 46 | gui::IGUIWindow* window = env->addWindow( |
47 | core::rect<s32>(460,375,630,470), false, L"Use 'E' + 'R' to change"); | 47 | core::rect<s32>(460,375,630,470), false, L"Use 'E' + 'R' to change"); |
48 | 48 | ||
49 | ListBox = env->addListBox( | 49 | ListBox = env->addListBox( |
50 | core::rect<s32>(2,22,165,88), window); | 50 | core::rect<s32>(2,22,165,88), window); |
51 | 51 | ||
52 | ListBox->addItem(L"Diffuse"); | 52 | ListBox->addItem(L"Diffuse"); |
53 | ListBox->addItem(L"Bump mapping"); | 53 | ListBox->addItem(L"Bump mapping"); |
54 | ListBox->addItem(L"Parallax mapping"); | 54 | ListBox->addItem(L"Parallax mapping"); |
55 | ListBox->setSelected(1); | 55 | ListBox->setSelected(1); |
56 | 56 | ||
57 | // create problem text | 57 | // create problem text |
58 | ProblemText = env->addStaticText( | 58 | ProblemText = env->addStaticText( |
59 | L"Your hardware or this renderer is not able to use the "\ | 59 | L"Your hardware or this renderer is not able to use the "\ |
60 | L"needed shaders for this material. Using fall back materials.", | 60 | L"needed shaders for this material. Using fall back materials.", |
61 | core::rect<s32>(150,20,470,80)); | 61 | core::rect<s32>(150,20,470,80)); |
62 | 62 | ||
63 | ProblemText->setOverrideColor(video::SColor(100,255,255,255)); | 63 | ProblemText->setOverrideColor(video::SColor(100,255,255,255)); |
64 | 64 | ||
65 | // set start material (prefer parallax mapping if available) | 65 | // set start material (prefer parallax mapping if available) |
66 | video::IMaterialRenderer* renderer = | 66 | video::IMaterialRenderer* renderer = |
67 | Driver->getMaterialRenderer(video::EMT_PARALLAX_MAP_SOLID); | 67 | Driver->getMaterialRenderer(video::EMT_PARALLAX_MAP_SOLID); |
68 | if (renderer && renderer->getRenderCapability() == 0) | 68 | if (renderer && renderer->getRenderCapability() == 0) |
69 | ListBox->setSelected(2); | 69 | ListBox->setSelected(2); |
70 | 70 | ||
71 | // set the material which is selected in the listbox | 71 | // set the material which is selected in the listbox |
72 | setMaterial(); | 72 | setMaterial(); |
73 | } | 73 | } |
74 | 74 | ||
75 | bool OnEvent(const SEvent& event) | 75 | bool OnEvent(const SEvent& event) |
76 | { | 76 | { |
77 | // check if user presses the key 'E' or 'R' | 77 | // check if user presses the key 'E' or 'R' |
78 | if (event.EventType == irr::EET_KEY_INPUT_EVENT && | 78 | if (event.EventType == irr::EET_KEY_INPUT_EVENT && |
79 | !event.KeyInput.PressedDown && Room && ListBox) | 79 | !event.KeyInput.PressedDown && Room && ListBox) |
80 | { | 80 | { |
81 | // change selected item in listbox | 81 | // change selected item in listbox |
82 | 82 | ||
83 | int sel = ListBox->getSelected(); | 83 | int sel = ListBox->getSelected(); |
84 | if (event.KeyInput.Key == irr::KEY_KEY_R) | 84 | if (event.KeyInput.Key == irr::KEY_KEY_R) |
85 | ++sel; | 85 | ++sel; |
86 | else | 86 | else |
87 | if (event.KeyInput.Key == irr::KEY_KEY_E) | 87 | if (event.KeyInput.Key == irr::KEY_KEY_E) |
88 | --sel; | 88 | --sel; |
89 | else | 89 | else |
90 | return false; | 90 | return false; |
91 | 91 | ||
92 | if (sel > 2) sel = 0; | 92 | if (sel > 2) sel = 0; |
93 | if (sel < 0) sel = 2; | 93 | if (sel < 0) sel = 2; |
94 | ListBox->setSelected(sel); | 94 | ListBox->setSelected(sel); |
95 | 95 | ||
96 | // set the material which is selected in the listbox | 96 | // set the material which is selected in the listbox |
97 | setMaterial(); | 97 | setMaterial(); |
98 | } | 98 | } |
99 | 99 | ||
100 | return false; | 100 | return false; |
101 | } | 101 | } |
102 | 102 | ||
103 | private: | 103 | private: |
104 | 104 | ||
105 | // sets the material of the room mesh the the one set in the | 105 | // sets the material of the room mesh the the one set in the |
106 | // list box. | 106 | // list box. |
107 | void setMaterial() | 107 | void setMaterial() |
108 | { | 108 | { |
109 | video::E_MATERIAL_TYPE type = video::EMT_SOLID; | 109 | video::E_MATERIAL_TYPE type = video::EMT_SOLID; |
110 | 110 | ||
111 | // change material setting | 111 | // change material setting |
112 | switch(ListBox->getSelected()) | 112 | switch(ListBox->getSelected()) |
113 | { | 113 | { |
114 | case 0: type = video::EMT_SOLID; | 114 | case 0: type = video::EMT_SOLID; |
115 | break; | 115 | break; |
116 | case 1: type = video::EMT_NORMAL_MAP_SOLID; | 116 | case 1: type = video::EMT_NORMAL_MAP_SOLID; |
117 | break; | 117 | break; |
118 | case 2: type = video::EMT_PARALLAX_MAP_SOLID; | 118 | case 2: type = video::EMT_PARALLAX_MAP_SOLID; |
119 | break; | 119 | break; |
120 | } | 120 | } |
121 | 121 | ||
122 | Room->setMaterialType(type); | 122 | Room->setMaterialType(type); |
123 | 123 | ||
124 | // change material setting | 124 | // change material setting |
125 | switch(ListBox->getSelected()) | 125 | switch(ListBox->getSelected()) |
126 | { | 126 | { |
127 | case 0: type = video::EMT_TRANSPARENT_VERTEX_ALPHA; | 127 | case 0: type = video::EMT_TRANSPARENT_VERTEX_ALPHA; |
128 | break; | 128 | break; |
129 | case 1: type = video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA; | 129 | case 1: type = video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA; |
130 | break; | 130 | break; |
131 | case 2: type = video::EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA; | 131 | case 2: type = video::EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA; |
132 | break; | 132 | break; |
133 | } | 133 | } |
134 | 134 | ||
135 | Earth->setMaterialType(type); | 135 | Earth->setMaterialType(type); |
136 | 136 | ||
137 | /* | 137 | /* |
138 | We need to add a warning if the materials will not be able to | 138 | We need to add a warning if the materials will not be able to |
139 | be displayed 100% correctly. This is no problem, they will be | 139 | be displayed 100% correctly. This is no problem, they will be |
140 | rendered using fall back materials, but at least the user | 140 | rendered using fall back materials, but at least the user |
141 | should know that it would look better on better hardware. We | 141 | should know that it would look better on better hardware. We |
142 | simply check if the material renderer is able to draw at full | 142 | simply check if the material renderer is able to draw at full |
143 | quality on the current hardware. The | 143 | quality on the current hardware. The |
144 | IMaterialRenderer::getRenderCapability() returns 0 if this is | 144 | IMaterialRenderer::getRenderCapability() returns 0 if this is |
145 | the case. | 145 | the case. |
146 | */ | 146 | */ |
147 | video::IMaterialRenderer* renderer = Driver->getMaterialRenderer(type); | 147 | video::IMaterialRenderer* renderer = Driver->getMaterialRenderer(type); |
148 | 148 | ||
149 | // display some problem text when problem | 149 | // display some problem text when problem |
150 | if (!renderer || renderer->getRenderCapability() != 0) | 150 | if (!renderer || renderer->getRenderCapability() != 0) |
151 | ProblemText->setVisible(true); | 151 | ProblemText->setVisible(true); |
152 | else | 152 | else |
153 | ProblemText->setVisible(false); | 153 | ProblemText->setVisible(false); |
154 | } | 154 | } |
155 | 155 | ||
156 | private: | 156 | private: |
157 | 157 | ||
158 | gui::IGUIStaticText* ProblemText; | 158 | gui::IGUIStaticText* ProblemText; |
159 | gui::IGUIListBox* ListBox; | 159 | gui::IGUIListBox* ListBox; |
160 | 160 | ||
161 | scene::ISceneNode* Room; | 161 | scene::ISceneNode* Room; |
162 | scene::ISceneNode* Earth; | 162 | scene::ISceneNode* Earth; |
163 | video::IVideoDriver* Driver; | 163 | video::IVideoDriver* Driver; |
164 | }; | 164 | }; |
165 | 165 | ||
166 | 166 | ||
167 | /* | 167 | /* |
168 | Now for the real fun. We create an Irrlicht Device and start to setup the scene. | 168 | Now for the real fun. We create an Irrlicht Device and start to setup the scene. |
169 | */ | 169 | */ |
170 | int main() | 170 | int main() |
171 | { | 171 | { |
172 | // ask user for driver | 172 | // ask user for driver |
173 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); | 173 | video::E_DRIVER_TYPE driverType=driverChoiceConsole(); |
174 | if (driverType==video::EDT_COUNT) | 174 | if (driverType==video::EDT_COUNT) |
175 | return 1; | 175 | return 1; |
176 | 176 | ||
177 | // create device | 177 | // create device |
178 | 178 | ||
179 | IrrlichtDevice* device = createDevice(driverType, | 179 | IrrlichtDevice* device = createDevice(driverType, |
180 | core::dimension2d<u32>(640, 480)); | 180 | core::dimension2d<u32>(640, 480)); |
181 | 181 | ||
182 | if (device == 0) | 182 | if (device == 0) |
183 | return 1; // could not create selected driver. | 183 | return 1; // could not create selected driver. |
184 | 184 | ||
185 | /* | 185 | /* |
186 | Before we start with the interesting stuff, we do some simple things: | 186 | Before we start with the interesting stuff, we do some simple things: |
187 | Store pointers to the most important parts of the engine (video driver, | 187 | Store pointers to the most important parts of the engine (video driver, |
188 | scene manager, gui environment) to safe us from typing too much, add an | 188 | scene manager, gui environment) to safe us from typing too much, add an |
189 | irrlicht engine logo to the window and a user controlled first person | 189 | irrlicht engine logo to the window and a user controlled first person |
190 | shooter style camera. Also, we let the engine know that it should store | 190 | shooter style camera. Also, we let the engine know that it should store |
191 | all textures in 32 bit. This necessary because for parallax mapping, we | 191 | all textures in 32 bit. This necessary because for parallax mapping, we |
192 | need 32 bit textures. | 192 | need 32 bit textures. |
193 | */ | 193 | */ |
194 | 194 | ||
195 | video::IVideoDriver* driver = device->getVideoDriver(); | 195 | video::IVideoDriver* driver = device->getVideoDriver(); |
196 | scene::ISceneManager* smgr = device->getSceneManager(); | 196 | scene::ISceneManager* smgr = device->getSceneManager(); |
197 | gui::IGUIEnvironment* env = device->getGUIEnvironment(); | 197 | gui::IGUIEnvironment* env = device->getGUIEnvironment(); |
198 | 198 | ||
199 | driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); | 199 | driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true); |
200 | 200 | ||
201 | // add irrlicht logo | 201 | // add irrlicht logo |
202 | env->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), | 202 | env->addImage(driver->getTexture("../../media/irrlichtlogo3.png"), |
203 | core::position2d<s32>(10,10)); | 203 | core::position2d<s32>(10,10)); |
204 | 204 | ||
205 | // add camera | 205 | // add camera |
206 | scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); | 206 | scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); |
207 | camera->setPosition(core::vector3df(-200,200,-200)); | 207 | camera->setPosition(core::vector3df(-200,200,-200)); |
208 | 208 | ||
209 | // disable mouse cursor | 209 | // disable mouse cursor |
210 | device->getCursorControl()->setVisible(false); | 210 | device->getCursorControl()->setVisible(false); |
211 | 211 | ||
212 | /* | 212 | /* |
213 | Because we want the whole scene to look a little bit scarier, we add | 213 | Because we want the whole scene to look a little bit scarier, we add |
214 | some fog to it. This is done by a call to IVideoDriver::setFog(). There | 214 | some fog to it. This is done by a call to IVideoDriver::setFog(). There |
215 | you can set various fog settings. In this example, we use pixel fog, | 215 | you can set various fog settings. In this example, we use pixel fog, |
216 | because it will work well with the materials we'll use in this example. | 216 | because it will work well with the materials we'll use in this example. |
217 | Please note that you will have to set the material flag EMF_FOG_ENABLE | 217 | Please note that you will have to set the material flag EMF_FOG_ENABLE |
218 | to 'true' in every scene node which should be affected by this fog. | 218 | to 'true' in every scene node which should be affected by this fog. |
219 | */ | 219 | */ |
220 | driver->setFog(video::SColor(0,138,125,81), video::EFT_FOG_LINEAR, 250, 1000, .003f, true, false); | 220 | driver->setFog(video::SColor(0,138,125,81), video::EFT_FOG_LINEAR, 250, 1000, .003f, true, false); |
221 | 221 | ||
222 | /* | 222 | /* |
223 | To be able to display something interesting, we load a mesh from a .3ds | 223 | To be able to display something interesting, we load a mesh from a .3ds |
224 | file which is a room I modeled with anim8or. It is the same room as | 224 | file which is a room I modeled with anim8or. It is the same room as |
225 | from the specialFX example. Maybe you remember from that tutorial, I am | 225 | from the specialFX example. Maybe you remember from that tutorial, I am |
226 | no good modeler at all and so I totally messed up the texture mapping | 226 | no good modeler at all and so I totally messed up the texture mapping |
227 | in this model, but we can simply repair it with the | 227 | in this model, but we can simply repair it with the |
228 | IMeshManipulator::makePlanarTextureMapping() method. | 228 | IMeshManipulator::makePlanarTextureMapping() method. |
229 | */ | 229 | */ |
230 | 230 | ||
231 | scene::IAnimatedMesh* roomMesh = smgr->getMesh("../../media/room.3ds"); | 231 | scene::IAnimatedMesh* roomMesh = smgr->getMesh("../../media/room.3ds"); |
232 | scene::ISceneNode* room = 0; | 232 | scene::ISceneNode* room = 0; |
233 | scene::ISceneNode* earth = 0; | 233 | scene::ISceneNode* earth = 0; |
234 | 234 | ||
235 | if (roomMesh) | 235 | if (roomMesh) |
236 | { | 236 | { |
237 | // The Room mesh doesn't have proper Texture Mapping on the | 237 | // The Room mesh doesn't have proper Texture Mapping on the |
238 | // floor, so we can recreate them on runtime | 238 | // floor, so we can recreate them on runtime |
239 | smgr->getMeshManipulator()->makePlanarTextureMapping( | 239 | smgr->getMeshManipulator()->makePlanarTextureMapping( |
240 | roomMesh->getMesh(0), 0.003f); | 240 | roomMesh->getMesh(0), 0.003f); |
241 | 241 | ||
242 | /* | 242 | /* |
243 | Now for the first exciting thing: If we successfully loaded the | 243 | Now for the first exciting thing: If we successfully loaded the |
244 | mesh we need to apply textures to it. Because we want this room | 244 | mesh we need to apply textures to it. Because we want this room |
245 | to be displayed with a very cool material, we have to do a | 245 | to be displayed with a very cool material, we have to do a |
246 | little bit more than just set the textures. Instead of only | 246 | little bit more than just set the textures. Instead of only |
247 | loading a color map as usual, we also load a height map which | 247 | loading a color map as usual, we also load a height map which |
248 | is simply a grayscale texture. From this height map, we create | 248 | is simply a grayscale texture. From this height map, we create |
249 | a normal map which we will set as second texture of the room. | 249 | a normal map which we will set as second texture of the room. |
250 | If you already have a normal map, you could directly set it, | 250 | If you already have a normal map, you could directly set it, |
251 | but I simply didn't find a nice normal map for this texture. | 251 | but I simply didn't find a nice normal map for this texture. |
252 | The normal map texture is being generated by the | 252 | The normal map texture is being generated by the |
253 | makeNormalMapTexture method of the VideoDriver. The second | 253 | makeNormalMapTexture method of the VideoDriver. The second |
254 | parameter specifies the height of the heightmap. If you set it | 254 | parameter specifies the height of the heightmap. If you set it |
255 | to a bigger value, the map will look more rocky. | 255 | to a bigger value, the map will look more rocky. |
256 | */ | 256 | */ |
257 | 257 | ||
258 | video::ITexture* normalMap = | 258 | video::ITexture* normalMap = |
259 | driver->getTexture("../../media/rockwall_height.bmp"); | 259 | driver->getTexture("../../media/rockwall_height.bmp"); |
260 | 260 | ||
261 | if (normalMap) | 261 | if (normalMap) |
262 | driver->makeNormalMapTexture(normalMap, 9.0f); | 262 | driver->makeNormalMapTexture(normalMap, 9.0f); |
263 | /* | 263 | /* |
264 | // The Normal Map and the displacement map/height map in the alpha channel | 264 | // The Normal Map and the displacement map/height map in the alpha channel |
265 | video::ITexture* normalMap = | 265 | video::ITexture* normalMap = |
266 | driver->getTexture("../../media/rockwall_NRM.tga"); | 266 | driver->getTexture("../../media/rockwall_NRM.tga"); |
267 | */ | 267 | */ |
268 | /* | 268 | /* |
269 | But just setting color and normal map is not everything. The | 269 | But just setting color and normal map is not everything. The |
270 | material we want to use needs some additional informations per | 270 | material we want to use needs some additional informations per |
271 | vertex like tangents and binormals. Because we are too lazy to | 271 | vertex like tangents and binormals. Because we are too lazy to |
272 | calculate that information now, we let Irrlicht do this for us. | 272 | calculate that information now, we let Irrlicht do this for us. |
273 | That's why we call IMeshManipulator::createMeshWithTangents(). | 273 | That's why we call IMeshManipulator::createMeshWithTangents(). |
274 | It creates a mesh copy with tangents and binormals from another | 274 | It creates a mesh copy with tangents and binormals from another |
275 | mesh. After we've done that, we simply create a standard | 275 | mesh. After we've done that, we simply create a standard |
276 | mesh scene node with this mesh copy, set color and normal map | 276 | mesh scene node with this mesh copy, set color and normal map |
277 | and adjust some other material settings. Note that we set | 277 | and adjust some other material settings. Note that we set |
278 | EMF_FOG_ENABLE to true to enable fog in the room. | 278 | EMF_FOG_ENABLE to true to enable fog in the room. |
279 | */ | 279 | */ |
280 | 280 | ||
281 | scene::IMesh* tangentMesh = smgr->getMeshManipulator()-> | 281 | scene::IMesh* tangentMesh = smgr->getMeshManipulator()-> |
282 | createMeshWithTangents(roomMesh->getMesh(0)); | 282 | createMeshWithTangents(roomMesh->getMesh(0)); |
283 | 283 | ||
284 | room = smgr->addMeshSceneNode(tangentMesh); | 284 | room = smgr->addMeshSceneNode(tangentMesh); |
285 | room->setMaterialTexture(0, | 285 | room->setMaterialTexture(0, |
286 | driver->getTexture("../../media/rockwall.jpg")); | 286 | driver->getTexture("../../media/rockwall.jpg")); |
287 | room->setMaterialTexture(1, normalMap); | 287 | room->setMaterialTexture(1, normalMap); |
288 | 288 | ||
289 | // Stones don't glitter.. | 289 | // Stones don't glitter.. |
290 | room->getMaterial(0).SpecularColor.set(0,0,0,0); | 290 | room->getMaterial(0).SpecularColor.set(0,0,0,0); |
291 | room->getMaterial(0).Shininess = 0.f; | 291 | room->getMaterial(0).Shininess = 0.f; |
292 | 292 | ||
293 | room->setMaterialFlag(video::EMF_FOG_ENABLE, true); | 293 | room->setMaterialFlag(video::EMF_FOG_ENABLE, true); |
294 | room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID); | 294 | room->setMaterialType(video::EMT_PARALLAX_MAP_SOLID); |
295 | // adjust height for parallax effect | 295 | // adjust height for parallax effect |
296 | room->getMaterial(0).MaterialTypeParam = 1.f / 64.f; | 296 | room->getMaterial(0).MaterialTypeParam = 1.f / 64.f; |
297 | 297 | ||
298 | // drop mesh because we created it with a create.. call. | 298 | // drop mesh because we created it with a create.. call. |
299 | tangentMesh->drop(); | 299 | tangentMesh->drop(); |
300 | } | 300 | } |
301 | 301 | ||
302 | /* | 302 | /* |
303 | After we've created a room shaded by per pixel lighting, we add a | 303 | After we've created a room shaded by per pixel lighting, we add a |
304 | sphere into it with the same material, but we'll make it transparent. | 304 | sphere into it with the same material, but we'll make it transparent. |
305 | In addition, because the sphere looks somehow like a familiar planet, | 305 | In addition, because the sphere looks somehow like a familiar planet, |
306 | we make it rotate. The procedure is similar as before. The difference | 306 | we make it rotate. The procedure is similar as before. The difference |
307 | is that we are loading the mesh from an .x file which already contains | 307 | is that we are loading the mesh from an .x file which already contains |
308 | a color map so we do not need to load it manually. But the sphere is a | 308 | a color map so we do not need to load it manually. But the sphere is a |
309 | little bit too small for our needs, so we scale it by the factor 50. | 309 | little bit too small for our needs, so we scale it by the factor 50. |
310 | */ | 310 | */ |
311 | 311 | ||
312 | // add earth sphere | 312 | // add earth sphere |
313 | 313 | ||
314 | scene::IAnimatedMesh* earthMesh = smgr->getMesh("../../media/earth.x"); | 314 | scene::IAnimatedMesh* earthMesh = smgr->getMesh("../../media/earth.x"); |
315 | if (earthMesh) | 315 | if (earthMesh) |
316 | { | 316 | { |
317 | //perform various task with the mesh manipulator | 317 | //perform various task with the mesh manipulator |
318 | scene::IMeshManipulator *manipulator = smgr->getMeshManipulator(); | 318 | scene::IMeshManipulator *manipulator = smgr->getMeshManipulator(); |
319 | 319 | ||
320 | // create mesh copy with tangent informations from original earth.x mesh | 320 | // create mesh copy with tangent informations from original earth.x mesh |
321 | scene::IMesh* tangentSphereMesh = | 321 | scene::IMesh* tangentSphereMesh = |
322 | manipulator->createMeshWithTangents(earthMesh->getMesh(0)); | 322 | manipulator->createMeshWithTangents(earthMesh->getMesh(0)); |
323 | 323 | ||
324 | // set the alpha value of all vertices to 200 | 324 | // set the alpha value of all vertices to 200 |
325 | manipulator->setVertexColorAlpha(tangentSphereMesh, 200); | 325 | manipulator->setVertexColorAlpha(tangentSphereMesh, 200); |
326 | 326 | ||
327 | // scale the mesh by factor 50 | 327 | // scale the mesh by factor 50 |
328 | core::matrix4 m; | 328 | core::matrix4 m; |
329 | m.setScale ( core::vector3df(50,50,50) ); | 329 | m.setScale ( core::vector3df(50,50,50) ); |
330 | manipulator->transform( tangentSphereMesh, m ); | 330 | manipulator->transform( tangentSphereMesh, m ); |
331 | 331 | ||
332 | earth = smgr->addMeshSceneNode(tangentSphereMesh); | 332 | earth = smgr->addMeshSceneNode(tangentSphereMesh); |
333 | 333 | ||
334 | earth->setPosition(core::vector3df(-70,130,45)); | 334 | earth->setPosition(core::vector3df(-70,130,45)); |
335 | 335 | ||
336 | // load heightmap, create normal map from it and set it | 336 | // load heightmap, create normal map from it and set it |
337 | video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.jpg"); | 337 | video::ITexture* earthNormalMap = driver->getTexture("../../media/earthbump.jpg"); |
338 | if (earthNormalMap) | 338 | if (earthNormalMap) |
339 | { | 339 | { |
340 | driver->makeNormalMapTexture(earthNormalMap, 20.0f); | 340 | driver->makeNormalMapTexture(earthNormalMap, 20.0f); |
341 | earth->setMaterialTexture(1, earthNormalMap); | 341 | earth->setMaterialTexture(1, earthNormalMap); |
342 | earth->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA); | 342 | earth->setMaterialType(video::EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA); |
343 | } | 343 | } |
344 | 344 | ||
345 | // adjust material settings | 345 | // adjust material settings |
346 | earth->setMaterialFlag(video::EMF_FOG_ENABLE, true); | 346 | earth->setMaterialFlag(video::EMF_FOG_ENABLE, true); |
347 | 347 | ||
348 | // add rotation animator | 348 | // add rotation animator |
349 | scene::ISceneNodeAnimator* anim = | 349 | scene::ISceneNodeAnimator* anim = |
350 | smgr->createRotationAnimator(core::vector3df(0,0.1f,0)); | 350 | smgr->createRotationAnimator(core::vector3df(0,0.1f,0)); |
351 | earth->addAnimator(anim); | 351 | earth->addAnimator(anim); |
352 | anim->drop(); | 352 | anim->drop(); |
353 | 353 | ||
354 | // drop mesh because we created it with a create.. call. | 354 | // drop mesh because we created it with a create.. call. |
355 | tangentSphereMesh->drop(); | 355 | tangentSphereMesh->drop(); |
356 | } | 356 | } |
357 | 357 | ||
358 | /* | 358 | /* |
359 | Per pixel lighted materials only look cool when there are moving | 359 | Per pixel lighted materials only look cool when there are moving |
360 | lights. So we add some. And because moving lights alone are so boring, | 360 | lights. So we add some. And because moving lights alone are so boring, |
361 | we add billboards to them, and a whole particle system to one of them. | 361 | we add billboards to them, and a whole particle system to one of them. |
362 | We start with the first light which is red and has only the billboard | 362 | We start with the first light which is red and has only the billboard |
363 | attached. | 363 | attached. |
364 | */ | 364 | */ |
365 | 365 | ||
366 | // add light 1 (more green) | 366 | // add light 1 (more green) |
367 | scene::ILightSceneNode* light1 = | 367 | scene::ILightSceneNode* light1 = |
368 | smgr->addLightSceneNode(0, core::vector3df(0,0,0), | 368 | smgr->addLightSceneNode(0, core::vector3df(0,0,0), |
369 | video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f); | 369 | video::SColorf(0.5f, 1.0f, 0.5f, 0.0f), 800.0f); |
370 | 370 | ||
371 | light1->setDebugDataVisible ( scene::EDS_BBOX ); | 371 | light1->setDebugDataVisible ( scene::EDS_BBOX ); |
372 | 372 | ||
373 | 373 | ||
374 | // add fly circle animator to light 1 | 374 | // add fly circle animator to light 1 |
375 | scene::ISceneNodeAnimator* anim = | 375 | scene::ISceneNodeAnimator* anim = |
376 | smgr->createFlyCircleAnimator (core::vector3df(50,300,0),190.0f, -0.003f); | 376 | smgr->createFlyCircleAnimator (core::vector3df(50,300,0),190.0f, -0.003f); |
377 | light1->addAnimator(anim); | 377 | light1->addAnimator(anim); |
378 | anim->drop(); | 378 | anim->drop(); |
379 | 379 | ||
380 | // attach billboard to the light | 380 | // attach billboard to the light |
381 | scene::IBillboardSceneNode* bill = | 381 | scene::IBillboardSceneNode* bill = |
382 | smgr->addBillboardSceneNode(light1, core::dimension2d<f32>(60, 60)); | 382 | smgr->addBillboardSceneNode(light1, core::dimension2d<f32>(60, 60)); |
383 | 383 | ||
384 | bill->setMaterialFlag(video::EMF_LIGHTING, false); | 384 | bill->setMaterialFlag(video::EMF_LIGHTING, false); |
385 | bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); | 385 | bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); |
386 | bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); | 386 | bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); |
387 | bill->setMaterialTexture(0, driver->getTexture("../../media/particlegreen.jpg")); | 387 | bill->setMaterialTexture(0, driver->getTexture("../../media/particlegreen.jpg")); |
388 | 388 | ||
389 | /* | 389 | /* |
390 | Now the same again, with the second light. The difference is that we | 390 | Now the same again, with the second light. The difference is that we |
391 | add a particle system to it too. And because the light moves, the | 391 | add a particle system to it too. And because the light moves, the |
392 | particles of the particlesystem will follow. If you want to know more | 392 | particles of the particlesystem will follow. If you want to know more |
393 | about how particle systems are created in Irrlicht, take a look at the | 393 | about how particle systems are created in Irrlicht, take a look at the |
394 | specialFx example. Maybe you will have noticed that we only add 2 | 394 | specialFx example. Maybe you will have noticed that we only add 2 |
395 | lights, this has a simple reason: The low end version of this material | 395 | lights, this has a simple reason: The low end version of this material |
396 | was written in ps1.1 and vs1.1, which doesn't allow more lights. You | 396 | was written in ps1.1 and vs1.1, which doesn't allow more lights. You |
397 | could add a third light to the scene, but it won't be used to shade the | 397 | could add a third light to the scene, but it won't be used to shade the |
398 | walls. But of course, this will change in future versions of Irrlicht | 398 | walls. But of course, this will change in future versions of Irrlicht |
399 | where higher versions of pixel/vertex shaders will be implemented too. | 399 | where higher versions of pixel/vertex shaders will be implemented too. |
400 | */ | 400 | */ |
401 | 401 | ||
402 | // add light 2 (red) | 402 | // add light 2 (red) |
403 | scene::ISceneNode* light2 = | 403 | scene::ISceneNode* light2 = |
404 | smgr->addLightSceneNode(0, core::vector3df(0,0,0), | 404 | smgr->addLightSceneNode(0, core::vector3df(0,0,0), |
405 | video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f); | 405 | video::SColorf(1.0f, 0.2f, 0.2f, 0.0f), 800.0f); |
406 | 406 | ||
407 | // add fly circle animator to light 2 | 407 | // add fly circle animator to light 2 |
408 | anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0), 200.0f, | 408 | anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0), 200.0f, |
409 | 0.001f, core::vector3df(0.2f, 0.9f, 0.f)); | 409 | 0.001f, core::vector3df(0.2f, 0.9f, 0.f)); |
410 | light2->addAnimator(anim); | 410 | light2->addAnimator(anim); |
411 | anim->drop(); | 411 | anim->drop(); |
412 | 412 | ||
413 | // attach billboard to light | 413 | // attach billboard to light |
414 | bill = smgr->addBillboardSceneNode(light2, core::dimension2d<f32>(120, 120)); | 414 | bill = smgr->addBillboardSceneNode(light2, core::dimension2d<f32>(120, 120)); |
415 | bill->setMaterialFlag(video::EMF_LIGHTING, false); | 415 | bill->setMaterialFlag(video::EMF_LIGHTING, false); |
416 | bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); | 416 | bill->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); |
417 | bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); | 417 | bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); |
418 | bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp")); | 418 | bill->setMaterialTexture(0, driver->getTexture("../../media/particlered.bmp")); |
419 | 419 | ||
420 | // add particle system | 420 | // add particle system |
421 | scene::IParticleSystemSceneNode* ps = | 421 | scene::IParticleSystemSceneNode* ps = |
422 | smgr->addParticleSystemSceneNode(false, light2); | 422 | smgr->addParticleSystemSceneNode(false, light2); |
423 | 423 | ||
424 | // create and set emitter | 424 | // create and set emitter |
425 | scene::IParticleEmitter* em = ps->createBoxEmitter( | 425 | scene::IParticleEmitter* em = ps->createBoxEmitter( |
426 | core::aabbox3d<f32>(-3,0,-3,3,1,3), | 426 | core::aabbox3d<f32>(-3,0,-3,3,1,3), |
427 | core::vector3df(0.0f,0.03f,0.0f), | 427 | core::vector3df(0.0f,0.03f,0.0f), |
428 | 80,100, | 428 | 80,100, |
429 | video::SColor(10,255,255,255), video::SColor(10,255,255,255), | 429 | video::SColor(10,255,255,255), video::SColor(10,255,255,255), |
430 | 400,1100); | 430 | 400,1100); |
431 | em->setMinStartSize(core::dimension2d<f32>(30.0f, 40.0f)); | 431 | em->setMinStartSize(core::dimension2d<f32>(30.0f, 40.0f)); |
432 | em->setMaxStartSize(core::dimension2d<f32>(30.0f, 40.0f)); | 432 | em->setMaxStartSize(core::dimension2d<f32>(30.0f, 40.0f)); |
433 | 433 | ||
434 | ps->setEmitter(em); | 434 | ps->setEmitter(em); |
435 | em->drop(); | 435 | em->drop(); |
436 | 436 | ||
437 | // create and set affector | 437 | // create and set affector |
438 | scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); | 438 | scene::IParticleAffector* paf = ps->createFadeOutParticleAffector(); |
439 | ps->addAffector(paf); | 439 | ps->addAffector(paf); |
440 | paf->drop(); | 440 | paf->drop(); |
441 | 441 | ||
442 | // adjust some material settings | 442 | // adjust some material settings |
443 | ps->setMaterialFlag(video::EMF_LIGHTING, false); | 443 | ps->setMaterialFlag(video::EMF_LIGHTING, false); |
444 | ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); | 444 | ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); |
445 | ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); | 445 | ps->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); |
446 | ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); | 446 | ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); |
447 | 447 | ||
448 | MyEventReceiver receiver(room, earth, env, driver); | 448 | MyEventReceiver receiver(room, earth, env, driver); |
449 | device->setEventReceiver(&receiver); | 449 | device->setEventReceiver(&receiver); |
450 | 450 | ||
451 | /* | 451 | /* |
452 | Finally, draw everything. That's it. | 452 | Finally, draw everything. That's it. |
453 | */ | 453 | */ |
454 | 454 | ||
455 | int lastFPS = -1; | 455 | int lastFPS = -1; |
456 | 456 | ||
457 | while(device->run()) | 457 | while(device->run()) |
458 | if (device->isWindowActive()) | 458 | if (device->isWindowActive()) |
459 | { | 459 | { |
460 | driver->beginScene(true, true, 0); | 460 | driver->beginScene(true, true, 0); |
461 | 461 | ||
462 | smgr->drawAll(); | 462 | smgr->drawAll(); |
463 | env->drawAll(); | 463 | env->drawAll(); |
464 | 464 | ||
465 | driver->endScene(); | 465 | driver->endScene(); |
466 | 466 | ||
467 | int fps = driver->getFPS(); | 467 | int fps = driver->getFPS(); |
468 | 468 | ||
469 | if (lastFPS != fps) | 469 | if (lastFPS != fps) |
470 | { | 470 | { |
471 | core::stringw str = L"Per pixel lighting example - Irrlicht Engine ["; | 471 | core::stringw str = L"Per pixel lighting example - Irrlicht Engine ["; |
472 | str += driver->getName(); | 472 | str += driver->getName(); |
473 | str += "] FPS:"; | 473 | str += "] FPS:"; |
474 | str += fps; | 474 | str += fps; |
475 | 475 | ||
476 | device->setWindowCaption(str.c_str()); | 476 | device->setWindowCaption(str.c_str()); |
477 | lastFPS = fps; | 477 | lastFPS = fps; |
478 | } | 478 | } |
479 | } | 479 | } |
480 | 480 | ||
481 | device->drop(); | 481 | device->drop(); |
482 | 482 | ||
483 | return 0; | 483 | return 0; |
484 | } | 484 | } |
485 | 485 | ||
486 | /* | 486 | /* |
487 | **/ | 487 | **/ |