1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
9
10 You may use this sample code for anything you like, it is not covered by the
11 same license as the rest of the engine.
12 -----------------------------------------------------------------------------
13 */
14
15 #ifndef _Sample_Ocean_H_
16 #define _Sample_Ocean_H_
17
18 #include "SdkSample.h"
19 #include "SamplePlugin.h"
20 #include "MaterialControls.h"
21
22 using namespace Ogre;
23 using namespace OgreBites;
24
25 #define MINSPEED .150f
26 #define MOVESPEED 30
27 #define MAXSPEED 1.800f
28
29 #define CONTROLS_PER_PAGE 5
30
31 enum OceanMaterial {
32 OCEAN1_CG,
33 OCEAN1_NATIVE,
34 OCEAN2_CG,
35 OCEAN2_NATIVE
36 };
37
38 class _OgreSampleClassExport Sample_Ocean : public SdkSample
39 {
40 public:
41 Sample_Ocean();
42 protected:
43 //Things from the frame listener
44 Ogre::Vector3 mTranslateVector;
45 int mSceneDetailIndex;
46 float mUpdateFreq;
47 bool mSpinLight;
48 // just to stop toggles flipping too fast
49 Ogre::TextureFilterOptions mFiltering;
50 int mAniso;
51
52 Ogre::SceneNode* mMainNode;
53 Ogre::Entity* mOceanSurfaceEnt;
54
55 size_t mCurrentMaterial;
56 size_t mCurrentPage;
57 size_t mNumPages;
58 Ogre::MaterialPtr mActiveMaterial;
59 Ogre::Pass* mActivePass;
60 Ogre::GpuProgramPtr mActiveFragmentProgram;
61 Ogre::GpuProgramPtr mActiveVertexProgram;
62 Ogre::GpuProgramParametersSharedPtr mActiveFragmentParameters;
63 Ogre::GpuProgramParametersSharedPtr mActiveVertexParameters;
64 Real mRotateSpeed;
65 Slider* mShaderControls[CONTROLS_PER_PAGE];
66
67 ShaderControlsContainer mShaderControlContainer;
68 MaterialControlsContainer mMaterialControlsContainer;
69
70 void setupGUI();
71 void setupScene();
72 virtual void setupContent();
73 virtual void cleanupContent();
74
75 void sliderMoved(Slider* slider);
76 void buttonHit(OgreBites::Button* button);
77 void checkBoxToggled(CheckBox* box);
78 void selectOceanMaterial(OceanMaterial newMaterial);
79 void itemSelected(SelectMenu* menu);
80 void changePage(int nextPage = -1);
81 virtual bool frameRenderingQueued(const FrameEvent& evt);
82 };
83
84 /**********************************************************************
85 Static declarations
86 **********************************************************************/
87 // Lights
88 #define NUM_LIGHTS 1
89
90 // the light
91 Ogre::Light* mLights[NUM_LIGHTS];
92 // billboards for lights
93 Ogre::BillboardSet* mLightFlareSets[NUM_LIGHTS];
94 Ogre::Billboard* mLightFlares[NUM_LIGHTS];
95 // Positions for lights
96 Ogre::Vector3 mLightPositions[NUM_LIGHTS] =
97 {
98 Ogre::Vector3(00, 400, 00)
99 };
100 // Base orientations of the lights
101 Ogre::Real mLightRotationAngles[NUM_LIGHTS] = { 35 };
102 Ogre::Vector3 mLightRotationAxes[NUM_LIGHTS] = {
103 Ogre::Vector3::UNIT_X
104 };
105 // Rotation speed for lights, degrees per second
106 Ogre::Real mLightSpeeds[NUM_LIGHTS] = { 30};
107
108 // Colours for the lights
109 Ogre::ColourValue mDiffuseLightColours[NUM_LIGHTS] =
110 {
111 Ogre::ColourValue(0.6, 0.6, 0.6)
112 };
113
114 Ogre::ColourValue mSpecularLightColours[NUM_LIGHTS] =
115 {
116 Ogre::ColourValue(0.5, 0.5, 0.5)
117 };
118
119 // Which lights are enabled
120 bool mLightState[NUM_LIGHTS] =
121 {
122 true
123 };
124
125 // the light nodes
126 Ogre::SceneNode* mLightNodes[NUM_LIGHTS];
127 // the light node pivots
128 Ogre::SceneNode* mLightPivots[NUM_LIGHTS];
129
130
Sample_Ocean()131 Sample_Ocean::Sample_Ocean()
132 {
133 mInfo["Title"] = "Ocean";
134 mInfo["Description"] = "An example demonstrating ocean rendering using shaders.";
135 mInfo["Thumbnail"] = "thumb_ocean.png";
136 mInfo["Category"] = "Environment";
137 }
138 /*************************************************************************
139 Sample_Ocean Methods
140 *************************************************************************/
cleanupContent()141 void Sample_Ocean::cleanupContent()
142 {
143 MeshManager::getSingleton().remove("OceanSurface");
144
145 // get rid of the shared pointers before shutting down ogre or exceptions occur
146 mActiveFragmentProgram.setNull();
147 mActiveFragmentParameters.setNull();
148 mActiveVertexProgram.setNull();
149 mActiveVertexParameters.setNull();
150 mActiveMaterial.setNull();
151 }
152
153 //--------------------------------------------------------------------------
setupGUI(void)154 void Sample_Ocean::setupGUI(void)
155 {
156 SelectMenu* selectMenu = mTrayMgr->createLongSelectMenu(
157 TL_TOPLEFT, "MaterialSelectMenu", "Material", 300, 200, 5);
158
159 for (size_t i=0; i<mMaterialControlsContainer.size(); i++)
160 {
161 selectMenu->addItem(mMaterialControlsContainer[i].getDisplayName());
162 }
163
164 mTrayMgr->createCheckBox(TL_TOPLEFT, "SpinLightButton", "Spin Light", 175)->setChecked(true);
165
166 mTrayMgr->createButton(TL_TOPRIGHT, "PageButtonControl", "Page", 175);
167
168 for (size_t i=0; i<CONTROLS_PER_PAGE; i++)
169 {
170 mShaderControls[i] = mTrayMgr->createThickSlider(TL_TOPRIGHT,
171 "ShaderControlSlider" + StringConverter::toString(i), "Control", 256, 80, 0, 1, 100);
172 }
173
174 selectMenu->selectItem(0);
175 mTrayMgr->showCursor();
176
177 }
178 //--------------------------------------------------------------------------
setupContent(void)179 void Sample_Ocean::setupContent(void)
180 {
181 loadAllMaterialControlFiles(mMaterialControlsContainer);
182 setupScene();
183 setupGUI();
184
185 // Position it at 500 in Z direction
186 mCamera->setPosition(Ogre::Vector3(0,0,0));
187 // Look back along -Z
188 mCamera->lookAt(Ogre::Vector3(0,0,-300));
189 mCamera->setNearClipDistance(1);
190
191 #if OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS
192 setDragLook(true);
193 #endif
194 }
195
setupScene()196 void Sample_Ocean::setupScene()
197 {
198 // Set ambient light
199 mSceneMgr->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3));
200 mSceneMgr->setSkyBox(true, "SkyBox", 1000);
201
202 mMainNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
203
204
205 for (unsigned int i = 0; i < NUM_LIGHTS; ++i)
206 {
207 mLightPivots[i] = mSceneMgr->getRootSceneNode()->createChildSceneNode();
208 mLightPivots[i]->rotate(mLightRotationAxes[i], Ogre::Angle(mLightRotationAngles[i]));
209 // Create a light, use default parameters
210 mLights[i] = mSceneMgr->createLight("Light" + Ogre::StringConverter::toString(i));
211 mLights[i]->setPosition(mLightPositions[i]);
212 mLights[i]->setDiffuseColour(mDiffuseLightColours[i]);
213 mLights[i]->setSpecularColour(mSpecularLightColours[i]);
214 mLights[i]->setVisible(mLightState[i]);
215 //mLights[i]->setAttenuation(400, 0.1 , 1 , 0);
216 // Attach light
217 mLightPivots[i]->attachObject(mLights[i]);
218 // Create billboard for light
219 mLightFlareSets[i] = mSceneMgr->createBillboardSet("Flare" + Ogre::StringConverter::toString(i));
220 mLightFlareSets[i]->setMaterialName("LightFlare");
221 mLightPivots[i]->attachObject(mLightFlareSets[i]);
222 mLightFlares[i] = mLightFlareSets[i]->createBillboard(mLightPositions[i]);
223 mLightFlares[i]->setColour(mDiffuseLightColours[i]);
224 mLightFlareSets[i]->setVisible(mLightState[i]);
225 }
226
227 // move the camera a bit right and make it look at the knot
228 mCamera->moveRelative(Ogre::Vector3(50, 0, 100));
229 mCamera->lookAt(0, 0, 0);
230
231 // Define a plane mesh that will be used for the ocean surface
232 Ogre::Plane oceanSurface;
233 oceanSurface.normal = Ogre::Vector3::UNIT_Y;
234 oceanSurface.d = 20;
235 Ogre::MeshManager::getSingleton().createPlane("OceanSurface",
236 Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
237 oceanSurface,
238 1000, 1000, 50, 50, true, 1, 1, 1, Ogre::Vector3::UNIT_Z);
239
240 mOceanSurfaceEnt = mSceneMgr->createEntity( "OceanSurface", "OceanSurface" );
241 mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(mOceanSurfaceEnt);
242 }
243
244
245 //--------------------------------------------------------------------------
sliderMoved(Slider * slider)246 void Sample_Ocean::sliderMoved(Slider* slider)
247 {
248 using namespace Ogre;
249
250 int sliderIndex = -1;
251 for (int i=0; i<CONTROLS_PER_PAGE; i++)
252 {
253 if (mShaderControls[i] == slider)
254 {
255 sliderIndex = i;
256 break;
257 }
258 }
259 assert(sliderIndex != -1);
260
261 size_t index = mCurrentPage * CONTROLS_PER_PAGE + sliderIndex;
262 const ShaderControl& ActiveShaderDef = mMaterialControlsContainer[mCurrentMaterial].getShaderControl(index);
263
264 float val = slider->getValue();
265
266 if(mActivePass)
267 {
268 switch(ActiveShaderDef.ValType)
269 {
270 case GPU_VERTEX:
271 case GPU_FRAGMENT:
272 {
273 GpuProgramParametersSharedPtr activeParameters =
274 (ActiveShaderDef.ValType == GPU_VERTEX) ?
275 mActiveVertexParameters : mActiveFragmentParameters;
276
277 if(!activeParameters.isNull())
278 {
279 activeParameters->_writeRawConstant(
280 ActiveShaderDef.PhysicalIndex + ActiveShaderDef.ElementIndex, val);
281 }
282 }
283 break;
284
285 case MAT_SPECULAR:
286 {
287 // get the specular values from the material pass
288 ColourValue OldSpec(mActivePass->getSpecular());
289 OldSpec[ActiveShaderDef.ElementIndex] = val;
290 mActivePass->setSpecular( OldSpec );
291 }
292
293 break;
294
295 case MAT_DIFFUSE:
296 {
297 // get the specular values from the material pass
298 ColourValue OldSpec(mActivePass->getDiffuse());
299 OldSpec[ActiveShaderDef.ElementIndex] = val;
300 mActivePass->setDiffuse( OldSpec );
301 }
302 break;
303
304 case MAT_AMBIENT:
305 {
306 // get the specular values from the material pass
307 ColourValue OldSpec(mActivePass->getAmbient());
308 OldSpec[ActiveShaderDef.ElementIndex] = val;
309 mActivePass->setAmbient( OldSpec );
310 }
311 break;
312
313 case MAT_SHININESS:
314 // get the specular values from the material pass
315 mActivePass->setShininess( val );
316 break;
317
318 case MAT_EMISSIVE:
319 break;
320 }
321 }
322 }
323
324 //--------------------------------------------------------------------------
changePage(int pageNum)325 void Sample_Ocean::changePage(int pageNum /* = -1 : toggle */)
326 {
327 if (mMaterialControlsContainer.empty()) return;
328 mCurrentPage = (pageNum == -1) ? (mCurrentPage+1) % mNumPages : pageNum;
329
330 static char pageText[64];
331 sprintf(pageText, "Parameters %lu / %d", mCurrentPage+1, (int)mNumPages);
332 static_cast<OgreBites::Button*>(mTrayMgr->getWidget("PageButtonControl"))->setCaption(pageText);
333
334 if(!mActiveMaterial.isNull() && mActiveMaterial->getNumSupportedTechniques())
335 {
336 Ogre::Technique* currentTechnique = mActiveMaterial->getSupportedTechnique(0);
337 if(currentTechnique)
338 {
339 mActivePass = currentTechnique->getPass(0);
340 if(mActivePass)
341 {
342 if (mActivePass->hasFragmentProgram())
343 {
344 mActiveFragmentProgram = mActivePass->getFragmentProgram();
345 mActiveFragmentParameters = mActivePass->getFragmentProgramParameters();
346 }
347 if (mActivePass->hasVertexProgram())
348 {
349 mActiveVertexProgram = mActivePass->getVertexProgram();
350 mActiveVertexParameters = mActivePass->getVertexProgramParameters();
351 }
352
353 size_t activeControlCount = mMaterialControlsContainer[mCurrentMaterial].getShaderControlCount();
354
355 size_t startControlIndex = mCurrentPage * CONTROLS_PER_PAGE;
356 int numControls = static_cast<int>(activeControlCount - startControlIndex);
357 if (numControls <= 0)
358 {
359 mCurrentPage = 0;
360 startControlIndex = 0;
361 numControls = (int)activeControlCount;
362 }
363
364 for (size_t i=0; i<CONTROLS_PER_PAGE; i++)
365 {
366 Slider* shaderControlSlider = mShaderControls[i];
367 if (i < (size_t)numControls)
368 {
369 shaderControlSlider->show();
370 size_t controlIndex = startControlIndex + i;
371 const ShaderControl& ActiveShaderDef = mMaterialControlsContainer[mCurrentMaterial].getShaderControl(controlIndex);
372 shaderControlSlider->setRange(ActiveShaderDef.MinVal, ActiveShaderDef.MaxVal, 50, false);
373 shaderControlSlider->setCaption(ActiveShaderDef.Name);
374
375 float uniformVal = 0.0;
376 switch(ActiveShaderDef.ValType)
377 {
378 case GPU_VERTEX:
379 case GPU_FRAGMENT:
380 {
381 Ogre::GpuProgramParametersSharedPtr activeParameters =
382 (ActiveShaderDef.ValType == GPU_VERTEX) ?
383 mActiveVertexParameters : mActiveFragmentParameters;
384 if(!activeParameters.isNull())
385 {
386 // use param name to get index : use appropriate parameters ptr
387 const Ogre::GpuConstantDefinition& def =
388 activeParameters->getConstantDefinition(ActiveShaderDef.ParamName);
389 ActiveShaderDef.PhysicalIndex = def.physicalIndex;
390 // use index to get RealConstantEntry
391 const float* pFloat = activeParameters->getFloatPointer(ActiveShaderDef.PhysicalIndex);
392 // set position of ScrollWidget as param value
393 uniformVal = pFloat[ActiveShaderDef.ElementIndex];
394 }
395 }
396 break;
397
398 case MAT_SPECULAR:
399 {
400 // get the specular values from the material pass
401
402 Ogre::ColourValue OldSpec(mActivePass->getSpecular());
403 uniformVal = OldSpec[ActiveShaderDef.ElementIndex];
404 }
405 break;
406
407 case MAT_DIFFUSE:
408 {
409 // get the diffuse values from the material pass
410
411 Ogre::ColourValue OldSpec(mActivePass->getDiffuse());
412 uniformVal = OldSpec[ActiveShaderDef.ElementIndex];
413 }
414 break;
415
416 case MAT_AMBIENT:
417 {
418 // get the ambient values from the material pass
419
420 Ogre::ColourValue OldSpec(mActivePass->getAmbient());
421 uniformVal = OldSpec[ActiveShaderDef.ElementIndex];
422 }
423 break;
424
425 case MAT_SHININESS:
426 {
427 // get the ambient values from the material pass
428 uniformVal = mActivePass->getShininess();
429 }
430
431 break;
432
433 case MAT_EMISSIVE:
434 {
435 // get the ambient values from the material pass
436
437 //ColourValue OldSpec(mActivePass->gete());
438 //activeScrollWidget->setScrollPosition( OldSpec.val[ActiveShaderDef->ElementIndex] );
439 }
440 break;
441 }
442 shaderControlSlider->setValue(uniformVal);
443
444 }
445 else
446 {
447 shaderControlSlider->hide();
448 }
449 }
450 }
451 }
452 }
453
454 }
itemSelected(SelectMenu * menu)455 void Sample_Ocean::itemSelected(SelectMenu *menu)
456 {
457 //Only one selection menu - the material one
458 mCurrentMaterial = menu->getSelectionIndex();
459 mActiveMaterial = Ogre::MaterialManager::getSingleton().getByName( mMaterialControlsContainer[mCurrentMaterial].getMaterialName() );
460 mActiveMaterial->load();
461 size_t numShaders = mMaterialControlsContainer[mCurrentMaterial].getShaderControlCount();
462 mNumPages = (numShaders / CONTROLS_PER_PAGE) + (numShaders % CONTROLS_PER_PAGE == 0 ? 0 : 1);
463 changePage(0);
464
465 if (mOceanSurfaceEnt)
466 mOceanSurfaceEnt->setMaterialName(mMaterialControlsContainer[mCurrentMaterial].getMaterialName());
467 }
frameRenderingQueued(const FrameEvent & evt)468 bool Sample_Ocean::frameRenderingQueued(const FrameEvent& evt)
469 {
470 mRotateSpeed = evt.timeSinceLastFrame * 20;
471 if(mSpinLight)
472 {
473 mLightPivots[0]->rotate(mLightRotationAxes[0], Ogre::Angle(mRotateSpeed * 2.0f));
474 }
475 return SdkSample::frameRenderingQueued(evt);
476 }
buttonHit(OgreBites::Button * button)477 void Sample_Ocean::buttonHit(OgreBites::Button* button)
478 {
479 //Only one button - change page
480 changePage();
481 }
482
checkBoxToggled(CheckBox * cb)483 void Sample_Ocean::checkBoxToggled(CheckBox* cb)
484 {
485 //Only one checkbox
486 mSpinLight = cb->isChecked();
487 }
488
489 #endif // end _Sample_Ocean_H_
490