basicClouds.cpp
Engine/source/environment/basicClouds.cpp
Public Functions
ConsoleDocClass(BasicClouds , "@brief Renders up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> three layers of scrolling cloud-cover textures <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">overhead.\n\n</a>" "%<a href="/coding/class/classbasicclouds/">BasicClouds</a> always renders overhead, following the camera. It is intended " "as part of the background of your level, rendering in front of Sky/<a href="/coding/class/classsun/">Sun</a> " "type objects and behind everything <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">else.\n\n</a>" "The parameters controlling the rendering of each texture are refered <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "and grouped as 'layers'. They are rendered in sequential order, so , layer 1 " "obscures layer 0, and so <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n\n</a>" "<a href="/coding/class/classbasicclouds/">BasicClouds</a> is not affected by scene lighting and is therefore not appropriate " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> scenes in which lighting radically changes, such as day/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">night.\n\n</a>" " @ingroup Atmosphere" )
Detailed Description
Public Functions
ConsoleDocClass(BasicClouds , "@brief Renders up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> three layers of scrolling cloud-cover textures <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">overhead.\n\n</a>" "%<a href="/coding/class/classbasicclouds/">BasicClouds</a> always renders overhead, following the camera. It is intended " "as part of the background of your level, rendering in front of Sky/<a href="/coding/class/classsun/">Sun</a> " "type objects and behind everything <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">else.\n\n</a>" "The parameters controlling the rendering of each texture are refered <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "and grouped as 'layers'. They are rendered in sequential order, so , layer 1 " "obscures layer 0, and so <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n\n</a>" "<a href="/coding/class/classbasicclouds/">BasicClouds</a> is not affected by scene lighting and is therefore not appropriate " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> scenes in which lighting radically changes, such as day/<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">night.\n\n</a>" " @ingroup Atmosphere" )
IMPLEMENT_CO_NETOBJECT_V1(BasicClouds )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "platform/profiler.h" 26#include "console/consoleTypes.h" 27#include "basicClouds.h" 28 29#include "gfx/gfxTransformSaver.h" 30#include "gfx/gfxTextureManager.h" 31#include "core/stream/fileStream.h" 32#include "core/stream/bitStream.h" 33#include "scene/sceneRenderState.h" 34#include "renderInstance/renderPassManager.h" 35#include "materials/shaderData.h" 36#include "math/mathIO.h" 37 38 39ConsoleDocClass( BasicClouds, 40 "@brief Renders up to three layers of scrolling cloud-cover textures overhead.\n\n" 41 42 "%BasicClouds always renders overhead, following the camera. It is intended " 43 "as part of the background of your level, rendering in front of Sky/Sun " 44 "type objects and behind everything else.\n\n" 45 46 "The parameters controlling the rendering of each texture are refered to " 47 "and grouped as 'layers'. They are rendered in sequential order, so, layer 1 " 48 "obscures layer 0, and so on.\n\n" 49 50 "BasicClouds is not affected by scene lighting and is therefore not appropriate " 51 "for scenes in which lighting radically changes, such as day/night.\n\n" 52 53 "@ingroup Atmosphere" 54); 55 56 57U32 BasicClouds::smVertStride = 50; 58U32 BasicClouds::smStrideMinusOne = 49; 59U32 BasicClouds::smVertCount = 50 * 50; 60U32 BasicClouds::smTriangleCount = smStrideMinusOne * smStrideMinusOne * 2; 61 62BasicClouds::BasicClouds() 63{ 64 mTypeMask |= EnvironmentObjectType | StaticObjectType; 65 mNetFlags.set(Ghostable | ScopeAlways); 66 67 mTimeSC = NULL; 68 mModelViewProjSC = NULL; 69 mTexScaleSC = NULL; 70 mTexDirectionSC = NULL; 71 mTexOffsetSC = NULL; 72 mDiffuseMapSC = NULL; 73 74 mLayerEnabled[0] = true; 75 mLayerEnabled[1] = true; 76 mLayerEnabled[2] = true; 77 78 // Default textures are assigned by the ObjectBuilderGui. 79 //mTexName[0] = "art/skies/clouds/cloud1"; 80 //mTexName[1] = "art/skies/clouds/cloud2"; 81 //mTexName[2] = "art/skies/clouds/cloud3"; 82 83 mHeight[0] = 4.0f; 84 mHeight[1] = 3.0f; 85 mHeight[2] = 2.0f; 86 87 mTexSpeed[0] = 0.0005f; 88 mTexSpeed[1] = 0.001f; 89 mTexSpeed[2] = 0.0003f; 90 91 mTexScale[0] = 1.0; 92 mTexScale[1] = 1.0; 93 mTexScale[2] = 1.0; 94 95 mTexDirection[0].set( 1.0f, 0.0f ); 96 mTexDirection[1].set( 1.0f, 0.0f ); 97 mTexDirection[2].set( 1.0f, 0.0f ); 98 99 mTexOffset[0].set( 0.5f, 0.5f ); 100 mTexOffset[1].set( 0.5f, 0.5f ); 101 mTexOffset[2].set( 0.5f, 0.5f ); 102} 103 104IMPLEMENT_CO_NETOBJECT_V1( BasicClouds ); 105 106// ConsoleObject... 107 108 109bool BasicClouds::onAdd() 110{ 111 if ( !Parent::onAdd() ) 112 return false; 113 114 setGlobalBounds(); 115 resetWorldBox(); 116 117 addToScene(); 118 119 if ( isClientObject() ) 120 { 121 _initTexture(); 122 _initBuffers(); 123 124 // Find ShaderData 125 ShaderData *shaderData; 126 mShader = Sim::findObject( "BasicCloudsShader", shaderData ) ? shaderData->getShader() : NULL; 127 if ( !mShader ) 128 { 129 Con::errorf( "BasicClouds::onAdd - could not find BasicCloudsShader" ); 130 return false; 131 } 132 133 // Create ShaderConstBuffer and Handles 134 mShaderConsts = mShader->allocConstBuffer(); 135 mModelViewProjSC = mShader->getShaderConstHandle( "$modelView" ); 136 mTimeSC = mShader->getShaderConstHandle( "$accumTime" ); 137 mTexScaleSC = mShader->getShaderConstHandle( "$texScale" ); 138 mTexDirectionSC = mShader->getShaderConstHandle( "$texDirection" ); 139 mTexOffsetSC = mShader->getShaderConstHandle( "$texOffset" ); 140 mDiffuseMapSC = mShader->getShaderConstHandle( "$diffuseMap" ); 141 142 // Create StateBlocks 143 GFXStateBlockDesc desc; 144 desc.setCullMode( GFXCullNone ); 145 desc.setBlend( true ); 146 desc.setZReadWrite( true, false ); 147 desc.samplersDefined = true; 148 desc.samplers[0].addressModeU = GFXAddressWrap; 149 desc.samplers[0].addressModeV = GFXAddressWrap; 150 desc.samplers[0].addressModeW = GFXAddressWrap; 151 desc.samplers[0].magFilter = GFXTextureFilterLinear; 152 desc.samplers[0].minFilter = GFXTextureFilterLinear; 153 desc.samplers[0].mipFilter = GFXTextureFilterLinear; 154 155 mStateblock = GFX->createStateBlock( desc ); 156 } 157 158 return true; 159} 160 161void BasicClouds::onRemove() 162{ 163 removeFromScene(); 164 165 Parent::onRemove(); 166} 167 168void BasicClouds::initPersistFields() 169{ 170 addGroup( "BasicClouds" ); 171 172 addArray( "Layers", TEX_COUNT ); 173 174 addField( "layerEnabled", TypeBool, Offset( mLayerEnabled, BasicClouds ), TEX_COUNT, 175 "Enable or disable rendering of this layer." ); 176 177 addField( "texture", TypeImageFilename, Offset( mTexName, BasicClouds ), TEX_COUNT, 178 "Texture for this layer." ); 179 180 addField( "texScale", TypeF32, Offset( mTexScale, BasicClouds ), TEX_COUNT, 181 "Texture repeat for this layer." ); 182 183 addField( "texDirection", TypePoint2F, Offset( mTexDirection, BasicClouds ), TEX_COUNT, 184 "Texture scroll direction for this layer, relative to the world axis." ); 185 186 addField( "texSpeed", TypeF32, Offset( mTexSpeed, BasicClouds ), TEX_COUNT, 187 "Texture scroll speed for this layer." ); 188 189 addField( "texOffset", TypePoint2F, Offset( mTexOffset, BasicClouds ), TEX_COUNT, 190 "UV offset for this layer." ); 191 192 addField( "height", TypeF32, Offset( mHeight, BasicClouds ), TEX_COUNT, 193 "Abstract number which controls the curvature and height of the dome mesh" ); 194 195 endArray( "Layers" ); 196 197 endGroup( "BasicClouds" ); 198 199 Parent::initPersistFields(); 200} 201 202void BasicClouds::inspectPostApply() 203{ 204 Parent::inspectPostApply(); 205 setMaskBits( BasicCloudsMask ); 206} 207 208 209// NetObject... 210 211 212U32 BasicClouds::packUpdate( NetConnection *conn, U32 mask, BitStream *stream ) 213{ 214 U32 retMask = Parent::packUpdate( conn, mask, stream ); 215 216 for ( U32 i = 0; i < TEX_COUNT; i++ ) 217 { 218 stream->writeFlag( mLayerEnabled[i] ); 219 220 stream->write( mTexName[i] ); 221 222 stream->write( mTexScale[i] ); 223 mathWrite( *stream, mTexDirection[i] ); 224 stream->write( mTexSpeed[i] ); 225 mathWrite( *stream, mTexOffset[i] ); 226 227 stream->write( mHeight[i] ); 228 } 229 230 return retMask; 231} 232 233void BasicClouds::unpackUpdate( NetConnection *conn, BitStream *stream ) 234{ 235 Parent::unpackUpdate( conn, stream ); 236 237 for ( U32 i = 0; i < TEX_COUNT; i++ ) 238 { 239 mLayerEnabled[i] = stream->readFlag(); 240 241 stream->read( &mTexName[i] ); 242 243 stream->read( &mTexScale[i] ); 244 mathRead( *stream, &mTexDirection[i] ); 245 stream->read( &mTexSpeed[i] ); 246 mathRead( *stream, &mTexOffset[i] ); 247 248 stream->read( &mHeight[i] ); 249 } 250 251 if ( isProperlyAdded() ) 252 { 253 // We could check if the height or texture have actually changed. 254 _initBuffers(); 255 _initTexture(); 256 } 257} 258 259 260// SceneObject... 261 262 263void BasicClouds::prepRenderImage( SceneRenderState *state ) 264{ 265 PROFILE_SCOPE( BasicClouds_prepRenderImage ); 266 267 bool isEnabled = false; 268 for ( U32 i = 0; i < TEX_COUNT; i++ ) 269 { 270 if ( mLayerEnabled[i] ) 271 { 272 isEnabled = true; 273 break; 274 } 275 } 276 277 if ( !isEnabled ) 278 return; 279 280 // This should be sufficient for most objects that don't manage zones, and 281 // don't need to return a specialized RenderImage... 282 ObjectRenderInst *ri = state->getRenderPass()->allocInst< ObjectRenderInst >(); 283 ri->renderDelegate.bind( this, &BasicClouds::renderObject ); 284 ri->type = RenderPassManager::RIT_Sky; 285 ri->defaultKey = 0; 286 ri->defaultKey2 = 0; 287 state->getRenderPass()->addInst( ri ); 288} 289 290void BasicClouds::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mi ) 291{ 292 GFXTransformSaver saver; 293 294 Point3F camPos = state->getCameraPosition(); 295 MatrixF xfm(true); 296 xfm.setPosition(camPos); 297 GFX->multWorld(xfm); 298 299 if ( state->isReflectPass() ) 300 GFX->setProjectionMatrix( state->getSceneManager()->getNonClipProjection() ); 301 302 GFX->setShader( mShader ); 303 GFX->setShaderConstBuffer( mShaderConsts ); 304 GFX->setStateBlock( mStateblock ); 305 306 MatrixF xform(GFX->getProjectionMatrix()); 307 xform *= GFX->getViewMatrix(); 308 xform *= GFX->getWorldMatrix(); 309 310 mShaderConsts->setSafe( mModelViewProjSC, xform ); 311 mShaderConsts->setSafe( mTimeSC, (F32)Sim::getCurrentTime() / 1000.0f ); 312 GFX->setPrimitiveBuffer( mPB ); 313 314 for ( U32 i = 0; i < TEX_COUNT; i++ ) 315 { 316 if ( !mLayerEnabled[i] ) 317 continue; 318 319 mShaderConsts->setSafe( mTexScaleSC, mTexScale[i] ); 320 mShaderConsts->setSafe( mTexDirectionSC, mTexDirection[i] * mTexSpeed[i] ); 321 mShaderConsts->setSafe( mTexOffsetSC, mTexOffset[i] ); 322 323 GFX->setTexture( mDiffuseMapSC->getSamplerRegister(), mTexture[i] ); 324 GFX->setVertexBuffer( mVB[i] ); 325 326 GFX->drawIndexedPrimitive( GFXTriangleList, 0, 0, smVertCount, 0, smTriangleCount ); 327 } 328} 329 330 331// BasicClouds Internal Methods.... 332 333 334void BasicClouds::_initTexture() 335{ 336 for ( U32 i = 0; i < TEX_COUNT; i++ ) 337 { 338 if ( !mLayerEnabled[i] ) 339 { 340 mTexture[i] = NULL; 341 continue; 342 } 343 344 if ( mTexName[i].isNotEmpty() ) 345 mTexture[i].set( mTexName[i], &GFXStaticTextureSRGBProfile, "BasicClouds" ); 346 347 if ( mTexture[i].isNull() ) 348 mTexture[i].set( GFXTextureManager::getWarningTexturePath(), &GFXStaticTextureSRGBProfile, "BasicClouds" ); 349 } 350} 351 352void BasicClouds::_initBuffers() 353{ 354 // Primitive Buffer... Is shared for all Layers. 355 356 mPB.set( GFX, smTriangleCount * 3, smTriangleCount, GFXBufferTypeStatic ); 357 358 U16 *pIdx = NULL; 359 mPB.lock(&pIdx); 360 U32 curIdx = 0; 361 362 for ( U32 y = 0; y < smStrideMinusOne; y++ ) 363 { 364 for ( U32 x = 0; x < smStrideMinusOne; x++ ) 365 { 366 U32 offset = x + y * smVertStride; 367 368 pIdx[curIdx] = offset; 369 curIdx++; 370 pIdx[curIdx] = offset + 1; 371 curIdx++; 372 pIdx[curIdx] = offset + smVertStride + 1; 373 curIdx++; 374 375 pIdx[curIdx] = offset; 376 curIdx++; 377 pIdx[curIdx] = offset + smVertStride + 1; 378 curIdx++; 379 pIdx[curIdx] = offset + smVertStride; 380 curIdx++; 381 } 382 } 383 384 mPB.unlock(); 385 386 // Vertex Buffer... 387 // Each layer has their own so they can be at different heights. 388 389 for ( U32 i = 0; i < TEX_COUNT; i++ ) 390 { 391 Point3F vertScale( 16.0f, 16.0f, mHeight[i] ); 392 F32 zOffset = -( mCos( mSqrt( 1.0f ) ) + 0.01f ); 393 394 mVB[i].set( GFX, smVertCount, GFXBufferTypeStatic ); 395 GFXVertexPT *pVert = mVB[i].lock(); 396 397 for ( U32 y = 0; y < smVertStride; y++ ) 398 { 399 F32 v = ( (F32)y / (F32)smStrideMinusOne - 0.5f ) * 2.0f; 400 401 for ( U32 x = 0; x < smVertStride; x++ ) 402 { 403 F32 u = ( (F32)x / (F32)smStrideMinusOne - 0.5f ) * 2.0f; 404 405 F32 sx = u; 406 F32 sy = v; 407 F32 sz = mCos( mSqrt( sx*sx + sy*sy ) ) + zOffset; 408 409 pVert->point.set( sx, sy, sz ); 410 pVert->point *= vertScale; 411 pVert->texCoord.set( u, v ); 412 pVert++; 413 } 414 } 415 416 mVB[i].unlock(); 417 } 418} 419