waterPlane.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "environment/waterPlane.h"
  24. #include "core/util/safeDelete.h"
  25. #include "scene/sceneRenderState.h"
  26. #include "scene/sceneManager.h"
  27. #include "lighting/lightInfo.h"
  28. #include "core/stream/bitStream.h"
  29. #include "math/mathIO.h"
  30. #include "math/mathUtils.h"
  31. #include "console/consoleTypes.h"
  32. #include "gui/3d/guiTSControl.h"
  33. #include "gfx/primBuilder.h"
  34. #include "gfx/gfxTransformSaver.h"
  35. #include "gfx/gfxDebugEvent.h"
  36. #include "gfx/gfxOcclusionQuery.h"
  37. #include "renderInstance/renderPassManager.h"
  38. #include "sim/netConnection.h"
  39. #include "scene/reflectionManager.h"
  40. #include "ts/tsShapeInstance.h"
  41. #include "T3D/gameFunctions.h"
  42. #include "postFx/postEffect.h"
  43. #include "math/util/matrixSet.h"
  44. extern ColorI gCanvasClearColor;
  45. #define BLEND_TEX_SIZE 256
  46. #define V_SHADER_PARAM_OFFSET 50
  47. IMPLEMENT_CO_NETOBJECT_V1(WaterPlane);
  48. ConsoleDocClass( WaterPlane,
  49. "@brief Represents a large body of water stretching to the horizon in all directions.\n\n"
  50. "WaterPlane's position is defined only height, the z element of position, "
  51. "it is infinite in xy and depth. %WaterPlane is designed to represent the "
  52. "ocean on an island scene and viewed from ground level; other uses may not "
  53. "be appropriate and a WaterBlock may be used.\n\n"
  54. "@see WaterObject for inherited functionality.\n\n"
  55. "Limitations:\n\n"
  56. "Because %WaterPlane cannot be projected exactly to the far-clip distance, "
  57. "other objects nearing this distance can have noticible artifacts as they "
  58. "clip through first the %WaterPlane and then the far plane.\n\n"
  59. "To avoid this large objects should be positioned such that they will not line up with "
  60. "the far-clip from vantage points the player is expected to be. In particular, "
  61. "your TerrainBlock should be completely contained by the far-clip distance.\n\n"
  62. "Viewing %WaterPlane from a high altitude with a tight far-clip distance "
  63. "will accentuate this limitation. %WaterPlane is primarily designed to "
  64. "be viewed from ground level.\n\n"
  65. "@ingroup Water"
  66. );
  67. WaterPlane::WaterPlane()
  68. {
  69. mGridElementSize = 1.0f;
  70. mGridSize = 101;
  71. mGridSizeMinusOne = mGridSize - 1;
  72. mNetFlags.set(Ghostable | ScopeAlways);
  73. mVertCount = 0;
  74. mIndxCount = 0;
  75. mPrimCount = 0;
  76. }
  77. WaterPlane::~WaterPlane()
  78. {
  79. }
  80. bool WaterPlane::onAdd()
  81. {
  82. if ( !Parent::onAdd() )
  83. return false;
  84. setGlobalBounds();
  85. resetWorldBox();
  86. addToScene();
  87. mWaterFogData.plane.set( 0, 0, 1, -getPosition().z );
  88. return true;
  89. }
  90. void WaterPlane::onRemove()
  91. {
  92. removeFromScene();
  93. Parent::onRemove();
  94. }
  95. void WaterPlane::initPersistFields()
  96. {
  97. addGroup( "WaterPlane" );
  98. addProtectedField( "gridSize", TypeS32, Offset( mGridSize, WaterPlane ), &protectedSetGridSize, &defaultProtectedGetFn,
  99. "Spacing between vertices in the WaterBlock mesh" );
  100. addProtectedField( "gridElementSize", TypeF32, Offset( mGridElementSize, WaterPlane ), &protectedSetGridElementSize, &defaultProtectedGetFn,
  101. "Duplicate of gridElementSize for backwards compatility");
  102. endGroup( "WaterPlane" );
  103. Parent::initPersistFields();
  104. removeField( "rotation" );
  105. removeField( "scale" );
  106. }
  107. U32 WaterPlane::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
  108. {
  109. U32 retMask = Parent::packUpdate(con, mask, stream);
  110. stream->write( mGridSize );
  111. stream->write( mGridElementSize );
  112. if ( stream->writeFlag( mask & UpdateMask ) )
  113. {
  114. stream->write( getPosition().z );
  115. }
  116. return retMask;
  117. }
  118. void WaterPlane::unpackUpdate(NetConnection* con, BitStream* stream)
  119. {
  120. Parent::unpackUpdate(con, stream);
  121. U32 inGridSize;
  122. stream->read( &inGridSize );
  123. setGridSize( inGridSize );
  124. F32 inGridElementSize;
  125. stream->read( &inGridElementSize );
  126. setGridElementSize( inGridElementSize );
  127. if( stream->readFlag() ) // UpdateMask
  128. {
  129. F32 posZ;
  130. stream->read( &posZ );
  131. Point3F newPos = getPosition();
  132. newPos.z = posZ;
  133. setPosition( newPos );
  134. }
  135. }
  136. void WaterPlane::setupVBIB( SceneRenderState *state )
  137. {
  138. const Frustum &frustum = state->getCullingFrustum();
  139. // Water base-color, assigned as color for all verts.
  140. const GFXVertexColor vertCol(mWaterFogData.color);
  141. // World-Up vector, assigned as normal for all verts.
  142. const Point3F worldUp( 0.0f, 0.0f, 1.0f );
  143. // World-unit size of a grid cell.
  144. const F32 squareSize = mGridElementSize;
  145. // Column/Row count.
  146. // So we don't neet to access class-specific member variables
  147. // in the code below.
  148. const U32 gridSize = mGridSize;
  149. // Number of verts in one column / row
  150. const U32 gridStride = gridSize + 1;
  151. // Grid is filled in this order...
  152. // Ex. Grid with gridSize of 2.
  153. //
  154. // Letters are cells.
  155. // Numbers are verts, enumerated in their order within the vert buffer.
  156. //
  157. // 6 7 8
  158. // (c) (d)
  159. // 3 4 5
  160. // (a) (b)
  161. // 0 1 2
  162. //
  163. // Note...
  164. // Camera would be positioned at vert 4 ( in this particular grid not a constant ).
  165. // Positive Y points UP the diagram ( verts 0, 3, 6 ).
  166. // Positive X points RIGHT across the diagram ( verts 0, 1, 2 ).
  167. // Length of a grid row/column divided by two.
  168. F32 gridSideHalfLen = squareSize * gridSize * 0.5f;
  169. // Position of the first vertex in the grid.
  170. // Relative to the camera this is the "Back Left" corner vert.
  171. const Point3F cornerPosition( -gridSideHalfLen, -gridSideHalfLen, 0.0f );
  172. // Number of verts in the grid centered on the camera.
  173. const U32 gridVertCount = gridStride * gridStride;
  174. // Number of verts surrounding the grid, projected by the frustum.
  175. const U32 borderVertCount = gridSize * 4;
  176. // Number of verts in the front-most row which are raised to the horizon.
  177. const U32 horizonVertCount = gridStride;
  178. // Total number of verts. Calculation explained above.
  179. mVertCount = gridVertCount + borderVertCount + horizonVertCount;
  180. // Fill the vertex buffer...
  181. mVertBuff.set( GFX, mVertCount, GFXBufferTypeStatic );
  182. GFXWaterVertex *vertPtr = mVertBuff.lock();
  183. // Fill verts in the camera centered grid...
  184. // Temorary storage for calculation of vert position.
  185. F32 xVal, yVal;
  186. for ( U32 i = 0; i < gridStride; i++ )
  187. {
  188. yVal = cornerPosition.y + (F32)( i * squareSize );
  189. for ( U32 j = 0; j < gridStride; j++ )
  190. {
  191. xVal = cornerPosition.x + (F32)( j * squareSize );
  192. vertPtr->point.set( xVal, yVal, 0.0f );
  193. vertPtr->color = vertCol;
  194. vertPtr->normal = worldUp;
  195. vertPtr->undulateData.set( xVal, yVal );
  196. vertPtr->horizonFactor.set( 0, 0, 0, 0 );
  197. vertPtr++;
  198. }
  199. }
  200. // Fill in 'border' verts, surrounding the grid, projected by the frustum.
  201. // Ex. Grid with gridSize of 2.
  202. //
  203. // Letters in parenthesis are cells.
  204. // x's are grid-verts ( we have already filled ).
  205. // Numbers are border verts, enumerated in their order within the vert buffer.
  206. //
  207. // Lines connecting verts explained in the code below.
  208. //
  209. // Front
  210. //
  211. // L 0------1 2 R
  212. // e x x x | i
  213. // f (c) (d) | g
  214. // t 7 x x x 3 h
  215. // | (a) (b) t
  216. // | x x x
  217. // 6 5------4
  218. //
  219. // Back
  220. //
  221. // As in previous diagram...
  222. // Camera would be positioned at vert 4 ( in this particular grid not a constant ).
  223. // Positive Y points UP the diagram ( verts 6, 7, 0 ).
  224. // Positive X points RIGHT across the diagram ( verts 0, 1, 2 ).
  225. // Iterator i is looping through the 4 'sides' of the grid.
  226. // Inner loop ( using iterator j ) will fill in a number of verts
  227. // where that count is 'gridSize'.
  228. //
  229. //
  230. // Ex. Given the grid with gridSize of 2 diagramed above,
  231. // Outer loop iterates through: Front, Right, Back, Left
  232. // Inner loop fills 2 verts per iteration of the outer loop: { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 }
  233. // Grid-space vectors indexed by 'side'.
  234. // Each vector describes the direction we iterate when
  235. // filling in verts ( mathematically the tangent ).
  236. const Point2F sBorderTangentVec [4] = {
  237. Point2F( 1, 0 ), // Front ( 0 )
  238. Point2F( 0, -1 ), // Right ( 1 )
  239. Point2F( -1, 0 ), // Back ( 2 )
  240. Point2F( 0, 1 ) // Left ( 3 )
  241. };
  242. // Normalized positions indexed by 'side'
  243. // Defines the 'start' position of each side, eg. the position of the first vert.
  244. // See Diagram below.
  245. const Point2F sBorderStartPos [4] = {
  246. Point2F( -1, 1 ), // Front ( 0 )
  247. Point2F( 1, 1 ), // Right ( 1 )
  248. Point2F( 1, -1 ), // Back ( 2 )
  249. Point2F( -1, -1 ) // Left ( 3 )
  250. };
  251. // Diagram of Start vert position per Side.
  252. //
  253. // Labeling convention for verts is 'As' where A is the first letter of
  254. // that side's descriptive name and lower-case s indicates 'start'.
  255. //
  256. //
  257. //
  258. // Front
  259. // (-1,1)
  260. // Fs------o-----Rs(1,1)R
  261. // | | i
  262. // | | g
  263. // o (0,0) o h
  264. // | | t
  265. // | |
  266. // L(-1,-1)Ls------o-----Bs
  267. // e (1,-1)
  268. // f Back
  269. // t
  270. // Calculate the world-space dimension of the border-vert-ring...
  271. // Diagram shows overall layout of the WaterPlane with a gridSize of 1,
  272. // with all 'quads' enumerated.
  273. // center-grid ( 1 ), border ( 2, 3, 4, 5 ), and horizon ( 6 ).
  274. //
  275. //
  276. // x------------x
  277. // \ 6 \ <- horizon quad is really 'above' the front border
  278. // x --------- x not in front of it
  279. // | \ 2 / |
  280. // | x---- x |
  281. // | | | |
  282. // | 5| 1 |3 |
  283. // | x --- x |
  284. // | / 4 \|
  285. // x------------x
  286. // WaterPlane renders relative to the camera rotation around z and xy position.
  287. //
  288. // That is, it rotates around the z-up axis with the camera such that the
  289. // camera is always facing towards the front border unless looking straight
  290. // down or up.
  291. //
  292. // Also note that the horizon verts are pulled straight up from the front
  293. // border verts.
  294. //
  295. // Therefore...
  296. //
  297. // The front border must be as close to the farclip plane as possible
  298. // so distant objects clip through the horizon and farplane at the same time.
  299. //
  300. // The left and right borders must be pulled outward a distance such
  301. // that water extends horizontally across the entire viewable area while
  302. // looking straight forward +y or straight down -z.
  303. //
  304. //
  305. const F32 farDistScale = 0.99f;
  306. //
  307. F32 farDist = frustum.getFarDist() * farDistScale;
  308. //
  309. F32 farWidth = (F32)state->getViewport().extent.x * farDist / state->getWorldToScreenScale().x;
  310. Point2F borderExtents( farWidth * 2.0f, farDist * 2.0f );
  311. Point2F borderHalfExtents( farWidth, farDist );
  312. Point2F borderDir;
  313. Point2F borderStart;
  314. for ( U32 i = 0; i < 4; i++ )
  315. {
  316. borderDir = sBorderTangentVec[i];
  317. borderStart = sBorderStartPos[i];
  318. for ( U32 j = 0; j < gridSize; j++ )
  319. {
  320. F32 frac = (F32)j / (F32)gridSize;
  321. Point2F pos( borderStart * borderHalfExtents );
  322. pos += borderDir * borderExtents * frac;
  323. vertPtr->point.set( pos.x, pos.y, 0.0f );
  324. vertPtr->undulateData.set( pos.x, pos.y );
  325. vertPtr->horizonFactor.set( 0, 0, 0, 0 );
  326. vertPtr->color = vertCol;
  327. vertPtr->normal = worldUp;
  328. vertPtr++;
  329. }
  330. }
  331. // Fill in row of horizion verts.
  332. // Verts are positioned identical to the front border, but will be
  333. // manipulated in z within the shader.
  334. //
  335. // Z position of 50.0f is unimportant unless you want to disable
  336. // shader manipulation and render in wireframe for debugging.
  337. for ( U32 i = 0; i < gridStride; i++ )
  338. {
  339. F32 frac = (F32)i / (F32)gridSize;
  340. Point2F pos( sBorderStartPos[0] * borderHalfExtents );
  341. pos += sBorderTangentVec[0] * borderExtents * frac;
  342. vertPtr->point.set( pos.x, pos.y, 50.0f );
  343. vertPtr->undulateData.set( pos.x, pos.y );
  344. vertPtr->horizonFactor.set( 1, 0, 0, 0 );
  345. vertPtr->color = vertCol;
  346. vertPtr->normal = worldUp;
  347. vertPtr++;
  348. }
  349. mVertBuff.unlock();
  350. // Fill in the PrimitiveBuffer...
  351. // 2 triangles per cell/quad
  352. const U32 gridTriCount = gridSize * gridSize * 2;
  353. // 4 sides, mGridSize quads per side, 2 triangles per quad
  354. const U32 borderTriCount = 4 * gridSize * 2;
  355. // 1 quad per gridSize, 2 triangles per quad
  356. // i.e. an extra row of 'cells' leading the front side of the grid
  357. const U32 horizonTriCount = gridSize * 2;
  358. mPrimCount = gridTriCount + borderTriCount + horizonTriCount;
  359. // 3 indices per triangle.
  360. mIndxCount = mPrimCount * 3;
  361. mPrimBuff.set( GFX, mIndxCount, mPrimCount, GFXBufferTypeStatic );
  362. U16 *idxPtr;
  363. mPrimBuff.lock(&idxPtr);
  364. // Temporaries to hold indices for the corner points of a quad.
  365. U32 p00, p01, p11, p10;
  366. U32 offset = 0;
  367. // Given a single cell of the grid diagramed below,
  368. // quad indice variables are in this orientation.
  369. //
  370. // p01 --- p11
  371. // | |
  372. // | |
  373. // p00 --- p10
  374. //
  375. // Positive Y points UP the diagram ( p00, p01 ).
  376. // Positive X points RIGHT across the diagram ( p00, p10 )
  377. //
  378. // i iterates bottom to top "column-wise"
  379. for ( U32 i = 0; i < mGridSize; i++ )
  380. {
  381. // j iterates left to right "row-wise"
  382. for ( U32 j = 0; j < mGridSize; j++ )
  383. {
  384. // where (j,i) is a particular cell.
  385. p00 = offset;
  386. p10 = offset + 1;
  387. p01 = offset + gridStride;
  388. p11 = offset + 1 + gridStride;
  389. // Top Left Triangle
  390. *idxPtr = p00;
  391. idxPtr++;
  392. *idxPtr = p01;
  393. idxPtr++;
  394. *idxPtr = p11;
  395. idxPtr++;
  396. // Bottom Right Triangle
  397. *idxPtr = p00;
  398. idxPtr++;
  399. *idxPtr = p11;
  400. idxPtr++;
  401. *idxPtr = p10;
  402. idxPtr++;
  403. offset += 1;
  404. }
  405. offset += 1;
  406. }
  407. // Fill border indices...
  408. // Given a grid size of 1,
  409. // the grid / border verts are in the vertex buffer in this order.
  410. //
  411. //
  412. // 4 5
  413. // 2 --- 3
  414. // | |
  415. // | |
  416. // 0 --- 1
  417. // 7 6
  418. //
  419. // Positive Y points UP the diagram ( p00, p01 ).
  420. // Positive X points RIGHT across the diagram ( p00, p10 )
  421. //
  422. // Note we duplicate the first border vert ( 4 ) since it is also the last
  423. // and this makes our loop easier.
  424. const U32 sBorderStartVert [4] = {
  425. gridStride * gridSize, // Index to the Top-Left grid vert.
  426. gridStride * gridSize + gridSize, // Index to the Top-Right grid vert.
  427. gridSize, // Index to the Bottom-Right grid vert.
  428. 0, // Index to the Bottom-Left grid vert.
  429. };
  430. const S32 sBorderStepSize [4] = {
  431. // Step size to the next grid vert along the specified side....
  432. 1, // Top
  433. -(S32)gridStride, // Right
  434. -1, // Bottom
  435. gridStride, // Left
  436. };
  437. const U32 firstBorderVert = gridStride * gridSize + gridStride;
  438. const U32 lastBorderVert = firstBorderVert + ( borderVertCount - 1 );
  439. U32 startBorderVert = firstBorderVert;
  440. U32 startGridVert;
  441. U32 curStepSize;
  442. for ( U32 i = 0; i < 4; i++ )
  443. {
  444. startGridVert = sBorderStartVert[i];
  445. curStepSize = sBorderStepSize[i];
  446. for ( U32 j = 0; j < gridSize; j++ )
  447. {
  448. // Each border cell is 1 quad, 2 triangles.
  449. p00 = startGridVert;
  450. p10 = startGridVert + curStepSize;
  451. p01 = startBorderVert;
  452. p11 = startBorderVert + 1;
  453. if ( p11 > lastBorderVert )
  454. p11 = firstBorderVert;
  455. // Top Left Triangle
  456. *idxPtr = p00;
  457. idxPtr++;
  458. *idxPtr = p01;
  459. idxPtr++;
  460. *idxPtr = p11;
  461. idxPtr++;
  462. // Bottom Right Triangle
  463. *idxPtr = p00;
  464. idxPtr++;
  465. *idxPtr = p11;
  466. idxPtr++;
  467. *idxPtr = p10;
  468. idxPtr++;
  469. startBorderVert++;
  470. startGridVert += curStepSize;
  471. }
  472. }
  473. // Fill in 'horizon' triangles.
  474. U32 curHorizonVert = lastBorderVert + 1;
  475. U32 curBorderVert = firstBorderVert;
  476. for ( U32 i = 0; i < gridSize; i++ )
  477. {
  478. p00 = curBorderVert;
  479. p10 = curBorderVert + 1;
  480. p01 = curHorizonVert;
  481. p11 = curHorizonVert + 1;
  482. // Top Left Triangle
  483. *idxPtr = p00;
  484. idxPtr++;
  485. *idxPtr = p01;
  486. idxPtr++;
  487. *idxPtr = p11;
  488. idxPtr++;
  489. // Bottom Right Triangle
  490. *idxPtr = p00;
  491. idxPtr++;
  492. *idxPtr = p11;
  493. idxPtr++;
  494. *idxPtr = p10;
  495. idxPtr++;
  496. curBorderVert++;
  497. curHorizonVert++;
  498. }
  499. mPrimBuff.unlock();
  500. }
  501. SceneData WaterPlane::setupSceneGraphInfo( SceneRenderState *state )
  502. {
  503. SceneData sgData;
  504. sgData.lights[0] = LIGHTMGR->getSpecialLight( LightManager::slSunLightType );
  505. // fill in water's transform
  506. sgData.objTrans = &getRenderTransform();
  507. // fog
  508. sgData.setFogParams( state->getSceneManager()->getFogData() );
  509. // misc
  510. sgData.backBuffTex = REFLECTMGR->getRefractTex();
  511. sgData.reflectTex = mPlaneReflector.reflectTex;
  512. sgData.wireframe = GFXDevice::getWireframe() || smWireframe;
  513. return sgData;
  514. }
  515. void WaterPlane::setShaderParams( SceneRenderState *state, BaseMatInstance* mat, const WaterMatParams& paramHandles)
  516. {
  517. // Set variables that will be assigned to shader consts within WaterCommon
  518. // before calling Parent::setShaderParams
  519. mUndulateMaxDist = mGridElementSize * mGridSizeMinusOne * 0.5f;
  520. Parent::setShaderParams( state, mat, paramHandles );
  521. // Now set the rest of the shader consts that are either unique to this
  522. // class or that WaterObject leaves to us to handle...
  523. MaterialParameters* matParams = mat->getMaterialParameters();
  524. // set vertex shader constants
  525. //-----------------------------------
  526. matParams->setSafe(paramHandles.mGridElementSizeSC, (F32)mGridElementSize);
  527. //matParams->setSafe( paramHandles.mReflectTexSizeSC, mReflectTexSize );
  528. if ( paramHandles.mModelMatSC->isValid() )
  529. matParams->set(paramHandles.mModelMatSC, getRenderTransform(), GFXSCT_Float4x4);
  530. // set pixel shader constants
  531. //-----------------------------------
  532. ColorF c( mWaterFogData.color );
  533. matParams->setSafe( paramHandles.mBaseColorSC, c );
  534. // By default we need to show a true reflection is fullReflect is enabled and
  535. // we are above water.
  536. F32 reflect = mPlaneReflector.isEnabled() && !isUnderwater( state->getCameraPosition() );
  537. // If we were occluded the last frame a query was fetched ( not necessarily last frame )
  538. // and we weren't updated last frame... we don't have a valid texture to show
  539. // so use the cubemap / fake reflection color this frame.
  540. if ( mPlaneReflector.lastUpdateMs != REFLECTMGR->getLastUpdateMs() && mPlaneReflector.isOccluded() )
  541. reflect = false;
  542. //Point4F reflectParams( getRenderPosition().z, mReflectMinDist, mReflectMaxDist, reflect );
  543. Point4F reflectParams( getRenderPosition().z, 0.0f, 1000.0f, !reflect );
  544. // TODO: This is a hack... why is this broken... check after
  545. // we merge advanced lighting with trunk!
  546. //
  547. reflectParams.z = 0.0f;
  548. matParams->setSafe( paramHandles.mReflectParamsSC, reflectParams );
  549. VectorF reflectNorm( 0, 0, 1 );
  550. matParams->setSafe(paramHandles.mReflectNormalSC, reflectNorm );
  551. }
  552. void WaterPlane::prepRenderImage( SceneRenderState *state )
  553. {
  554. PROFILE_SCOPE(WaterPlane_prepRenderImage);
  555. if( !state->isDiffusePass() )
  556. return;
  557. mBasicLighting = dStricmp( LIGHTMGR->getId(), "BLM" ) == 0;
  558. mUnderwater = isUnderwater( state->getCameraPosition() );
  559. mMatrixSet->setSceneView(GFX->getWorldMatrix());
  560. const Frustum &frustum = state->getCameraFrustum();
  561. if ( mPrimBuff.isNull() ||
  562. mGenerateVB ||
  563. frustum != mFrustum )
  564. {
  565. mFrustum = frustum;
  566. setupVBIB( state );
  567. mGenerateVB = false;
  568. MatrixF proj( true );
  569. MathUtils::getZBiasProjectionMatrix( 0.0001f, mFrustum, &proj );
  570. mMatrixSet->setSceneProjection(proj);
  571. }
  572. _getWaterPlane( state->getCameraPosition(), mWaterPlane, mWaterPos );
  573. mWaterFogData.plane = mWaterPlane;
  574. mPlaneReflector.refplane = mWaterPlane;
  575. updateUnderwaterEffect( state );
  576. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  577. ri->renderDelegate.bind( this, &WaterObject::renderObject );
  578. ri->type = RenderPassManager::RIT_Water;
  579. state->getRenderPass()->addInst( ri );
  580. //mRenderUpdateCount++;
  581. }
  582. void WaterPlane::innerRender( SceneRenderState *state )
  583. {
  584. GFXDEBUGEVENT_SCOPE( WaterPlane_innerRender, ColorI( 255, 0, 0 ) );
  585. const Point3F &camPosition = state->getCameraPosition();
  586. Point3F rvec, fvec, uvec, pos;
  587. const MatrixF &objMat = getTransform(); //getRenderTransform();
  588. const MatrixF &camMat = state->getCameraTransform();
  589. MatrixF renderMat( true );
  590. camMat.getColumn( 1, &fvec );
  591. uvec.set( 0, 0, 1 );
  592. rvec = mCross( fvec, uvec );
  593. rvec.normalize();
  594. fvec = mCross( uvec, rvec );
  595. pos = camPosition;
  596. pos.z = objMat.getPosition().z;
  597. renderMat.setColumn( 0, rvec );
  598. renderMat.setColumn( 1, fvec );
  599. renderMat.setColumn( 2, uvec );
  600. renderMat.setColumn( 3, pos );
  601. setRenderTransform( renderMat );
  602. // Setup SceneData
  603. SceneData sgData = setupSceneGraphInfo( state );
  604. // set the material
  605. S32 matIdx = getMaterialIndex( camPosition );
  606. if ( !initMaterial( matIdx ) )
  607. return;
  608. BaseMatInstance *mat = mMatInstances[matIdx];
  609. WaterMatParams matParams = mMatParamHandles[matIdx];
  610. // render the geometry
  611. if ( mat )
  612. {
  613. // setup proj/world transform
  614. mMatrixSet->restoreSceneViewProjection();
  615. mMatrixSet->setWorld(getRenderTransform());
  616. setShaderParams( state, mat, matParams );
  617. while( mat->setupPass( state, sgData ) )
  618. {
  619. mat->setSceneInfo(state, sgData);
  620. mat->setTransforms(*mMatrixSet, state);
  621. setCustomTextures( matIdx, mat->getCurPass(), matParams );
  622. // set vert/prim buffer
  623. GFX->setVertexBuffer( mVertBuff );
  624. GFX->setPrimitiveBuffer( mPrimBuff );
  625. GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, mVertCount, 0, mPrimCount );
  626. }
  627. }
  628. }
  629. bool WaterPlane::isUnderwater( const Point3F &pnt ) const
  630. {
  631. F32 height = getPosition().z;
  632. F32 diff = pnt.z - height;
  633. return ( diff < 0.1 );
  634. }
  635. F32 WaterPlane::distanceTo( const Point3F& point ) const
  636. {
  637. if( isUnderwater( point ) )
  638. return 0.f;
  639. else
  640. return ( point.z - getPosition().z );
  641. }
  642. void WaterPlane::inspectPostApply()
  643. {
  644. Parent::inspectPostApply();
  645. setMaskBits( UpdateMask );
  646. }
  647. void WaterPlane::setTransform( const MatrixF &mat )
  648. {
  649. // We only accept the z value from the new transform.
  650. MatrixF newMat( true );
  651. Point3F newPos = getPosition();
  652. newPos.z = mat.getPosition().z;
  653. newMat.setPosition( newPos );
  654. Parent::setTransform( newMat );
  655. // Parent::setTransforms ends up setting our worldBox to something other than
  656. // global, so we have to set it back... but we can't actually call setGlobalBounds
  657. // again because it does extra work adding and removing us from the container.
  658. mGlobalBounds = true;
  659. mObjBox.minExtents.set(-1e10, -1e10, -1e10);
  660. mObjBox.maxExtents.set( 1e10, 1e10, 1e10);
  661. // Keep mWaterPlane up to date.
  662. mWaterFogData.plane.set( 0, 0, 1, -getPosition().z );
  663. }
  664. void WaterPlane::onStaticModified( const char* slotName, const char*newValue )
  665. {
  666. Parent::onStaticModified( slotName, newValue );
  667. if ( dStricmp( slotName, "surfMaterial" ) == 0 )
  668. setMaskBits( MaterialMask );
  669. }
  670. bool WaterPlane::castRay(const Point3F& start, const Point3F& end, RayInfo* info )
  671. {
  672. // Simply look for the hit on the water plane
  673. // and ignore any future issues with waves, etc.
  674. const Point3F norm(0,0,1);
  675. PlaneF plane( Point3F::Zero, norm );
  676. F32 hit = plane.intersect( start, end );
  677. if ( hit < 0.0f || hit > 1.0f )
  678. return false;
  679. info->t = hit;
  680. info->object = this;
  681. info->point = start + ( ( end - start ) * hit );
  682. info->normal = norm;
  683. info->material = mMatInstances[ WaterMat ];
  684. return true;
  685. }
  686. F32 WaterPlane::getWaterCoverage( const Box3F &testBox ) const
  687. {
  688. F32 posZ = getPosition().z;
  689. F32 coverage = 0.0f;
  690. if ( posZ > testBox.minExtents.z )
  691. {
  692. if ( posZ < testBox.maxExtents.z )
  693. coverage = (posZ - testBox.minExtents.z) / (testBox.maxExtents.z - testBox.minExtents.z);
  694. else
  695. coverage = 1.0f;
  696. }
  697. return coverage;
  698. }
  699. F32 WaterPlane::getSurfaceHeight( const Point2F &pos ) const
  700. {
  701. return getPosition().z;
  702. }
  703. void WaterPlane::onReflectionInfoChanged()
  704. {
  705. /*
  706. if ( isClientObject() && GFX->getPixelShaderVersion() >= 1.4 )
  707. {
  708. if ( mFullReflect )
  709. REFLECTMGR->registerObject( this, ReflectDelegate( this, &WaterPlane::updateReflection ), mReflectPriority, mReflectMaxRateMs, mReflectMaxDist );
  710. else
  711. {
  712. REFLECTMGR->unregisterObject( this );
  713. mReflectTex = NULL;
  714. }
  715. }
  716. */
  717. }
  718. void WaterPlane::setGridSize( U32 inSize )
  719. {
  720. if ( inSize == mGridSize )
  721. return;
  722. // GridSize must be an odd number.
  723. //if ( inSize % 2 == 0 )
  724. // inSize++;
  725. // GridSize must be at least 1
  726. inSize = getMax( inSize, (U32)1 );
  727. mGridSize = inSize;
  728. mGridSizeMinusOne = mGridSize - 1;
  729. mGenerateVB = true;
  730. setMaskBits( UpdateMask );
  731. }
  732. void WaterPlane::setGridElementSize( F32 inSize )
  733. {
  734. if ( inSize == mGridElementSize )
  735. return;
  736. // GridElementSize must be greater than 0
  737. inSize = getMax( inSize, 0.0001f );
  738. mGridElementSize = inSize;
  739. mGenerateVB = true;
  740. setMaskBits( UpdateMask );
  741. }
  742. bool WaterPlane::protectedSetGridSize( void *obj, const char *index, const char *data )
  743. {
  744. WaterPlane *object = static_cast<WaterPlane*>(obj);
  745. S32 size = dAtoi( data );
  746. object->setGridSize( size );
  747. // We already set the field.
  748. return false;
  749. }
  750. bool WaterPlane::protectedSetGridElementSize( void *obj, const char *index, const char *data )
  751. {
  752. WaterPlane *object = static_cast<WaterPlane*>(obj);
  753. F32 size = dAtof( data );
  754. object->setGridElementSize( size );
  755. // We already set the field.
  756. return false;
  757. }
  758. void WaterPlane::_getWaterPlane( const Point3F &camPos, PlaneF &outPlane, Point3F &outPos )
  759. {
  760. outPos = getPosition();
  761. outPlane.set( outPos, Point3F(0,0,1) );
  762. }