cloudLayer.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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 "platform/profiler.h"
  24. #include "console/consoleTypes.h"
  25. #include "cloudLayer.h"
  26. #include "gfx/gfxTransformSaver.h"
  27. #include "gfx/gfxTextureManager.h"
  28. #include "core/stream/fileStream.h"
  29. #include "core/stream/bitStream.h"
  30. #include "scene/sceneRenderState.h"
  31. #include "renderInstance/renderPassManager.h"
  32. #include "gfx/primBuilder.h"
  33. #include "materials/materialManager.h"
  34. #include "materials/customMaterialDefinition.h"
  35. #include "materials/shaderData.h"
  36. #include "lighting/lightInfo.h"
  37. #include "math/mathIO.h"
  38. ConsoleDocClass( CloudLayer,
  39. "@brief A layer of clouds which change shape over time and are affected by scene lighting.\n\n"
  40. "%CloudLayer always renders overhead, following the camera. It is intended "
  41. "as part of the background of your level, rendering in front of Sky/Sun "
  42. "type objects and behind everything else.\n\n"
  43. "The illusion of clouds forming and changing over time is controlled by the "
  44. "normal/opacity texture and the three sets of texture animation parameters. "
  45. "The texture is sampled three times. The first sample defines overall cloud "
  46. "density, where clouds are likely to form and their general size and shape. "
  47. "The second two samples control how it changes over time; they are "
  48. "combined and used as modifiers to the first sample.\n\n"
  49. "%CloudLayer is affected by scene lighting and is designed to be used in "
  50. "scenes with dynamic lighting or time of day changes.\n\n"
  51. "@ingroup Atmosphere"
  52. );
  53. GFXImplementVertexFormat( GFXCloudVertex )
  54. {
  55. addElement( "POSITION", GFXDeclType_Float3 );
  56. addElement( "NORMAL", GFXDeclType_Float3 );
  57. addElement( "BINORMAL", GFXDeclType_Float3 );
  58. addElement( "TANGENT", GFXDeclType_Float3 );
  59. addElement( "TEXCOORD", GFXDeclType_Float2, 0 );
  60. }
  61. U32 CloudLayer::smVertStride = 50;
  62. U32 CloudLayer::smStrideMinusOne = smVertStride - 1;
  63. U32 CloudLayer::smVertCount = smVertStride * smVertStride;
  64. U32 CloudLayer::smTriangleCount = smStrideMinusOne * smStrideMinusOne * 2;
  65. CloudLayer::CloudLayer()
  66. : mLastTime( 0 ),
  67. mBaseColor( 0.9f, 0.9f, 0.9f, 1.0f ),
  68. mExposure( 1.0f ),
  69. mCoverage( 0.5f ),
  70. mWindSpeed( 1.0f )
  71. {
  72. mTypeMask |= EnvironmentObjectType | StaticObjectType;
  73. mNetFlags.set(Ghostable | ScopeAlways);
  74. mModelViewProjSC = NULL;
  75. mAmbientColorSC = NULL;
  76. mSunColorSC = NULL;
  77. mSunVecSC = NULL;
  78. mTexScaleSC = NULL;
  79. mBaseColorSC = NULL;
  80. mCoverageSC = NULL;
  81. mExposureSC = NULL;
  82. mEyePosWorldSC = NULL;
  83. mNormalHeightMapSC = NULL;
  84. mTexOffsetSC[0] = mTexOffsetSC[1] = mTexOffsetSC[2] = 0;
  85. mTexScale[0] = 1.0;
  86. mTexScale[1] = 1.0;
  87. mTexScale[2] = 1.0;
  88. mTexDirection[0].set( 1.0f, 0.0f );
  89. mTexDirection[1].set( 0.0f, 1.0f );
  90. mTexDirection[2].set( 0.5f, 0.0f );
  91. mTexSpeed[0] = 0.005f;
  92. mTexSpeed[1] = 0.005f;
  93. mTexSpeed[2] = 0.005f;
  94. mTexOffset[0] = mTexOffset[1] = mTexOffset[2] = Point2F::Zero;
  95. mHeight = 4.0f;
  96. }
  97. IMPLEMENT_CO_NETOBJECT_V1( CloudLayer );
  98. // ConsoleObject...
  99. bool CloudLayer::onAdd()
  100. {
  101. if ( !Parent::onAdd() )
  102. return false;
  103. setGlobalBounds();
  104. resetWorldBox();
  105. addToScene();
  106. if ( isClientObject() )
  107. {
  108. _initTexture();
  109. _initBuffers();
  110. // Find ShaderData
  111. ShaderData *shaderData;
  112. mShader = Sim::findObject( "CloudLayerShader", shaderData ) ?
  113. shaderData->getShader() : NULL;
  114. if ( !mShader )
  115. {
  116. Con::errorf( "CloudLayer::onAdd - could not find CloudLayerShader" );
  117. return false;
  118. }
  119. // Create ShaderConstBuffer and Handles
  120. mShaderConsts = mShader->allocConstBuffer();
  121. mModelViewProjSC = mShader->getShaderConstHandle( "$modelView" );
  122. mEyePosWorldSC = mShader->getShaderConstHandle( "$eyePosWorld" );
  123. mSunVecSC = mShader->getShaderConstHandle( "$sunVec" );
  124. mTexOffsetSC[0] = mShader->getShaderConstHandle( "$texOffset0" );
  125. mTexOffsetSC[1] = mShader->getShaderConstHandle( "$texOffset1" );
  126. mTexOffsetSC[2] = mShader->getShaderConstHandle( "$texOffset2" );
  127. mTexScaleSC = mShader->getShaderConstHandle( "$texScale" );
  128. mAmbientColorSC = mShader->getShaderConstHandle( "$ambientColor" );
  129. mSunColorSC = mShader->getShaderConstHandle( "$sunColor" );
  130. mCoverageSC = mShader->getShaderConstHandle( "$cloudCoverage" );
  131. mExposureSC = mShader->getShaderConstHandle( "$cloudExposure" );
  132. mBaseColorSC = mShader->getShaderConstHandle( "$cloudBaseColor" );
  133. mNormalHeightMapSC = mShader->getShaderConstHandle( "$normalHeightMap" );
  134. // Create StateBlocks
  135. GFXStateBlockDesc desc;
  136. desc.setCullMode( GFXCullNone );
  137. desc.setBlend( true );
  138. desc.setZReadWrite( true, false );
  139. desc.samplersDefined = true;
  140. desc.samplers[0].addressModeU = GFXAddressWrap;
  141. desc.samplers[0].addressModeV = GFXAddressWrap;
  142. desc.samplers[0].addressModeW = GFXAddressWrap;
  143. desc.samplers[0].magFilter = GFXTextureFilterLinear;
  144. desc.samplers[0].minFilter = GFXTextureFilterLinear;
  145. desc.samplers[0].mipFilter = GFXTextureFilterLinear;
  146. desc.samplers[0].textureColorOp = GFXTOPModulate;
  147. mStateblock = GFX->createStateBlock( desc );
  148. }
  149. return true;
  150. }
  151. void CloudLayer::onRemove()
  152. {
  153. removeFromScene();
  154. Parent::onRemove();
  155. }
  156. void CloudLayer::initPersistFields()
  157. {
  158. addGroup( "CloudLayer" );
  159. addField( "texture", TypeImageFilename, Offset( mTextureName, CloudLayer ),
  160. "An RGBA texture which should contain normals and opacity (density)." );
  161. addArray( "Textures", TEX_COUNT );
  162. addField( "texScale", TypeF32, Offset( mTexScale, CloudLayer ), TEX_COUNT,
  163. "Controls the texture repeat of this slot." );
  164. addField( "texDirection", TypePoint2F, Offset( mTexDirection, CloudLayer ), TEX_COUNT,
  165. "Controls the direction this slot scrolls." );
  166. addField( "texSpeed", TypeF32, Offset( mTexSpeed, CloudLayer ), TEX_COUNT,
  167. "Controls the speed this slot scrolls." );
  168. endArray( "Textures" );
  169. addField( "baseColor", TypeColorF, Offset( mBaseColor, CloudLayer ),
  170. "Base cloud color before lighting." );
  171. addField( "exposure", TypeF32, Offset( mExposure, CloudLayer ),
  172. "Brightness scale so CloudLayer can be overblown if desired." );
  173. addField( "coverage", TypeF32, Offset( mCoverage, CloudLayer ),
  174. "Fraction of sky covered by clouds 0-1." );
  175. addField( "windSpeed", TypeF32, Offset( mWindSpeed, CloudLayer ),
  176. "Overall scalar to texture scroll speed." );
  177. addField( "height", TypeF32, Offset( mHeight, CloudLayer ),
  178. "Abstract number which controls the curvature and height of the dome mesh." );
  179. endGroup( "CloudLayer" );
  180. Parent::initPersistFields();
  181. }
  182. void CloudLayer::inspectPostApply()
  183. {
  184. Parent::inspectPostApply();
  185. setMaskBits( CloudLayerMask );
  186. }
  187. // NetObject...
  188. U32 CloudLayer::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
  189. {
  190. U32 retMask = Parent::packUpdate( conn, mask, stream );
  191. stream->write( mTextureName );
  192. for ( U32 i = 0; i < TEX_COUNT; i++ )
  193. {
  194. stream->write( mTexScale[i] );
  195. stream->write( mTexSpeed[i] );
  196. mathWrite( *stream, mTexDirection[i] );
  197. }
  198. stream->write( mBaseColor );
  199. stream->write( mCoverage );
  200. stream->write( mExposure );
  201. stream->write( mWindSpeed );
  202. stream->write( mHeight );
  203. return retMask;
  204. }
  205. void CloudLayer::unpackUpdate( NetConnection *conn, BitStream *stream )
  206. {
  207. Parent::unpackUpdate( conn, stream );
  208. String oldTextureName = mTextureName;
  209. stream->read( &mTextureName );
  210. for ( U32 i = 0; i < TEX_COUNT; i++ )
  211. {
  212. stream->read( &mTexScale[i] );
  213. stream->read( &mTexSpeed[i] );
  214. mathRead( *stream, &mTexDirection[i] );
  215. }
  216. stream->read( &mBaseColor );
  217. F32 oldCoverage = mCoverage;
  218. stream->read( &mCoverage );
  219. stream->read( &mExposure );
  220. stream->read( &mWindSpeed );
  221. F32 oldHeight = mHeight;
  222. stream->read( &mHeight );
  223. if ( isProperlyAdded() )
  224. {
  225. if ( ( oldTextureName != mTextureName ) || ( ( oldCoverage == 0.0f ) != ( mCoverage == 0.0f ) ) )
  226. _initTexture();
  227. if ( oldHeight != mHeight )
  228. _initBuffers();
  229. }
  230. }
  231. // SceneObject...
  232. void CloudLayer::prepRenderImage( SceneRenderState *state )
  233. {
  234. PROFILE_SCOPE( CloudLayer_prepRenderImage );
  235. if ( mCoverage <= 0.0f )
  236. return;
  237. if ( state->isDiffusePass() )
  238. {
  239. // Scroll textures...
  240. U32 time = Sim::getCurrentTime();
  241. F32 delta = (F32)( time - mLastTime ) / 1000.0f;
  242. mLastTime = time;
  243. for ( U32 i = 0; i < 3; i++ )
  244. {
  245. mTexOffset[i] += mTexDirection[i] * mTexSpeed[i] * delta * mWindSpeed;
  246. }
  247. }
  248. // This should be sufficient for most objects that don't manage zones, and
  249. // don't need to return a specialized RenderImage...
  250. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  251. ri->renderDelegate.bind( this, &CloudLayer::renderObject );
  252. ri->type = RenderPassManager::RIT_Sky;
  253. ri->defaultKey = 0;
  254. ri->defaultKey2 = 0;
  255. state->getRenderPass()->addInst( ri );
  256. }
  257. void CloudLayer::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mi )
  258. {
  259. GFXTransformSaver saver;
  260. const Point3F &camPos = state->getCameraPosition();
  261. MatrixF xfm(true);
  262. xfm.setPosition(camPos);
  263. GFX->multWorld(xfm);
  264. if ( state->isReflectPass() )
  265. GFX->setProjectionMatrix( state->getSceneManager()->getNonClipProjection() );
  266. GFX->setShader( mShader );
  267. GFX->setShaderConstBuffer( mShaderConsts );
  268. GFX->setStateBlock( mStateblock );
  269. // Set all the shader consts...
  270. MatrixF xform(GFX->getProjectionMatrix());
  271. xform *= GFX->getViewMatrix();
  272. xform *= GFX->getWorldMatrix();
  273. mShaderConsts->setSafe( mModelViewProjSC, xform );
  274. mShaderConsts->setSafe( mEyePosWorldSC, camPos );
  275. LightInfo *lightinfo = LIGHTMGR->getSpecialLight(LightManager::slSunLightType);
  276. const LinearColorF &sunlight = state->getAmbientLightColor();
  277. Point3F ambientColor( sunlight.red, sunlight.green, sunlight.blue );
  278. mShaderConsts->setSafe( mAmbientColorSC, ambientColor );
  279. const LinearColorF &sunColor = lightinfo->getColor();
  280. Point3F data( sunColor.red, sunColor.green, sunColor.blue );
  281. mShaderConsts->setSafe( mSunColorSC, data );
  282. mShaderConsts->setSafe( mSunVecSC, lightinfo->getDirection() );
  283. for ( U32 i = 0; i < TEX_COUNT; i++ )
  284. mShaderConsts->setSafe( mTexOffsetSC[i], mTexOffset[i] );
  285. Point3F scale( mTexScale[0], mTexScale[1], mTexScale[2] );
  286. mShaderConsts->setSafe( mTexScaleSC, scale );
  287. Point3F color;
  288. color.set( mBaseColor.red, mBaseColor.green, mBaseColor.blue );
  289. mShaderConsts->setSafe( mBaseColorSC, color );
  290. mShaderConsts->setSafe( mCoverageSC, mCoverage );
  291. mShaderConsts->setSafe( mExposureSC, mExposure );
  292. GFX->setTexture( mNormalHeightMapSC->getSamplerRegister(), mTexture );
  293. GFX->setVertexBuffer( mVB );
  294. GFX->setPrimitiveBuffer( mPB );
  295. GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, smVertCount, 0, smTriangleCount );
  296. }
  297. // CloudLayer Internal Methods....
  298. void CloudLayer::_initTexture()
  299. {
  300. if ( mCoverage <= 0.0f )
  301. {
  302. mTexture = NULL;
  303. return;
  304. }
  305. if ( mTextureName.isNotEmpty() )
  306. mTexture.set( mTextureName, &GFXNormalMapProfile, "CloudLayer" );
  307. if ( mTexture.isNull() )
  308. mTexture.set( GFXTextureManager::getWarningTexturePath(), &GFXNormalMapProfile, "CloudLayer" );
  309. }
  310. void CloudLayer::_initBuffers()
  311. {
  312. // Vertex Buffer...
  313. Point3F vertScale( 16.0f, 16.0f, mHeight );
  314. F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f );
  315. mVB.set( GFX, smVertCount, GFXBufferTypeStatic );
  316. GFXCloudVertex *pVert = mVB.lock();
  317. if(!pVert) return;
  318. for ( U32 y = 0; y < smVertStride; y++ )
  319. {
  320. F32 v = ( (F32)y / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
  321. for ( U32 x = 0; x < smVertStride; x++ )
  322. {
  323. F32 u = ( (F32)x / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
  324. F32 sx = u;
  325. F32 sy = v;
  326. F32 sz = mCos( mSqrt( sx*sx + sy*sy ) ) + zOffset;
  327. //F32 sz = 1.0f;
  328. pVert->point.set( sx, sy, sz );
  329. pVert->point *= vertScale;
  330. // The vert to our right.
  331. Point3F rpnt;
  332. F32 ru = ( (F32)( x + 1 ) / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
  333. F32 rv = v;
  334. rpnt.x = ru;
  335. rpnt.y = rv;
  336. rpnt.z = mCos( mSqrt( rpnt.x*rpnt.x + rpnt.y*rpnt.y ) ) + zOffset;
  337. rpnt *= vertScale;
  338. // The vert to our front.
  339. Point3F fpnt;
  340. F32 fu = u;
  341. F32 fv = ( (F32)( y + 1 ) / (F32)smStrideMinusOne - 0.5f ) * 2.0f;
  342. fpnt.x = fu;
  343. fpnt.y = fv;
  344. fpnt.z = mCos( mSqrt( fpnt.x*fpnt.x + fpnt.y*fpnt.y ) ) + zOffset;
  345. fpnt *= vertScale;
  346. Point3F fvec = fpnt - pVert->point;
  347. fvec.normalize();
  348. Point3F rvec = rpnt - pVert->point;
  349. rvec.normalize();
  350. pVert->normal = mCross( fvec, rvec );
  351. pVert->normal.normalize();
  352. pVert->binormal = fvec;
  353. pVert->tangent = rvec;
  354. pVert->texCoord.set( u, v );
  355. pVert++;
  356. }
  357. }
  358. mVB.unlock();
  359. // Primitive Buffer...
  360. mPB.set( GFX, smTriangleCount * 3, smTriangleCount, GFXBufferTypeStatic );
  361. U16 *pIdx = NULL;
  362. mPB.lock(&pIdx);
  363. U32 curIdx = 0;
  364. for ( U32 y = 0; y < smStrideMinusOne; y++ )
  365. {
  366. for ( U32 x = 0; x < smStrideMinusOne; x++ )
  367. {
  368. U32 offset = x + y * smVertStride;
  369. pIdx[curIdx] = offset;
  370. curIdx++;
  371. pIdx[curIdx] = offset + 1;
  372. curIdx++;
  373. pIdx[curIdx] = offset + smVertStride + 1;
  374. curIdx++;
  375. pIdx[curIdx] = offset;
  376. curIdx++;
  377. pIdx[curIdx] = offset + smVertStride + 1;
  378. curIdx++;
  379. pIdx[curIdx] = offset + smVertStride;
  380. curIdx++;
  381. }
  382. }
  383. mPB.unlock();
  384. }